From c764d91b6a69f589fa2a7a409229c9829e644562 Mon Sep 17 00:00:00 2001 From: Moshe Immerman Date: Fri, 14 Jul 2023 14:12:04 +0300 Subject: [PATCH] feat: add cel support * chore: drop unsafe functions * chore: add new functions * feat: add new interface * feat: add cel functions * chore: add tests * manually edit some cel functions to support unsupported go types in cel env --------- Co-authored-by: Aditya Thebe --- .github/workflows/test.yml | 22 + Dockerfile.integration | 7 - aws/doc.go | 2 - aws/ec2info.go | 215 -- aws/ec2info_test.go | 195 -- aws/ec2meta.go | 156 -- aws/ec2meta_test.go | 75 - aws/kms.go | 60 - aws/kms_test.go | 52 - aws/sts.go | 76 - aws/sts_test.go | 106 - aws/testutils.go | 86 - cel/cel_test.go | 4 +- cmd/gencel.go | 4 +- cmd/gencel_test.go | 4 +- config.go | 144 -- config_test.go | 48 - context.go | 38 - context_test.go | 59 - crypto/aes.go | 88 - crypto/aes_test.go | 67 - crypto/crypto_fuzz_test.go | 56 - crypto/doc.go | 2 - crypto/ecdsa.go | 72 - crypto/ecdsa_test.go | 79 - crypto/pbkdf2.go | 57 - crypto/pbkdf2_test.go | 87 - crypto/rsa.go | 109 -- crypto/rsa_test.go | 138 -- data/data.go | 42 - data/data_test.go | 70 - data/datasource.go | 378 ---- data/datasource_aws_sm.go | 87 - data/datasource_aws_sm_test.go | 176 -- data/datasource_awssmp.go | 78 - data/datasource_awssmp_test.go | 143 -- data/datasource_blob.go | 170 -- data/datasource_env.go | 19 - data/datasource_env_test.go | 55 - data/datasource_file.go | 85 - data/datasource_file_test.go | 70 - data/datasource_git.go | 329 ---- data/datasource_git_test.go | 486 ----- data/datasource_http.go | 63 - data/datasource_http_test.go | 149 -- data/datasource_merge.go | 101 - data/datasource_merge_test.go | 152 -- data/datasource_stdin.go | 33 - data/datasource_stdin_test.go | 22 - data/datasource_test.go | 428 ---- data/mimetypes.go | 25 - data/mimetypes_test.go | 22 - env/env.go | 70 - env/env_test.go | 121 -- file/file.go | 105 - file/file_test.go | 122 -- func_test.go | 13 - funcs.go | 29 +- funcs/aws.go | 150 -- funcs/aws_test.go | 46 - funcs/base64_gen.go | 67 + funcs/cel_gen_exports.go | 49 +- funcs/conv.go | 5 - funcs/crypto.go | 209 -- funcs/crypto_gen.go | 267 --- funcs/crypto_test.go | 180 +- funcs/data.go | 17 +- funcs/data_test.go | 2 +- funcs/env.go | 47 - funcs/env_test.go | 37 - funcs/file.go | 91 - funcs/file_gen.go | 141 -- funcs/file_test.go | 80 - funcs/funcs.go | 15 - funcs/gcp.go | 54 - funcs/gcp_test.go | 26 - funcs/k8s.go | 42 + funcs/k8s_gen.go | 58 + funcs/net.go | 232 --- funcs/net_test.go | 155 -- funcs/sockaddr.go | 128 -- funcs/sockaddr_gen.go | 364 ---- funcs/sockaddr_test.go | 26 - funcs/sprig.go | 16 - funcs/strings.go | 45 +- funcs/strings_gen.go | 90 +- funcs/test.go | 7 + funcs/time.go | 7 +- gcp/meta.go | 130 -- gencel/file.go | 3 + gencel/generator.go | 56 +- go.mod | 118 +- go.sum | 2913 +--------------------------- internal/config/configfile.go | 652 ------- internal/config/configfile_test.go | 935 --------- internal/config/types.go | 94 - internal/config/types_test.go | 88 - internal/deprecated/deprecated.go | 14 - k8s/cel_gen_exports.go | 24 + k8s/k8s.go | 98 + k8s/k8s_test.go | 33 + k8s/testdata.go | 175 ++ net/net.go | 70 - net/net_test.go | 37 - plugins.go | 175 -- plugins_test.go | 116 -- strings/bytes.go | 114 ++ strings/bytes_test.go | 28 + strings/cel_gen_exports.go | 32 + strings/duration.go | 426 ++++ strings/duration_gen.go | 105 + strings/duration_test.go | 34 + strings/semver.go | 23 + strings/semver_test.go | 13 + template.go | 110 ++ template_test.go | 67 + time/time.go | 9 +- 117 files changed, 1749 insertions(+), 13347 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 aws/doc.go delete mode 100644 aws/ec2info.go delete mode 100644 aws/ec2info_test.go delete mode 100644 aws/ec2meta.go delete mode 100644 aws/ec2meta_test.go delete mode 100644 aws/kms.go delete mode 100644 aws/kms_test.go delete mode 100644 aws/sts.go delete mode 100644 aws/sts_test.go delete mode 100644 aws/testutils.go delete mode 100644 config.go delete mode 100644 config_test.go delete mode 100644 context.go delete mode 100644 context_test.go delete mode 100644 crypto/aes.go delete mode 100644 crypto/aes_test.go delete mode 100644 crypto/crypto_fuzz_test.go delete mode 100644 crypto/doc.go delete mode 100644 crypto/ecdsa.go delete mode 100644 crypto/ecdsa_test.go delete mode 100644 crypto/pbkdf2.go delete mode 100644 crypto/pbkdf2_test.go delete mode 100644 crypto/rsa.go delete mode 100644 crypto/rsa_test.go delete mode 100644 data/datasource.go delete mode 100644 data/datasource_aws_sm.go delete mode 100644 data/datasource_aws_sm_test.go delete mode 100644 data/datasource_awssmp.go delete mode 100644 data/datasource_awssmp_test.go delete mode 100644 data/datasource_blob.go delete mode 100644 data/datasource_env.go delete mode 100644 data/datasource_env_test.go delete mode 100644 data/datasource_file.go delete mode 100644 data/datasource_file_test.go delete mode 100644 data/datasource_git.go delete mode 100644 data/datasource_git_test.go delete mode 100644 data/datasource_http.go delete mode 100644 data/datasource_http_test.go delete mode 100644 data/datasource_merge.go delete mode 100644 data/datasource_merge_test.go delete mode 100644 data/datasource_stdin.go delete mode 100644 data/datasource_stdin_test.go delete mode 100644 data/datasource_test.go delete mode 100644 data/mimetypes.go delete mode 100644 data/mimetypes_test.go delete mode 100644 env/env.go delete mode 100644 env/env_test.go delete mode 100644 file/file.go delete mode 100644 file/file_test.go delete mode 100644 func_test.go delete mode 100644 funcs/aws.go delete mode 100644 funcs/aws_test.go create mode 100644 funcs/base64_gen.go delete mode 100644 funcs/env.go delete mode 100644 funcs/env_test.go delete mode 100644 funcs/file.go delete mode 100644 funcs/file_gen.go delete mode 100644 funcs/file_test.go delete mode 100644 funcs/funcs.go delete mode 100644 funcs/gcp.go delete mode 100644 funcs/gcp_test.go create mode 100644 funcs/k8s.go create mode 100644 funcs/k8s_gen.go delete mode 100644 funcs/net.go delete mode 100644 funcs/net_test.go delete mode 100644 funcs/sockaddr.go delete mode 100644 funcs/sockaddr_gen.go delete mode 100644 funcs/sockaddr_test.go delete mode 100644 funcs/sprig.go delete mode 100644 gcp/meta.go delete mode 100644 internal/config/configfile.go delete mode 100644 internal/config/configfile_test.go delete mode 100644 internal/config/types.go delete mode 100644 internal/config/types_test.go delete mode 100644 internal/deprecated/deprecated.go create mode 100644 k8s/cel_gen_exports.go create mode 100644 k8s/k8s.go create mode 100644 k8s/k8s_test.go create mode 100644 k8s/testdata.go delete mode 100644 net/net.go delete mode 100644 net/net_test.go delete mode 100644 plugins.go delete mode 100644 plugins_test.go create mode 100644 strings/bytes.go create mode 100644 strings/bytes_test.go create mode 100644 strings/cel_gen_exports.go create mode 100644 strings/duration.go create mode 100644 strings/duration_gen.go create mode 100644 strings/duration_test.go create mode 100644 strings/semver.go create mode 100644 strings/semver_test.go create mode 100644 template.go create mode 100644 template_test.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..e82561596 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,22 @@ +name: test +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.20.x + - name: Checkout code + uses: actions/checkout@v2 + - name: Test + run: go test ./... diff --git a/Dockerfile.integration b/Dockerfile.integration index 502b5ca58..d9fd17d00 100644 --- a/Dockerfile.integration +++ b/Dockerfile.integration @@ -1,12 +1,5 @@ -FROM vault:1.11.3 AS vault - -FROM consul:1.13.1 AS consul - FROM golang:1.19-alpine -COPY --from=vault /bin/vault /bin/vault -COPY --from=consul /bin/consul /bin/consul - RUN apk add --no-cache make tzdata WORKDIR /go/src/github.com/hairyhenderson/gomplate/ diff --git a/aws/doc.go b/aws/doc.go deleted file mode 100644 index 1155433ce..000000000 --- a/aws/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package aws contains functions which wrap various Amazon Web Services APIs -package aws diff --git a/aws/ec2info.go b/aws/ec2info.go deleted file mode 100644 index 9486152c7..000000000 --- a/aws/ec2info.go +++ /dev/null @@ -1,215 +0,0 @@ -package aws - -import ( - "fmt" - "net/http" - "os" - "strconv" - "sync" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/flanksource/gomplate/v3/env" -) - -var describerClient InstanceDescriber - -var ( - co ClientOptions - coInit sync.Once - sdkSession *session.Session - sdkSessionInit sync.Once -) - -// ClientOptions - -type ClientOptions struct { - Timeout time.Duration -} - -// Ec2Info - -type Ec2Info struct { - describer func() (InstanceDescriber, error) - metaClient *Ec2Meta - cache map[string]interface{} -} - -// InstanceDescriber - A subset of ec2iface.EC2API that we can use to call EC2.DescribeInstances -type InstanceDescriber interface { - DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) -} - -// GetClientOptions - Centralised reading of AWS_TIMEOUT -// ... but cannot use in vault/auth.go as different strconv.Atoi error handling -func GetClientOptions() ClientOptions { - coInit.Do(func() { - timeout := env.Getenv("AWS_TIMEOUT") - if timeout == "" { - timeout = "500" - } - - t, err := strconv.Atoi(timeout) - if err != nil { - panic(fmt.Errorf("invalid AWS_TIMEOUT value '%s' - must be an integer: %w", timeout, err)) - } - - co.Timeout = time.Duration(t) * time.Millisecond - }) - return co -} - -// SDKSession - -func SDKSession(region ...string) *session.Session { - sdkSessionInit.Do(func() { - options := GetClientOptions() - timeout := options.Timeout - if timeout == 0 { - timeout = 500 * time.Millisecond - } - - config := aws.NewConfig() - config = config.WithHTTPClient(&http.Client{Timeout: timeout}) - - if env.Getenv("AWS_ANON") == "true" { - config = config.WithCredentials(credentials.AnonymousCredentials) - } - - metaRegion := "" - if len(region) > 0 { - metaRegion = region[0] - } else { - var err error - metaRegion, err = getRegion() - if err != nil { - panic(fmt.Errorf("failed to determine EC2 region: %w", err)) - } - } - if metaRegion != "" && metaRegion != unknown { - config = config.WithRegion(metaRegion) - } - config = config.WithCredentialsChainVerboseErrors(true) - - sdkSession = session.Must(session.NewSessionWithOptions(session.Options{ - Config: *config, - SharedConfigState: session.SharedConfigEnable, - })) - }) - return sdkSession -} - -// Attempts to get the EC2 region to use. If we're running on an EC2 Instance -// and neither AWS_REGION nor AWS_DEFAULT_REGION are set, we'll infer from EC2 -// metadata. -// Once https://github.com/aws/aws-sdk-go/issues/1103 is resolve this should be -// tidier! -func getRegion(m ...*Ec2Meta) (string, error) { - region := "" - _, default1 := os.LookupEnv("AWS_REGION") - _, default2 := os.LookupEnv("AWS_DEFAULT_REGION") - if !default1 && !default2 { - // Maybe we're in EC2, let's try to read metadata - var metaClient *Ec2Meta - if len(m) > 0 { - metaClient = m[0] - } else { - metaClient = NewEc2Meta(GetClientOptions()) - } - var err error - region, err = metaClient.Region() - if err != nil { - return "", fmt.Errorf("failed to determine EC2 region: %w", err) - } - } - return region, nil -} - -// NewEc2Info - -func NewEc2Info(options ClientOptions) (info *Ec2Info) { - metaClient := NewEc2Meta(options) - return &Ec2Info{ - describer: func() (InstanceDescriber, error) { - if describerClient == nil { - session := SDKSession() - describerClient = ec2.New(session) - } - return describerClient, nil - }, - metaClient: metaClient, - cache: make(map[string]interface{}), - } -} - -// Tag - -func (e *Ec2Info) Tag(tag string, def ...string) (string, error) { - output, err := e.describeInstance() - if err != nil { - return "", err - } - if output == nil { - return returnDefault(def), nil - } - - if len(output.Reservations) > 0 && - len(output.Reservations[0].Instances) > 0 && - len(output.Reservations[0].Instances[0].Tags) > 0 { - for _, v := range output.Reservations[0].Instances[0].Tags { - if *v.Key == tag { - return *v.Value, nil - } - } - } - - return returnDefault(def), nil -} - -func (e *Ec2Info) Tags() (map[string]string, error) { - tags := map[string]string{} - - output, err := e.describeInstance() - if err != nil { - return tags, err - } - if output == nil { - return tags, nil - } - - if len(output.Reservations) > 0 && - len(output.Reservations[0].Instances) > 0 && - len(output.Reservations[0].Instances[0].Tags) > 0 { - for _, v := range output.Reservations[0].Instances[0].Tags { - tags[*v.Key] = *v.Value - } - } - - return tags, nil -} - -func (e *Ec2Info) describeInstance() (output *ec2.DescribeInstancesOutput, err error) { - // cache the InstanceDescriber here - d, err := e.describer() - if err != nil || e.metaClient.nonAWS { - return nil, err - } - - if cached, ok := e.cache["DescribeInstances"]; ok { - output = cached.(*ec2.DescribeInstancesOutput) - } else { - instanceID, err := e.metaClient.Meta("instance-id") - if err != nil { - return nil, err - } - input := &ec2.DescribeInstancesInput{ - InstanceIds: aws.StringSlice([]string{instanceID}), - } - - output, err = d.DescribeInstances(input) - if err != nil { - // default to nil if we can't describe the instance - this could be for any reason - return nil, nil - } - e.cache["DescribeInstances"] = output - } - return output, nil -} diff --git a/aws/ec2info_test.go b/aws/ec2info_test.go deleted file mode 100644 index b2ca93360..000000000 --- a/aws/ec2info_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package aws - -import ( - "os" - "sync" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/stretchr/testify/assert" -) - -func TestTag_MissingKey(t *testing.T) { - ec2meta := MockEC2Meta(map[string]string{"instance-id": "i-1234"}, nil, "") - - client := DummyInstanceDescriber{ - tags: []*ec2.Tag{ - { - Key: aws.String("foo"), - Value: aws.String("bar"), - }, - { - Key: aws.String("baz"), - Value: aws.String("qux"), - }, - }, - } - e := &Ec2Info{ - describer: func() (InstanceDescriber, error) { - return client, nil - }, - metaClient: ec2meta, - cache: make(map[string]interface{}), - } - - assert.Empty(t, must(e.Tag("missing"))) - assert.Equal(t, "default", must(e.Tag("missing", "default"))) -} - -func TestTag_ValidKey(t *testing.T) { - ec2meta := MockEC2Meta(map[string]string{"instance-id": "i-1234"}, nil, "") - - client := DummyInstanceDescriber{ - tags: []*ec2.Tag{ - { - Key: aws.String("foo"), - Value: aws.String("bar"), - }, - { - Key: aws.String("baz"), - Value: aws.String("qux"), - }, - }, - } - e := &Ec2Info{ - describer: func() (InstanceDescriber, error) { - return client, nil - }, - metaClient: ec2meta, - cache: make(map[string]interface{}), - } - - assert.Equal(t, "bar", must(e.Tag("foo"))) - assert.Equal(t, "bar", must(e.Tag("foo", "default"))) -} - -func TestTags(t *testing.T) { - ec2meta := MockEC2Meta(map[string]string{"instance-id": "i-1234"}, nil, "") - client := DummyInstanceDescriber{ - tags: []*ec2.Tag{ - { - Key: aws.String("foo"), - Value: aws.String("bar"), - }, - { - Key: aws.String("baz"), - Value: aws.String("qux"), - }, - }, - } - e := &Ec2Info{ - describer: func() (InstanceDescriber, error) { - return client, nil - }, - metaClient: ec2meta, - cache: make(map[string]interface{}), - } - - assert.Equal(t, map[string]string{"foo": "bar", "baz": "qux"}, must(e.Tags())) -} - -func TestTag_NonEC2(t *testing.T) { - ec2meta := MockEC2Meta(nil, nil, "") - ec2meta.nonAWS = true - - client := DummyInstanceDescriber{} - e := &Ec2Info{ - describer: func() (InstanceDescriber, error) { - return client, nil - }, - metaClient: ec2meta, - cache: make(map[string]interface{}), - } - - assert.Equal(t, "", must(e.Tag("foo"))) - assert.Equal(t, "default", must(e.Tag("foo", "default"))) -} - -func TestNewEc2Info(t *testing.T) { - ec2meta := MockEC2Meta(map[string]string{"instance-id": "i-1234"}, nil, "") - client := DummyInstanceDescriber{ - tags: []*ec2.Tag{ - { - Key: aws.String("foo"), - Value: aws.String("bar"), - }, - { - Key: aws.String("baz"), - Value: aws.String("qux"), - }, - }, - } - e := NewEc2Info(ClientOptions{}) - e.describer = func() (InstanceDescriber, error) { - return client, nil - } - e.metaClient = ec2meta - - assert.Equal(t, "bar", must(e.Tag("foo"))) - assert.Equal(t, "bar", must(e.Tag("foo", "default"))) -} - -func TestGetRegion(t *testing.T) { - oldReg, ok := os.LookupEnv("AWS_REGION") - if ok { - defer os.Setenv("AWS_REGION", oldReg) - } - oldDefReg, ok := os.LookupEnv("AWS_DEFAULT_REGION") - if ok { - defer os.Setenv("AWS_REGION", oldDefReg) - } - - os.Setenv("AWS_REGION", "kalamazoo") - os.Unsetenv("AWS_DEFAULT_REGION") - region, err := getRegion() - assert.NoError(t, err) - assert.Empty(t, region) - - os.Setenv("AWS_DEFAULT_REGION", "kalamazoo") - os.Unsetenv("AWS_REGION") - region, err = getRegion() - assert.NoError(t, err) - assert.Empty(t, region) - - os.Unsetenv("AWS_DEFAULT_REGION") - metaClient := NewDummyEc2Meta() - region, err = getRegion(metaClient) - assert.NoError(t, err) - assert.Equal(t, "unknown", region) - - ec2meta := MockEC2Meta(nil, nil, "us-east-1") - - region, err = getRegion(ec2meta) - assert.NoError(t, err) - assert.Equal(t, "us-east-1", region) -} - -func TestGetClientOptions(t *testing.T) { - oldVar, ok := os.LookupEnv("AWS_TIMEOUT") - if ok { - defer os.Setenv("AWS_TIMEOUT", oldVar) - } - - co := GetClientOptions() - assert.Equal(t, ClientOptions{Timeout: 500 * time.Millisecond}, co) - - os.Setenv("AWS_TIMEOUT", "42") - // reset the Once - coInit = sync.Once{} - co = GetClientOptions() - assert.Equal(t, ClientOptions{Timeout: 42 * time.Millisecond}, co) - - os.Setenv("AWS_TIMEOUT", "123") - // without resetting the Once, expect to be reused - co = GetClientOptions() - assert.Equal(t, ClientOptions{Timeout: 42 * time.Millisecond}, co) - - os.Setenv("AWS_TIMEOUT", "foo") - // reset the Once - coInit = sync.Once{} - assert.Panics(t, func() { - GetClientOptions() - }) -} diff --git a/aws/ec2meta.go b/aws/ec2meta.go deleted file mode 100644 index b63883284..000000000 --- a/aws/ec2meta.go +++ /dev/null @@ -1,156 +0,0 @@ -package aws - -import ( - "net/http" - "strings" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/flanksource/gomplate/v3/env" -) - -const ( - // the default region - unknown = "unknown" -) - -// Ec2Meta - -type Ec2Meta struct { - metadataCache map[string]string - dynamicdataCache map[string]string - ec2MetadataProvider func() (EC2Metadata, error) - nonAWS bool -} - -type EC2Metadata interface { - GetMetadata(p string) (string, error) - GetDynamicData(p string) (string, error) - Region() (string, error) -} - -// NewEc2Meta - -func NewEc2Meta(options ClientOptions) *Ec2Meta { - return &Ec2Meta{ - metadataCache: make(map[string]string), - dynamicdataCache: make(map[string]string), - ec2MetadataProvider: func() (EC2Metadata, error) { - config := aws.NewConfig() - config = config.WithHTTPClient(&http.Client{Timeout: options.Timeout}) - if endpoint := env.Getenv("AWS_META_ENDPOINT"); endpoint != "" { - config = config.WithEndpoint(endpoint) - } - - s, err := session.NewSession(config) - if err != nil { - return nil, err - } - - return ec2metadata.New(s), nil - }, - } -} - -// returnDefault - -func returnDefault(def []string) string { - if len(def) > 0 { - return def[0] - } - return "" -} - -func unreachable(err error) bool { - if strings.Contains(err.Error(), "request canceled") || - strings.Contains(err.Error(), "no route to host") || - strings.Contains(err.Error(), "host is down") { - return true - } - - return false -} - -func (e *Ec2Meta) retrieveMetadata(key string, def ...string) (string, error) { - if value, ok := e.metadataCache[key]; ok { - return value, nil - } - - if e.nonAWS { - return returnDefault(def), nil - } - - emd, err := e.ec2MetadataProvider() - if err != nil { - return "", err - } - - value, err := emd.GetMetadata(key) - if err != nil { - if unreachable(err) { - e.nonAWS = true - } - return returnDefault(def), nil - } - e.metadataCache[key] = value - - return value, nil -} - -func (e *Ec2Meta) retrieveDynamicdata(key string, def ...string) (string, error) { - if value, ok := e.dynamicdataCache[key]; ok { - return value, nil - } - - if e.nonAWS { - return returnDefault(def), nil - } - - emd, err := e.ec2MetadataProvider() - if err != nil { - return "", err - } - - value, err := emd.GetDynamicData(key) - if err != nil { - if unreachable(err) { - e.nonAWS = true - } - return returnDefault(def), nil - } - e.dynamicdataCache[key] = value - - return value, nil -} - -// Meta - -func (e *Ec2Meta) Meta(key string, def ...string) (string, error) { - return e.retrieveMetadata(key, def...) -} - -// Dynamic - -func (e *Ec2Meta) Dynamic(key string, def ...string) (string, error) { - return e.retrieveDynamicdata(key, def...) -} - -// Region - -func (e *Ec2Meta) Region(def ...string) (string, error) { - defaultRegion := returnDefault(def) - if defaultRegion == "" { - defaultRegion = unknown - } - - if e.nonAWS { - return defaultRegion, nil - } - - emd, err := e.ec2MetadataProvider() - if err != nil { - return "", err - } - - region, err := emd.Region() - if err != nil || region == "" { - return defaultRegion, nil - } - - return region, nil -} diff --git a/aws/ec2meta_test.go b/aws/ec2meta_test.go deleted file mode 100644 index 732f97b6e..000000000 --- a/aws/ec2meta_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package aws - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" -) - -func must(r interface{}, err error) interface{} { - if err != nil { - panic(err) - } - return r -} - -func TestMeta_MissingKey(t *testing.T) { - ec2meta := MockEC2Meta(nil, nil, "") - - assert.Empty(t, must(ec2meta.Meta("foo"))) - assert.Equal(t, "default", must(ec2meta.Meta("foo", "default"))) -} - -func TestMeta_ValidKey(t *testing.T) { - ec2meta := MockEC2Meta(map[string]string{"instance-id": "i-1234"}, nil, "") - - assert.Equal(t, "i-1234", must(ec2meta.Meta("instance-id"))) - assert.Equal(t, "i-1234", must(ec2meta.Meta("instance-id", "unused default"))) -} - -func TestDynamic_MissingKey(t *testing.T) { - ec2meta := MockEC2Meta(nil, nil, "") - - assert.Empty(t, must(ec2meta.Dynamic("foo"))) - assert.Equal(t, "default", must(ec2meta.Dynamic("foo", "default"))) -} - -func TestDynamic_ValidKey(t *testing.T) { - ec2meta := MockEC2Meta(nil, map[string]string{"instance-id": "i-1234"}, "") - - assert.Equal(t, "i-1234", must(ec2meta.Dynamic("instance-id"))) - assert.Equal(t, "i-1234", must(ec2meta.Dynamic("instance-id", "unused default"))) -} - -func TestRegion_NoRegion(t *testing.T) { - ec2meta := MockEC2Meta(nil, nil, "") - - assert.Equal(t, "unknown", must(ec2meta.Region())) -} - -func TestRegion_NoRegionWithDefault(t *testing.T) { - ec2meta := MockEC2Meta(nil, nil, "") - - assert.Equal(t, "foo", must(ec2meta.Region("foo"))) -} - -func TestRegion_KnownRegion(t *testing.T) { - ec2meta := MockEC2Meta(nil, nil, "us-east-1") - - assert.Equal(t, "us-east-1", must(ec2meta.Region())) -} - -func TestUnreachable(t *testing.T) { - assert.False(t, unreachable(errors.New("foo"))) - assert.True(t, unreachable(errors.New("host is down"))) - assert.True(t, unreachable(errors.New("request canceled"))) - assert.True(t, unreachable(errors.New("no route to host"))) -} - -func TestRetrieveMetadata_NonEC2(t *testing.T) { - ec2meta := NewEc2Meta(ClientOptions{}) - ec2meta.nonAWS = true - - assert.Equal(t, "foo", must(ec2meta.retrieveMetadata("", "foo"))) -} diff --git a/aws/kms.go b/aws/kms.go deleted file mode 100644 index 6704e3676..000000000 --- a/aws/kms.go +++ /dev/null @@ -1,60 +0,0 @@ -package aws - -import ( - b64 "github.com/flanksource/gomplate/v3/base64" - - "github.com/aws/aws-sdk-go/service/kms" -) - -// KMSAPI is a subset of kmsiface.KMSAPI -type KMSAPI interface { - Encrypt(input *kms.EncryptInput) (*kms.EncryptOutput, error) - Decrypt(input *kms.DecryptInput) (*kms.DecryptOutput, error) -} - -// KMS is an AWS KMS client -type KMS struct { - Client KMSAPI -} - -// NewKMS - Create new AWS KMS client using an SDKSession -func NewKMS(option ClientOptions) *KMS { - client := kms.New(SDKSession()) - return &KMS{ - Client: client, - } -} - -// Encrypt plaintext using the specified key. -// Returns a base64 encoded ciphertext -func (k *KMS) Encrypt(keyID, plaintext string) (string, error) { - input := &kms.EncryptInput{ - KeyId: &keyID, - Plaintext: []byte(plaintext), - } - output, err := k.Client.Encrypt(input) - if err != nil { - return "", err - } - ciphertext, err := b64.Encode(output.CiphertextBlob) - if err != nil { - return "", err - } - return ciphertext, nil -} - -// Decrypt a base64 encoded ciphertext -func (k *KMS) Decrypt(ciphertext string) (string, error) { - ciphertextBlob, err := b64.Decode(ciphertext) - if err != nil { - return "", err - } - input := &kms.DecryptInput{ - CiphertextBlob: ciphertextBlob, - } - output, err := k.Client.Decrypt(input) - if err != nil { - return "", err - } - return string(output.Plaintext), nil -} diff --git a/aws/kms_test.go b/aws/kms_test.go deleted file mode 100644 index 1d8c18ded..000000000 --- a/aws/kms_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package aws - -import ( - "strings" - "testing" - - "github.com/aws/aws-sdk-go/service/kms" - b64 "github.com/flanksource/gomplate/v3/base64" - "github.com/stretchr/testify/assert" -) - -// MockKMS is a mock KMSAPI implementation -type MockKMS struct{} - -// Mocks Encrypt operation returns an upper case version of plaintext -func (m *MockKMS) Encrypt(input *kms.EncryptInput) (*kms.EncryptOutput, error) { - return &kms.EncryptOutput{ - CiphertextBlob: []byte(strings.ToUpper(string(input.Plaintext))), - }, nil -} - -// Mocks Decrypt operation -func (m *MockKMS) Decrypt(input *kms.DecryptInput) (*kms.DecryptOutput, error) { - s := []byte(strings.ToLower(string(input.CiphertextBlob))) - return &kms.DecryptOutput{ - Plaintext: s, - }, nil -} - -func TestEncrypt(t *testing.T) { - // create a mock KMS client - c := &MockKMS{} - kmsClient := &KMS{Client: c} - - // Success - resp, err := kmsClient.Encrypt("dummykey", "plaintextvalue") - assert.NoError(t, err) - expectedResp, _ := b64.Encode([]byte("PLAINTEXTVALUE")) - assert.EqualValues(t, expectedResp, resp) -} - -func TestDecrypt(t *testing.T) { - // create a mock KMS client - c := &MockKMS{} - kmsClient := &KMS{Client: c} - encodedCiphertextBlob, _ := b64.Encode([]byte("CIPHERVALUE")) - - // Success - resp, err := kmsClient.Decrypt(encodedCiphertextBlob) - assert.NoError(t, err) - assert.EqualValues(t, "ciphervalue", resp) -} diff --git a/aws/sts.go b/aws/sts.go deleted file mode 100644 index 336b8f865..000000000 --- a/aws/sts.go +++ /dev/null @@ -1,76 +0,0 @@ -package aws - -import ( - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/sts" -) - -// STS - -type STS struct { - identifier func() CallerIdentitifier - cache map[string]interface{} -} - -var identifierClient CallerIdentitifier - -// CallerIdentitifier - an interface to wrap GetCallerIdentity -type CallerIdentitifier interface { - GetCallerIdentity(*sts.GetCallerIdentityInput) (*sts.GetCallerIdentityOutput, error) -} - -// NewSTS - -func NewSTS(options ClientOptions) *STS { - return &STS{ - identifier: func() CallerIdentitifier { - if identifierClient == nil { - session := SDKSession() - identifierClient = sts.New(session) - } - return identifierClient - }, - cache: make(map[string]interface{}), - } -} - -func (s *STS) getCallerID() (*sts.GetCallerIdentityOutput, error) { - i := s.identifier() - if val, ok := s.cache["GetCallerIdentity"]; ok { - if c, ok := val.(*sts.GetCallerIdentityOutput); ok { - return c, nil - } - } - in := &sts.GetCallerIdentityInput{} - out, err := i.GetCallerIdentity(in) - if err != nil { - return nil, err - } - s.cache["GetCallerIdentity"] = out - return out, nil -} - -// UserID - -func (s *STS) UserID() (string, error) { - cid, err := s.getCallerID() - if err != nil { - return "", err - } - return aws.StringValue(cid.UserId), nil -} - -// Account - -func (s *STS) Account() (string, error) { - cid, err := s.getCallerID() - if err != nil { - return "", err - } - return aws.StringValue(cid.Account), nil -} - -// Arn - -func (s *STS) Arn() (string, error) { - cid, err := s.getCallerID() - if err != nil { - return "", err - } - return aws.StringValue(cid.Arn), nil -} diff --git a/aws/sts_test.go b/aws/sts_test.go deleted file mode 100644 index 85bbeccd7..000000000 --- a/aws/sts_test.go +++ /dev/null @@ -1,106 +0,0 @@ -package aws - -import ( - "errors" - "testing" - - "github.com/aws/aws-sdk-go/aws" - - "github.com/aws/aws-sdk-go/service/sts" - "github.com/stretchr/testify/assert" -) - -func TestNewSTS(t *testing.T) { - s := NewSTS(ClientOptions{}) - cid := &DummyCallerIdentifier{ - account: "acct", - userID: "uid", - arn: "arn", - } - s.identifier = func() CallerIdentitifier { - return cid - } - - out, err := s.getCallerID() - assert.NoError(t, err) - assert.EqualValues(t, &sts.GetCallerIdentityOutput{ - Account: aws.String("acct"), - Arn: aws.String("arn"), - UserId: aws.String("uid"), - }, out) - - assert.Equal(t, "acct", must(s.Account())) - assert.Equal(t, "arn", must(s.Arn())) - assert.Equal(t, "uid", must(s.UserID())) - - s = NewSTS(ClientOptions{}) - cid = &DummyCallerIdentifier{ - account: "acct", - userID: "uid", - arn: "arn", - } - oldIDClient := identifierClient - identifierClient = cid - defer func() { identifierClient = oldIDClient }() - - out, err = s.getCallerID() - assert.NoError(t, err) - assert.EqualValues(t, &sts.GetCallerIdentityOutput{ - Account: aws.String("acct"), - Arn: aws.String("arn"), - UserId: aws.String("uid"), - }, out) - - assert.Equal(t, "acct", must(s.Account())) - assert.Equal(t, "arn", must(s.Arn())) - assert.Equal(t, "uid", must(s.UserID())) -} - -func TestGetCallerIDErrors(t *testing.T) { - s := NewSTS(ClientOptions{}) - cid := &DummyCallerIdentifier{ - account: "acct", - userID: "uid", - arn: "arn", - } - s.identifier = func() CallerIdentitifier { - return cid - } - - out, err := s.Account() - assert.NoError(t, err) - assert.Equal(t, "acct", out) - - s = NewSTS(ClientOptions{}) - cid = &DummyCallerIdentifier{ - err: errors.New("ERRORED"), - } - s.identifier = func() CallerIdentitifier { - return cid - } - - _, err = s.Account() - assert.EqualError(t, err, "ERRORED") - _, err = s.UserID() - assert.EqualError(t, err, "ERRORED") - _, err = s.Arn() - assert.EqualError(t, err, "ERRORED") -} - -type DummyCallerIdentifier struct { - err error - account, arn, userID string -} - -func (c *DummyCallerIdentifier) GetCallerIdentity(*sts.GetCallerIdentityInput) (*sts.GetCallerIdentityOutput, error) { - if c.err != nil { - return nil, c.err - } - - out := &sts.GetCallerIdentityOutput{ - Account: aws.String(c.account), - Arn: aws.String(c.arn), - UserId: aws.String(c.userID), - } - return out, nil -} diff --git a/aws/testutils.go b/aws/testutils.go deleted file mode 100644 index bc57e1178..000000000 --- a/aws/testutils.go +++ /dev/null @@ -1,86 +0,0 @@ -package aws - -import ( - "fmt" - - "github.com/aws/aws-sdk-go/service/ec2" -) - -// MockEC2Meta - -func MockEC2Meta(data map[string]string, dynamicData map[string]string, region string) *Ec2Meta { - return &Ec2Meta{ - metadataCache: map[string]string{}, - dynamicdataCache: map[string]string{}, - ec2MetadataProvider: func() (EC2Metadata, error) { - return &DummEC2MetadataProvider{ - data: data, - dynamicData: dynamicData, - region: region, - }, nil - }, - } -} - -// NewDummyEc2Info - -func NewDummyEc2Info(metaClient *Ec2Meta) *Ec2Info { - i := &Ec2Info{ - metaClient: metaClient, - describer: func() (InstanceDescriber, error) { return DummyInstanceDescriber{}, nil }, - cache: map[string]interface{}{}, - } - return i -} - -// NewDummyEc2Meta - -func NewDummyEc2Meta() *Ec2Meta { - return &Ec2Meta{ - nonAWS: true, - } -} - -// DummyInstanceDescriber - test doubles -type DummyInstanceDescriber struct { - tags []*ec2.Tag -} - -// DescribeInstances - -func (d DummyInstanceDescriber) DescribeInstances(*ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { - output := &ec2.DescribeInstancesOutput{ - Reservations: []*ec2.Reservation{ - { - Instances: []*ec2.Instance{ - { - Tags: d.tags, - }, - }, - }, - }, - } - return output, nil -} - -type DummEC2MetadataProvider struct { - data map[string]string - dynamicData map[string]string - region string -} - -func (d DummEC2MetadataProvider) GetMetadata(p string) (string, error) { - v, ok := d.data[p] - if !ok { - return "", fmt.Errorf("cannot find %v", p) - } - return v, nil -} - -func (d DummEC2MetadataProvider) GetDynamicData(p string) (string, error) { - v, ok := d.dynamicData[p] - if !ok { - return "", fmt.Errorf("cannot find %v", p) - } - return v, nil -} - -func (d DummEC2MetadataProvider) Region() (string, error) { - return d.region, nil -} diff --git a/cel/cel_test.go b/cel/cel_test.go index 89d42c682..e941d2bf6 100644 --- a/cel/cel_test.go +++ b/cel/cel_test.go @@ -5,7 +5,7 @@ import ( "github.com/flanksource/gomplate/v3/funcs" "github.com/google/cel-go/cel" - "gotest.tools/v3/assert" + "github.com/stretchr/testify/assert" ) func panIf(err error) { @@ -29,7 +29,7 @@ func executeTemplate(t *testing.T, i int, input string, output any) { out, _, err := prg.Eval(map[string]any{}) panIf(err) - assert.DeepEqual(t, out.Value(), output) + assert.EqualValues(t, out.Value(), output) } func TestCelNamespace(t *testing.T) { diff --git a/cmd/gencel.go b/cmd/gencel.go index 7339ca099..570d6fad6 100644 --- a/cmd/gencel.go +++ b/cmd/gencel.go @@ -2,8 +2,8 @@ package main import ( "flag" + "fmt" - "github.com/flanksource/commons/logger" "github.com/flanksource/gomplate/v3/gencel" ) @@ -13,7 +13,7 @@ func main() { if len(args) == 0 { args = []string{"."} } - logger.Infof("Generating cel functions for %s\n", args) + fmt.Printf("Generating cel functions for %s\n", args) g := gencel.Generator{} g.ParsePkg(args...) diff --git a/cmd/gencel_test.go b/cmd/gencel_test.go index 9b3b47d67..c2be71544 100644 --- a/cmd/gencel_test.go +++ b/cmd/gencel_test.go @@ -1,17 +1,17 @@ package main import ( + "fmt" "os" "testing" - "github.com/flanksource/commons/logger" "github.com/flanksource/gomplate/v3/gencel" ) // Not really a test but just a runner so it's easier to attach a debugger. func TestGencel(t *testing.T) { wd, _ := os.Getwd() - logger.Infof("WD: %s", wd) + fmt.Printf("WD: %s", wd) args := []string{"../funcs"} g := gencel.Generator{} diff --git a/config.go b/config.go deleted file mode 100644 index ba4a5129d..000000000 --- a/config.go +++ /dev/null @@ -1,144 +0,0 @@ -package gomplate - -import ( - "io" - "os" - "strings" - - "github.com/flanksource/gomplate/v3/internal/config" - "github.com/flanksource/gomplate/v3/internal/iohelpers" -) - -// Config - values necessary for rendering templates with gomplate. -// Mainly for use by the CLI -// -// Deprecated: this type will be phased out, internal/config.Config is used -// everywhere else, and will be exposed as API in a future version -type Config struct { - Input string - InputFiles []string - InputDir string - ExcludeGlob []string - OutputFiles []string - OutputDir string - OutputMap string - OutMode string - Out io.Writer - - DataSources []string - DataSourceHeaders []string - Contexts []string - - Plugins []string - - LDelim string - RDelim string - - Templates []string -} - -// defaults - sets any unset fields to their default value (if applicable) -func (o *Config) defaults() *Config { - if o.OutputDir == "" { - o.OutputDir = "." - } - if o.InputFiles == nil { - o.InputFiles = []string{"-"} - } - if o.OutputFiles == nil { - o.OutputFiles = []string{"-"} - } - if o.LDelim == "" { - o.LDelim = "{{" - } - if o.RDelim == "" { - o.RDelim = "}}" - } - return o -} - -// nolint: gocyclo -func (o *Config) String() string { - o.defaults() - - c := "input: " - switch { - case o.Input != "": - c += "" - case o.InputDir != "": - c += o.InputDir - default: - c += strings.Join(o.InputFiles, ", ") - } - - if len(o.ExcludeGlob) > 0 { - c += "\nexclude: " + strings.Join(o.ExcludeGlob, ", ") - } - - c += "\noutput: " - switch { - case o.InputDir != "" && o.OutputDir != ".": - c += o.OutputDir - case o.OutputMap != "": - c += o.OutputMap - default: - c += strings.Join(o.OutputFiles, ", ") - } - - if o.OutMode != "" { - c += "\nchmod: " + o.OutMode - } - - if len(o.DataSources) > 0 { - c += "\ndatasources: " + strings.Join(o.DataSources, ", ") - } - if len(o.DataSourceHeaders) > 0 { - c += "\ndatasourceheaders: " + strings.Join(o.DataSourceHeaders, ", ") - } - if len(o.Contexts) > 0 { - c += "\ncontexts: " + strings.Join(o.Contexts, ", ") - } - - if len(o.Plugins) > 0 { - c += "\nplugins: " + strings.Join(o.Plugins, ", ") - } - - if o.LDelim != "{{" { - c += "\nleft_delim: " + o.LDelim - } - if o.RDelim != "}}" { - c += "\nright_delim: " + o.RDelim - } - - if len(o.Templates) > 0 { - c += "\ntemplates: " + strings.Join(o.Templates, ", ") - } - return c -} - -func (o *Config) toNewConfig() (*config.Config, error) { - cfg := &config.Config{ - Input: o.Input, - InputFiles: o.InputFiles, - InputDir: o.InputDir, - ExcludeGlob: o.ExcludeGlob, - OutputFiles: o.OutputFiles, - OutputDir: o.OutputDir, - OutputMap: o.OutputMap, - OutMode: o.OutMode, - LDelim: o.LDelim, - RDelim: o.RDelim, - Stdin: os.Stdin, - Stdout: &iohelpers.NopCloser{Writer: o.Out}, - Stderr: os.Stderr, - } - err := cfg.ParsePluginFlags(o.Plugins) - if err != nil { - return nil, err - } - err = cfg.ParseDataSourceFlags(o.DataSources, o.Contexts, o.Templates, o.DataSourceHeaders) - if err != nil { - return nil, err - } - return cfg, nil -} diff --git a/config_test.go b/config_test.go deleted file mode 100644 index 0ddefc3e8..000000000 --- a/config_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package gomplate - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestConfigString(t *testing.T) { - c := &Config{} - - expected := `input: - -output: -` - assert.Equal(t, expected, c.String()) - - c = &Config{ - LDelim: "L", - RDelim: "R", - Input: "foo", - OutputFiles: []string{"-"}, - Templates: []string{"foo=foo.t", "bar=bar.t"}, - } - expected = `input: -output: - -left_delim: L -right_delim: R -templates: foo=foo.t, bar=bar.t` - - assert.Equal(t, expected, c.String()) - - c = &Config{ - InputDir: "in/", - OutputDir: "out/", - } - expected = `input: in/ -output: out/` - - assert.Equal(t, expected, c.String()) - - c = &Config{ - InputDir: "in/", - OutputMap: "{{ .in }}", - } - expected = `input: in/ -output: {{ .in }}` - - assert.Equal(t, expected, c.String()) -} diff --git a/context.go b/context.go deleted file mode 100644 index 980bbc206..000000000 --- a/context.go +++ /dev/null @@ -1,38 +0,0 @@ -package gomplate - -import ( - "context" - "os" - "strings" - - "github.com/flanksource/gomplate/v3/data" -) - -// context for templates -type tmplctx map[string]interface{} - -// Env - Map environment variables for use in a template -func (c *tmplctx) Env() map[string]string { - env := make(map[string]string) - for _, i := range os.Environ() { - sep := strings.Index(i, "=") - env[i[0:sep]] = i[sep+1:] - } - return env -} - -// createTmplContext reads the datasources for the given aliases -func createTmplContext(ctx context.Context, aliases []string, d *data.Data) (interface{}, error) { - var err error - tctx := &tmplctx{} - for _, a := range aliases { - if a == "." { - return d.Datasource(a) - } - (*tctx)[a], err = d.Datasource(a) - if err != nil { - return nil, err - } - } - return tctx, nil -} diff --git a/context_test.go b/context_test.go deleted file mode 100644 index 347a9bc14..000000000 --- a/context_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package gomplate - -import ( - "context" - "net/url" - "os" - "testing" - - "github.com/flanksource/gomplate/v3/data" - - "github.com/stretchr/testify/assert" -) - -func TestEnvMapifiesEnvironment(t *testing.T) { - c := &tmplctx{} - env := c.Env() - assert.Equal(t, env["USER"], os.Getenv("USER")) -} - -func TestEnvGetsUpdatedEnvironment(t *testing.T) { - c := &tmplctx{} - assert.Empty(t, c.Env()["FOO"]) - assert.NoError(t, os.Setenv("FOO", "foo")) - assert.Equal(t, c.Env()["FOO"], "foo") -} - -func TestCreateContext(t *testing.T) { - ctx := context.Background() - c, err := createTmplContext(ctx, nil, nil) - assert.NoError(t, err) - assert.Empty(t, c) - - fooURL := "env:///foo?type=application/yaml" - barURL := "env:///bar?type=application/yaml" - uf, _ := url.Parse(fooURL) - ub, _ := url.Parse(barURL) - d := &data.Data{ - Sources: map[string]*data.Source{ - "foo": {URL: uf}, - ".": {URL: ub}, - }, - } - os.Setenv("foo", "foo: bar") - defer os.Unsetenv("foo") - c, err = createTmplContext(ctx, []string{"foo"}, d) - assert.NoError(t, err) - assert.IsType(t, &tmplctx{}, c) - tctx := c.(*tmplctx) - ds := ((*tctx)["foo"]).(map[string]interface{}) - assert.Equal(t, "bar", ds["foo"]) - - os.Setenv("bar", "bar: baz") - defer os.Unsetenv("bar") - c, err = createTmplContext(ctx, []string{"."}, d) - assert.NoError(t, err) - assert.IsType(t, map[string]interface{}{}, c) - ds = c.(map[string]interface{}) - assert.Equal(t, "baz", ds["bar"]) -} diff --git a/crypto/aes.go b/crypto/aes.go deleted file mode 100644 index b3fab8dc3..000000000 --- a/crypto/aes.go +++ /dev/null @@ -1,88 +0,0 @@ -package crypto - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "io" -) - -// EncryptAESCBC - use a 128, 192, or 256 bit key to encrypt the given content -// using AES-CBC. The output will not be encoded. Usually the output would be -// base64-encoded for display. Empty content will not be encrypted. -// -// This function is compatible with Helm's decryptAES function, when the output -// is base64-encoded, and when the key is 256 bits long. -func EncryptAESCBC(key []byte, in []byte) ([]byte, error) { - if len(in) == 0 { - return in, nil - } - - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - // Pad the content to be a multiple of the block size, with the pad length - // as the content. Note that the padding will be a full block when the - // content is already a multiple of the block size. - // This algorithm is described in the TLS spec: - // https://datatracker.ietf.org/doc/html/rfc5246#section-6.2.3.2 - bs := block.BlockSize() - pl := bs - len(in)%bs - - // pad with pl, repeated pl times - in = append(in, bytes.Repeat([]byte{byte(pl)}, pl)...) - - out := make([]byte, bs+len(in)) - - // Generate a random IV. Must be the same length as the block size, and is - // stored at the beginning of the output slice unencrypted, so that it can - // be used for decryption. - iv := out[:bs] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - - // encrypt the content into the rest of the output slice - mode := cipher.NewCBCEncrypter(block, iv) - mode.CryptBlocks(out[bs:], in) - - return out, nil -} - -// DecryptAESCBC - use a 128, 192, or 256 bit key to decrypt the given content -// using AES-CBC. The output will not be encoded. Empty content will not be -// decrypted. -// -// This function is compatible with Helm's encryptAES function, when the input -// is base64-decoded, and when the key is 256 bits long. -func DecryptAESCBC(key []byte, in []byte) ([]byte, error) { - if len(in) == 0 { - return nil, nil - } - - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - // the first block is the IV, unencrypted - iv := in[:aes.BlockSize] - - // the rest of the content is encrypted - in = in[aes.BlockSize:] - - out := make([]byte, len(in)) - - mode := cipher.NewCBCDecrypter(block, iv) - mode.CryptBlocks(out, in) - - // content must always be padded with at least one byte, and the padding - // byte must be the padding length - pl := int(out[len(out)-1]) - out = out[:len(out)-pl] - - return out, nil -} diff --git a/crypto/aes_test.go b/crypto/aes_test.go deleted file mode 100644 index df00b14b9..000000000 --- a/crypto/aes_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package crypto - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestEncryptDecryptAESCBC(t *testing.T) { - // empty key is invalid - _, err := EncryptAESCBC([]byte{}, []byte("foo")) - assert.Error(t, err) - - // wrong-length keys are invalid - _, err = EncryptAESCBC(bytes.Repeat([]byte{'a'}, 1), []byte("foo")) - assert.Error(t, err) - - _, err = EncryptAESCBC(bytes.Repeat([]byte{'a'}, 15), []byte("foo")) - assert.Error(t, err) - - key := make([]byte, 32) - copy(key, []byte("password")) - - // empty content is a pass-through - out, err := EncryptAESCBC(key, []byte{}) - assert.NoError(t, err) - assert.Equal(t, []byte{}, out) - - testdata := [][]byte{ - bytes.Repeat([]byte{'a'}, 1), - bytes.Repeat([]byte{'a'}, 15), - bytes.Repeat([]byte{'a'}, 16), - bytes.Repeat([]byte{'a'}, 31), - bytes.Repeat([]byte{'a'}, 32), - } - - for _, d := range testdata { - out, err = EncryptAESCBC(key, d) - assert.NoError(t, err) - assert.NotEqual(t, d, out) - - out, err = DecryptAESCBC(key, out) - assert.NoError(t, err) - assert.Equal(t, d, out) - } - - // 128-bit key - key = bytes.Repeat([]byte{'a'}, 16) - out, err = EncryptAESCBC(key, []byte("foo")) - assert.NoError(t, err) - assert.NotEqual(t, []byte("foo"), out) - - out, err = DecryptAESCBC(key, out) - assert.NoError(t, err) - assert.Equal(t, []byte("foo"), out) - - // 192-bit key - key = bytes.Repeat([]byte{'a'}, 24) - out, err = EncryptAESCBC(key, []byte("foo")) - assert.NoError(t, err) - assert.NotEqual(t, []byte("foo"), out) - - out, err = DecryptAESCBC(key, out) - assert.NoError(t, err) - assert.Equal(t, []byte("foo"), out) -} diff --git a/crypto/crypto_fuzz_test.go b/crypto/crypto_fuzz_test.go deleted file mode 100644 index dad98654f..000000000 --- a/crypto/crypto_fuzz_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package crypto - -import ( - "bytes" - "testing" -) - -func FuzzCryptAESCBC(f *testing.F) { - key := bytes.Repeat([]byte{'a'}, 16) - f.Add(key, []byte("some random text to be encrypted")) - - key = bytes.Repeat([]byte{'a'}, 32) - f.Add(key, []byte(`more random - text to be - encrypted, with non-ascii characters: - ΤΟΙΣ πᾶσι χρόνος καὶ καιρὸς τῷ παντὶ πράγματι ὑπὸ τὸν οὐρανόν. καιρὸς τοῦ - τεκεῖν καὶ καιρὸς τοῦ ἀποθανεῖν, καιρὸς τοῦ φυτεῦσαι καὶ καιρὸς τοῦ ἐκτῖλαι τὸ - πεφυτευμένον, καιρὸς τοῦ ἀποκτεῖναι καὶ καιρὸς τοῦ ἰάσασθαι, καιρὸς τοῦ παρακολουθεῖν - and also: - 何事にも定まった時があります。 - 生まれる時、死ぬ時、植える時、収穫の時、育てる時、枯れる時、葉が降る時、落ちる時、落とされる時、 - そして、それらの時には、それぞれの人々は、それぞれの幸福を知っています。 - 殺す時、病気が治る時、壊す時、やり直す時.`)) - - f.Fuzz(func(t *testing.T, key, in []byte) { - // make sure we have a key of the right length - var k []byte - switch { - case len(key) <= 16: - k = make([]byte, 16) - case len(key) <= 24: - k = make([]byte, 24) - default: - k = make([]byte, 32) - } - copy(k, key) - - out, err := EncryptAESCBC(k, in) - if err != nil { - t.Error(err) - return - } - if len(in) == 0 && len(out) != 0 { - t.Error("empty input should return empty output") - return - } - - dec, err := DecryptAESCBC(k, out) - if err != nil { - t.Error(err) - } - if !bytes.Equal(in, dec) { - t.Errorf("%q != %q (encrypted: %q)", in, dec, out) - } - }) -} diff --git a/crypto/doc.go b/crypto/doc.go deleted file mode 100644 index 38bc0b6d2..000000000 --- a/crypto/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package crypto contains functions to help perform hashing and simple encryption operations -package crypto diff --git a/crypto/ecdsa.go b/crypto/ecdsa.go deleted file mode 100644 index 6f3773908..000000000 --- a/crypto/ecdsa.go +++ /dev/null @@ -1,72 +0,0 @@ -package crypto - -import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/x509" - "encoding/pem" - "fmt" -) - -var ( - // Curves is a map of curve names to curves - Curves = map[string]elliptic.Curve{ - "P224": elliptic.P224(), - "P256": elliptic.P256(), - "P384": elliptic.P384(), - "P521": elliptic.P521(), - } -) - -// ECDSAGenerateKey - -func ECDSAGenerateKey(curve elliptic.Curve) ([]byte, error) { - priv, err := ecdsa.GenerateKey(curve, rand.Reader) - if err != nil { - return nil, fmt.Errorf("failed to generate ECDSA private key: %w", err) - } - - der, err := x509.MarshalECPrivateKey(priv) - if err != nil { - return nil, fmt.Errorf("failed to marshal ECDSA private key: %w", err) - } - - block := &pem.Block{ - Type: "EC PRIVATE KEY", - Bytes: der, - } - buf := &bytes.Buffer{} - - err = pem.Encode(buf, block) - if err != nil { - return nil, fmt.Errorf("failed to encode generated ECDSA private key: pem encoding failed: %w", err) - } - - return buf.Bytes(), nil -} - -// ECDSADerivePublicKey - -func ECDSADerivePublicKey(privatekey []byte) ([]byte, error) { - block, _ := pem.Decode(privatekey) - if block == nil { - return nil, fmt.Errorf("failed to read key: no key found") - } - - priv, err := x509.ParseECPrivateKey(block.Bytes) - if err != nil { - return nil, fmt.Errorf("invalid private key: %w", err) - } - - b, err := x509.MarshalPKIXPublicKey(&priv.PublicKey) - if err != nil { - return nil, fmt.Errorf("failed to marshal PKIX public key: %w", err) - } - - block = &pem.Block{ - Type: "PUBLIC KEY", - Bytes: b, - } - - return pem.EncodeToMemory(block), nil -} diff --git a/crypto/ecdsa_test.go b/crypto/ecdsa_test.go deleted file mode 100644 index 186dd7eb6..000000000 --- a/crypto/ecdsa_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/x509" - "encoding/pem" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func genECDSAPrivKey() (*ecdsa.PrivateKey, string) { - priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - der, _ := x509.MarshalECPrivateKey(priv) - privBlock := &pem.Block{ - Type: "EC PRIVATE KEY", - Bytes: der, - } - return priv, string(pem.EncodeToMemory(privBlock)) -} - -func deriveECPubkey(priv *ecdsa.PrivateKey) string { - b, _ := x509.MarshalPKIXPublicKey(&priv.PublicKey) - pubBlock := &pem.Block{ - Type: "PUBLIC KEY", - Bytes: b, - } - testPubKey := string(pem.EncodeToMemory(pubBlock)) - return testPubKey -} - -func TestECDSAGenerateKey(t *testing.T) { - key, err := ECDSAGenerateKey(elliptic.P224()) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(string(key), - "-----BEGIN EC PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(string(key), - "-----END EC PRIVATE KEY-----\n")) - - key, err = ECDSAGenerateKey(elliptic.P256()) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(string(key), - "-----BEGIN EC PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(string(key), - "-----END EC PRIVATE KEY-----\n")) - - key, err = ECDSAGenerateKey(elliptic.P384()) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(string(key), - "-----BEGIN EC PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(string(key), - "-----END EC PRIVATE KEY-----\n")) - - key, err = ECDSAGenerateKey(elliptic.P521()) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(string(key), - "-----BEGIN EC PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(string(key), - "-----END EC PRIVATE KEY-----\n")) -} - -func TestECDSADerivePublicKey(t *testing.T) { - _, err := ECDSADerivePublicKey(nil) - assert.Error(t, err) - - _, err = ECDSADerivePublicKey([]byte(`-----BEGIN FOO----- - -----END FOO-----`)) - assert.Error(t, err) - - priv, privKey := genECDSAPrivKey() - expected := deriveECPubkey(priv) - - actual, err := ECDSADerivePublicKey([]byte(privKey)) - assert.NoError(t, err) - assert.Equal(t, expected, string(actual)) -} diff --git a/crypto/pbkdf2.go b/crypto/pbkdf2.go deleted file mode 100644 index 683194ba5..000000000 --- a/crypto/pbkdf2.go +++ /dev/null @@ -1,57 +0,0 @@ -package crypto - -import ( - "crypto" - "crypto/sha1" //nolint: gosec - "crypto/sha256" - "crypto/sha512" - "hash" - - "github.com/pkg/errors" - - "golang.org/x/crypto/pbkdf2" -) - -var hashFuncs map[crypto.Hash]func() hash.Hash - -func init() { - hashFuncs = make(map[crypto.Hash]func() hash.Hash) - hashFuncs[crypto.SHA1] = sha1.New - hashFuncs[crypto.SHA224] = sha256.New224 - hashFuncs[crypto.SHA256] = sha256.New - hashFuncs[crypto.SHA384] = sha512.New384 - hashFuncs[crypto.SHA512] = sha512.New - hashFuncs[crypto.SHA512_224] = sha512.New512_224 - hashFuncs[crypto.SHA512_256] = sha512.New512_256 -} - -// StrToHash - find a hash given a certain string -func StrToHash(hash string) (crypto.Hash, error) { - switch hash { - case "SHA1", "SHA-1": - return crypto.SHA1, nil - case "SHA224", "SHA-224": - return crypto.SHA224, nil - case "SHA256", "SHA-256": - return crypto.SHA256, nil - case "SHA384", "SHA-384": - return crypto.SHA384, nil - case "SHA512", "SHA-512": - return crypto.SHA512, nil - case "SHA512_224", "SHA512/224", "SHA-512_224", "SHA-512/224": - return crypto.SHA512_224, nil - case "SHA512_256", "SHA512/256", "SHA-512_256", "SHA-512/256": - return crypto.SHA512_256, nil - } - return 0, errors.Errorf("no such hash %s", hash) -} - -// PBKDF2 - Run the Password-Based Key Derivation Function #2 as defined in -// RFC 8018 (PKCS #5 v2.1) -func PBKDF2(password, salt []byte, iter, keylen int, hashFunc crypto.Hash) ([]byte, error) { - h, ok := hashFuncs[hashFunc] - if !ok { - return nil, errors.Errorf("hashFunc not supported: %v", hashFunc) - } - return pbkdf2.Key(password, salt, iter, keylen, h), nil -} diff --git a/crypto/pbkdf2_test.go b/crypto/pbkdf2_test.go deleted file mode 100644 index 327ee322a..000000000 --- a/crypto/pbkdf2_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package crypto - -import ( - "crypto" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPBKDF2(t *testing.T) { - t.Parallel() - - dk, err := PBKDF2([]byte{}, []byte{}, 0, 0, 0) - assert.Nil(t, dk) - assert.Error(t, err) - - // IEEE 802.11i-2004 test vectors - dk, err = PBKDF2([]byte("password"), []byte("IEEE"), 4096, 32, crypto.SHA1) - assert.EqualValues(t, []byte{ - 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef, - 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90, - 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2, - 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e, - }, dk) - assert.NoError(t, err) - - dk, err = PBKDF2([]byte("ThisIsAPassword"), []byte("ThisIsASSID"), 4096, 32, crypto.SHA1) - assert.EqualValues(t, []byte{ - 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6, - 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3, - 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08, - 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf, - }, dk) - assert.NoError(t, err) - - dk, err = PBKDF2([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), []byte("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"), 4096, 32, crypto.SHA1) - assert.EqualValues(t, []byte{ - 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83, - 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c, - 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48, - 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62, - }, dk) - assert.NoError(t, err) - - // some longer hash functions - dk, err = PBKDF2([]byte("password"), []byte("IEEE"), 4096, 64, crypto.SHA512) - assert.EqualValues(t, []byte{ - 0xc1, 0x6f, 0x4c, 0xb6, 0xd0, 0x3e, 0x23, 0x61, - 0x43, 0x99, 0xde, 0xe5, 0xe7, 0xf6, 0x76, 0xfb, - 0x1d, 0xa0, 0xeb, 0x94, 0x71, 0xb6, 0xa7, 0x4a, - 0x6c, 0x5b, 0xc9, 0x34, 0xc6, 0xec, 0x7d, 0x2a, - 0xb7, 0x02, 0x8f, 0xbb, 0x10, 0x00, 0xb1, 0xbe, - 0xb9, 0x7f, 0x17, 0x64, 0x60, 0x45, 0xd8, 0x14, - 0x47, 0x92, 0x35, 0x2f, 0x66, 0x76, 0xd1, 0x3b, - 0x20, 0xa4, 0xc0, 0x37, 0x54, 0x90, 0x3d, 0x7e, - }, dk) - assert.NoError(t, err) -} - -func TestStrToHash(t *testing.T) { - t.Parallel() - - h, err := StrToHash("foo") - assert.Zero(t, h) - assert.Error(t, err) - h, err = StrToHash("SHA-1") - assert.Equal(t, crypto.SHA1, h) - assert.NoError(t, err) - h, err = StrToHash("SHA224") - assert.Equal(t, crypto.SHA224, h) - assert.NoError(t, err) - h, err = StrToHash("SHA-256") - assert.Equal(t, crypto.SHA256, h) - assert.NoError(t, err) - h, err = StrToHash("SHA384") - assert.Equal(t, crypto.SHA384, h) - assert.NoError(t, err) - h, err = StrToHash("SHA-512") - assert.Equal(t, crypto.SHA512, h) - assert.NoError(t, err) - h, err = StrToHash("SHA-512/224") - assert.Equal(t, crypto.SHA512_224, h) - assert.NoError(t, err) - h, err = StrToHash("SHA512/256") - assert.Equal(t, crypto.SHA512_256, h) - assert.NoError(t, err) -} diff --git a/crypto/rsa.go b/crypto/rsa.go deleted file mode 100644 index 22b92b71e..000000000 --- a/crypto/rsa.go +++ /dev/null @@ -1,109 +0,0 @@ -package crypto - -import ( - "bytes" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "fmt" - "strings" -) - -// RSAEncrypt - use the given public key to encrypt the given plaintext. The key -// should be a PEM-encoded RSA public key in PKIX, ASN.1 DER form, typically -// beginning with "PUBLIC KEY". PKCS#1 format is also supported as a fallback. -// The output will not be encoded, so consider base64-encoding it for display. -func RSAEncrypt(key string, in []byte) ([]byte, error) { - block, _ := pem.Decode([]byte(key)) - if block == nil { - return nil, fmt.Errorf("failed to read key %q: no key found", key) - } - - pub, err := x509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - if strings.Contains(err.Error(), "use ParsePKCS1PublicKey instead") { - pub, err = x509.ParsePKCS1PublicKey(block.Bytes) - } - if err != nil { - return nil, fmt.Errorf("failed to parse public key: %w", err) - } - } - pubKey, ok := pub.(*rsa.PublicKey) - if !ok { - return nil, fmt.Errorf("public key in wrong format, was %T", pub) - } - - out, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, in) - return out, err -} - -// RSADecrypt - decrypt the ciphertext with the given private key. The key -// must be a PEM-encoded RSA private key in PKCS#1, ASN.1 DER form, typically -// beginning with "RSA PRIVATE KEY". The input text must be plain ciphertext, -// not base64-encoded. -func RSADecrypt(key string, in []byte) ([]byte, error) { - block, _ := pem.Decode([]byte(key)) - if block == nil { - return nil, fmt.Errorf("failed to read key %q: no key found", key) - } - - priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return nil, fmt.Errorf("invalid private key: %w", err) - } - - out, err := priv.Decrypt(nil, in, nil) - if err != nil { - return nil, fmt.Errorf("failed to decrypt: %w", err) - } - return out, nil -} - -// RSAGenerateKey - -func RSAGenerateKey(bits int) ([]byte, error) { - // Protect against CWE-326: Inadequate Encryption Strength - // https://cwe.mitre.org/data/definitions/326.html - if bits < 2048 { - return nil, fmt.Errorf("RSA key size must be at least 2048 bits") - } - priv, err := rsa.GenerateKey(rand.Reader, bits) - if err != nil { - return nil, fmt.Errorf("failed to generate RSA private key: %w", err) - } - block := &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(priv), - } - buf := &bytes.Buffer{} - err = pem.Encode(buf, block) - if err != nil { - return nil, fmt.Errorf("failed to encode generated RSA private key: pem encoding failed: %w", err) - } - return buf.Bytes(), nil -} - -// RSADerivePublicKey - -func RSADerivePublicKey(privateKey []byte) ([]byte, error) { - block, _ := pem.Decode(privateKey) - if block == nil { - return nil, fmt.Errorf("failed to read key: no key found") - } - - priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return nil, fmt.Errorf("invalid private key: %w", err) - } - - b, err := x509.MarshalPKIXPublicKey(&priv.PublicKey) - if err != nil { - return nil, fmt.Errorf("failed to marshal PKIX public key: %w", err) - } - - block = &pem.Block{ - Type: "PUBLIC KEY", - Bytes: b, - } - - return pem.EncodeToMemory(block), nil -} diff --git a/crypto/rsa_test.go b/crypto/rsa_test.go deleted file mode 100644 index 42297f2c2..000000000 --- a/crypto/rsa_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package crypto - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func genPKCS1PrivKey() (*rsa.PrivateKey, string) { - rsaPriv, _ := rsa.GenerateKey(rand.Reader, 4096) - privBlock := &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(rsaPriv), - } - return rsaPriv, string(pem.EncodeToMemory(privBlock)) -} - -// func derivePKIXPrivKey(priv *rsa.PrivateKey) string { -// privBlock := &pem.Block{ -// Type: "RSA PRIVATE KEY", -// Bytes: x509.MarshalPKCS1PrivateKey(priv), -// } -// return string(pem.EncodeToMemory(privBlock)) -// } - -func derivePKIXPubKey(priv *rsa.PrivateKey) string { - b, _ := x509.MarshalPKIXPublicKey(&priv.PublicKey) - pubBlock := &pem.Block{ - Type: "PUBLIC KEY", - Bytes: b, - } - testPubKey := string(pem.EncodeToMemory(pubBlock)) - return testPubKey -} - -func derivePKCS1PubKey(priv *rsa.PrivateKey) string { - b := x509.MarshalPKCS1PublicKey(&priv.PublicKey) - pubBlock := &pem.Block{ - Type: "RSA PUBLIC KEY", - Bytes: b, - } - testPubKey := string(pem.EncodeToMemory(pubBlock)) - return testPubKey -} - -func TestRSACrypt(t *testing.T) { - t.Parallel() - - priv, testPrivKey := genPKCS1PrivKey() - - testdata := []struct { - name string - encKey string - decKey string - in []byte - }{ - {"pkix key", derivePKIXPubKey(priv), testPrivKey, []byte("hello world")}, - {"pkcs1 key", derivePKCS1PubKey(priv), testPrivKey, []byte("hello world")}, - } - - for _, d := range testdata { - d := d - t.Run(d.name, func(t *testing.T) { - t.Parallel() - - enc, err := RSAEncrypt(d.encKey, d.in) - assert.NoError(t, err) - - dec, err := RSADecrypt(d.decKey, enc) - assert.NoError(t, err) - assert.Equal(t, d.in, dec) - }) - } - - t.Run("bad key", func(t *testing.T) { - t.Parallel() - - in := []byte("hello world") - key := "bad key" - _, err := RSAEncrypt(key, in) - assert.Error(t, err) - - _, err = RSADecrypt(key, in) - assert.Error(t, err) - }) - - t.Run("empty key", func(t *testing.T) { - t.Parallel() - - in := []byte("hello world") - key := "" - _, err := RSAEncrypt(key, in) - assert.Error(t, err) - - _, err = RSADecrypt(key, in) - assert.Error(t, err) - }) -} - -func TestRSAGenerateKey(t *testing.T) { - t.Parallel() - - _, err := RSAGenerateKey(0) - assert.Error(t, err) - - _, err = RSAGenerateKey(12) - assert.Error(t, err) - - key, err := RSAGenerateKey(2048) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(string(key), - "-----BEGIN RSA PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(string(key), - "-----END RSA PRIVATE KEY-----\n")) -} - -func TestRSADerivePublicKey(t *testing.T) { - t.Parallel() - - _, err := RSADerivePublicKey(nil) - assert.Error(t, err) - - _, err = RSADerivePublicKey([]byte(`-----BEGIN FOO----- ------END FOO-----`)) - assert.Error(t, err) - - priv, privKey := genPKCS1PrivKey() - expected := derivePKIXPubKey(priv) - - actual, err := RSADerivePublicKey([]byte(privKey)) - assert.NoError(t, err) - assert.Equal(t, expected, string(actual)) -} diff --git a/data/data.go b/data/data.go index 3c11c4cc8..86a01d836 100644 --- a/data/data.go +++ b/data/data.go @@ -12,12 +12,7 @@ import ( "io" "strings" - "github.com/joho/godotenv" - - "github.com/Shopify/ejson" - ejsonJson "github.com/Shopify/ejson/json" "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/env" // XXX: replace once https://github.com/BurntSushi/toml/pull/179 is merged "github.com/hairyhenderson/toml" @@ -51,33 +46,9 @@ func JSON(in string) (map[string]interface{}, error) { return out, err } - _, ok := out[ejsonJson.PublicKeyField] - if ok { - out, err = decryptEJSON(in) - } return out, err } -// decryptEJSON - decrypts an ejson input, and unmarshals it, stripping the _public_key field. -func decryptEJSON(in string) (map[string]interface{}, error) { - keyDir := env.Getenv("EJSON_KEYDIR", "/opt/ejson/keys") - key := env.Getenv("EJSON_KEY") - - rIn := bytes.NewBufferString(in) - rOut := &bytes.Buffer{} - err := ejson.Decrypt(rIn, rOut, keyDir, key) - if err != nil { - return nil, errors.WithStack(err) - } - obj := make(map[string]interface{}) - out, err := unmarshalObj(obj, rOut.String(), yaml.Unmarshal) - if err != nil { - return nil, errors.WithStack(err) - } - delete(out, ejsonJson.PublicKeyField) - return out, nil -} - // JSONArray - Unmarshal a JSON Array func JSONArray(in string) ([]interface{}, error) { obj := make([]interface{}, 1) @@ -189,19 +160,6 @@ func TOML(in string) (interface{}, error) { return unmarshalObj(obj, in, toml.Unmarshal) } -// dotEnv - Unmarshal a dotenv file -func dotEnv(in string) (interface{}, error) { - env, err := godotenv.Unmarshal(in) - if err != nil { - return nil, err - } - out := make(map[string]interface{}) - for k, v := range env { - out[k] = v - } - return out, nil -} - func parseCSV(args ...string) ([][]string, []string, error) { in, delim, hdr := csvParseArgs(args...) c := csv.NewReader(strings.NewReader(in)) diff --git a/data/data_test.go b/data/data_test.go index 07593ea4a..f033dac9c 100644 --- a/data/data_test.go +++ b/data/data_test.go @@ -9,10 +9,6 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" - - "os" - - "gotest.tools/v3/fs" ) func TestUnmarshalObj(t *testing.T) { @@ -505,72 +501,6 @@ true = true assert.Equal(t, expected, out) } -func TestDecryptEJSON(t *testing.T) { - privateKey := "e282d979654f88267f7e6c2d8268f1f4314b8673579205ed0029b76de9c8223f" - publicKey := "6e05ec625bcdca34864181cc43e6fcc20a57732a453bc2f4a2e117ffdf1a6762" - expected := map[string]interface{}{ - "password": "supersecret", - "_unencrypted": "notsosecret", - } - in := `{ - "_public_key": "` + publicKey + `", - "password": "EJ[1:yJ7n4UorqxkJZMoKevIA1dJeDvaQhkbgENIVZW18jig=:0591iW+paVSh4APOytKBVW/ZcxHO/5wO:TssnpVtkiXmpDIxPlXSiYdgnWyd44stGcwG1]", - "_unencrypted": "notsosecret" - }` - - os.Setenv("EJSON_KEY", privateKey) - defer os.Unsetenv("EJSON_KEY") - actual, err := decryptEJSON(in) - assert.NoError(t, err) - assert.EqualValues(t, expected, actual) - - actual, err = JSON(in) - assert.NoError(t, err) - assert.EqualValues(t, expected, actual) - - tmpDir := fs.NewDir(t, "gomplate-ejsontest", - fs.WithFile(publicKey, privateKey), - ) - defer tmpDir.Remove() - - os.Unsetenv("EJSON_KEY") - os.Setenv("EJSON_KEY_FILE", tmpDir.Join(publicKey)) - defer os.Unsetenv("EJSON_KEY_FILE") - actual, err = decryptEJSON(in) - assert.NoError(t, err) - assert.EqualValues(t, expected, actual) - - os.Unsetenv("EJSON_KEY") - os.Unsetenv("EJSON_KEY_FILE") - os.Setenv("EJSON_KEYDIR", tmpDir.Path()) - defer os.Unsetenv("EJSON_KEYDIR") - actual, err = decryptEJSON(in) - assert.NoError(t, err) - assert.EqualValues(t, expected, actual) -} - -func TestDotEnv(t *testing.T) { - in := `FOO=a regular unquoted value -export BAR=another value, exports are ignored - -# comments are totally ignored, as are blank lines -FOO.BAR = "values can be double-quoted, and shell\nescapes are supported" - -BAZ = "variable expansion: ${FOO}" -QUX='single quotes ignore $variables' -` - expected := map[string]interface{}{ - "FOO": "a regular unquoted value", - "BAR": "another value, exports are ignored", - "FOO.BAR": "values can be double-quoted, and shell\nescapes are supported", - "BAZ": "variable expansion: a regular unquoted value", - "QUX": "single quotes ignore $variables", - } - out, err := dotEnv(in) - assert.NoError(t, err) - assert.EqualValues(t, expected, out) -} - func TestStringifyYAMLArrayMapKeys(t *testing.T) { cases := []struct { input []interface{} diff --git a/data/datasource.go b/data/datasource.go deleted file mode 100644 index 0e7940820..000000000 --- a/data/datasource.go +++ /dev/null @@ -1,378 +0,0 @@ -package data - -import ( - "context" - "fmt" - "mime" - "net/http" - "net/url" - "path/filepath" - "sort" - "strings" - - "github.com/spf13/afero" - - "github.com/pkg/errors" - - "github.com/flanksource/gomplate/v3/internal/config" -) - -func regExtension(ext, typ string) { - err := mime.AddExtensionType(ext, typ) - if err != nil { - panic(err) - } -} - -func init() { - // Add some types we want to be able to handle which can be missing by default - regExtension(".json", jsonMimetype) - regExtension(".yml", yamlMimetype) - regExtension(".yaml", yamlMimetype) - regExtension(".csv", csvMimetype) - regExtension(".toml", tomlMimetype) - regExtension(".env", envMimetype) -} - -// registerReaders registers the source-reader functions -func (d *Data) registerReaders() { - d.sourceReaders = make(map[string]func(context.Context, *Source, ...string) ([]byte, error)) - - d.sourceReaders["aws+smp"] = readAWSSMP - d.sourceReaders["aws+sm"] = readAWSSecretsManager - d.sourceReaders["env"] = readEnv - d.sourceReaders["file"] = readFile - d.sourceReaders["http"] = readHTTP - d.sourceReaders["https"] = readHTTP - d.sourceReaders["merge"] = d.readMerge - d.sourceReaders["stdin"] = readStdin - d.sourceReaders["s3"] = readBlob - d.sourceReaders["gs"] = readBlob - d.sourceReaders["git"] = readGit - d.sourceReaders["git+file"] = readGit - d.sourceReaders["git+http"] = readGit - d.sourceReaders["git+https"] = readGit - d.sourceReaders["git+ssh"] = readGit -} - -// lookupReader - return the reader function for the given scheme -func (d *Data) lookupReader(scheme string) (func(context.Context, *Source, ...string) ([]byte, error), error) { - if d.sourceReaders == nil { - d.registerReaders() - } - r, ok := d.sourceReaders[scheme] - if !ok { - return nil, errors.Errorf("scheme %s not registered", scheme) - } - return r, nil -} - -// Data - -// Deprecated: will be replaced in future -type Data struct { - Ctx context.Context - - Sources map[string]*Source - - sourceReaders map[string]func(context.Context, *Source, ...string) ([]byte, error) - cache map[string][]byte - - // headers from the --datasource-header/-H option that don't reference datasources from the commandline - ExtraHeaders map[string]http.Header -} - -// Cleanup - clean up datasources before shutting the process down - things -// like Logging out happen here -func (d *Data) Cleanup() { - for _, s := range d.Sources { - s.cleanup() - } -} - -// NewData - constructor for Data -// Deprecated: will be replaced in future -func NewData(datasourceArgs, headerArgs []string) (*Data, error) { - cfg := &config.Config{} - err := cfg.ParseDataSourceFlags(datasourceArgs, nil, nil, headerArgs) - if err != nil { - return nil, err - } - data := FromConfig(context.Background(), cfg) - return data, nil -} - -// FromConfig - internal use only! -func FromConfig(ctx context.Context, cfg *config.Config) *Data { - // XXX: This is temporary, and will be replaced with something a bit cleaner - // when datasources are refactored - ctx = ContextWithStdin(ctx, cfg.Stdin) - - sources := map[string]*Source{} - for alias, d := range cfg.DataSources { - sources[alias] = &Source{ - Alias: alias, - URL: d.URL, - Header: d.Header, - } - } - for alias, d := range cfg.Context { - sources[alias] = &Source{ - Alias: alias, - URL: d.URL, - Header: d.Header, - } - } - return &Data{ - Ctx: ctx, - Sources: sources, - ExtraHeaders: cfg.ExtraHeaders, - } -} - -// Source - a data source -// Deprecated: will be replaced in future -type Source struct { - Alias string - URL *url.URL - Header http.Header // used for http[s]: URLs, nil otherwise - fs afero.Fs // used for file: URLs, nil otherwise - hc *http.Client // used for http[s]: URLs, nil otherwise - asmpg awssmpGetter // used for aws+smp:, nil otherwise - awsSecretsManager awsSecretsManagerGetter // used for aws+sm, nil otherwise - mediaType string -} - -func (s *Source) inherit(parent *Source) { - s.fs = parent.fs - s.hc = parent.hc - s.asmpg = parent.asmpg -} - -func (s *Source) cleanup() { -} - -// mimeType returns the MIME type to use as a hint for parsing the datasource. -// It's expected that the datasource will have already been read before -// this function is called, and so the Source's Type property may be already set. -// -// The MIME type is determined by these rules: -// 1. the 'type' URL query parameter is used if present -// 2. otherwise, the Type property on the Source is used, if present -// 3. otherwise, a MIME type is calculated from the file extension, if the extension is registered -// 4. otherwise, the default type of 'text/plain' is used -func (s *Source) mimeType(arg string) (mimeType string, err error) { - if len(arg) > 0 { - if strings.HasPrefix(arg, "//") { - arg = arg[1:] - } - if !strings.HasPrefix(arg, "/") { - arg = "/" + arg - } - } - argURL, err := url.Parse(arg) - if err != nil { - return "", fmt.Errorf("mimeType: couldn't parse arg %q: %w", arg, err) - } - mediatype := argURL.Query().Get("type") - if mediatype == "" { - mediatype = s.URL.Query().Get("type") - } - - if mediatype == "" { - mediatype = s.mediaType - } - - // make it so + doesn't need to be escaped - mediatype = strings.ReplaceAll(mediatype, " ", "+") - - if mediatype == "" { - ext := filepath.Ext(argURL.Path) - mediatype = mime.TypeByExtension(ext) - } - - if mediatype == "" { - ext := filepath.Ext(s.URL.Path) - mediatype = mime.TypeByExtension(ext) - } - - if mediatype != "" { - t, _, err := mime.ParseMediaType(mediatype) - if err != nil { - return "", errors.Wrapf(err, "MIME type was %q", mediatype) - } - mediatype = t - return mediatype, nil - } - - return textMimetype, nil -} - -// String is the method to format the flag's value, part of the flag.Value interface. -// The String method's output will be used in diagnostics. -func (s *Source) String() string { - return fmt.Sprintf("%s=%s (%s)", s.Alias, s.URL.String(), s.mediaType) -} - -// DefineDatasource - -func (d *Data) DefineDatasource(alias, value string) (string, error) { - if alias == "" { - return "", errors.New("datasource alias must be provided") - } - if d.DatasourceExists(alias) { - return "", nil - } - srcURL, err := config.ParseSourceURL(value) - if err != nil { - return "", err - } - s := &Source{ - Alias: alias, - URL: srcURL, - Header: d.ExtraHeaders[alias], - } - if d.Sources == nil { - d.Sources = make(map[string]*Source) - } - d.Sources[alias] = s - return "", nil -} - -// DatasourceExists - -func (d *Data) DatasourceExists(alias string) bool { - _, ok := d.Sources[alias] - return ok -} - -func (d *Data) lookupSource(alias string) (*Source, error) { - source, ok := d.Sources[alias] - if !ok { - srcURL, err := url.Parse(alias) - if err != nil || !srcURL.IsAbs() { - return nil, errors.Errorf("Undefined datasource '%s'", alias) - } - source = &Source{ - Alias: alias, - URL: srcURL, - Header: d.ExtraHeaders[alias], - } - d.Sources[alias] = source - } - if source.Alias == "" { - source.Alias = alias - } - return source, nil -} - -func (d *Data) readDataSource(ctx context.Context, alias string, args ...string) (data, mimeType string, err error) { - source, err := d.lookupSource(alias) - if err != nil { - return "", "", err - } - b, err := d.readSource(ctx, source, args...) - if err != nil { - return "", "", errors.Wrapf(err, "Couldn't read datasource '%s'", alias) - } - - subpath := "" - if len(args) > 0 { - subpath = args[0] - } - mimeType, err = source.mimeType(subpath) - if err != nil { - return "", "", err - } - return string(b), mimeType, nil -} - -// Include - -func (d *Data) Include(alias string, args ...string) (string, error) { - data, _, err := d.readDataSource(d.Ctx, alias, args...) - return data, err -} - -// Datasource - -func (d *Data) Datasource(alias string, args ...string) (interface{}, error) { - data, mimeType, err := d.readDataSource(d.Ctx, alias, args...) - if err != nil { - return nil, err - } - - return parseData(mimeType, data) -} - -func parseData(mimeType, s string) (out interface{}, err error) { - switch mimeAlias(mimeType) { - case jsonMimetype: - out, err = JSON(s) - if err != nil { - // maybe it's a JSON array - out, err = JSONArray(s) - } - case jsonArrayMimetype: - out, err = JSONArray(s) - case yamlMimetype: - out, err = YAML(s) - if err != nil { - // maybe it's a YAML array - out, err = YAMLArray(s) - } - case csvMimetype: - out, err = CSV(s) - case tomlMimetype: - out, err = TOML(s) - case envMimetype: - out, err = dotEnv(s) - case textMimetype: - out = s - default: - return nil, errors.Errorf("Datasources of type %s not yet supported", mimeType) - } - return out, err -} - -// DatasourceReachable - Determines if the named datasource is reachable with -// the given arguments. Reads from the datasource, and discards the returned data. -func (d *Data) DatasourceReachable(alias string, args ...string) bool { - source, ok := d.Sources[alias] - if !ok { - return false - } - _, err := d.readSource(d.Ctx, source, args...) - return err == nil -} - -// readSource returns the (possibly cached) data from the given source, -// as referenced by the given args -func (d *Data) readSource(ctx context.Context, source *Source, args ...string) ([]byte, error) { - if d.cache == nil { - d.cache = make(map[string][]byte) - } - cacheKey := source.Alias - for _, v := range args { - cacheKey += v - } - cached, ok := d.cache[cacheKey] - if ok { - return cached, nil - } - r, err := d.lookupReader(source.URL.Scheme) - if err != nil { - return nil, errors.Wrap(err, "Datasource not yet supported") - } - data, err := r(ctx, source, args...) - if err != nil { - return nil, err - } - d.cache[cacheKey] = data - return data, nil -} - -// Show all datasources - -func (d *Data) ListDatasources() []string { - datasources := make([]string, 0, len(d.Sources)) - for source := range d.Sources { - datasources = append(datasources, source) - } - sort.Strings(datasources) - return datasources -} diff --git a/data/datasource_aws_sm.go b/data/datasource_aws_sm.go deleted file mode 100644 index 56559b2d2..000000000 --- a/data/datasource_aws_sm.go +++ /dev/null @@ -1,87 +0,0 @@ -package data - -import ( - "context" - "fmt" - "net/url" - "path" - "strings" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/secretsmanager" - - gaws "github.com/flanksource/gomplate/v3/aws" -) - -// awsSecretsManagerGetter - A subset of Secrets Manager API for use in unit testing -type awsSecretsManagerGetter interface { - GetSecretValueWithContext(ctx context.Context, input *secretsmanager.GetSecretValueInput, opts ...request.Option) (*secretsmanager.GetSecretValueOutput, error) -} - -func parseDatasourceURLArgs(sourceURL *url.URL, args ...string) (params map[string]interface{}, p string, err error) { - if len(args) >= 2 { - err = fmt.Errorf("maximum two arguments to %s datasource: alias, extraPath (found %d)", - sourceURL.Scheme, len(args)) - return nil, "", err - } - - p = sourceURL.Path - params = make(map[string]interface{}) - for key, val := range sourceURL.Query() { - params[key] = strings.Join(val, " ") - } - - if p == "" && sourceURL.Opaque != "" { - p = sourceURL.Opaque - } - - if len(args) == 1 { - parsed, err := url.Parse(args[0]) - if err != nil { - return nil, "", err - } - - if parsed.Path != "" { - p = path.Join(p, parsed.Path) - if strings.HasSuffix(parsed.Path, "/") { - p += "/" - } - } - - for key, val := range parsed.Query() { - params[key] = strings.Join(val, " ") - } - } - return params, p, nil -} - -func readAWSSecretsManager(ctx context.Context, source *Source, args ...string) (output []byte, err error) { - if source.awsSecretsManager == nil { - source.awsSecretsManager = secretsmanager.New(gaws.SDKSession()) - } - - _, paramPath, err := parseDatasourceURLArgs(source.URL, args...) - if err != nil { - return nil, err - } - - return readAWSSecretsManagerParam(ctx, source, paramPath) -} - -func readAWSSecretsManagerParam(ctx context.Context, source *Source, paramPath string) ([]byte, error) { - input := &secretsmanager.GetSecretValueInput{ - SecretId: aws.String(paramPath), - } - - response, err := source.awsSecretsManager.GetSecretValueWithContext(ctx, input) - if err != nil { - return nil, fmt.Errorf("reading aws+sm source %q: %w", source.Alias, err) - } - - if response.SecretString != nil { - return []byte(*response.SecretString), nil - } - - return response.SecretBinary, nil -} diff --git a/data/datasource_aws_sm_test.go b/data/datasource_aws_sm_test.go deleted file mode 100644 index c274dcf8c..000000000 --- a/data/datasource_aws_sm_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package data - -import ( - "context" - "net/url" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/secretsmanager" - "github.com/stretchr/testify/assert" -) - -// DummyAWSSecretsManagerSecretGetter - test double -type DummyAWSSecretsManagerSecretGetter struct { - t *testing.T - secretValut *secretsmanager.GetSecretValueOutput - err awserr.Error - mockGetSecretValue func(input *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) -} - -func (d DummyAWSSecretsManagerSecretGetter) GetSecretValueWithContext(ctx context.Context, input *secretsmanager.GetSecretValueInput, opts ...request.Option) (*secretsmanager.GetSecretValueOutput, error) { - if d.mockGetSecretValue != nil { - output, err := d.mockGetSecretValue(input) - return output, err - } - if d.err != nil { - return nil, d.err - } - assert.NotNil(d.t, d.secretValut, "Must provide a param if no error!") - return d.secretValut, nil -} - -func simpleAWSSecretsManagerSourceHelper(dummyGetter awsSecretsManagerGetter) *Source { - return &Source{ - Alias: "foo", - URL: &url.URL{ - Scheme: "aws+sm", - Path: "/foo", - }, - awsSecretsManager: dummyGetter, - } -} - -func TestAWSSecretsManager_ParseAWSSecretsManagerArgs(t *testing.T) { - _, _, err := parseDatasourceURLArgs(mustParseURL("base"), "extra", "too many!") - assert.Error(t, err) - - tplain := map[string]interface{}{"type": "text/plain"} - - data := []struct { - eParams map[string]interface{} - u string - ePath string - args string - }{ - {u: "noddy", ePath: "noddy"}, - {u: "base", ePath: "base/extra", args: "extra"}, - {u: "/foo/", ePath: "/foo/extra", args: "/extra"}, - {u: "aws+sm:///foo", ePath: "/foo/bar", args: "bar"}, - {u: "aws+sm:foo", ePath: "foo"}, - {u: "aws+sm:foo/bar", ePath: "foo/bar"}, - {u: "aws+sm:/foo/bar", ePath: "/foo/bar"}, - {u: "aws+sm:foo", ePath: "foo/baz", args: "baz"}, - {u: "aws+sm:foo/bar", ePath: "foo/bar/baz", args: "baz"}, - {u: "aws+sm:/foo/bar", ePath: "/foo/bar/baz", args: "baz"}, - {u: "aws+sm:///foo", ePath: "/foo/dir/", args: "dir/"}, - {u: "aws+sm:///foo/", ePath: "/foo/"}, - {u: "aws+sm:///foo/", ePath: "/foo/baz", args: "baz"}, - {eParams: tplain, u: "aws+sm:foo?type=text/plain", ePath: "foo/baz", args: "baz"}, - {eParams: tplain, u: "aws+sm:foo/bar?type=text/plain", ePath: "foo/bar/baz", args: "baz"}, - {eParams: tplain, u: "aws+sm:/foo/bar?type=text/plain", ePath: "/foo/bar/baz", args: "baz"}, - { - eParams: map[string]interface{}{ - "type": "application/json", - "param": "quux", - }, - u: "aws+sm:/foo/bar?type=text/plain", - ePath: "/foo/bar/baz/qux", - args: "baz/qux?type=application/json¶m=quux", - }, - } - - for _, d := range data { - args := []string{d.args} - if d.args == "" { - args = nil - } - params, p, err := parseDatasourceURLArgs(mustParseURL(d.u), args...) - assert.NoError(t, err) - if d.eParams == nil { - assert.Empty(t, params) - } else { - assert.EqualValues(t, d.eParams, params) - } - assert.Equal(t, d.ePath, p) - } -} - -func TestAWSSecretsManager_GetParameterSetup(t *testing.T) { - calledOk := false - s := simpleAWSSecretsManagerSourceHelper(DummyAWSSecretsManagerSecretGetter{ - t: t, - mockGetSecretValue: func(input *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) { - assert.Equal(t, "/foo/bar", *input.SecretId) - calledOk = true - return &secretsmanager.GetSecretValueOutput{SecretString: aws.String("blub")}, nil - }, - }) - - _, err := readAWSSecretsManager(context.Background(), s, "/bar") - assert.True(t, calledOk) - assert.Nil(t, err) -} - -func TestAWSSecretsManager_GetParameterSetupWrongArgs(t *testing.T) { - calledOk := false - s := simpleAWSSecretsManagerSourceHelper(DummyAWSSecretsManagerSecretGetter{ - t: t, - mockGetSecretValue: func(input *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) { - assert.Equal(t, "/foo/bar", *input.SecretId) - calledOk = true - return &secretsmanager.GetSecretValueOutput{SecretString: aws.String("blub")}, nil - }, - }) - - _, err := readAWSSecretsManager(context.Background(), s, "/bar", "/foo", "/bla") - assert.False(t, calledOk) - assert.Error(t, err) -} - -func TestAWSSecretsManager_GetParameterMissing(t *testing.T) { - expectedErr := awserr.New("ParameterNotFound", "Test of error message", nil) - s := simpleAWSSecretsManagerSourceHelper(DummyAWSSecretsManagerSecretGetter{ - t: t, - err: expectedErr, - }) - - _, err := readAWSSecretsManager(context.Background(), s, "") - assert.Error(t, err, "Test of error message") -} - -func TestAWSSecretsManager_ReadSecret(t *testing.T) { - calledOk := false - s := simpleAWSSecretsManagerSourceHelper(DummyAWSSecretsManagerSecretGetter{ - t: t, - mockGetSecretValue: func(input *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) { - assert.Equal(t, "/foo/bar", *input.SecretId) - calledOk = true - return &secretsmanager.GetSecretValueOutput{SecretString: aws.String("blub")}, nil - }, - }) - - output, err := readAWSSecretsManagerParam(context.Background(), s, "/foo/bar") - assert.True(t, calledOk) - assert.NoError(t, err) - assert.Equal(t, []byte("blub"), output) -} - -func TestAWSSecretsManager_ReadSecretBinary(t *testing.T) { - calledOk := false - s := simpleAWSSecretsManagerSourceHelper(DummyAWSSecretsManagerSecretGetter{ - t: t, - mockGetSecretValue: func(input *secretsmanager.GetSecretValueInput) (*secretsmanager.GetSecretValueOutput, error) { - assert.Equal(t, "/foo/bar", *input.SecretId) - calledOk = true - return &secretsmanager.GetSecretValueOutput{SecretBinary: []byte("supersecret")}, nil - }, - }) - - output, err := readAWSSecretsManagerParam(context.Background(), s, "/foo/bar") - assert.True(t, calledOk) - assert.NoError(t, err) - assert.Equal(t, []byte("supersecret"), output) -} diff --git a/data/datasource_awssmp.go b/data/datasource_awssmp.go deleted file mode 100644 index ee6a76a6d..000000000 --- a/data/datasource_awssmp.go +++ /dev/null @@ -1,78 +0,0 @@ -package data - -import ( - "context" - "strings" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ssm" - "github.com/pkg/errors" - - gaws "github.com/flanksource/gomplate/v3/aws" -) - -// awssmpGetter - A subset of SSM API for use in unit testing -type awssmpGetter interface { - GetParameterWithContext(ctx context.Context, input *ssm.GetParameterInput, opts ...request.Option) (*ssm.GetParameterOutput, error) - GetParametersByPathWithContext(ctx context.Context, input *ssm.GetParametersByPathInput, opts ...request.Option) (*ssm.GetParametersByPathOutput, error) -} - -func readAWSSMP(ctx context.Context, source *Source, args ...string) (data []byte, err error) { - if source.asmpg == nil { - source.asmpg = ssm.New(gaws.SDKSession()) - } - - _, paramPath, err := parseDatasourceURLArgs(source.URL, args...) - if err != nil { - return nil, err - } - - source.mediaType = jsonMimetype - switch { - case strings.HasSuffix(paramPath, "/"): - source.mediaType = jsonArrayMimetype - data, err = listAWSSMPParams(ctx, source, paramPath) - default: - data, err = readAWSSMPParam(ctx, source, paramPath) - } - return data, err -} - -func readAWSSMPParam(ctx context.Context, source *Source, paramPath string) ([]byte, error) { - input := &ssm.GetParameterInput{ - Name: aws.String(paramPath), - WithDecryption: aws.Bool(true), - } - - response, err := source.asmpg.GetParameterWithContext(ctx, input) - - if err != nil { - return nil, errors.Wrapf(err, "Error reading aws+smp from AWS using GetParameter with input %v", input) - } - - result := *response.Parameter - - output, err := ToJSON(result) - return []byte(output), err -} - -// listAWSSMPParams - supports directory semantics, returns array -func listAWSSMPParams(ctx context.Context, source *Source, paramPath string) ([]byte, error) { - input := &ssm.GetParametersByPathInput{ - Path: aws.String(paramPath), - } - - response, err := source.asmpg.GetParametersByPathWithContext(ctx, input) - if err != nil { - return nil, errors.Wrapf(err, "Error reading aws+smp from AWS using GetParameter with input %v", input) - } - - listing := make([]string, len(response.Parameters)) - for i, p := range response.Parameters { - listing[i] = (*p.Name)[len(paramPath):] - } - - output, err := ToJSON(listing) - return []byte(output), err -} diff --git a/data/datasource_awssmp_test.go b/data/datasource_awssmp_test.go deleted file mode 100644 index 7fac1084b..000000000 --- a/data/datasource_awssmp_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package data - -import ( - "context" - "encoding/json" - "net/url" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/ssm" - "github.com/stretchr/testify/assert" -) - -// DummyParamGetter - test double -type DummyParamGetter struct { - err awserr.Error - t *testing.T - param *ssm.Parameter - mockGetParameter func(*ssm.GetParameterInput) (*ssm.GetParameterOutput, error) - params []*ssm.Parameter -} - -func (d DummyParamGetter) GetParameterWithContext(ctx context.Context, input *ssm.GetParameterInput, opts ...request.Option) (*ssm.GetParameterOutput, error) { - if d.mockGetParameter != nil { - output, err := d.mockGetParameter(input) - return output, err - } - if d.err != nil { - return nil, d.err - } - assert.NotNil(d.t, d.param, "Must provide a param if no error!") - return &ssm.GetParameterOutput{ - Parameter: d.param, - }, nil -} - -func (d DummyParamGetter) GetParametersByPathWithContext(ctx context.Context, input *ssm.GetParametersByPathInput, opts ...request.Option) (*ssm.GetParametersByPathOutput, error) { - if d.err != nil { - return nil, d.err - } - assert.NotNil(d.t, d.params, "Must provide a param if no error!") - return &ssm.GetParametersByPathOutput{ - Parameters: d.params, - }, nil -} - -func simpleAWSSourceHelper(dummy awssmpGetter) *Source { - return &Source{ - Alias: "foo", - URL: &url.URL{ - Scheme: "aws+smp", - Path: "/foo", - }, - asmpg: dummy, - } -} - -func TestAWSSMP_GetParameterSetup(t *testing.T) { - calledOk := false - s := simpleAWSSourceHelper(DummyParamGetter{ - t: t, - mockGetParameter: func(input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error) { - assert.Equal(t, "/foo/bar", *input.Name) - assert.True(t, *input.WithDecryption) - calledOk = true - return &ssm.GetParameterOutput{ - Parameter: &ssm.Parameter{}, - }, nil - }, - }) - - _, err := readAWSSMP(context.Background(), s, "/bar") - assert.True(t, calledOk) - assert.Nil(t, err) -} - -func TestAWSSMP_GetParameterValidOutput(t *testing.T) { - expected := &ssm.Parameter{ - Name: aws.String("/foo"), - Type: aws.String("String"), - Value: aws.String("val"), - Version: aws.Int64(1), - } - s := simpleAWSSourceHelper(DummyParamGetter{ - t: t, - param: expected, - }) - - output, err := readAWSSMP(context.Background(), s, "") - assert.Nil(t, err) - actual := &ssm.Parameter{} - err = json.Unmarshal(output, &actual) - assert.Nil(t, err) - assert.Equal(t, expected, actual) - assert.Equal(t, jsonMimetype, s.mediaType) -} - -func TestAWSSMP_GetParameterMissing(t *testing.T) { - expectedErr := awserr.New("ParameterNotFound", "Test of error message", nil) - s := simpleAWSSourceHelper(DummyParamGetter{ - t: t, - err: expectedErr, - }) - - _, err := readAWSSMP(context.Background(), s, "") - assert.Error(t, err, "Test of error message") -} - -func TestAWSSMP_listAWSSMPParams(t *testing.T) { - ctx := context.Background() - s := simpleAWSSourceHelper(DummyParamGetter{ - t: t, - err: awserr.New("ParameterNotFound", "foo", nil), - }) - _, err := listAWSSMPParams(ctx, s, "") - assert.Error(t, err) - - s = simpleAWSSourceHelper(DummyParamGetter{ - t: t, - params: []*ssm.Parameter{ - {Name: aws.String("/a")}, - {Name: aws.String("/b")}, - {Name: aws.String("/c")}, - }, - }) - data, err := listAWSSMPParams(ctx, s, "/") - assert.NoError(t, err) - assert.Equal(t, []byte(`["a","b","c"]`), data) - - s = simpleAWSSourceHelper(DummyParamGetter{ - t: t, - params: []*ssm.Parameter{ - {Name: aws.String("/a/a")}, - {Name: aws.String("/a/b")}, - {Name: aws.String("/a/c")}, - }, - }) - data, err = listAWSSMPParams(ctx, s, "/a/") - assert.NoError(t, err) - assert.Equal(t, []byte(`["a","b","c"]`), data) -} diff --git a/data/datasource_blob.go b/data/datasource_blob.go deleted file mode 100644 index 19356d284..000000000 --- a/data/datasource_blob.go +++ /dev/null @@ -1,170 +0,0 @@ -package data - -import ( - "bytes" - "context" - "encoding/json" - "io" - "mime" - "net/url" - "path" - "strings" - - gaws "github.com/flanksource/gomplate/v3/aws" - "github.com/flanksource/gomplate/v3/env" - "github.com/pkg/errors" - - "gocloud.dev/blob" - "gocloud.dev/blob/gcsblob" - "gocloud.dev/blob/s3blob" - "gocloud.dev/gcp" -) - -func readBlob(ctx context.Context, source *Source, args ...string) (output []byte, err error) { - if len(args) >= 2 { - return nil, errors.New("maximum two arguments to blob datasource: alias, extraPath") - } - - key := source.URL.Path - if len(args) == 1 { - key = path.Join(key, args[0]) - } - - opener, err := newOpener(ctx, source.URL) - if err != nil { - return nil, err - } - - mux := blob.URLMux{} - mux.RegisterBucket(source.URL.Scheme, opener) - - u := blobURL(source.URL) - bucket, err := mux.OpenBucket(ctx, u) - if err != nil { - return nil, err - } - defer bucket.Close() - - var r func(context.Context, *blob.Bucket, string) (string, []byte, error) - if strings.HasSuffix(key, "/") { - r = listBucket - } else { - r = getBlob - } - - mediaType, data, err := r(ctx, bucket, key) - if mediaType != "" { - source.mediaType = mediaType - } - return data, err -} - -// create the correct kind of blob.BucketURLOpener for the given URL -func newOpener(ctx context.Context, u *url.URL) (opener blob.BucketURLOpener, err error) { - switch u.Scheme { - case "s3": - // set up a "regular" gomplate AWS SDK session - sess := gaws.SDKSession() - // see https://gocloud.dev/concepts/urls/#muxes - opener = &s3blob.URLOpener{ConfigProvider: sess} - case "gs": - creds, err := gcp.DefaultCredentials(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to retrieve GCP credentials") - } - - client, err := gcp.NewHTTPClient( - gcp.DefaultTransport(), - gcp.CredentialsTokenSource(creds)) - if err != nil { - return nil, errors.Wrap(err, "failed to create GCP HTTP client") - } - opener = &gcsblob.URLOpener{ - Client: client, - } - } - return opener, nil -} - -func getBlob(ctx context.Context, bucket *blob.Bucket, key string) (mediaType string, data []byte, err error) { - key = strings.TrimPrefix(key, "/") - attr, err := bucket.Attributes(ctx, key) - if err != nil { - return "", nil, errors.Wrapf(err, "failed to retrieve attributes for %s", key) - } - if attr.ContentType != "" { - mt, _, e := mime.ParseMediaType(attr.ContentType) - if e != nil { - return "", nil, e - } - mediaType = mt - } - data, err = bucket.ReadAll(ctx, key) - return mediaType, data, errors.Wrapf(err, "failed to read %s", key) -} - -// calls the bucket listing API, returning a JSON Array -func listBucket(ctx context.Context, bucket *blob.Bucket, path string) (mediaType string, data []byte, err error) { - path = strings.TrimPrefix(path, "/") - opts := &blob.ListOptions{ - Prefix: path, - Delimiter: "/", - } - li := bucket.List(opts) - keys := []string{} - for { - obj, err := li.Next(ctx) - if err == io.EOF { - break - } - if err != nil { - return "", nil, err - } - keys = append(keys, strings.TrimPrefix(obj.Key, path)) - } - - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - if err := enc.Encode(keys); err != nil { - return "", nil, err - } - b := buf.Bytes() - // chop off the newline added by the json encoder - data = b[:len(b)-1] - return jsonArrayMimetype, data, nil -} - -// copy/sanitize the URL for the Go CDK - it doesn't like params it can't parse -func blobURL(u *url.URL) string { - out := cloneURL(u) - q := out.Query() - - for param := range q { - switch u.Scheme { - case "s3": - switch param { - case "region", "endpoint", "disableSSL", "s3ForcePathStyle": - default: - q.Del(param) - } - case "gs": - switch param { - case "access_id", "private_key_path": - default: - q.Del(param) - } - } - } - - if u.Scheme == "s3" { - // handle AWS_S3_ENDPOINT env var - endpoint := env.Getenv("AWS_S3_ENDPOINT") - if endpoint != "" { - q.Set("endpoint", endpoint) - } - } - - out.RawQuery = q.Encode() - - return out.String() -} diff --git a/data/datasource_env.go b/data/datasource_env.go deleted file mode 100644 index c84bcf098..000000000 --- a/data/datasource_env.go +++ /dev/null @@ -1,19 +0,0 @@ -package data - -import ( - "context" - "strings" - - "github.com/flanksource/gomplate/v3/env" -) - -func readEnv(ctx context.Context, source *Source, args ...string) (b []byte, err error) { - n := source.URL.Path - n = strings.TrimPrefix(n, "/") - if n == "" { - n = source.URL.Opaque - } - - b = []byte(env.Getenv(n)) - return b, nil -} diff --git a/data/datasource_env_test.go b/data/datasource_env_test.go deleted file mode 100644 index c7723b3b2..000000000 --- a/data/datasource_env_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package data - -import ( - "context" - "net/url" - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -func mustParseURL(in string) *url.URL { - u, _ := url.Parse(in) - return u -} - -func TestReadEnv(t *testing.T) { - ctx := context.Background() - - content := []byte(`hello world`) - os.Setenv("HELLO_WORLD", "hello world") - defer os.Unsetenv("HELLO_WORLD") - os.Setenv("HELLO_UNIVERSE", "hello universe") - defer os.Unsetenv("HELLO_UNIVERSE") - - source := &Source{Alias: "foo", URL: mustParseURL("env:HELLO_WORLD")} - - actual, err := readEnv(ctx, source) - assert.NoError(t, err) - assert.Equal(t, content, actual) - - source = &Source{Alias: "foo", URL: mustParseURL("env:/HELLO_WORLD")} - - actual, err = readEnv(ctx, source) - assert.NoError(t, err) - assert.Equal(t, content, actual) - - source = &Source{Alias: "foo", URL: mustParseURL("env:///HELLO_WORLD")} - - actual, err = readEnv(ctx, source) - assert.NoError(t, err) - assert.Equal(t, content, actual) - - source = &Source{Alias: "foo", URL: mustParseURL("env:HELLO_WORLD?foo=bar")} - - actual, err = readEnv(ctx, source) - assert.NoError(t, err) - assert.Equal(t, content, actual) - - source = &Source{Alias: "foo", URL: mustParseURL("env:///HELLO_WORLD?foo=bar")} - - actual, err = readEnv(ctx, source) - assert.NoError(t, err) - assert.Equal(t, content, actual) -} diff --git a/data/datasource_file.go b/data/datasource_file.go deleted file mode 100644 index e6be04409..000000000 --- a/data/datasource_file.go +++ /dev/null @@ -1,85 +0,0 @@ -package data - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/url" - "os" - "path/filepath" - "strings" - - "github.com/spf13/afero" - - "github.com/pkg/errors" -) - -func readFile(ctx context.Context, source *Source, args ...string) ([]byte, error) { - if source.fs == nil { - source.fs = afero.NewOsFs() - } - - p := filepath.FromSlash(source.URL.Path) - - if len(args) == 1 { - parsed, err := url.Parse(args[0]) - if err != nil { - return nil, err - } - - if parsed.Path != "" { - p = filepath.Join(p, parsed.Path) - } - - // reset the media type - it may have been set by a parent dir read - source.mediaType = "" - } - - // make sure we can access the file - i, err := source.fs.Stat(p) - if err != nil { - return nil, errors.Wrapf(err, "Can't stat %s", p) - } - - if strings.HasSuffix(p, string(filepath.Separator)) { - source.mediaType = jsonArrayMimetype - if i.IsDir() { - return readFileDir(source, p) - } - return nil, errors.Errorf("%s is not a directory", p) - } - - f, err := source.fs.OpenFile(p, os.O_RDONLY, 0) - if err != nil { - return nil, errors.Wrapf(err, "Can't open %s", p) - } - - defer f.Close() - - b, err := io.ReadAll(f) - if err != nil { - return nil, errors.Wrapf(err, "Can't read %s", p) - } - return b, nil -} - -func readFileDir(source *Source, p string) ([]byte, error) { - names, err := afero.ReadDir(source.fs, p) - if err != nil { - return nil, err - } - files := make([]string, len(names)) - for i, v := range names { - files[i] = v.Name() - } - - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - if err := enc.Encode(files); err != nil { - return nil, err - } - b := buf.Bytes() - // chop off the newline added by the json encoder - return b[:len(b)-1], nil -} diff --git a/data/datasource_file_test.go b/data/datasource_file_test.go deleted file mode 100644 index 8f2a7f0a2..000000000 --- a/data/datasource_file_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package data - -import ( - "context" - "testing" - - "github.com/spf13/afero" - - "github.com/stretchr/testify/assert" -) - -func TestReadFile(t *testing.T) { - ctx := context.Background() - - content := []byte(`hello world`) - fs := afero.NewMemMapFs() - - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write(content) - - _ = fs.Mkdir("/tmp/partial", 0777) - f, _ = fs.Create("/tmp/partial/foo.txt") - _, _ = f.Write(content) - _, _ = fs.Create("/tmp/partial/bar.txt") - _, _ = fs.Create("/tmp/partial/baz.txt") - _ = f.Close() - - source := &Source{Alias: "foo", URL: mustParseURL("file:///tmp/foo")} - source.fs = fs - - actual, err := readFile(ctx, source) - assert.NoError(t, err) - assert.Equal(t, content, actual) - - source = &Source{Alias: "bogus", URL: mustParseURL("file:///bogus")} - source.fs = fs - _, err = readFile(ctx, source) - assert.Error(t, err) - - source = &Source{Alias: "partial", URL: mustParseURL("file:///tmp/partial")} - source.fs = fs - actual, err = readFile(ctx, source, "foo.txt") - assert.NoError(t, err) - assert.Equal(t, content, actual) - - source = &Source{Alias: "dir", URL: mustParseURL("file:///tmp/partial/")} - source.fs = fs - actual, err = readFile(ctx, source) - assert.NoError(t, err) - assert.Equal(t, []byte(`["bar.txt","baz.txt","foo.txt"]`), actual) - - source = &Source{Alias: "dir", URL: mustParseURL("file:///tmp/partial/?type=application/json")} - source.fs = fs - actual, err = readFile(ctx, source) - assert.NoError(t, err) - assert.Equal(t, []byte(`["bar.txt","baz.txt","foo.txt"]`), actual) - mime, err := source.mimeType("") - assert.NoError(t, err) - assert.Equal(t, "application/json", mime) - - source = &Source{Alias: "dir", URL: mustParseURL("file:///tmp/partial/?type=application/json")} - source.fs = fs - actual, err = readFile(ctx, source, "foo.txt") - assert.NoError(t, err) - assert.Equal(t, content, actual) - mime, err = source.mimeType("") - assert.NoError(t, err) - assert.Equal(t, "application/json", mime) -} diff --git a/data/datasource_git.go b/data/datasource_git.go deleted file mode 100644 index 1cb4bfdbf..000000000 --- a/data/datasource_git.go +++ /dev/null @@ -1,329 +0,0 @@ -package data - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "net/url" - "os" - "path" - "path/filepath" - "strings" - - "github.com/flanksource/gomplate/v3/base64" - "github.com/flanksource/gomplate/v3/env" - "github.com/rs/zerolog" - - "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/memfs" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/transport" - "github.com/go-git/go-git/v5/plumbing/transport/client" - "github.com/go-git/go-git/v5/plumbing/transport/http" - "github.com/go-git/go-git/v5/plumbing/transport/ssh" - "github.com/go-git/go-git/v5/storage/memory" -) - -func readGit(ctx context.Context, source *Source, args ...string) ([]byte, error) { - g := gitsource{} - - u := source.URL - repoURL, path, err := g.parseGitPath(u, args...) - if err != nil { - return nil, err - } - - depth := 1 - if u.Scheme == "git+file" { - // we can't do shallow clones for filesystem repos apparently - depth = 0 - } - - fs, _, err := g.clone(ctx, repoURL, depth) - if err != nil { - return nil, err - } - - mimeType, out, err := g.read(fs, path) - if mimeType != "" { - source.mediaType = mimeType - } - return out, err -} - -type gitsource struct { -} - -func (g gitsource) parseArgURL(arg string) (u *url.URL, err error) { - if strings.HasPrefix(arg, "//") { - u, err = url.Parse(arg[1:]) - u.Path = "/" + u.Path - } else { - u, err = url.Parse(arg) - } - - if err != nil { - return nil, fmt.Errorf("failed to parse arg %s: %w", arg, err) - } - return u, err -} - -func (g gitsource) parseQuery(orig, arg *url.URL) string { - q := orig.Query() - pq := arg.Query() - for k, vs := range pq { - for _, v := range vs { - q.Add(k, v) - } - } - return q.Encode() -} - -func (g gitsource) parseArgPath(u *url.URL, arg string) (repo, p string) { - // if the source URL already specified a repo and subpath, the whole - // arg is interpreted as subpath - if strings.Contains(u.Path, "//") || strings.HasPrefix(arg, "//") { - return "", arg - } - - parts := strings.SplitN(arg, "//", 2) - repo = parts[0] - if len(parts) == 2 { - p = "/" + parts[1] - } - return repo, p -} - -// Massage the URL and args together to produce the repo to clone, -// and the path to read. -// The path is delimited from the repo by '//' -func (g gitsource) parseGitPath(u *url.URL, args ...string) (out *url.URL, p string, err error) { - if u == nil { - return nil, "", fmt.Errorf("parseGitPath: no url provided (%v)", u) - } - // copy the input url so we can modify it - out = cloneURL(u) - - parts := strings.SplitN(out.Path, "//", 2) - switch len(parts) { - case 1: - p = "/" - case 2: - p = "/" + parts[1] - - i := strings.LastIndex(out.Path, p) - out.Path = out.Path[:i-1] - } - - if len(args) > 0 { - argURL, uerr := g.parseArgURL(args[0]) - if uerr != nil { - return nil, "", uerr - } - repo, argpath := g.parseArgPath(u, argURL.Path) - out.Path = path.Join(out.Path, repo) - p = path.Join(p, argpath) - - out.RawQuery = g.parseQuery(u, argURL) - - if argURL.Fragment != "" { - out.Fragment = argURL.Fragment - } - } - return out, p, err -} - -// nolint: interfacer -func cloneURL(u *url.URL) *url.URL { - out, _ := url.Parse(u.String()) - return out -} - -// refFromURL - extract the ref from the URL fragment if present -func (g gitsource) refFromURL(u *url.URL) plumbing.ReferenceName { - switch { - case strings.HasPrefix(u.Fragment, "refs/"): - return plumbing.ReferenceName(u.Fragment) - case u.Fragment != "": - return plumbing.NewBranchReferenceName(u.Fragment) - default: - return plumbing.ReferenceName("") - } -} - -// refFromRemoteHead - extract the ref from the remote HEAD, to work around -// hard-coded 'master' default branch in go-git. -// Should be unnecessary once https://github.com/go-git/go-git/issues/249 is -// fixed. -func (g gitsource) refFromRemoteHead(ctx context.Context, u *url.URL, auth transport.AuthMethod) (plumbing.ReferenceName, error) { - e, err := transport.NewEndpoint(u.String()) - if err != nil { - return "", err - } - - cli, err := client.NewClient(e) - if err != nil { - return "", err - } - - s, err := cli.NewUploadPackSession(e, auth) - if err != nil { - return "", err - } - - info, err := s.AdvertisedReferencesContext(ctx) - if err != nil { - return "", err - } - - refs, err := info.AllReferences() - if err != nil { - return "", err - } - - headRef, ok := refs["HEAD"] - if !ok { - return "", fmt.Errorf("no HEAD ref found") - } - - return headRef.Target(), nil -} - -// clone a repo for later reading through http(s), git, or ssh. u must be the URL to the repo -// itself, and must have any file path stripped -func (g gitsource) clone(ctx context.Context, repoURL *url.URL, depth int) (billy.Filesystem, *git.Repository, error) { - fs := memfs.New() - storer := memory.NewStorage() - - // preserve repoURL by cloning it - u := cloneURL(repoURL) - - auth, err := g.auth(u) - if err != nil { - return nil, nil, err - } - - if strings.HasPrefix(u.Scheme, "git+") { - scheme := u.Scheme[len("git+"):] - u.Scheme = scheme - } - - ref := g.refFromURL(u) - u.Fragment = "" - u.RawQuery = "" - - // attempt to get the ref from the remote so we don't default to master - if ref == "" { - ref, err = g.refFromRemoteHead(ctx, u, auth) - if err != nil { - zerolog.Ctx(ctx).Warn(). - Stringer("repoURL", u). - Err(err). - Msg("failed to get ref from remote, using default") - } - } - - opts := &git.CloneOptions{ - URL: u.String(), - Auth: auth, - Depth: depth, - ReferenceName: ref, - SingleBranch: true, - Tags: git.NoTags, - } - repo, err := git.CloneContext(ctx, storer, fs, opts) - if u.Scheme == "file" && err == transport.ErrRepositoryNotFound && !strings.HasSuffix(u.Path, ".git") { - // maybe this has a `.git` subdirectory... - u = cloneURL(repoURL) - u.Path = path.Join(u.Path, ".git") - return g.clone(ctx, u, depth) - } - if err != nil { - return nil, nil, fmt.Errorf("git clone for %v failed: %w", repoURL, err) - } - return fs, repo, nil -} - -// read - reads the provided path out of a git repo -func (g gitsource) read(fs billy.Filesystem, path string) (string, []byte, error) { - fi, err := fs.Stat(path) - if err != nil { - return "", nil, fmt.Errorf("can't stat %s: %w", path, err) - } - if fi.IsDir() || strings.HasSuffix(path, string(filepath.Separator)) { - out, rerr := g.readDir(fs, path) - return jsonArrayMimetype, out, rerr - } - - f, err := fs.OpenFile(path, os.O_RDONLY, 0) - if err != nil { - return "", nil, fmt.Errorf("can't open %s: %w", path, err) - } - - b, err := io.ReadAll(f) - if err != nil { - return "", nil, fmt.Errorf("can't read %s: %w", path, err) - } - - return "", b, nil -} - -func (g gitsource) readDir(fs billy.Filesystem, path string) ([]byte, error) { - names, err := fs.ReadDir(path) - if err != nil { - return nil, fmt.Errorf("couldn't read dir %s: %w", path, err) - } - files := make([]string, len(names)) - for i, v := range names { - files[i] = v.Name() - } - - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - if err := enc.Encode(files); err != nil { - return nil, err - } - b := buf.Bytes() - // chop off the newline added by the json encoder - return b[:len(b)-1], nil -} - -/* -auth methods: -- ssh named key (no password support) - - GIT_SSH_KEY (base64-encoded) or GIT_SSH_KEY_FILE (base64-encoded, or not) - -- ssh agent auth (preferred) -- http basic auth (for github, gitlab, bitbucket tokens) -- http token auth (bearer token, somewhat unusual) -*/ -func (g gitsource) auth(u *url.URL) (auth transport.AuthMethod, err error) { - user := u.User.Username() - switch u.Scheme { - case "git+http", "git+https": - if pass, ok := u.User.Password(); ok { - auth = &http.BasicAuth{Username: user, Password: pass} - } else if pass := env.Getenv("GIT_HTTP_PASSWORD"); pass != "" { - auth = &http.BasicAuth{Username: user, Password: pass} - } else if tok := env.Getenv("GIT_HTTP_TOKEN"); tok != "" { - // note docs on TokenAuth - this is rarely to be used - auth = &http.TokenAuth{Token: tok} - } - case "git+ssh": - k := env.Getenv("GIT_SSH_KEY") - if k != "" { - var key []byte - key, err = base64.Decode(k) - if err != nil { - key = []byte(k) - } - auth, err = ssh.NewPublicKeys(user, key, "") - } else { - auth, err = ssh.NewSSHAgentAuth(user) - } - } - return auth, err -} diff --git a/data/datasource_git_test.go b/data/datasource_git_test.go deleted file mode 100644 index 157e14a86..000000000 --- a/data/datasource_git_test.go +++ /dev/null @@ -1,486 +0,0 @@ -package data - -import ( - "context" - "encoding/base64" - "fmt" - "io" - "net/url" - "os" - "strings" - "testing" - "time" - - "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/memfs" - "github.com/go-git/go-billy/v5/osfs" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/plumbing/cache" - "github.com/go-git/go-git/v5/plumbing/object" - "github.com/go-git/go-git/v5/plumbing/transport/client" - "github.com/go-git/go-git/v5/plumbing/transport/http" - "github.com/go-git/go-git/v5/plumbing/transport/server" - "github.com/go-git/go-git/v5/plumbing/transport/ssh" - "github.com/go-git/go-git/v5/storage/filesystem" - - "golang.org/x/crypto/ssh/testdata" - - "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" -) - -func TestParseArgPath(t *testing.T) { - t.Parallel() - g := gitsource{} - - data := []struct { - url string - arg string - repo, path string - }{ - {"git+file:///foo//foo", - "/bar", - "", "/bar"}, - {"git+file:///foo//bar", - "/baz//qux", - "", "/baz//qux"}, - {"git+https://example.com/foo", - "/bar", - "/bar", ""}, - {"git+https://example.com/foo", - "//bar", - "", "//bar"}, - {"git+https://example.com/foo//bar", - "//baz", - "", "//baz"}, - {"git+https://example.com/foo", - "/bar//baz", - "/bar", "/baz"}, - {"git+https://example.com/foo?type=t", - "/bar//baz", - "/bar", "/baz"}, - {"git+https://example.com/foo#master", - "/bar//baz", - "/bar", "/baz"}, - {"git+https://example.com/foo", - "//bar", - "", "//bar"}, - {"git+https://example.com/foo?type=t", - "//baz", - "", "//baz"}, - {"git+https://example.com/foo?type=t#v1", - "//bar", - "", "//bar"}, - } - - for i, d := range data { - d := d - t.Run(fmt.Sprintf("%d:(%q,%q)==(%q,%q)", i, d.url, d.arg, d.repo, d.path), func(t *testing.T) { - t.Parallel() - u, _ := url.Parse(d.url) - repo, path := g.parseArgPath(u, d.arg) - assert.Equal(t, d.repo, repo) - assert.Equal(t, d.path, path) - }) - } -} - -func TestParseGitPath(t *testing.T) { - t.Parallel() - g := gitsource{} - _, _, err := g.parseGitPath(nil) - assert.ErrorContains(t, err, "") - - u := mustParseURL("http://example.com//foo") - assert.Equal(t, "//foo", u.Path) - parts := strings.SplitN(u.Path, "//", 2) - assert.Equal(t, 2, len(parts)) - assert.DeepEqual(t, []string{"", "foo"}, parts) - - data := []struct { - url string - args string - repo, path string - }{ - {"git+https://github.com/hairyhenderson/gomplate//docs-src/content/functions/aws.yml", - "", - "git+https://github.com/hairyhenderson/gomplate", - "/docs-src/content/functions/aws.yml"}, - {"git+ssh://github.com/hairyhenderson/gomplate.git", - "", - "git+ssh://github.com/hairyhenderson/gomplate.git", - "/"}, - {"https://github.com", - "", - "https://github.com", - "/"}, - {"git://example.com/foo//file.txt#someref", - "", - "git://example.com/foo#someref", "/file.txt"}, - {"git+file:///home/foo/repo//file.txt#someref", - "", - "git+file:///home/foo/repo#someref", "/file.txt"}, - {"git+file:///repo", - "", - "git+file:///repo", "/"}, - {"git+file:///foo//foo", - "", - "git+file:///foo", "/foo"}, - {"git+file:///foo//foo", - "/bar", - "git+file:///foo", "/foo/bar"}, - {"git+file:///foo//bar", - // in this case the // is meaningless - "/baz//qux", - "git+file:///foo", "/bar/baz/qux"}, - {"git+https://example.com/foo", - "/bar", - "git+https://example.com/foo/bar", "/"}, - {"git+https://example.com/foo", - "//bar", - "git+https://example.com/foo", "/bar"}, - {"git+https://example.com//foo", - "/bar", - "git+https://example.com", "/foo/bar"}, - {"git+https://example.com/foo//bar", - "//baz", - "git+https://example.com/foo", "/bar/baz"}, - {"git+https://example.com/foo", - "/bar//baz", - "git+https://example.com/foo/bar", "/baz"}, - {"git+https://example.com/foo?type=t", - "/bar//baz", - "git+https://example.com/foo/bar?type=t", "/baz"}, - {"git+https://example.com/foo#master", - "/bar//baz", - "git+https://example.com/foo/bar#master", "/baz"}, - {"git+https://example.com/foo", - "/bar//baz?type=t", - "git+https://example.com/foo/bar?type=t", "/baz"}, - {"git+https://example.com/foo", - "/bar//baz#master", - "git+https://example.com/foo/bar#master", "/baz"}, - {"git+https://example.com/foo", - "//bar?type=t", - "git+https://example.com/foo?type=t", "/bar"}, - {"git+https://example.com/foo", - "//bar#master", - "git+https://example.com/foo#master", "/bar"}, - {"git+https://example.com/foo?type=t", - "//bar#master", - "git+https://example.com/foo?type=t#master", "/bar"}, - {"git+https://example.com/foo?type=t#v1", - "//bar?type=j#v2", - "git+https://example.com/foo?type=t&type=j#v2", "/bar"}, - } - - for i, d := range data { - d := d - t.Run(fmt.Sprintf("%d:(%q,%q)==(%q,%q)", i, d.url, d.args, d.repo, d.path), func(t *testing.T) { - t.Parallel() - u, _ := url.Parse(d.url) - args := []string{d.args} - if d.args == "" { - args = nil - } - repo, path, err := g.parseGitPath(u, args...) - assert.NilError(t, err) - assert.Equal(t, d.repo, repo.String()) - assert.Equal(t, d.path, path) - }) - } -} - -func TestReadGitRepo(t *testing.T) { - g := gitsource{} - fs := setupGitRepo(t) - fs, err := fs.Chroot("/repo") - assert.NilError(t, err) - - _, _, err = g.read(fs, "/bogus") - assert.ErrorContains(t, err, "can't stat /bogus") - - mtype, out, err := g.read(fs, "/foo") - assert.NilError(t, err) - assert.Equal(t, `["bar"]`, string(out)) - assert.Equal(t, jsonArrayMimetype, mtype) - - mtype, out, err = g.read(fs, "/foo/bar") - assert.NilError(t, err) - assert.Equal(t, `["hi.txt"]`, string(out)) - assert.Equal(t, jsonArrayMimetype, mtype) - - mtype, out, err = g.read(fs, "/foo/bar/hi.txt") - assert.NilError(t, err) - assert.Equal(t, `hello world`, string(out)) - assert.Equal(t, "", mtype) -} - -var testHashes = map[string]string{} - -func setupGitRepo(t *testing.T) billy.Filesystem { - fs := memfs.New() - fs.MkdirAll("/repo/.git", os.ModeDir) - repo, _ := fs.Chroot("/repo") - dot, _ := repo.Chroot("/.git") - s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault()) - - r, err := git.Init(s, repo) - assert.NilError(t, err) - - // default to main - h := plumbing.NewSymbolicReference(plumbing.HEAD, plumbing.ReferenceName("refs/heads/main")) - err = s.SetReference(h) - assert.NilError(t, err) - - // config needs to be created after setting up a "normal" fs repo - // this is possibly a bug in git-go? - c, err := r.Config() - assert.NilError(t, err) - - c.Init.DefaultBranch = "main" - - s.SetConfig(c) - assert.NilError(t, err) - - w, err := r.Worktree() - assert.NilError(t, err) - - repo.MkdirAll("/foo/bar", os.ModeDir) - f, err := repo.Create("/foo/bar/hi.txt") - assert.NilError(t, err) - _, err = f.Write([]byte("hello world")) - assert.NilError(t, err) - _, err = w.Add(f.Name()) - assert.NilError(t, err) - hash, err := w.Commit("initial commit", &git.CommitOptions{Author: &object.Signature{}}) - assert.NilError(t, err) - - ref, err := r.CreateTag("v1", hash, nil) - assert.NilError(t, err) - testHashes["v1"] = hash.String() - - branchName := plumbing.NewBranchReferenceName("mybranch") - err = w.Checkout(&git.CheckoutOptions{ - Branch: branchName, - Hash: ref.Hash(), - Create: true, - }) - assert.NilError(t, err) - - f, err = repo.Create("/secondfile.txt") - assert.NilError(t, err) - _, err = f.Write([]byte("another file\n")) - assert.NilError(t, err) - n := f.Name() - _, err = w.Add(n) - assert.NilError(t, err) - hash, err = w.Commit("second commit", &git.CommitOptions{ - Author: &object.Signature{ - Name: "John Doe", - }, - }) - ref = plumbing.NewHashReference(branchName, hash) - assert.NilError(t, err) - testHashes["mybranch"] = ref.Hash().String() - - // make the repo dirty - _, err = f.Write([]byte("dirty file")) - assert.NilError(t, err) - - // set up a bare repo - fs.MkdirAll("/bare.git", os.ModeDir) - fs.MkdirAll("/barewt", os.ModeDir) - repo, _ = fs.Chroot("/barewt") - dot, _ = fs.Chroot("/bare.git") - s = filesystem.NewStorage(dot, nil) - - r, err = git.Init(s, repo) - assert.NilError(t, err) - - w, err = r.Worktree() - assert.NilError(t, err) - - f, err = repo.Create("/hello.txt") - assert.NilError(t, err) - f.Write([]byte("hello world")) - w.Add(f.Name()) - _, err = w.Commit("initial commit", &git.CommitOptions{ - Author: &object.Signature{ - Name: "John Doe", - Email: "john@doe.org", - When: time.Now(), - }, - }) - assert.NilError(t, err) - - return fs -} - -func overrideFSLoader(fs billy.Filesystem) { - l := server.NewFilesystemLoader(fs) - client.InstallProtocol("file", server.NewClient(l)) -} - -func TestOpenFileRepo(t *testing.T) { - ctx := context.Background() - repoFS := setupGitRepo(t) - g := gitsource{} - - overrideFSLoader(repoFS) - defer overrideFSLoader(osfs.New("")) - - fs, _, err := g.clone(ctx, mustParseURL("git+file:///repo"), 0) - assert.NilError(t, err) - - f, err := fs.Open("/foo/bar/hi.txt") - assert.NilError(t, err) - b, _ := io.ReadAll(f) - assert.Equal(t, "hello world", string(b)) - - _, repo, err := g.clone(ctx, mustParseURL("git+file:///repo#main"), 0) - assert.NilError(t, err) - - ref, err := repo.Reference(plumbing.NewBranchReferenceName("main"), true) - assert.NilError(t, err) - assert.Equal(t, "refs/heads/main", ref.Name().String()) - - _, repo, err = g.clone(ctx, mustParseURL("git+file:///repo#refs/tags/v1"), 0) - assert.NilError(t, err) - - ref, err = repo.Head() - assert.NilError(t, err) - assert.Equal(t, testHashes["v1"], ref.Hash().String()) - - _, repo, err = g.clone(ctx, mustParseURL("git+file:///repo/#mybranch"), 0) - assert.NilError(t, err) - - ref, err = repo.Head() - assert.NilError(t, err) - assert.Equal(t, "refs/heads/mybranch", ref.Name().String()) - assert.Equal(t, testHashes["mybranch"], ref.Hash().String()) -} - -func TestOpenBareFileRepo(t *testing.T) { - ctx := context.Background() - repoFS := setupGitRepo(t) - g := gitsource{} - - overrideFSLoader(repoFS) - defer overrideFSLoader(osfs.New("")) - - fs, _, err := g.clone(ctx, mustParseURL("git+file:///bare.git"), 0) - assert.NilError(t, err) - - f, err := fs.Open("/hello.txt") - assert.NilError(t, err) - b, _ := io.ReadAll(f) - assert.Equal(t, "hello world", string(b)) -} - -func TestReadGit(t *testing.T) { - ctx := context.Background() - repoFS := setupGitRepo(t) - - overrideFSLoader(repoFS) - defer overrideFSLoader(osfs.New("")) - - s := &Source{ - Alias: "hi", - URL: mustParseURL("git+file:///bare.git//hello.txt"), - } - b, err := readGit(ctx, s) - assert.NilError(t, err) - assert.Equal(t, "hello world", string(b)) - - s = &Source{ - Alias: "hi", - URL: mustParseURL("git+file:///bare.git"), - } - b, err = readGit(ctx, s) - assert.NilError(t, err) - assert.Equal(t, "application/array+json", s.mediaType) - assert.Equal(t, `["hello.txt"]`, string(b)) -} - -func TestGitAuth(t *testing.T) { - g := gitsource{} - a, err := g.auth(mustParseURL("git+file:///bare.git")) - assert.NilError(t, err) - assert.Equal(t, nil, a) - - a, err = g.auth(mustParseURL("git+https://example.com/foo")) - assert.NilError(t, err) - assert.Assert(t, is.Nil(a)) - - a, err = g.auth(mustParseURL("git+https://user:swordfish@example.com/foo")) - assert.NilError(t, err) - assert.DeepEqual(t, &http.BasicAuth{Username: "user", Password: "swordfish"}, a) - - os.Setenv("GIT_HTTP_PASSWORD", "swordfish") - defer os.Unsetenv("GIT_HTTP_PASSWORD") - a, err = g.auth(mustParseURL("git+https://user@example.com/foo")) - assert.NilError(t, err) - assert.DeepEqual(t, &http.BasicAuth{Username: "user", Password: "swordfish"}, a) - os.Unsetenv("GIT_HTTP_PASSWORD") - - os.Setenv("GIT_HTTP_TOKEN", "mytoken") - defer os.Unsetenv("GIT_HTTP_TOKEN") - a, err = g.auth(mustParseURL("git+https://user@example.com/foo")) - assert.NilError(t, err) - assert.DeepEqual(t, &http.TokenAuth{Token: "mytoken"}, a) - os.Unsetenv("GIT_HTTP_TOKEN") - - if os.Getenv("SSH_AUTH_SOCK") == "" { - t.Log("no SSH_AUTH_SOCK - skipping ssh agent test") - } else { - a, err = g.auth(mustParseURL("git+ssh://git@example.com/foo")) - assert.NilError(t, err) - sa, ok := a.(*ssh.PublicKeysCallback) - assert.Equal(t, true, ok) - assert.Equal(t, "git", sa.User) - } - - key := string(testdata.PEMBytes["ed25519"]) - os.Setenv("GIT_SSH_KEY", key) - defer os.Unsetenv("GIT_SSH_KEY") - a, err = g.auth(mustParseURL("git+ssh://git@example.com/foo")) - assert.NilError(t, err) - ka, ok := a.(*ssh.PublicKeys) - assert.Equal(t, true, ok) - assert.Equal(t, "git", ka.User) - os.Unsetenv("GIT_SSH_KEY") - - key = base64.StdEncoding.EncodeToString(testdata.PEMBytes["ed25519"]) - os.Setenv("GIT_SSH_KEY", key) - defer os.Unsetenv("GIT_SSH_KEY") - a, err = g.auth(mustParseURL("git+ssh://git@example.com/foo")) - assert.NilError(t, err) - ka, ok = a.(*ssh.PublicKeys) - assert.Equal(t, true, ok) - assert.Equal(t, "git", ka.User) - os.Unsetenv("GIT_SSH_KEY") -} - -func TestRefFromURL(t *testing.T) { - t.Parallel() - g := gitsource{} - data := []struct { - url, expected string - }{ - {"git://localhost:1234/foo/bar.git//baz", ""}, - {"git+http://localhost:1234/foo/bar.git//baz", ""}, - {"git+ssh://localhost:1234/foo/bar.git//baz", ""}, - {"git+file:///foo/bar.git//baz", ""}, - {"git://localhost:1234/foo/bar.git//baz#master", "refs/heads/master"}, - {"git+http://localhost:1234/foo/bar.git//baz#mybranch", "refs/heads/mybranch"}, - {"git+ssh://localhost:1234/foo/bar.git//baz#refs/tags/foo", "refs/tags/foo"}, - {"git+file:///foo/bar.git//baz#mybranch", "refs/heads/mybranch"}, - } - - for _, d := range data { - out := g.refFromURL(mustParseURL(d.url)) - assert.Equal(t, plumbing.ReferenceName(d.expected), out) - } -} diff --git a/data/datasource_http.go b/data/datasource_http.go deleted file mode 100644 index 1061a3a19..000000000 --- a/data/datasource_http.go +++ /dev/null @@ -1,63 +0,0 @@ -package data - -import ( - "context" - "io" - "mime" - "net/http" - "net/url" - "time" - - "github.com/pkg/errors" -) - -func buildURL(base *url.URL, args ...string) (*url.URL, error) { - if len(args) == 0 { - return base, nil - } - p, err := url.Parse(args[0]) - if err != nil { - return nil, errors.Wrapf(err, "bad sub-path %s", args[0]) - } - return base.ResolveReference(p), nil -} - -func readHTTP(ctx context.Context, source *Source, args ...string) ([]byte, error) { - if source.hc == nil { - source.hc = &http.Client{Timeout: time.Second * 5} - } - u, err := buildURL(source.URL, args...) - if err != nil { - return nil, err - } - req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) - if err != nil { - return nil, err - } - req.Header = source.Header - res, err := source.hc.Do(req) - if err != nil { - return nil, err - } - body, err := io.ReadAll(res.Body) - if err != nil { - return nil, err - } - err = res.Body.Close() - if err != nil { - return nil, err - } - if res.StatusCode != 200 { - err := errors.Errorf("Unexpected HTTP status %d on GET from %s: %s", res.StatusCode, source.URL, string(body)) - return nil, err - } - ctypeHdr := res.Header.Get("Content-Type") - if ctypeHdr != "" { - mediatype, _, e := mime.ParseMediaType(ctypeHdr) - if e != nil { - return nil, e - } - source.mediaType = mediatype - } - return body, nil -} diff --git a/data/datasource_http_test.go b/data/datasource_http_test.go deleted file mode 100644 index 5d2797128..000000000 --- a/data/datasource_http_test.go +++ /dev/null @@ -1,149 +0,0 @@ -package data - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" -) - -func must(r interface{}, err error) interface{} { - if err != nil { - panic(err) - } - return r -} - -func setupHTTP(code int, mimetype string, body string) (*httptest.Server, *http.Client) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - w.Header().Set("Content-Type", mimetype) - w.WriteHeader(code) - if body == "" { - // mirror back the headers - fmt.Fprintln(w, must(marshalObj(r.Header, json.Marshal))) - } else { - fmt.Fprintln(w, body) - } - })) - - client := &http.Client{ - Transport: &http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL) - }, - }, - } - - return server, client -} - -func TestHTTPFile(t *testing.T) { - server, client := setupHTTP(200, "application/json; charset=utf-8", `{"hello": "world"}`) - defer server.Close() - - sources := make(map[string]*Source) - sources["foo"] = &Source{ - Alias: "foo", - URL: &url.URL{ - Scheme: "http", - Host: "example.com", - Path: "/foo", - }, - hc: client, - } - data := &Data{ - Ctx: context.Background(), - Sources: sources, - } - - expected := map[string]interface{}{ - "hello": "world", - } - - actual, err := data.Datasource("foo") - assert.NoError(t, err) - assert.Equal(t, must(marshalObj(expected, json.Marshal)), must(marshalObj(actual, json.Marshal))) - - actual, err = data.Datasource(server.URL) - assert.NoError(t, err) - assert.Equal(t, must(marshalObj(expected, json.Marshal)), must(marshalObj(actual, json.Marshal))) -} - -func TestHTTPFileWithHeaders(t *testing.T) { - server, client := setupHTTP(200, jsonMimetype, "") - defer server.Close() - - sources := make(map[string]*Source) - sources["foo"] = &Source{ - Alias: "foo", - URL: &url.URL{ - Scheme: "http", - Host: "example.com", - Path: "/foo", - }, - hc: client, - Header: http.Header{ - "Foo": {"bar"}, - "foo": {"baz"}, - "User-Agent": {}, - "Accept-Encoding": {"test"}, - }, - } - data := &Data{ - Ctx: context.Background(), - Sources: sources, - } - expected := http.Header{ - "Accept-Encoding": {"test"}, - "Foo": {"bar", "baz"}, - } - actual, err := data.Datasource("foo") - assert.NoError(t, err) - assert.Equal(t, must(marshalObj(expected, json.Marshal)), must(marshalObj(actual, json.Marshal))) - - expected = http.Header{ - "Accept-Encoding": {"test"}, - "Foo": {"bar", "baz"}, - "User-Agent": {"Go-http-client/1.1"}, - } - data = &Data{ - Ctx: context.Background(), - Sources: sources, - ExtraHeaders: map[string]http.Header{server.URL: expected}, - } - actual, err = data.Datasource(server.URL) - assert.NoError(t, err) - assert.Equal(t, must(marshalObj(expected, json.Marshal)), must(marshalObj(actual, json.Marshal))) -} - -func TestBuildURL(t *testing.T) { - expected := "https://example.com/index.html" - base := mustParseURL(expected) - u, err := buildURL(base) - assert.NoError(t, err) - assert.Equal(t, expected, u.String()) - - expected = "https://example.com/index.html" - base = mustParseURL("https://example.com") - u, err = buildURL(base, "index.html") - assert.NoError(t, err) - assert.Equal(t, expected, u.String()) - - expected = "https://example.com/a/b/c/index.html" - base = mustParseURL("https://example.com/a/") - u, err = buildURL(base, "b/c/index.html") - assert.NoError(t, err) - assert.Equal(t, expected, u.String()) - - expected = "https://example.com/bar/baz/index.html" - base = mustParseURL("https://example.com/foo") - u, err = buildURL(base, "bar/baz/index.html") - assert.NoError(t, err) - assert.Equal(t, expected, u.String()) -} diff --git a/data/datasource_merge.go b/data/datasource_merge.go deleted file mode 100644 index 44ed4c837..000000000 --- a/data/datasource_merge.go +++ /dev/null @@ -1,101 +0,0 @@ -package data - -import ( - "context" - "strings" - - "github.com/flanksource/gomplate/v3/coll" - "github.com/flanksource/gomplate/v3/internal/config" - - "github.com/pkg/errors" -) - -// readMerge demultiplexes a `merge:` datasource. The 'args' parameter currently -// has no meaning for this source. -// -// URI format is 'merge:|[|...]' where `` -// is a supported URI or a pre-defined alias name. -// -// Query strings and fragments are interpreted relative to the merged data, not -// the source data. To merge datasources with query strings or fragments, define -// separate sources first and specify the alias names. HTTP headers are also not -// supported directly. -func (d *Data) readMerge(ctx context.Context, source *Source, args ...string) ([]byte, error) { - opaque := source.URL.Opaque - parts := strings.Split(opaque, "|") - if len(parts) < 2 { - return nil, errors.New("need at least 2 datasources to merge") - } - data := make([]map[string]interface{}, len(parts)) - for i, part := range parts { - // supports either URIs or aliases - subSource, err := d.lookupSource(part) - if err != nil { - // maybe it's a relative filename? - u, uerr := config.ParseSourceURL(part) - if uerr != nil { - return nil, uerr - } - subSource = &Source{ - Alias: part, - URL: u, - } - } - subSource.inherit(source) - - b, err := d.readSource(ctx, subSource) - if err != nil { - return nil, errors.Wrapf(err, "Couldn't read datasource '%s'", part) - } - - mimeType, err := subSource.mimeType("") - if err != nil { - return nil, errors.Wrapf(err, "failed to read datasource %s", subSource.URL) - } - - data[i], err = parseMap(mimeType, string(b)) - if err != nil { - return nil, err - } - } - - // Merge the data together - b, err := mergeData(data) - if err != nil { - return nil, err - } - - source.mediaType = yamlMimetype - return b, nil -} - -func mergeData(data []map[string]interface{}) (out []byte, err error) { - dst := data[0] - data = data[1:] - - dst, err = coll.Merge(dst, data...) - if err != nil { - return nil, err - } - - s, err := ToYAML(dst) - if err != nil { - return nil, err - } - return []byte(s), nil -} - -func parseMap(mimeType, data string) (map[string]interface{}, error) { - datum, err := parseData(mimeType, data) - if err != nil { - return nil, err - } - var m map[string]interface{} - switch datum := datum.(type) { - case map[string]interface{}: - m = datum - default: - return nil, errors.Errorf("unexpected data type '%T' for datasource (type %s); merge: can only merge maps", datum, mimeType) - } - return m, nil -} diff --git a/data/datasource_merge_test.go b/data/datasource_merge_test.go deleted file mode 100644 index 2d81c98a1..000000000 --- a/data/datasource_merge_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package data - -import ( - "context" - "net/url" - "os" - "path/filepath" - "testing" - - "github.com/spf13/afero" - - "github.com/stretchr/testify/assert" -) - -func TestReadMerge(t *testing.T) { - ctx := context.Background() - - jsonContent := `{"hello": "world"}` - yamlContent := "hello: earth\ngoodnight: moon\n" - arrayContent := `["hello", "world"]` - - mergedContent := "goodnight: moon\nhello: world\n" - - fs := afero.NewMemMapFs() - - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/jsonfile.json") - _, _ = f.WriteString(jsonContent) - f, _ = fs.Create("/tmp/array.json") - _, _ = f.WriteString(arrayContent) - f, _ = fs.Create("/tmp/yamlfile.yaml") - _, _ = f.WriteString(yamlContent) - f, _ = fs.Create("/tmp/textfile.txt") - _, _ = f.WriteString(`plain text...`) - - wd, _ := os.Getwd() - _ = fs.Mkdir(wd, 0777) - f, _ = fs.Create(filepath.Join(wd, "jsonfile.json")) - _, _ = f.WriteString(jsonContent) - f, _ = fs.Create(filepath.Join(wd, "array.json")) - _, _ = f.WriteString(arrayContent) - f, _ = fs.Create(filepath.Join(wd, "yamlfile.yaml")) - _, _ = f.WriteString(yamlContent) - f, _ = fs.Create(filepath.Join(wd, "textfile.txt")) - _, _ = f.WriteString(`plain text...`) - - source := &Source{Alias: "foo", URL: mustParseURL("merge:file:///tmp/jsonfile.json|file:///tmp/yamlfile.yaml")} - source.fs = fs - d := &Data{ - Sources: map[string]*Source{ - "foo": source, - "bar": {Alias: "bar", URL: mustParseURL("file:///tmp/jsonfile.json")}, - "baz": {Alias: "baz", URL: mustParseURL("file:///tmp/yamlfile.yaml")}, - "text": {Alias: "text", URL: mustParseURL("file:///tmp/textfile.txt")}, - "badscheme": {Alias: "badscheme", URL: mustParseURL("bad:///scheme.json")}, - "badtype": {Alias: "badtype", URL: mustParseURL("file:///tmp/textfile.txt?type=foo/bar")}, - "array": {Alias: "array", URL: mustParseURL("file:///tmp/array.json?type=" + url.QueryEscape(jsonArrayMimetype))}, - }, - } - - actual, err := d.readMerge(ctx, source) - assert.NoError(t, err) - assert.Equal(t, mergedContent, string(actual)) - - source.URL = mustParseURL("merge:bar|baz") - actual, err = d.readMerge(ctx, source) - assert.NoError(t, err) - assert.Equal(t, mergedContent, string(actual)) - - source.URL = mustParseURL("merge:./jsonfile.json|baz") - actual, err = d.readMerge(ctx, source) - assert.NoError(t, err) - assert.Equal(t, mergedContent, string(actual)) - - source.URL = mustParseURL("merge:file:///tmp/jsonfile.json") - _, err = d.readMerge(ctx, source) - assert.Error(t, err) - - source.URL = mustParseURL("merge:bogusalias|file:///tmp/jsonfile.json") - _, err = d.readMerge(ctx, source) - assert.Error(t, err) - - source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|badscheme") - _, err = d.readMerge(ctx, source) - assert.Error(t, err) - - source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|badtype") - _, err = d.readMerge(ctx, source) - assert.Error(t, err) - - source.URL = mustParseURL("merge:file:///tmp/jsonfile.json|array") - _, err = d.readMerge(ctx, source) - assert.Error(t, err) -} - -func TestMergeData(t *testing.T) { - def := map[string]interface{}{ - "f": true, - "t": false, - "z": "def", - } - out, err := mergeData([]map[string]interface{}{def}) - assert.NoError(t, err) - assert.Equal(t, "f: true\nt: false\nz: def\n", string(out)) - - over := map[string]interface{}{ - "f": false, - "t": true, - "z": "over", - } - out, err = mergeData([]map[string]interface{}{over, def}) - assert.NoError(t, err) - assert.Equal(t, "f: false\nt: true\nz: over\n", string(out)) - - over = map[string]interface{}{ - "f": false, - "t": true, - "z": "over", - "m": map[string]interface{}{ - "a": "aaa", - }, - } - out, err = mergeData([]map[string]interface{}{over, def}) - assert.NoError(t, err) - assert.Equal(t, "f: false\nm:\n a: aaa\nt: true\nz: over\n", string(out)) - - uber := map[string]interface{}{ - "z": "über", - } - out, err = mergeData([]map[string]interface{}{uber, over, def}) - assert.NoError(t, err) - assert.Equal(t, "f: false\nm:\n a: aaa\nt: true\nz: über\n", string(out)) - - uber = map[string]interface{}{ - "m": "notamap", - "z": map[string]interface{}{ - "b": "bbb", - }, - } - out, err = mergeData([]map[string]interface{}{uber, over, def}) - assert.NoError(t, err) - assert.Equal(t, "f: false\nm: notamap\nt: true\nz:\n b: bbb\n", string(out)) - - uber = map[string]interface{}{ - "m": map[string]interface{}{ - "b": "bbb", - }, - } - out, err = mergeData([]map[string]interface{}{uber, over, def}) - assert.NoError(t, err) - assert.Equal(t, "f: false\nm:\n a: aaa\n b: bbb\nt: true\nz: over\n", string(out)) -} diff --git a/data/datasource_stdin.go b/data/datasource_stdin.go deleted file mode 100644 index 4592b2091..000000000 --- a/data/datasource_stdin.go +++ /dev/null @@ -1,33 +0,0 @@ -package data - -import ( - "context" - "io" - "os" - - "github.com/pkg/errors" -) - -func readStdin(ctx context.Context, source *Source, args ...string) ([]byte, error) { - stdin := stdinFromContext(ctx) - - b, err := io.ReadAll(stdin) - if err != nil { - return nil, errors.Wrapf(err, "Can't read %s", stdin) - } - return b, nil -} - -type stdinCtxKey struct{} - -func ContextWithStdin(ctx context.Context, r io.Reader) context.Context { - return context.WithValue(ctx, stdinCtxKey{}, r) -} - -func stdinFromContext(ctx context.Context) io.Reader { - if r, ok := ctx.Value(stdinCtxKey{}).(io.Reader); ok { - return r - } - - return os.Stdin -} diff --git a/data/datasource_stdin_test.go b/data/datasource_stdin_test.go deleted file mode 100644 index 6cd34133d..000000000 --- a/data/datasource_stdin_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package data - -import ( - "context" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestReadStdin(t *testing.T) { - ctx := context.Background() - - ctx = ContextWithStdin(ctx, strings.NewReader("foo")) - out, err := readStdin(ctx, nil) - assert.NoError(t, err) - assert.Equal(t, []byte("foo"), out) - - ctx = ContextWithStdin(ctx, errorReader{}) - _, err = readStdin(ctx, nil) - assert.Error(t, err) -} diff --git a/data/datasource_test.go b/data/datasource_test.go deleted file mode 100644 index 1aebba8f2..000000000 --- a/data/datasource_test.go +++ /dev/null @@ -1,428 +0,0 @@ -package data - -import ( - "context" - "fmt" - "net/http" - "net/url" - "runtime" - "testing" - - "github.com/flanksource/gomplate/v3/internal/config" - "github.com/spf13/afero" - - "github.com/stretchr/testify/assert" -) - -const osWindows = "windows" - -func TestNewData(t *testing.T) { - d, err := NewData(nil, nil) - assert.NoError(t, err) - assert.Len(t, d.Sources, 0) - - d, err = NewData([]string{"foo=http:///foo.json"}, nil) - assert.NoError(t, err) - assert.Equal(t, "/foo.json", d.Sources["foo"].URL.Path) - - d, err = NewData([]string{"foo=http:///foo.json"}, []string{}) - assert.NoError(t, err) - assert.Equal(t, "/foo.json", d.Sources["foo"].URL.Path) - assert.Empty(t, d.Sources["foo"].Header) - - d, err = NewData([]string{"foo=http:///foo.json"}, []string{"bar=Accept: blah"}) - assert.NoError(t, err) - assert.Equal(t, "/foo.json", d.Sources["foo"].URL.Path) - assert.Empty(t, d.Sources["foo"].Header) - - d, err = NewData([]string{"foo=http:///foo.json"}, []string{"foo=Accept: blah"}) - assert.NoError(t, err) - assert.Equal(t, "/foo.json", d.Sources["foo"].URL.Path) - assert.Equal(t, "blah", d.Sources["foo"].Header["Accept"][0]) -} - -func TestDatasource(t *testing.T) { - setup := func(ext, mime string, contents []byte) *Data { - fname := "foo." + ext - fs := afero.NewMemMapFs() - var uPath string - var f afero.File - if runtime.GOOS == osWindows { - _ = fs.Mkdir("C:\\tmp", 0777) - f, _ = fs.Create("C:\\tmp\\" + fname) - uPath = "C:/tmp/" + fname - } else { - _ = fs.Mkdir("/tmp", 0777) - f, _ = fs.Create("/tmp/" + fname) - uPath = "/tmp/" + fname - } - _, _ = f.Write(contents) - - sources := map[string]*Source{ - "foo": { - Alias: "foo", - URL: &url.URL{Scheme: "file", Path: uPath}, - mediaType: mime, - fs: fs, - }, - } - return &Data{Sources: sources} - } - test := func(ext, mime string, contents []byte, expected interface{}) { - data := setup(ext, mime, contents) - - actual, err := data.Datasource("foo") - assert.NoError(t, err) - assert.Equal(t, expected, actual) - } - - testObj := func(ext, mime string, contents []byte) { - test(ext, mime, contents, - map[string]interface{}{ - "hello": map[string]interface{}{"cruel": "world"}, - }) - } - - testObj("json", jsonMimetype, []byte(`{"hello":{"cruel":"world"}}`)) - testObj("yml", yamlMimetype, []byte("hello:\n cruel: world\n")) - test("json", jsonMimetype, []byte(`[1, "two", true]`), - []interface{}{1, "two", true}) - test("yaml", yamlMimetype, []byte("---\n- 1\n- two\n- true\n"), - []interface{}{1, "two", true}) - - d := setup("", textMimetype, nil) - actual, err := d.Datasource("foo") - assert.NoError(t, err) - assert.Equal(t, "", actual) - - _, err = d.Datasource("bar") - assert.Error(t, err) -} - -func TestDatasourceReachable(t *testing.T) { - fname := "foo.json" - fs := afero.NewMemMapFs() - var uPath string - var f afero.File - if runtime.GOOS == osWindows { - _ = fs.Mkdir("C:\\tmp", 0777) - f, _ = fs.Create("C:\\tmp\\" + fname) - uPath = "C:/tmp/" + fname - } else { - _ = fs.Mkdir("/tmp", 0777) - f, _ = fs.Create("/tmp/" + fname) - uPath = "/tmp/" + fname - } - _, _ = f.Write([]byte("{}")) - - sources := map[string]*Source{ - "foo": { - Alias: "foo", - URL: &url.URL{Scheme: "file", Path: uPath}, - mediaType: jsonMimetype, - fs: fs, - }, - "bar": { - Alias: "bar", - URL: &url.URL{Scheme: "file", Path: "/bogus"}, - fs: fs, - }, - } - data := &Data{Sources: sources} - - assert.True(t, data.DatasourceReachable("foo")) - assert.False(t, data.DatasourceReachable("bar")) -} - -func TestDatasourceExists(t *testing.T) { - sources := map[string]*Source{ - "foo": {Alias: "foo"}, - } - data := &Data{Sources: sources} - assert.True(t, data.DatasourceExists("foo")) - assert.False(t, data.DatasourceExists("bar")) -} - -func TestInclude(t *testing.T) { - ext := "txt" - contents := "hello world" - fname := "foo." + ext - fs := afero.NewMemMapFs() - - var uPath string - var f afero.File - if runtime.GOOS == osWindows { - _ = fs.Mkdir("C:\\tmp", 0777) - f, _ = fs.Create("C:\\tmp\\" + fname) - uPath = "C:/tmp/" + fname - } else { - _ = fs.Mkdir("/tmp", 0777) - f, _ = fs.Create("/tmp/" + fname) - uPath = "/tmp/" + fname - } - _, _ = f.Write([]byte(contents)) - - sources := map[string]*Source{ - "foo": { - Alias: "foo", - URL: &url.URL{Scheme: "file", Path: uPath}, - mediaType: textMimetype, - fs: fs, - }, - } - data := &Data{ - Sources: sources, - } - actual, err := data.Include("foo") - assert.NoError(t, err) - assert.Equal(t, contents, actual) -} - -type errorReader struct{} - -func (e errorReader) Read(p []byte) (n int, err error) { - return 0, fmt.Errorf("error") -} - -// nolint: megacheck -func TestDefineDatasource(t *testing.T) { - d := &Data{} - _, err := d.DefineDatasource("", "foo.json") - assert.Error(t, err) - - d = &Data{} - _, err = d.DefineDatasource("", "../foo.json") - assert.Error(t, err) - - d = &Data{} - _, err = d.DefineDatasource("", "ftp://example.com/foo.yml") - assert.Error(t, err) - - d = &Data{} - _, err = d.DefineDatasource("data", "foo.json") - s := d.Sources["data"] - assert.NoError(t, err) - assert.Equal(t, "data", s.Alias) - assert.Equal(t, "file", s.URL.Scheme) - assert.True(t, s.URL.IsAbs()) - - d = &Data{} - _, err = d.DefineDatasource("data", "/otherdir/foo.json") - s = d.Sources["data"] - assert.NoError(t, err) - assert.Equal(t, "data", s.Alias) - assert.Equal(t, "file", s.URL.Scheme) - assert.True(t, s.URL.IsAbs()) - assert.Equal(t, "/otherdir/foo.json", s.URL.Path) - - d = &Data{} - _, err = d.DefineDatasource("data", "sftp://example.com/blahblah/foo.json") - s = d.Sources["data"] - assert.NoError(t, err) - assert.Equal(t, "data", s.Alias) - assert.Equal(t, "sftp", s.URL.Scheme) - assert.True(t, s.URL.IsAbs()) - assert.Equal(t, "/blahblah/foo.json", s.URL.Path) - - d = &Data{ - Sources: map[string]*Source{ - "data": {Alias: "data"}, - }, - } - _, err = d.DefineDatasource("data", "/otherdir/foo.json") - s = d.Sources["data"] - assert.NoError(t, err) - assert.Equal(t, "data", s.Alias) - assert.Nil(t, s.URL) - - d = &Data{} - _, err = d.DefineDatasource("data", "/otherdir/foo?type=application/x-env") - s = d.Sources["data"] - assert.NoError(t, err) - assert.Equal(t, "data", s.Alias) - m, err := s.mimeType("") - assert.NoError(t, err) - assert.Equal(t, "application/x-env", m) -} - -func TestMimeType(t *testing.T) { - s := &Source{URL: mustParseURL("http://example.com/list?type=a/b/c")} - _, err := s.mimeType("") - assert.Error(t, err) - - data := []struct { - url string - mediaType string - expected string - }{ - {"http://example.com/foo.json", - "", - jsonMimetype}, - {"http://example.com/foo.json", - "text/foo", - "text/foo"}, - {"http://example.com/foo.json?type=application/yaml", - "text/foo", - "application/yaml"}, - {"http://example.com/list?type=application/array%2Bjson", - "text/foo", - "application/array+json"}, - {"http://example.com/list?type=application/array+json", - "", - "application/array+json"}, - {"http://example.com/unknown", - "", - "text/plain"}, - } - - for i, d := range data { - d := d - t.Run(fmt.Sprintf("%d:%q,%q==%q", i, d.url, d.mediaType, d.expected), func(t *testing.T) { - s := &Source{URL: mustParseURL(d.url), mediaType: d.mediaType} - mt, err := s.mimeType("") - assert.NoError(t, err) - assert.Equal(t, d.expected, mt) - }) - } -} - -func TestMimeTypeWithArg(t *testing.T) { - s := &Source{URL: mustParseURL("http://example.com")} - _, err := s.mimeType("h\nttp://foo") - assert.Error(t, err) - - data := []struct { - url string - mediaType string - arg string - expected string - }{ - {"http://example.com/unknown", - "", - "/foo.json", - "application/json"}, - {"http://example.com/unknown", - "", - "foo.json", - "application/json"}, - {"http://example.com/", - "text/foo", - "/foo.json", - "text/foo"}, - {"git+https://example.com/myrepo", - "", - "//foo.yaml", - "application/yaml"}, - {"http://example.com/foo.json", - "", - "/foo.yaml", - "application/yaml"}, - {"http://example.com/foo.json?type=application/array+yaml", - "", - "/foo.yaml", - "application/array+yaml"}, - {"http://example.com/foo.json?type=application/array+yaml", - "", - "/foo.yaml?type=application/yaml", - "application/yaml"}, - {"http://example.com/foo.json?type=application/array+yaml", - "text/plain", - "/foo.yaml?type=application/yaml", - "application/yaml"}, - } - - for i, d := range data { - d := d - t.Run(fmt.Sprintf("%d:%q,%q,%q==%q", i, d.url, d.mediaType, d.arg, d.expected), func(t *testing.T) { - s := &Source{URL: mustParseURL(d.url), mediaType: d.mediaType} - mt, err := s.mimeType(d.arg) - assert.NoError(t, err) - assert.Equal(t, d.expected, mt) - }) - } -} - -func TestFromConfig(t *testing.T) { - ctx := context.Background() - - cfg := &config.Config{} - actual := FromConfig(ctx, cfg) - expected := &Data{ - Ctx: actual.Ctx, - Sources: map[string]*Source{}, - } - assert.EqualValues(t, expected, actual) - - cfg = &config.Config{ - DataSources: map[string]config.DataSource{ - "foo": { - URL: mustParseURL("http://example.com"), - }, - }, - } - actual = FromConfig(ctx, cfg) - expected = &Data{ - Ctx: actual.Ctx, - Sources: map[string]*Source{ - "foo": { - Alias: "foo", - URL: mustParseURL("http://example.com"), - }, - }, - } - assert.EqualValues(t, expected, actual) - - cfg = &config.Config{ - DataSources: map[string]config.DataSource{ - "foo": { - URL: mustParseURL("http://foo.com"), - }, - }, - Context: map[string]config.DataSource{ - "bar": { - URL: mustParseURL("http://bar.com"), - Header: http.Header{ - "Foo": []string{"bar"}, - }, - }, - }, - ExtraHeaders: map[string]http.Header{ - "baz": { - "Foo": []string{"bar"}, - }, - }, - } - actual = FromConfig(ctx, cfg) - expected = &Data{ - Ctx: actual.Ctx, - Sources: map[string]*Source{ - "foo": { - Alias: "foo", - URL: mustParseURL("http://foo.com"), - }, - "bar": { - Alias: "bar", - URL: mustParseURL("http://bar.com"), - Header: http.Header{ - "Foo": []string{"bar"}, - }, - }, - }, - ExtraHeaders: map[string]http.Header{ - "baz": { - "Foo": []string{"bar"}, - }, - }, - } - assert.EqualValues(t, expected, actual) -} - -func TestListDatasources(t *testing.T) { - sources := map[string]*Source{ - "foo": {Alias: "foo"}, - "bar": {Alias: "bar"}, - } - data := &Data{Sources: sources} - - assert.Equal(t, []string{"bar", "foo"}, data.ListDatasources()) -} diff --git a/data/mimetypes.go b/data/mimetypes.go deleted file mode 100644 index bdc12ad4c..000000000 --- a/data/mimetypes.go +++ /dev/null @@ -1,25 +0,0 @@ -package data - -const ( - textMimetype = "text/plain" - csvMimetype = "text/csv" - jsonMimetype = "application/json" - jsonArrayMimetype = "application/array+json" - tomlMimetype = "application/toml" - yamlMimetype = "application/yaml" - envMimetype = "application/x-env" -) - -// mimeTypeAliases defines a mapping for non-canonical mime types that are -// sometimes seen in the wild -var mimeTypeAliases = map[string]string{ - "application/x-yaml": yamlMimetype, - "application/text": textMimetype, -} - -func mimeAlias(m string) string { - if a, ok := mimeTypeAliases[m]; ok { - return a - } - return m -} diff --git a/data/mimetypes_test.go b/data/mimetypes_test.go deleted file mode 100644 index 0dd1ab052..000000000 --- a/data/mimetypes_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package data - -import ( - "testing" - - "gotest.tools/v3/assert" -) - -func TestMimeAlias(t *testing.T) { - t.Parallel() - data := []struct { - in, out string - }{ - {csvMimetype, csvMimetype}, - {yamlMimetype, yamlMimetype}, - {"application/x-yaml", yamlMimetype}, - } - - for _, d := range data { - assert.Equal(t, d.out, mimeAlias(d.in)) - } -} diff --git a/env/env.go b/env/env.go deleted file mode 100644 index b8bbbfa52..000000000 --- a/env/env.go +++ /dev/null @@ -1,70 +0,0 @@ -// Package env contains functions that retrieve data from the environment -package env - -import ( - "io" - "os" - "strings" - - "github.com/spf13/afero" -) - -// Getenv - retrieves the value of the environment variable named by the key. -// If the variable is unset, but the same variable ending in `_FILE` is set, the -// referenced file will be read into the value. -// Otherwise the provided default (or an emptry string) is returned. -func Getenv(key string, def ...string) string { - return getenvVFS(afero.NewOsFs(), key, def...) -} - -// ExpandEnv - like os.ExpandEnv, except supports `_FILE` vars as well -func ExpandEnv(s string) string { - return expandEnvVFS(afero.NewOsFs(), s) -} - -// expandEnvVFS - -func expandEnvVFS(fs afero.Fs, s string) string { - return os.Expand(s, func(s string) string { - return getenvVFS(fs, s) - }) -} - -// getenvVFS - a convenience function intended for internal use only! -func getenvVFS(fs afero.Fs, key string, def ...string) string { - val := getenvFile(fs, key) - if val == "" && len(def) > 0 { - return def[0] - } - - return val -} - -func getenvFile(fs afero.Fs, key string) string { - val := os.Getenv(key) - if val != "" { - return val - } - - p := os.Getenv(key + "_FILE") - if p != "" { - val, err := readFile(fs, p) - if err != nil { - return "" - } - return strings.TrimSpace(val) - } - - return "" -} - -func readFile(fs afero.Fs, p string) (string, error) { - f, err := fs.OpenFile(p, os.O_RDONLY, 0) - if err != nil { - return "", err - } - b, err := io.ReadAll(f) - if err != nil { - return "", err - } - return string(b), nil -} diff --git a/env/env_test.go b/env/env_test.go deleted file mode 100644 index 122c23803..000000000 --- a/env/env_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package env - -import ( - "errors" - "os" - "testing" - - "github.com/spf13/afero" - - "github.com/stretchr/testify/assert" -) - -func TestGetenv(t *testing.T) { - assert.Empty(t, Getenv("FOOBARBAZ")) - assert.Equal(t, os.Getenv("USER"), Getenv("USER")) - assert.Equal(t, "default value", Getenv("BLAHBLAHBLAH", "default value")) -} - -func TestGetenvFile(t *testing.T) { - fs := afero.NewMemMapFs() - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write([]byte("foo")) - - defer os.Unsetenv("FOO_FILE") - os.Setenv("FOO_FILE", "/tmp/foo") - assert.Equal(t, "foo", getenvVFS(fs, "FOO", "bar")) - - os.Setenv("FOO_FILE", "/tmp/missing") - assert.Equal(t, "bar", getenvVFS(fs, "FOO", "bar")) - - _, _ = fs.Create("/tmp/unreadable") - fs = writeOnly(fs) - os.Setenv("FOO_FILE", "/tmp/unreadable") - assert.Equal(t, "bar", getenvVFS(fs, "FOO", "bar")) -} - -func TestExpandEnv(t *testing.T) { - assert.Empty(t, ExpandEnv("${FOOBARBAZ}")) - assert.Equal(t, os.Getenv("USER"), ExpandEnv("$USER")) - assert.Equal(t, "something", ExpandEnv("something$BLAHBLAHBLAH")) - assert.Equal(t, os.Getenv("USER")+": "+os.Getenv("HOME"), - ExpandEnv("$USER: ${HOME}")) -} - -func TestExpandEnvFile(t *testing.T) { - fs := afero.NewMemMapFs() - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write([]byte("foo")) - - defer os.Unsetenv("FOO_FILE") - os.Setenv("FOO_FILE", "/tmp/foo") - assert.Equal(t, "foo is foo", expandEnvVFS(fs, "foo is $FOO")) - - os.Setenv("FOO_FILE", "/tmp/missing") - assert.Equal(t, "empty", expandEnvVFS(fs, "${FOO}empty")) - - _, _ = fs.Create("/tmp/unreadable") - fs = writeOnly(fs) - os.Setenv("FOO_FILE", "/tmp/unreadable") - assert.Equal(t, "", expandEnvVFS(fs, "${FOO}")) -} - -// Maybe extract this into a separate package sometime... -// writeOnly - represents a filesystem that's writeable, but read operations fail -func writeOnly(fs afero.Fs) afero.Fs { - return &woFS{fs} -} - -type woFS struct { - afero.Fs -} - -func (fs woFS) Remove(name string) error { - return fs.Fs.Remove(name) -} - -func (fs woFS) Rename(oldpath, newpath string) error { - return fs.Fs.Rename(oldpath, newpath) -} - -func (fs woFS) Mkdir(name string, perm os.FileMode) error { - return fs.Fs.Mkdir(name, perm) -} - -func (fs woFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { - f, err := fs.Fs.OpenFile(name, flag, perm) - if err != nil { - return writeOnlyFile(f), err - } - return writeOnlyFile(f), nil -} - -func (fs woFS) ReadDir(path string) ([]os.FileInfo, error) { - return nil, ErrWriteOnly -} - -func (fs woFS) Stat(name string) (os.FileInfo, error) { - return nil, ErrWriteOnly -} - -func writeOnlyFile(f afero.File) afero.File { - return &woFile{f} -} - -type woFile struct { - afero.File -} - -// Write is disabled and returns ErrWriteOnly -func (f woFile) Write(p []byte) (n int, err error) { - return f.File.Write(p) -} - -// Read is disabled and returns ErrWriteOnly -func (f woFile) Read([]byte) (n int, err error) { - return 0, ErrWriteOnly -} - -var ErrWriteOnly = errors.New("filesystem is write-only") diff --git a/file/file.go b/file/file.go deleted file mode 100644 index 8778eee14..000000000 --- a/file/file.go +++ /dev/null @@ -1,105 +0,0 @@ -// Package file contains functions for working with files and directories on the local filesystem -package file - -import ( - "io" - "os" - "path/filepath" - "strings" - - "github.com/flanksource/gomplate/v3/internal/iohelpers" - "github.com/pkg/errors" - - "github.com/spf13/afero" -) - -// for overriding in tests -var fs = afero.NewOsFs() - -// Read the contents of the referenced file, as a string. -func Read(filename string) (string, error) { - inFile, err := fs.OpenFile(filename, os.O_RDONLY, 0) - if err != nil { - return "", errors.Wrapf(err, "failed to open %s", filename) - } - // nolint: errcheck - defer inFile.Close() - bytes, err := io.ReadAll(inFile) - if err != nil { - err = errors.Wrapf(err, "read failed for %s", filename) - return "", err - } - return string(bytes), nil -} - -// ReadDir gets a directory listing. -func ReadDir(path string) ([]string, error) { - f, err := fs.Open(path) - if err != nil { - return nil, err - } - i, err := f.Stat() - if err != nil { - return nil, err - } - if i.IsDir() { - return f.Readdirnames(0) - } - return nil, errors.New("file is not a directory") -} - -// Write the given content to the file, truncating any existing file, and -// creating the directory structure leading up to it if necessary. -func Write(filename string, content []byte) error { - err := assertPathInWD(filename) - if err != nil { - return errors.Wrapf(err, "failed to open %s", filename) - } - - fi, err := os.Stat(filename) - if err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "failed to stat %s", filename) - } - mode := iohelpers.NormalizeFileMode(0o644) - if fi != nil { - mode = fi.Mode() - } - err = fs.MkdirAll(filepath.Dir(filename), 0o755) - if err != nil { - return errors.Wrapf(err, "failed to make dirs for %s", filename) - } - inFile, err := fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) - if err != nil { - return errors.Wrapf(err, "failed to open %s", filename) - } - - defer inFile.Close() - - n, err := inFile.Write(content) - if err != nil { - return errors.Wrapf(err, "failed to write %s", filename) - } - if n != len(content) { - return errors.Wrapf(err, "short write on %s (%d bytes)", filename, n) - } - return nil -} - -func assertPathInWD(filename string) error { - wd, err := os.Getwd() - if err != nil { - return err - } - f, err := filepath.Abs(filename) - if err != nil { - return err - } - r, err := filepath.Rel(wd, f) - if err != nil { - return err - } - if strings.HasPrefix(r, "..") { - return errors.Errorf("path %s not contained by working directory %s (rel: %s)", filename, wd, r) - } - return nil -} diff --git a/file/file_test.go b/file/file_test.go deleted file mode 100644 index 215acbfe6..000000000 --- a/file/file_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package file - -import ( - "os" - "path/filepath" - "testing" - - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" - tfs "gotest.tools/v3/fs" -) - -func TestRead(t *testing.T) { - origfs := fs - defer func() { fs = origfs }() - fs = afero.NewMemMapFs() - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write([]byte("foo")) - - actual, err := Read("/tmp/foo") - assert.NoError(t, err) - assert.Equal(t, "foo", actual) - - _, err = Read("/tmp/bar") - assert.Error(t, err) -} - -func TestReadDir(t *testing.T) { - origfs := fs - defer func() { fs = origfs }() - fs = afero.NewMemMapFs() - fs.Mkdir("/tmp", 0777) - fs.Create("/tmp/foo") - fs.Create("/tmp/bar") - fs.Create("/tmp/baz") - fs.Mkdir("/tmp/qux", 0777) - fs.Create("/tmp/qux/quux") - - actual, err := ReadDir("/tmp") - assert.NoError(t, err) - assert.Equal(t, []string{"bar", "baz", "foo", "qux"}, actual) - - _, err = ReadDir("/tmp/foo") - assert.Error(t, err) -} - -func TestWrite(t *testing.T) { - oldwd, _ := os.Getwd() - defer os.Chdir(oldwd) - - rootDir := tfs.NewDir(t, "gomplate-test") - defer rootDir.Remove() - - newwd := rootDir.Join("the", "path", "we", "want") - badwd := rootDir.Join("some", "other", "dir") - fs.MkdirAll(newwd, 0755) - fs.MkdirAll(badwd, 0755) - newwd, _ = filepath.EvalSymlinks(newwd) - badwd, _ = filepath.EvalSymlinks(badwd) - - err := os.Chdir(newwd) - assert.NoError(t, err) - - err = Write("/foo", []byte("Hello world")) - assert.Error(t, err) - - rel, err := filepath.Rel(newwd, badwd) - assert.NoError(t, err) - err = Write(rel, []byte("Hello world")) - assert.Error(t, err) - - foopath := filepath.Join(newwd, "foo") - err = Write(foopath, []byte("Hello world")) - assert.NoError(t, err) - - out, err := os.ReadFile(foopath) - assert.NoError(t, err) - assert.Equal(t, "Hello world", string(out)) - - err = Write(foopath, []byte("truncate")) - assert.NoError(t, err) - - out, err = os.ReadFile(foopath) - assert.NoError(t, err) - assert.Equal(t, "truncate", string(out)) - - foopath = filepath.Join(newwd, "nonexistant", "subdir", "foo") - err = Write(foopath, []byte("Hello subdirranean world!")) - assert.NoError(t, err) - - out, err = os.ReadFile(foopath) - assert.NoError(t, err) - assert.Equal(t, "Hello subdirranean world!", string(out)) -} - -func TestAssertPathInWD(t *testing.T) { - oldwd, _ := os.Getwd() - defer os.Chdir(oldwd) - - err := assertPathInWD("/tmp") - assert.Error(t, err) - - err = assertPathInWD(filepath.Join(oldwd, "subpath")) - assert.NoError(t, err) - - err = assertPathInWD("subpath") - assert.NoError(t, err) - - err = assertPathInWD("./subpath") - assert.NoError(t, err) - - err = assertPathInWD(filepath.Join("..", "bogus")) - assert.Error(t, err) - - err = assertPathInWD(filepath.Join("..", "..", "bogus")) - assert.Error(t, err) - - base := filepath.Base(oldwd) - err = assertPathInWD(filepath.Join("..", base)) - assert.NoError(t, err) -} diff --git a/func_test.go b/func_test.go deleted file mode 100644 index 6356528d4..000000000 --- a/func_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package gomplate - -import ( - "context" - "testing" -) - -func TestSprigFuncs(t *testing.T) { - funcs := CreateFuncs(context.Background(), nil) - if _, ok := funcs["semver"]; !ok { - t.Errorf("semver function not found") - } -} diff --git a/funcs.go b/funcs.go index 2be542eb2..31a85733c 100644 --- a/funcs.go +++ b/funcs.go @@ -4,41 +4,27 @@ import ( "context" "text/template" - "github.com/flanksource/gomplate/v3/data" "github.com/flanksource/gomplate/v3/funcs" //nolint:staticcheck - "github.com/flanksource/gomplate/v3/internal/config" ) -// Funcs - -// Deprecated: use CreateFuncs instead -func Funcs(d *data.Data) template.FuncMap { - return CreateFuncs(context.Background(), d) -} - // CreateFuncs - function mappings are created here -func CreateFuncs(ctx context.Context, d *data.Data) template.FuncMap { +func CreateFuncs(ctx context.Context) template.FuncMap { f := template.FuncMap{} - addToMap(f, funcs.CreateDataFuncs(ctx, d)) - addToMap(f, funcs.CreateAWSFuncs(ctx)) - addToMap(f, funcs.CreateGCPFuncs(ctx)) + addToMap(f, funcs.CreateDataFuncs(ctx)) addToMap(f, funcs.CreateBase64Funcs(ctx)) - addToMap(f, funcs.CreateNetFuncs(ctx)) addToMap(f, funcs.CreateReFuncs(ctx)) addToMap(f, funcs.CreateStringFuncs(ctx)) - addToMap(f, funcs.CreateEnvFuncs(ctx)) addToMap(f, funcs.CreateConvFuncs(ctx)) addToMap(f, funcs.CreateTimeFuncs(ctx)) addToMap(f, funcs.CreateMathFuncs(ctx)) addToMap(f, funcs.CreateCryptoFuncs(ctx)) - addToMap(f, funcs.CreateFileFuncs(ctx)) + addToMap(f, funcs.CreateKubernetesFuncs(ctx)) addToMap(f, funcs.CreateFilePathFuncs(ctx)) addToMap(f, funcs.CreatePathFuncs(ctx)) - addToMap(f, funcs.CreateSockaddrFuncs(ctx)) addToMap(f, funcs.CreateTestFuncs(ctx)) addToMap(f, funcs.CreateCollFuncs(ctx)) addToMap(f, funcs.CreateUUIDFuncs(ctx)) addToMap(f, funcs.CreateRandomFuncs(ctx)) - funcs.AddSprigFuncs(ctx, f) return f } @@ -48,12 +34,3 @@ func addToMap(dst, src map[string]interface{}) { dst[k] = v } } - -// SetExperimental enables experimental functions and features in the given -// context. This must be done before creating functions. The set of experimental -// features enabled by this is not fixed and will change over time. -func SetExperimental(ctx context.Context) context.Context { - // This just calls the internal function. This is here to make experimental - // functions available to external packages. - return config.SetExperimental(ctx) -} diff --git a/funcs/aws.go b/funcs/aws.go deleted file mode 100644 index f6a1128b6..000000000 --- a/funcs/aws.go +++ /dev/null @@ -1,150 +0,0 @@ -package funcs - -import ( - "context" - "sync" - - "github.com/flanksource/gomplate/v3/aws" - "github.com/flanksource/gomplate/v3/conv" -) - -// AWSNS - the aws namespace -// Deprecated: don't use -// -//nolint:golint -func AWSNS() *Funcs { - return &Funcs{} -} - -// AWSFuncs - -// Deprecated: use CreateAWSFuncs instead -func AWSFuncs(f map[string]interface{}) { - f2 := CreateAWSFuncs(context.Background()) - for k, v := range f2 { - f[k] = v - } -} - -// CreateAWSFuncs - -func CreateAWSFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} - - ns := &Funcs{ - ctx: ctx, - awsopts: aws.GetClientOptions(), - } - - f["aws"] = func() interface{} { return ns } - - // global aliases - for backwards compatibility - f["ec2meta"] = ns.EC2Meta - f["ec2dynamic"] = ns.EC2Dynamic - f["ec2tag"] = ns.EC2Tag - f["ec2tags"] = ns.EC2Tags - f["ec2region"] = ns.EC2Region - return f -} - -// Funcs - -type Funcs struct { - ctx context.Context - - meta *aws.Ec2Meta - info *aws.Ec2Info - kms *aws.KMS - sts *aws.STS - metaInit sync.Once - infoInit sync.Once - kmsInit sync.Once - stsInit sync.Once - awsopts aws.ClientOptions -} - -// EC2Region - -func (a *Funcs) EC2Region(def ...string) (string, error) { - a.metaInit.Do(a.initMeta) - return a.meta.Region(def...) -} - -// EC2Meta - -func (a *Funcs) EC2Meta(key string, def ...string) (string, error) { - a.metaInit.Do(a.initMeta) - return a.meta.Meta(key, def...) -} - -// EC2Dynamic - -func (a *Funcs) EC2Dynamic(key string, def ...string) (string, error) { - a.metaInit.Do(a.initMeta) - return a.meta.Dynamic(key, def...) -} - -// EC2Tag - -func (a *Funcs) EC2Tag(tag string, def ...string) (string, error) { - a.infoInit.Do(a.initInfo) - return a.info.Tag(tag, def...) -} - -// EC2Tag - -func (a *Funcs) EC2Tags() (map[string]string, error) { - a.infoInit.Do(a.initInfo) - return a.info.Tags() -} - -// KMSEncrypt - -func (a *Funcs) KMSEncrypt(keyID, plaintext interface{}) (string, error) { - a.kmsInit.Do(a.initKMS) - return a.kms.Encrypt(conv.ToString(keyID), conv.ToString(plaintext)) -} - -// KMSDecrypt - -func (a *Funcs) KMSDecrypt(ciphertext interface{}) (string, error) { - a.kmsInit.Do(a.initKMS) - return a.kms.Decrypt(conv.ToString(ciphertext)) -} - -// UserID - Gets the unique identifier of the calling entity. The exact value -// depends on the type of entity making the call. The values returned are those -// listed in the aws:userid column in the Principal table -// (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#principaltable) -// found on the Policy Variables reference page in the IAM User Guide. -func (a *Funcs) UserID() (string, error) { - a.stsInit.Do(a.initSTS) - return a.sts.UserID() -} - -// Account - Gets the AWS account ID number of the account that owns or -// contains the calling entity. -func (a *Funcs) Account() (string, error) { - a.stsInit.Do(a.initSTS) - return a.sts.Account() -} - -// ARN - Gets the AWS ARN associated with the calling entity -func (a *Funcs) ARN() (string, error) { - a.stsInit.Do(a.initSTS) - return a.sts.Arn() -} - -func (a *Funcs) initMeta() { - if a.meta == nil { - a.meta = aws.NewEc2Meta(a.awsopts) - } -} - -func (a *Funcs) initInfo() { - if a.info == nil { - a.info = aws.NewEc2Info(a.awsopts) - } -} - -func (a *Funcs) initKMS() { - if a.kms == nil { - a.kms = aws.NewKMS(a.awsopts) - } -} - -func (a *Funcs) initSTS() { - if a.sts == nil { - a.sts = aws.NewSTS(a.awsopts) - } -} diff --git a/funcs/aws_test.go b/funcs/aws_test.go deleted file mode 100644 index 520d6c58a..000000000 --- a/funcs/aws_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package funcs - -import ( - "context" - "strconv" - "testing" - - "github.com/flanksource/gomplate/v3/aws" - "github.com/stretchr/testify/assert" -) - -func TestCreateAWSFuncs(t *testing.T) { - t.Parallel() - - for i := 0; i < 10; i++ { - // Run this a bunch to catch race conditions - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - fmap := CreateAWSFuncs(ctx) - actual := fmap["aws"].(func() interface{}) - - assert.Same(t, ctx, actual().(*Funcs).ctx) - }) - } -} - -func TestAWSFuncs(t *testing.T) { - t.Parallel() - - m := aws.NewDummyEc2Meta() - i := aws.NewDummyEc2Info(m) - af := &Funcs{meta: m, info: i} - assert.Equal(t, "unknown", must(af.EC2Region())) - assert.Equal(t, "", must(af.EC2Meta("foo"))) - assert.Equal(t, "", must(af.EC2Tag("foo"))) - assert.Equal(t, "unknown", must(af.EC2Region())) -} - -func must(r interface{}, err error) interface{} { - if err != nil { - panic(err) - } - return r -} diff --git a/funcs/base64_gen.go b/funcs/base64_gen.go new file mode 100644 index 000000000..08d76711f --- /dev/null +++ b/funcs/base64_gen.go @@ -0,0 +1,67 @@ +// Code generated by gencel. DO NOT EDIT. + +package funcs + +import "github.com/google/cel-go/cel" +import "github.com/google/cel-go/common/types" +import "github.com/google/cel-go/common/types/ref" + +var base64EncodeGen = cel.Function("base64.Encode", + cel.Overload("base64.Encode_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Base64Funcs + + a0, a1 := x.Encode(args[0]) + return types.DefaultTypeAdapter.NativeToValue([]any{ + a0, a1, + }) + + }), + ), +) + +var base64DecodeGen = cel.Function("base64.Decode", + cel.Overload("base64.Decode_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Base64Funcs + + a0, a1 := x.Decode(args[0]) + return types.DefaultTypeAdapter.NativeToValue([]any{ + a0, a1, + }) + + }), + ), +) + +var base64DecodeBytesGen = cel.Function("base64.DecodeBytes", + cel.Overload("base64.DecodeBytes_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Base64Funcs + + a0, a1 := x.DecodeBytes(args[0]) + return types.DefaultTypeAdapter.NativeToValue([]any{ + a0, a1, + }) + + }), + ), +) diff --git a/funcs/cel_gen_exports.go b/funcs/cel_gen_exports.go index 7bf5f9df3..abfd7a28d 100644 --- a/funcs/cel_gen_exports.go +++ b/funcs/cel_gen_exports.go @@ -22,6 +22,9 @@ func transferSlice[K any](arg ref.Val) []K { } var CelEnvOption = []cel.EnvOption{ + base64EncodeGen, + base64DecodeGen, + base64DecodeBytesGen, collSliceGen, collHasGen, collDictGen, @@ -58,8 +61,6 @@ var CelEnvOption = []cel.EnvOption{ convToStringsGen, convDefaultGen, convDictGen, - cryptoPBKDF2Gen, - cryptoWPAPSKGen, cryptoSHA1Gen, cryptoSHA224Gen, cryptoSHA256Gen, @@ -74,17 +75,6 @@ var CelEnvOption = []cel.EnvOption{ cryptoSHA512BytesGen, cryptoSHA512_224BytesGen, cryptoSHA512_256BytesGen, - cryptoBcryptGen, - cryptoRSAEncryptGen, - cryptoRSADecryptGen, - cryptoRSADecryptBytesGen, - cryptoRSAGenerateKeyGen, - cryptoRSADerivePublicKeyGen, - cryptoECDSAGenerateKeyGen, - cryptoECDSADerivePublicKeyGen, - cryptoEncryptAESGen, - cryptoDecryptAESGen, - cryptoDecryptAESBytesGen, dataJSONGen, dataJSONArrayGen, dataYAMLGen, @@ -98,13 +88,6 @@ var CelEnvOption = []cel.EnvOption{ dataToJSONPrettyGen, dataToYAMLGen, dataToTOMLGen, - fileReadGen, - fileStatGen, - fileExistsGen, - fileIsDirGen, - fileReadDirGen, - fileWalkGen, - fileWriteGen, filepathBaseGen, filepathCleanGen, filepathDirGen, @@ -117,6 +100,9 @@ var CelEnvOption = []cel.EnvOption{ filepathSplitGen, filepathToSlashGen, filepathVolumeNameGen, + k8sIsHealthyGen, + k8sGetStatusGen, + k8sGetHealthGen, mathIsIntGen, mathIsFloatGen, mathcontainsFloatGen, @@ -156,25 +142,10 @@ var CelEnvOption = []cel.EnvOption{ regexpReplaceGen, regexpReplaceLiteralGen, regexpSplitGen, - sockaddrGetAllInterfacesGen, - sockaddrGetDefaultInterfacesGen, - sockaddrGetPrivateInterfacesGen, - sockaddrGetPublicInterfacesGen, - sockaddrSortGen, - sockaddrExcludeGen, - sockaddrIncludeGen, - sockaddrAttrGen, - sockaddrJoinGen, - sockaddrLimitGen, - sockaddrOffsetGen, - sockaddrUniqueGen, - sockaddrMathGen, - sockaddrGetPrivateIPGen, - sockaddrGetPrivateIPsGen, - sockaddrGetPublicIPGen, - sockaddrGetPublicIPsGen, - sockaddrGetInterfaceIPGen, - sockaddrGetInterfaceIPsGen, + stringsHumanDurationGen, + stringsHumanSizeGen, + stringsSemverGen, + stringsSemverCompareGen, stringsAbbrevGen, stringsReplaceAllGen, stringsContainsGen, diff --git a/funcs/conv.go b/funcs/conv.go index d9235031c..5a0ce725c 100644 --- a/funcs/conv.go +++ b/funcs/conv.go @@ -7,7 +7,6 @@ import ( "github.com/flanksource/gomplate/v3/coll" "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/internal/deprecated" ) // ConvNS - @@ -46,7 +45,6 @@ type ConvFuncs struct { // Bool - // Deprecated: use ToBool instead func (f *ConvFuncs) Bool(s interface{}) bool { - deprecated.WarnDeprecated(f.ctx, "conv.Bool is deprecated - use conv.ToBool instead") return conv.Bool(conv.ToString(s)) } @@ -63,7 +61,6 @@ func (ConvFuncs) ToBools(in ...interface{}) []bool { // Slice - // Deprecated: use coll.Slice instead func (f *ConvFuncs) Slice(args ...interface{}) []interface{} { - deprecated.WarnDeprecated(f.ctx, "conv.Slice is deprecated - use coll.Slice instead") return coll.Slice(args...) } @@ -75,7 +72,6 @@ func (ConvFuncs) Join(in interface{}, sep string) (string, error) { // Has - // Deprecated: use coll.Has instead func (f *ConvFuncs) Has(in interface{}, key string) bool { - deprecated.WarnDeprecated(f.ctx, "conv.Has is deprecated - use coll.Has instead") return coll.Has(in, key) } @@ -155,6 +151,5 @@ func (ConvFuncs) Default(def, in interface{}) interface{} { // Dict - // Deprecated: use coll.Dict instead func (f *ConvFuncs) Dict(in ...interface{}) (map[string]interface{}, error) { - deprecated.WarnDeprecated(f.ctx, "conv.Dict is deprecated - use coll.Dict instead") return coll.Dict(in...) } diff --git a/funcs/crypto.go b/funcs/crypto.go index a1736a87c..223d85528 100644 --- a/funcs/crypto.go +++ b/funcs/crypto.go @@ -2,20 +2,10 @@ package funcs import ( "context" - gcrypto "crypto" - "crypto/elliptic" "crypto/sha1" //nolint: gosec "crypto/sha256" "crypto/sha512" "fmt" - "strings" - - "golang.org/x/crypto/bcrypt" - - "github.com/flanksource/gomplate/v3/conv" - "github.com/pkg/errors" - - "github.com/flanksource/gomplate/v3/crypto" ) // CryptoNS - the crypto namespace @@ -47,33 +37,6 @@ type CryptoFuncs struct { ctx context.Context } -// PBKDF2 - Run the Password-Based Key Derivation Function #2 as defined in -// RFC 2898 (PKCS #5 v2.0). This function outputs the binary result in hex -// format. -func (CryptoFuncs) PBKDF2(password, salt, iter, keylen interface{}, hashFunc ...string) (k string, err error) { - var h gcrypto.Hash - if len(hashFunc) == 0 { - h = gcrypto.SHA1 - } else { - h, err = crypto.StrToHash(hashFunc[0]) - if err != nil { - return "", err - } - } - pw := toBytes(password) - s := toBytes(salt) - i := conv.ToInt(iter) - kl := conv.ToInt(keylen) - - dk, err := crypto.PBKDF2(pw, s, i, kl, h) - return fmt.Sprintf("%02x", dk), err -} - -// WPAPSK - Convert an ASCII passphrase to WPA PSK for a given SSID -func (f CryptoFuncs) WPAPSK(ssid, password interface{}) (string, error) { - return f.PBKDF2(password, ssid, 4096, 32) -} - // SHA1 - Note: SHA-1 is cryptographically broken and should not be used for secure applications. func (f CryptoFuncs) SHA1(input interface{}) string { // nolint: gosec @@ -177,175 +140,3 @@ func (CryptoFuncs) SHA512_256Bytes(input interface{}) ([]byte, error) { copy(out, b[:]) return out, nil } - -// Bcrypt - -func (CryptoFuncs) Bcrypt(args ...interface{}) (string, error) { - input := "" - cost := bcrypt.DefaultCost - if len(args) == 0 { - return "", errors.Errorf("bcrypt requires at least an 'input' value") - } - if len(args) == 1 { - input = conv.ToString(args[0]) - } - if len(args) == 2 { - cost = conv.ToInt(args[0]) - input = conv.ToString(args[1]) - } - hash, err := bcrypt.GenerateFromPassword([]byte(input), cost) - return string(hash), err -} - -// RSAEncrypt - -// Experimental! -func (f *CryptoFuncs) RSAEncrypt(key string, in interface{}) ([]byte, error) { - if err := checkExperimental(f.ctx); err != nil { - return nil, err - } - msg := toBytes(in) - return crypto.RSAEncrypt(key, msg) -} - -// RSADecrypt - -// Experimental! -func (f *CryptoFuncs) RSADecrypt(key string, in []byte) (string, error) { - if err := checkExperimental(f.ctx); err != nil { - return "", err - } - out, err := crypto.RSADecrypt(key, in) - return string(out), err -} - -// RSADecryptBytes - -// Experimental! -func (f *CryptoFuncs) RSADecryptBytes(key string, in []byte) ([]byte, error) { - if err := checkExperimental(f.ctx); err != nil { - return nil, err - } - out, err := crypto.RSADecrypt(key, in) - return out, err -} - -// RSAGenerateKey - -// Experimental! -func (f *CryptoFuncs) RSAGenerateKey(args ...interface{}) (string, error) { - if err := checkExperimental(f.ctx); err != nil { - return "", err - } - bits := 4096 - if len(args) == 1 { - bits = conv.ToInt(args[0]) - } else if len(args) > 1 { - return "", fmt.Errorf("wrong number of args: want 0 or 1, got %d", len(args)) - } - out, err := crypto.RSAGenerateKey(bits) - return string(out), err -} - -// RSADerivePublicKey - -// Experimental! -func (f *CryptoFuncs) RSADerivePublicKey(privateKey string) (string, error) { - if err := checkExperimental(f.ctx); err != nil { - return "", err - } - out, err := crypto.RSADerivePublicKey([]byte(privateKey)) - return string(out), err -} - -// ECDSAGenerateKey - -// Experimental! -func (f *CryptoFuncs) ECDSAGenerateKey(args ...interface{}) (string, error) { - if err := checkExperimental(f.ctx); err != nil { - return "", err - } - - curve := elliptic.P256() - if len(args) == 1 { - c := conv.ToString(args[0]) - c = strings.ToUpper(c) - c = strings.ReplaceAll(c, "-", "") - var ok bool - curve, ok = crypto.Curves[c] - if !ok { - return "", fmt.Errorf("unknown curve: %s", c) - } - } else if len(args) > 1 { - return "", fmt.Errorf("wrong number of args: want 0 or 1, got %d", len(args)) - } - - out, err := crypto.ECDSAGenerateKey(curve) - return string(out), err -} - -// ECDSADerivePublicKey - -// Experimental! -func (f *CryptoFuncs) ECDSADerivePublicKey(privateKey string) (string, error) { - if err := checkExperimental(f.ctx); err != nil { - return "", err - } - - out, err := crypto.ECDSADerivePublicKey([]byte(privateKey)) - return string(out), err -} - -// EncryptAES - -// Experimental! -func (f *CryptoFuncs) EncryptAES(key string, args ...interface{}) ([]byte, error) { - if err := checkExperimental(f.ctx); err != nil { - return nil, err - } - - k, msg, err := parseAESArgs(key, args...) - if err != nil { - return nil, err - } - - return crypto.EncryptAESCBC(k, msg) -} - -// DecryptAES - -// Experimental! -func (f *CryptoFuncs) DecryptAES(key string, args ...interface{}) (string, error) { - if err := checkExperimental(f.ctx); err != nil { - return "", err - } - - out, err := f.DecryptAESBytes(key, args...) - return conv.ToString(out), err -} - -// DecryptAESBytes - -// Experimental! -func (f *CryptoFuncs) DecryptAESBytes(key string, args ...interface{}) ([]byte, error) { - if err := checkExperimental(f.ctx); err != nil { - return nil, err - } - - k, msg, err := parseAESArgs(key, args...) - if err != nil { - return nil, err - } - - return crypto.DecryptAESCBC(k, msg) -} - -func parseAESArgs(key string, args ...interface{}) ([]byte, []byte, error) { - keyBits := 256 // default to AES-256-CBC - - var msg []byte - - switch len(args) { - case 1: - msg = toBytes(args[0]) - case 2: - keyBits = conv.ToInt(args[0]) - msg = toBytes(args[1]) - default: - return nil, nil, fmt.Errorf("wrong number of args: want 2 or 3, got %d", len(args)) - } - - k := make([]byte, keyBits/8) - copy(k, []byte(key)) - - return k, msg, nil -} diff --git a/funcs/crypto_gen.go b/funcs/crypto_gen.go index 5bb9eda9d..46d08b016 100644 --- a/funcs/crypto_gen.go +++ b/funcs/crypto_gen.go @@ -6,47 +6,6 @@ import "github.com/google/cel-go/cel" import "github.com/google/cel-go/common/types" import "github.com/google/cel-go/common/types/ref" -var cryptoPBKDF2Gen = cel.Function("crypto.PBKDF2", - cel.Overload("crypto.PBKDF2_interface{}_interface{}_interface{}_interface{}_string", - - []*cel.Type{ - cel.DynType, cel.DynType, cel.DynType, cel.DynType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[string](args[4].(ref.Val)) - - a0, a1 := x.PBKDF2(args[0], args[1], args[2], args[3], list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoWPAPSKGen = cel.Function("crypto.WPAPSK", - cel.Overload("crypto.WPAPSK_interface{}_interface{}", - - []*cel.Type{ - cel.DynType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - - a0, a1 := x.WPAPSK(args[0], args[1]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - var cryptoSHA1Gen = cel.Function("crypto.SHA1", cel.Overload("crypto.SHA1_interface{}", @@ -305,229 +264,3 @@ var cryptoSHA512_256BytesGen = cel.Function("crypto.SHA512_256Bytes", }), ), ) - -var cryptoBcryptGen = cel.Function("crypto.Bcrypt", - cel.Overload("crypto.Bcrypt_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[interface{}](args[0].(ref.Val)) - - a0, a1 := x.Bcrypt(list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoRSAEncryptGen = cel.Function("crypto.RSAEncrypt", - cel.Overload("crypto.RSAEncrypt_string_interface{}", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - - a0, a1 := x.RSAEncrypt(args[0].Value().(string), args[1]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoRSADecryptGen = cel.Function("crypto.RSADecrypt", - cel.Overload("crypto.RSADecrypt_string_[]byte", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - - a0, a1 := x.RSADecrypt(args[0].Value().(string), args[1].Value().([]byte)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoRSADecryptBytesGen = cel.Function("crypto.RSADecryptBytes", - cel.Overload("crypto.RSADecryptBytes_string_[]byte", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - - a0, a1 := x.RSADecryptBytes(args[0].Value().(string), args[1].Value().([]byte)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoRSAGenerateKeyGen = cel.Function("crypto.RSAGenerateKey", - cel.Overload("crypto.RSAGenerateKey_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[interface{}](args[0].(ref.Val)) - - a0, a1 := x.RSAGenerateKey(list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoRSADerivePublicKeyGen = cel.Function("crypto.RSADerivePublicKey", - cel.Overload("crypto.RSADerivePublicKey_string", - - []*cel.Type{ - cel.StringType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - - a0, a1 := x.RSADerivePublicKey(args[0].Value().(string)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoECDSAGenerateKeyGen = cel.Function("crypto.ECDSAGenerateKey", - cel.Overload("crypto.ECDSAGenerateKey_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[interface{}](args[0].(ref.Val)) - - a0, a1 := x.ECDSAGenerateKey(list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoECDSADerivePublicKeyGen = cel.Function("crypto.ECDSADerivePublicKey", - cel.Overload("crypto.ECDSADerivePublicKey_string", - - []*cel.Type{ - cel.StringType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - - a0, a1 := x.ECDSADerivePublicKey(args[0].Value().(string)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoEncryptAESGen = cel.Function("crypto.EncryptAES", - cel.Overload("crypto.EncryptAES_string_interface{}", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[interface{}](args[1].(ref.Val)) - - a0, a1 := x.EncryptAES(args[0].Value().(string), list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoDecryptAESGen = cel.Function("crypto.DecryptAES", - cel.Overload("crypto.DecryptAES_string_interface{}", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[interface{}](args[1].(ref.Val)) - - a0, a1 := x.DecryptAES(args[0].Value().(string), list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var cryptoDecryptAESBytesGen = cel.Function("crypto.DecryptAESBytes", - cel.Overload("crypto.DecryptAESBytes_string_interface{}", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x CryptoFuncs - list := transferSlice[interface{}](args[1].(ref.Val)) - - a0, a1 := x.DecryptAESBytes(args[0].Value().(string), list...) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) diff --git a/funcs/crypto_test.go b/funcs/crypto_test.go index 8f5093e1e..4d2674a04 100644 --- a/funcs/crypto_test.go +++ b/funcs/crypto_test.go @@ -3,10 +3,8 @@ package funcs import ( "context" "strconv" - "strings" "testing" - "github.com/flanksource/gomplate/v3/internal/config" "github.com/stretchr/testify/assert" ) @@ -26,32 +24,7 @@ func TestCreateCryptoFuncs(t *testing.T) { } func testCryptoNS() *CryptoFuncs { - return &CryptoFuncs{ctx: config.SetExperimental(context.Background())} -} - -func TestPBKDF2(t *testing.T) { - t.Parallel() - - c := testCryptoNS() - dk, err := c.PBKDF2("password", []byte("IEEE"), "4096", 32) - assert.Equal(t, "f42c6fc52df0ebef9ebb4b90b38a5f902e83fe1b135a70e23aed762e9710a12e", dk) - assert.NoError(t, err) - - dk, err = c.PBKDF2([]byte("password"), "IEEE", 4096, "64", "SHA-512") - assert.Equal(t, "c16f4cb6d03e23614399dee5e7f676fb1da0eb9471b6a74a6c5bc934c6ec7d2ab7028fbb1000b1beb97f17646045d8144792352f6676d13b20a4c03754903d7e", dk) - assert.NoError(t, err) - - _, err = c.PBKDF2(nil, nil, nil, nil, "bogus") - assert.Error(t, err) -} - -func TestWPAPSK(t *testing.T) { - t.Parallel() - - c := testCryptoNS() - dk, err := c.WPAPSK("password", "MySSID") - assert.Equal(t, "3a98def84b11644a17ebcc9b17955d2360ce8b8a85b8a78413fc551d722a84e7", dk) - assert.NoError(t, err) + return &CryptoFuncs{} } func TestSHA(t *testing.T) { @@ -74,154 +47,3 @@ func TestSHA(t *testing.T) { assert.Equal(t, sha512_224, c.SHA512_224(in)) assert.Equal(t, sha512_256, c.SHA512_256(in)) } - -func TestBcrypt(t *testing.T) { - t.Parallel() - - if testing.Short() { - t.Skip("skipping slow test") - } - - in := "foo" - c := testCryptoNS() - - t.Run("no arg default", func(t *testing.T) { - t.Parallel() - - actual, err := c.Bcrypt(in) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(actual, "$2a$10$")) - }) - - t.Run("cost less than min", func(t *testing.T) { - t.Parallel() - - actual, err := c.Bcrypt(0, in) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(actual, "$2a$10$")) - }) - - t.Run("cost equal to min", func(t *testing.T) { - t.Parallel() - - actual, err := c.Bcrypt(4, in) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(actual, "$2a$04$")) - }) - - t.Run("no args errors", func(t *testing.T) { - t.Parallel() - - _, err := c.Bcrypt() - assert.Error(t, err) - }) -} - -func TestRSAGenerateKey(t *testing.T) { - t.Parallel() - - c := testCryptoNS() - _, err := c.RSAGenerateKey(0) - assert.Error(t, err) - - _, err = c.RSAGenerateKey(0, "foo", true) - assert.Error(t, err) - - key, err := c.RSAGenerateKey(2048) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(key, - "-----BEGIN RSA PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(key, - "-----END RSA PRIVATE KEY-----\n")) -} - -func TestECDSAGenerateKey(t *testing.T) { - c := testCryptoNS() - _, err := c.ECDSAGenerateKey("") - assert.Error(t, err) - - _, err = c.ECDSAGenerateKey(0, "P-999", true) - assert.Error(t, err) - - key, err := c.ECDSAGenerateKey("P-256") - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(key, - "-----BEGIN EC PRIVATE KEY-----")) - assert.True(t, strings.HasSuffix(key, - "-----END EC PRIVATE KEY-----\n")) -} - -func TestECDSADerivePublicKey(t *testing.T) { - c := testCryptoNS() - - _, err := c.ECDSADerivePublicKey("") - assert.Error(t, err) - - key, _ := c.ECDSAGenerateKey("P-256") - pub, err := c.ECDSADerivePublicKey(key) - assert.NoError(t, err) - assert.True(t, strings.HasPrefix(pub, - "-----BEGIN PUBLIC KEY-----")) - assert.True(t, strings.HasSuffix(pub, - "-----END PUBLIC KEY-----\n")) -} - -func TestRSACrypt(t *testing.T) { - t.Parallel() - - if testing.Short() { - t.Skip("skipping slow test") - } - - c := testCryptoNS() - key, err := c.RSAGenerateKey() - assert.NoError(t, err) - pub, err := c.RSADerivePublicKey(key) - assert.NoError(t, err) - - in := "hello world" - enc, err := c.RSAEncrypt(pub, in) - assert.NoError(t, err) - - dec, err := c.RSADecrypt(key, enc) - assert.NoError(t, err) - assert.Equal(t, in, dec) - - b, err := c.RSADecryptBytes(key, enc) - assert.NoError(t, err) - assert.Equal(t, dec, string(b)) -} - -func TestAESCrypt(t *testing.T) { - c := testCryptoNS() - key := "0123456789012345" - in := "hello world" - - _, err := c.EncryptAES(key, 1, 2, 3, 4) - assert.Error(t, err) - - _, err = c.DecryptAES(key, 1, 2, 3, 4) - assert.Error(t, err) - - enc, err := c.EncryptAES(key, in) - assert.NoError(t, err) - - dec, err := c.DecryptAES(key, enc) - assert.NoError(t, err) - assert.Equal(t, in, dec) - - b, err := c.DecryptAESBytes(key, enc) - assert.NoError(t, err) - assert.Equal(t, dec, string(b)) - - enc, err = c.EncryptAES(key, 128, in) - assert.NoError(t, err) - - dec, err = c.DecryptAES(key, 128, enc) - assert.NoError(t, err) - assert.Equal(t, in, dec) - - b, err = c.DecryptAESBytes(key, 128, enc) - assert.NoError(t, err) - assert.Equal(t, dec, string(b)) -} diff --git a/funcs/data.go b/funcs/data.go index 08c197cfe..98dfa15e8 100644 --- a/funcs/data.go +++ b/funcs/data.go @@ -13,24 +13,9 @@ func DataNS() *DataFuncs { return &DataFuncs{} } -// AddDataFuncs - -// Deprecated: use CreateDataFuncs instead -func AddDataFuncs(f map[string]interface{}, d *data.Data) { - for k, v := range CreateDataFuncs(context.Background(), d) { - f[k] = v - } -} - // CreateDataFuncs - -func CreateDataFuncs(ctx context.Context, d *data.Data) map[string]interface{} { +func CreateDataFuncs(ctx context.Context) map[string]interface{} { f := map[string]interface{}{} - f["datasource"] = d.Datasource - f["ds"] = d.Datasource - f["datasourceExists"] = d.DatasourceExists - f["datasourceReachable"] = d.DatasourceReachable - f["defineDatasource"] = d.DefineDatasource - f["include"] = d.Include - f["listDatasources"] = d.ListDatasources ns := &DataFuncs{ctx} diff --git a/funcs/data_test.go b/funcs/data_test.go index 1b3a6dcee..7aa209f3a 100644 --- a/funcs/data_test.go +++ b/funcs/data_test.go @@ -17,7 +17,7 @@ func TestCreateDataFuncs(t *testing.T) { t.Parallel() ctx := context.Background() - fmap := CreateDataFuncs(ctx, nil) + fmap := CreateDataFuncs(ctx) actual := fmap["data"].(func() interface{}) assert.Same(t, ctx, actual().(*DataFuncs).ctx) diff --git a/funcs/env.go b/funcs/env.go deleted file mode 100644 index a079d8c79..000000000 --- a/funcs/env.go +++ /dev/null @@ -1,47 +0,0 @@ -package funcs - -import ( - "context" - - "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/env" -) - -// EnvNS - the Env namespace -// Deprecated: don't use -func EnvNS() *EnvFuncs { - return &EnvFuncs{} -} - -// AddEnvFuncs - -// Deprecated: use CreateEnvFuncs instead -func AddEnvFuncs(f map[string]interface{}) { - for k, v := range CreateEnvFuncs(context.Background()) { - f[k] = v - } -} - -// CreateEnvFuncs - -func CreateEnvFuncs(ctx context.Context) map[string]interface{} { - ns := &EnvFuncs{ctx} - - return map[string]interface{}{ - "env": func() interface{} { return ns }, - "getenv": ns.Getenv, - } -} - -// EnvFuncs - -type EnvFuncs struct { - ctx context.Context -} - -// Getenv - -func (EnvFuncs) Getenv(key interface{}, def ...string) string { - return env.Getenv(conv.ToString(key), def...) -} - -// ExpandEnv - -func (EnvFuncs) ExpandEnv(s interface{}) string { - return env.ExpandEnv(conv.ToString(s)) -} diff --git a/funcs/env_test.go b/funcs/env_test.go deleted file mode 100644 index f37ee3dab..000000000 --- a/funcs/env_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package funcs - -import ( - "context" - "os" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCreateEnvFuncs(t *testing.T) { - t.Parallel() - - for i := 0; i < 10; i++ { - // Run this a bunch to catch race conditions - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - fmap := CreateEnvFuncs(ctx) - actual := fmap["env"].(func() interface{}) - - assert.Same(t, ctx, actual().(*EnvFuncs).ctx) - }) - } -} - -func TestEnvGetenv(t *testing.T) { - t.Parallel() - - ef := &EnvFuncs{} - expected := os.Getenv("USER") - assert.Equal(t, expected, ef.Getenv("USER")) - - assert.Equal(t, "foo", ef.Getenv("bogusenvvar", "foo")) -} diff --git a/funcs/file.go b/funcs/file.go deleted file mode 100644 index 5c9e0af68..000000000 --- a/funcs/file.go +++ /dev/null @@ -1,91 +0,0 @@ -package funcs - -import ( - "context" - "os" - - "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/file" - "github.com/spf13/afero" -) - -// FileNS - the File namespace -// Deprecated: don't use -func FileNS() *FileFuncs { - return &FileFuncs{} -} - -// AddFileFuncs - -// Deprecated: use CreateFileFuncs instead -func AddFileFuncs(f map[string]interface{}) { - for k, v := range CreateFileFuncs(context.Background()) { - f[k] = v - } -} - -// CreateFileFuncs - -func CreateFileFuncs(ctx context.Context) map[string]interface{} { - ns := &FileFuncs{ - ctx: ctx, - fs: afero.NewOsFs(), - } - return map[string]interface{}{ - "file": func() interface{} { return ns }, - } -} - -// FileFuncs - -type FileFuncs struct { - ctx context.Context - fs afero.Fs -} - -// Read - -func (f *FileFuncs) Read(path interface{}) (string, error) { - return file.Read(conv.ToString(path)) -} - -// Stat - -func (f *FileFuncs) Stat(path interface{}) (os.FileInfo, error) { - return f.fs.Stat(conv.ToString(path)) -} - -// Exists - -func (f *FileFuncs) Exists(path interface{}) bool { - _, err := f.Stat(conv.ToString(path)) - return err == nil -} - -// IsDir - -func (f *FileFuncs) IsDir(path interface{}) bool { - i, err := f.Stat(conv.ToString(path)) - return err == nil && i.IsDir() -} - -// ReadDir - -func (f *FileFuncs) ReadDir(path interface{}) ([]string, error) { - return file.ReadDir(conv.ToString(path)) -} - -// Walk - -func (f *FileFuncs) Walk(path interface{}) ([]string, error) { - files := make([]string, 0) - err := afero.Walk(f.fs, conv.ToString(path), func(subpath string, finfo os.FileInfo, err error) error { - if err != nil { - return err - } - files = append(files, subpath) - return nil - }) - return files, err -} - -// Write - -func (f *FileFuncs) Write(path interface{}, data interface{}) (s string, err error) { - if b, ok := data.([]byte); ok { - err = file.Write(conv.ToString(path), b) - } else { - err = file.Write(conv.ToString(path), []byte(conv.ToString(data))) - } - return "", err -} diff --git a/funcs/file_gen.go b/funcs/file_gen.go deleted file mode 100644 index be050476a..000000000 --- a/funcs/file_gen.go +++ /dev/null @@ -1,141 +0,0 @@ -// Code generated by gencel. DO NOT EDIT. - -package funcs - -import "github.com/google/cel-go/cel" -import "github.com/google/cel-go/common/types" -import "github.com/google/cel-go/common/types/ref" - -var fileReadGen = cel.Function("file.Read", - cel.Overload("file.Read_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - a0, a1 := x.Read(args[0]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var fileStatGen = cel.Function("file.Stat", - cel.Overload("file.Stat_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - a0, a1 := x.Stat(args[0]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var fileExistsGen = cel.Function("file.Exists", - cel.Overload("file.Exists_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.BoolType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - return types.DefaultTypeAdapter.NativeToValue(x.Exists(args[0])) - - }), - ), -) - -var fileIsDirGen = cel.Function("file.IsDir", - cel.Overload("file.IsDir_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.BoolType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - return types.DefaultTypeAdapter.NativeToValue(x.IsDir(args[0])) - - }), - ), -) - -var fileReadDirGen = cel.Function("file.ReadDir", - cel.Overload("file.ReadDir_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - a0, a1 := x.ReadDir(args[0]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var fileWalkGen = cel.Function("file.Walk", - cel.Overload("file.Walk_interface{}", - - []*cel.Type{ - cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - a0, a1 := x.Walk(args[0]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var fileWriteGen = cel.Function("file.Write", - cel.Overload("file.Write_interface{}_interface{}", - - []*cel.Type{ - cel.DynType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x FileFuncs - - a0, a1 := x.Write(args[0], args[1]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) diff --git a/funcs/file_test.go b/funcs/file_test.go deleted file mode 100644 index 372d00d86..000000000 --- a/funcs/file_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package funcs - -import ( - "context" - "path/filepath" - "strconv" - "testing" - - "github.com/spf13/afero" - "github.com/stretchr/testify/assert" -) - -func TestCreateFileFuncs(t *testing.T) { - t.Parallel() - - for i := 0; i < 10; i++ { - // Run this a bunch to catch race conditions - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - fmap := CreateFileFuncs(ctx) - actual := fmap["file"].(func() interface{}) - - assert.Same(t, ctx, actual().(*FileFuncs).ctx) - }) - } -} - -func TestFileExists(t *testing.T) { - t.Parallel() - - fs := afero.NewMemMapFs() - ff := &FileFuncs{fs: fs} - - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write([]byte("foo")) - - assert.True(t, ff.Exists("/tmp/foo")) - assert.False(t, ff.Exists("/tmp/bar")) -} - -func TestFileIsDir(t *testing.T) { - t.Parallel() - - fs := afero.NewMemMapFs() - ff := &FileFuncs{fs: fs} - - _ = fs.Mkdir("/tmp", 0777) - f, _ := fs.Create("/tmp/foo") - _, _ = f.Write([]byte("foo")) - - assert.True(t, ff.IsDir("/tmp")) - assert.False(t, ff.IsDir("/tmp/foo")) -} - -func TestFileWalk(t *testing.T) { - t.Parallel() - - fs := afero.NewMemMapFs() - ff := &FileFuncs{fs: fs} - - _ = fs.Mkdir("/tmp", 0777) - _ = fs.Mkdir("/tmp/bar", 0777) - _ = fs.Mkdir("/tmp/bar/baz", 0777) - f, _ := fs.Create("/tmp/bar/baz/foo") - _, _ = f.Write([]byte("foo")) - - expectedLists := [][]string{{"tmp"}, {"tmp", "bar"}, {"tmp", "bar", "baz"}, {"tmp", "bar", "baz", "foo"}} - expectedPaths := make([]string, 0) - for _, path := range expectedLists { - expectedPaths = append(expectedPaths, string(filepath.Separator)+filepath.Join(path...)) - } - - actualPaths, err := ff.Walk(string(filepath.Separator) + "tmp") - - assert.NoError(t, err) - assert.Equal(t, expectedPaths, actualPaths) -} diff --git a/funcs/funcs.go b/funcs/funcs.go deleted file mode 100644 index 4fe0aaaf5..000000000 --- a/funcs/funcs.go +++ /dev/null @@ -1,15 +0,0 @@ -package funcs - -import ( - "context" - "fmt" - - "github.com/flanksource/gomplate/v3/internal/config" -) - -func checkExperimental(ctx context.Context) error { - if !config.ExperimentalEnabled(ctx) { - return fmt.Errorf("experimental function, but experimental mode not enabled") - } - return nil -} diff --git a/funcs/gcp.go b/funcs/gcp.go deleted file mode 100644 index a01695c24..000000000 --- a/funcs/gcp.go +++ /dev/null @@ -1,54 +0,0 @@ -package funcs - -import ( - "context" - "sync" - - "github.com/flanksource/gomplate/v3/gcp" -) - -// GCPNS - the gcp namespace -// Deprecated: don't use -func GCPNS() *GcpFuncs { - return &GcpFuncs{gcpopts: gcp.GetClientOptions()} -} - -// AddGCPFuncs - -// Deprecated: use CreateGCPFuncs instead -func AddGCPFuncs(f map[string]interface{}) { - for k, v := range CreateGCPFuncs(context.Background()) { - f[k] = v - } -} - -// CreateGCPFuncs - -func CreateGCPFuncs(ctx context.Context) map[string]interface{} { - ns := &GcpFuncs{ - ctx: ctx, - gcpopts: gcp.GetClientOptions(), - } - return map[string]interface{}{ - "gcp": func() interface{} { return ns }, - } -} - -// GcpFuncs - -type GcpFuncs struct { - ctx context.Context - - meta *gcp.MetaClient - metaInit sync.Once - gcpopts gcp.ClientOptions -} - -// Meta - -func (a *GcpFuncs) Meta(key string, def ...string) (string, error) { - a.metaInit.Do(a.initGcpMeta) - return a.meta.Meta(key, def...) -} - -func (a *GcpFuncs) initGcpMeta() { - if a.meta == nil { - a.meta = gcp.NewMetaClient(a.gcpopts) - } -} diff --git a/funcs/gcp_test.go b/funcs/gcp_test.go deleted file mode 100644 index b235bce8a..000000000 --- a/funcs/gcp_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package funcs - -import ( - "context" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCreateGCPFuncs(t *testing.T) { - t.Parallel() - - for i := 0; i < 10; i++ { - // Run this a bunch to catch race conditions - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - fmap := CreateGCPFuncs(ctx) - actual := fmap["gcp"].(func() interface{}) - - assert.Same(t, ctx, actual().(*GcpFuncs).ctx) - }) - } -} diff --git a/funcs/k8s.go b/funcs/k8s.go new file mode 100644 index 000000000..87cfd74d7 --- /dev/null +++ b/funcs/k8s.go @@ -0,0 +1,42 @@ +package funcs + +import ( + "context" + "encoding/json" + + "github.com/flanksource/gomplate/v3/k8s" +) + +type KubernetesFuncs struct { +} + +// CreateFilePathFuncs - +func CreateKubernetesFuncs(ctx context.Context) map[string]interface{} { + f := map[string]interface{}{} + ns := &KubernetesFuncs{} + f["k8s"] = func() interface{} { return ns } + f["isHealthy"] = ns.IsHealthy + f["getStatus"] = ns.GetStatus + f["getHealth"] = ns.GetHealth + return f +} + +func (ns KubernetesFuncs) IsHealthy(in interface{}) bool { + return k8s.IsHealthy(in) +} + +func (ns KubernetesFuncs) GetStatus(in interface{}) string { + return k8s.GetStatus(in) +} + +func (ns KubernetesFuncs) GetHealth(in interface{}) k8s.HealthStatus { + return k8s.GetHealth(in) +} + +func (ns KubernetesFuncs) GetHealthMap(in interface{}) map[string]string { + v := k8s.GetHealth(in) + b, _ := json.Marshal(v) + var r map[string]string + _ = json.Unmarshal(b, &r) + return r +} diff --git a/funcs/k8s_gen.go b/funcs/k8s_gen.go new file mode 100644 index 000000000..2d9c25d5a --- /dev/null +++ b/funcs/k8s_gen.go @@ -0,0 +1,58 @@ +// Code generated by gencel. DO NOT EDIT. + +package funcs + +import "github.com/google/cel-go/cel" +import "github.com/google/cel-go/common/types" +import "github.com/google/cel-go/common/types/ref" + +var k8sIsHealthyGen = cel.Function("IsHealthy", + cel.Overload("IsHealthy_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.BoolType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x KubernetesFuncs + + return types.DefaultTypeAdapter.NativeToValue(x.IsHealthy(args[0])) + + }), + ), +) + +var k8sGetStatusGen = cel.Function("GetStatus", + cel.Overload("GetStatus_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.StringType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x KubernetesFuncs + + return types.DefaultTypeAdapter.NativeToValue(x.GetStatus(args[0])) + + }), + ), +) + +var k8sGetHealthGen = cel.Function("GetHealth", + cel.Overload("GetHealth_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x KubernetesFuncs + + return types.DefaultTypeAdapter.NativeToValue(x.GetHealthMap(args[0])) + + }), + ), +) diff --git a/funcs/net.go b/funcs/net.go deleted file mode 100644 index 162afac4c..000000000 --- a/funcs/net.go +++ /dev/null @@ -1,232 +0,0 @@ -package funcs - -import ( - "context" - "math/big" - stdnet "net" - "net/netip" - - "github.com/apparentlymart/go-cidr/cidr" - "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/net" - "github.com/pkg/errors" -) - -// NetNS - the net namespace -// Deprecated: don't use -func NetNS() *NetFuncs { - return &NetFuncs{} -} - -// AddNetFuncs - -// Deprecated: use CreateNetFuncs instead -func AddNetFuncs(f map[string]interface{}) { - for k, v := range CreateNetFuncs(context.Background()) { - f[k] = v - } -} - -// CreateNetFuncs - -func CreateNetFuncs(ctx context.Context) map[string]interface{} { - ns := &NetFuncs{ctx} - return map[string]interface{}{ - "net": func() interface{} { return ns }, - } -} - -// NetFuncs - -type NetFuncs struct { - ctx context.Context -} - -// LookupIP - -func (f NetFuncs) LookupIP(name interface{}) (string, error) { - return net.LookupIP(conv.ToString(name)) -} - -// LookupIPs - -func (f NetFuncs) LookupIPs(name interface{}) ([]string, error) { - return net.LookupIPs(conv.ToString(name)) -} - -// LookupCNAME - -func (f NetFuncs) LookupCNAME(name interface{}) (string, error) { - return net.LookupCNAME(conv.ToString(name)) -} - -// LookupSRV - -func (f NetFuncs) LookupSRV(name interface{}) (*stdnet.SRV, error) { - return net.LookupSRV(conv.ToString(name)) -} - -// LookupSRVs - -func (f NetFuncs) LookupSRVs(name interface{}) ([]*stdnet.SRV, error) { - return net.LookupSRVs(conv.ToString(name)) -} - -// LookupTXT - -func (f NetFuncs) LookupTXT(name interface{}) ([]string, error) { - return net.LookupTXT(conv.ToString(name)) -} - -// ParseIP - -func (f NetFuncs) ParseIP(ip interface{}) (netip.Addr, error) { - return netip.ParseAddr(conv.ToString(ip)) -} - -// ParseIPPrefix - -func (f NetFuncs) ParseIPPrefix(ipprefix interface{}) (netip.Prefix, error) { - return netip.ParsePrefix(conv.ToString(ipprefix)) -} - -// StdParseIP - -func (f NetFuncs) StdParseIP(prefix interface{}) (stdnet.IP, error) { - ip := stdnet.ParseIP(conv.ToString(prefix)) - if ip == nil { - return nil, errors.Errorf("invalid IP address") - } - return ip, nil -} - -func (f NetFuncs) stdParseCIDR(prefix interface{}) (*stdnet.IPNet, error) { - if n, ok := prefix.(*stdnet.IPNet); ok { - return n, nil - } - - _, network, err := stdnet.ParseCIDR(conv.ToString(prefix)) - return network, err -} - -// StdParseCIDR - -func (f NetFuncs) StdParseCIDR(prefix interface{}) (*stdnet.IPNet, error) { - return f.stdParseCIDR(prefix) -} - -func (f NetFuncs) CIDRHost(hostnum interface{}, prefix interface{}) (*stdnet.IP, error) { - return f.CidrHost(hostnum, prefix) -} - -// CidrHost - -func (f NetFuncs) CidrHost(hostnum interface{}, prefix interface{}) (*stdnet.IP, error) { - network, err := f.stdParseCIDR(prefix) - if err != nil { - return nil, err - } - - ip, err := cidr.HostBig(network, big.NewInt(conv.ToInt64(hostnum))) - return &ip, err -} - -// CidrNetmask - -func (f NetFuncs) CIDRNetmask(prefix interface{}) (*stdnet.IP, error) { - return f.CidrNetmask(prefix) -} - -// CidrNetmask - -func (f NetFuncs) CidrNetmask(prefix interface{}) (*stdnet.IP, error) { - network, err := f.stdParseCIDR(prefix) - if err != nil { - return nil, err - } - - if len(network.IP) != stdnet.IPv4len { - return nil, errors.Errorf("only IPv4 networks are supported") - } - - netmask := stdnet.IP(network.Mask) - return &netmask, nil -} - -// CidrSubnets - -func (f NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]*stdnet.IPNet, error) { - return f.CidrSubnets(newbits, prefix) -} - -// CidrSubnets - -func (f NetFuncs) CidrSubnets(newbits interface{}, prefix interface{}) ([]*stdnet.IPNet, error) { - network, err := f.stdParseCIDR(prefix) - if err != nil { - return nil, err - } - - nBits := conv.ToInt(newbits) - if nBits < 1 { - return nil, errors.Errorf("must extend prefix by at least one bit") - } - - maxNetNum := int64(1 << uint64(nBits)) - retValues := make([]*stdnet.IPNet, maxNetNum) - for i := int64(0); i < maxNetNum; i++ { - subnet, err := cidr.SubnetBig(network, nBits, big.NewInt(i)) - if err != nil { - return nil, err - } - retValues[i] = subnet - } - - return retValues, nil -} - -// CidrSubnetSizes - -func (f NetFuncs) CIDRSubnetSizes(args ...interface{}) ([]*stdnet.IPNet, error) { - return f.CidrSubnetSizes(args...) -} - -// CidrSubnetSizes - -func (f NetFuncs) CidrSubnetSizes(args ...interface{}) ([]*stdnet.IPNet, error) { - if len(args) < 2 { - return nil, errors.Errorf("wrong number of args: want 2 or more, got %d", len(args)) - } - - network, err := f.stdParseCIDR(args[len(args)-1]) - if err != nil { - return nil, err - } - newbits := conv.ToInts(args[:len(args)-1]...) - - startPrefixLen, _ := network.Mask.Size() - firstLength := newbits[0] - - firstLength += startPrefixLen - retValues := make([]*stdnet.IPNet, len(newbits)) - - current, _ := cidr.PreviousSubnet(network, firstLength) - - for i, length := range newbits { - if length < 1 { - return nil, errors.Errorf("must extend prefix by at least one bit") - } - // For portability with 32-bit systems where the subnet number - // will be a 32-bit int, we only allow extension of 32 bits in - // one call even if we're running on a 64-bit machine. - // (Of course, this is significant only for IPv6.) - if length > 32 { - return nil, errors.Errorf("may not extend prefix by more than 32 bits") - } - - length += startPrefixLen - if length > (len(network.IP) * 8) { - protocol := "IP" - switch len(network.IP) { - case stdnet.IPv4len: - protocol = "IPv4" - case stdnet.IPv6len: - protocol = "IPv6" - } - return nil, errors.Errorf("would extend prefix to %d bits, which is too long for an %s address", length, protocol) - } - - next, rollover := cidr.NextSubnet(current, length) - if rollover || !network.Contains(next.IP) { - // If we run out of suffix bits in the base CIDR prefix then - // NextSubnet will start incrementing the prefix bits, which - // we don't allow because it would then allocate addresses - // outside of the caller's given prefix. - return nil, errors.Errorf("not enough remaining address space for a subnet with a prefix of %d bits after %s", length, current.String()) - } - current = next - retValues[i] = current - } - - return retValues, nil -} diff --git a/funcs/net_test.go b/funcs/net_test.go deleted file mode 100644 index 53d317d9e..000000000 --- a/funcs/net_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package funcs - -import ( - "context" - stdnet "net" - "net/netip" - "strconv" - "testing" - - "github.com/flanksource/gomplate/v3/internal/config" - "github.com/stretchr/testify/assert" -) - -func TestCreateNetFuncs(t *testing.T) { - t.Parallel() - - for i := 0; i < 10; i++ { - // Run this a bunch to catch race conditions - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - fmap := CreateNetFuncs(ctx) - actual := fmap["net"].(func() interface{}) - - assert.Same(t, ctx, actual().(*NetFuncs).ctx) - }) - } -} - -func TestNetLookupIP(t *testing.T) { - t.Parallel() - - n := NetFuncs{} - assert.Equal(t, "127.0.0.1", must(n.LookupIP("localhost"))) -} -func TestParseIPPrefix(t *testing.T) { - t.Parallel() - - n := NetFuncs{} - _, err := n.ParseIPPrefix("not an IP") - assert.Error(t, err) - - _, err = n.ParseIPPrefix("1.1.1.1") - assert.Error(t, err) - - ipprefix, err := n.ParseIPPrefix("192.168.0.2/28") - assert.NoError(t, err) - assert.Equal(t, "192.168.0.0/28", ipprefix.Masked().String()) -} - -func testNetNS() *NetFuncs { - return &NetFuncs{ctx: config.SetExperimental(context.Background())} -} - -func TestCIDRHost(t *testing.T) { - n := testNetNS() - - // net.IPNet - _, netIP, _ := stdnet.ParseCIDR("10.12.127.0/20") - - ip, err := n.CIDRHost(16, netIP) - assert.NoError(t, err) - assert.Equal(t, "10.12.112.16", ip.String()) - - ip, err = n.CIDRHost(268, netIP) - assert.NoError(t, err) - assert.Equal(t, "10.12.113.12", ip.String()) - - _, netIP, _ = stdnet.ParseCIDR("fd00:fd12:3456:7890:00a2::/72") - ip, err = n.CIDRHost(34, netIP) - assert.NoError(t, err) - assert.Equal(t, "fd00:fd12:3456:7890::22", ip.String()) - - ipPrefix, _ := netip.ParsePrefix("10.12.127.0/20") - - ip, err = n.CIDRHost(16, ipPrefix) - assert.NoError(t, err) - assert.Equal(t, "10.12.112.16", ip.String()) - - ip, err = n.CIDRHost(268, ipPrefix) - assert.NoError(t, err) - assert.Equal(t, "10.12.113.12", ip.String()) - - ipPrefix, _ = n.ParseIPPrefix("fd00:fd12:3456:7890:00a2::/72") - ip, err = n.CIDRHost(34, ipPrefix) - assert.NoError(t, err) - assert.Equal(t, "fd00:fd12:3456:7890::22", ip.String()) - - // net/netip.Prefix - prefix := netip.MustParsePrefix("10.12.127.0/20") - - ip, err = n.CIDRHost(16, prefix) - assert.NoError(t, err) - assert.Equal(t, "10.12.112.16", ip.String()) - - ip, err = n.CIDRHost(268, prefix) - assert.NoError(t, err) - assert.Equal(t, "10.12.113.12", ip.String()) - - prefix = netip.MustParsePrefix("fd00:fd12:3456:7890:00a2::/72") - ip, err = n.CIDRHost(34, prefix) - assert.NoError(t, err) - assert.Equal(t, "fd00:fd12:3456:7890::22", ip.String()) -} - -func TestCIDRNetmask(t *testing.T) { - n := testNetNS() - - ip, err := n.CIDRNetmask("10.0.0.0/12") - assert.NoError(t, err) - assert.Equal(t, "255.240.0.0", ip.String()) -} - -func TestCIDRSubnets(t *testing.T) { - n := testNetNS() - network := netip.MustParsePrefix("10.0.0.0/16") - - subnets, err := n.CIDRSubnets(-1, network) - assert.Nil(t, subnets) - assert.Error(t, err) - - subnets, err = n.CIDRSubnets(2, network) - assert.NoError(t, err) - assert.Len(t, subnets, 4) - assert.Equal(t, "10.0.0.0/18", subnets[0].String()) - assert.Equal(t, "10.0.64.0/18", subnets[1].String()) - assert.Equal(t, "10.0.128.0/18", subnets[2].String()) - assert.Equal(t, "10.0.192.0/18", subnets[3].String()) -} - -func TestCIDRSubnetSizes(t *testing.T) { - n := testNetNS() - network := netip.MustParsePrefix("10.1.0.0/16") - - subnets, err := n.CIDRSubnetSizes(network) - assert.Nil(t, subnets) - assert.Error(t, err) - - subnets, err = n.CIDRSubnetSizes(32, network) - assert.Nil(t, subnets) - assert.Error(t, err) - - subnets, err = n.CIDRSubnetSizes(-1, network) - assert.Nil(t, subnets) - assert.Error(t, err) - - subnets, err = n.CIDRSubnetSizes(4, 4, 8, 4, network) - assert.NoError(t, err) - assert.Len(t, subnets, 4) - assert.Equal(t, "10.1.0.0/20", subnets[0].String()) - assert.Equal(t, "10.1.16.0/20", subnets[1].String()) - assert.Equal(t, "10.1.32.0/24", subnets[2].String()) - assert.Equal(t, "10.1.48.0/20", subnets[3].String()) -} diff --git a/funcs/sockaddr.go b/funcs/sockaddr.go deleted file mode 100644 index c4554a77f..000000000 --- a/funcs/sockaddr.go +++ /dev/null @@ -1,128 +0,0 @@ -package funcs - -import ( - "context" - - "github.com/hashicorp/go-sockaddr" - "github.com/hashicorp/go-sockaddr/template" -) - -// SockaddrNS - the sockaddr namespace -// Deprecated: don't use -func SockaddrNS() *SockaddrFuncs { - return &SockaddrFuncs{} -} - -// AddSockaddrFuncs - -// Deprecated: use CreateSockaddrFuncs instead -func AddSockaddrFuncs(f map[string]interface{}) { - f["sockaddr"] = SockaddrNS -} - -// CreateSockaddrFuncs - -func CreateSockaddrFuncs(ctx context.Context) map[string]interface{} { - ns := &SockaddrFuncs{ctx} - return map[string]interface{}{ - "sockaddr": func() interface{} { return ns }, - } -} - -// SockaddrFuncs - -type SockaddrFuncs struct { - ctx context.Context -} - -// GetAllInterfaces - -func (SockaddrFuncs) GetAllInterfaces() (sockaddr.IfAddrs, error) { - return sockaddr.GetAllInterfaces() -} - -// GetDefaultInterfaces - -func (SockaddrFuncs) GetDefaultInterfaces() (sockaddr.IfAddrs, error) { - return sockaddr.GetDefaultInterfaces() -} - -// GetPrivateInterfaces - -func (SockaddrFuncs) GetPrivateInterfaces() (sockaddr.IfAddrs, error) { - return sockaddr.GetPrivateInterfaces() -} - -// GetPublicInterfaces - -func (SockaddrFuncs) GetPublicInterfaces() (sockaddr.IfAddrs, error) { - return sockaddr.GetPublicInterfaces() -} - -// Sort - -func (SockaddrFuncs) Sort(selectorParam string, inputIfAddrs sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.SortIfBy(selectorParam, inputIfAddrs) -} - -// Exclude - -func (SockaddrFuncs) Exclude(selectorName, selectorParam string, inputIfAddrs sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.ExcludeIfs(selectorName, selectorParam, inputIfAddrs) -} - -// Include - -func (SockaddrFuncs) Include(selectorName, selectorParam string, inputIfAddrs sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.IncludeIfs(selectorName, selectorParam, inputIfAddrs) -} - -// Attr - -func (SockaddrFuncs) Attr(selectorName string, ifAddrsRaw interface{}) (string, error) { - return template.Attr(selectorName, ifAddrsRaw) -} - -// Join - -func (SockaddrFuncs) Join(selectorName, joinString string, inputIfAddrs sockaddr.IfAddrs) (string, error) { - return sockaddr.JoinIfAddrs(selectorName, joinString, inputIfAddrs) -} - -// Limit - -func (SockaddrFuncs) Limit(lim uint, in sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.LimitIfAddrs(lim, in) -} - -// Offset - -func (SockaddrFuncs) Offset(off int, in sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.OffsetIfAddrs(off, in) -} - -// Unique - -func (SockaddrFuncs) Unique(selectorName string, inputIfAddrs sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.UniqueIfAddrsBy(selectorName, inputIfAddrs) -} - -// Math - -func (SockaddrFuncs) Math(operation, value string, inputIfAddrs sockaddr.IfAddrs) (sockaddr.IfAddrs, error) { - return sockaddr.IfAddrsMath(operation, value, inputIfAddrs) -} - -// GetPrivateIP - -func (SockaddrFuncs) GetPrivateIP() (string, error) { - return sockaddr.GetPrivateIP() -} - -// GetPrivateIPs - -func (SockaddrFuncs) GetPrivateIPs() (string, error) { - return sockaddr.GetPrivateIPs() -} - -// GetPublicIP - -func (SockaddrFuncs) GetPublicIP() (string, error) { - return sockaddr.GetPublicIP() -} - -// GetPublicIPs - -func (SockaddrFuncs) GetPublicIPs() (string, error) { - return sockaddr.GetPublicIPs() -} - -// GetInterfaceIP - -func (SockaddrFuncs) GetInterfaceIP(namedIfRE string) (string, error) { - return sockaddr.GetInterfaceIP(namedIfRE) -} - -// GetInterfaceIPs - -func (SockaddrFuncs) GetInterfaceIPs(namedIfRE string) (string, error) { - return sockaddr.GetInterfaceIPs(namedIfRE) -} diff --git a/funcs/sockaddr_gen.go b/funcs/sockaddr_gen.go deleted file mode 100644 index 0ea52eb57..000000000 --- a/funcs/sockaddr_gen.go +++ /dev/null @@ -1,364 +0,0 @@ -// Code generated by gencel. DO NOT EDIT. - -package funcs - -import "github.com/google/cel-go/cel" -import "github.com/google/cel-go/common/types" -import "github.com/google/cel-go/common/types/ref" -import sockaddr "github.com/hashicorp/go-sockaddr" - -var sockaddrGetAllInterfacesGen = cel.Function("sockaddr.GetAllInterfaces", - cel.Overload("sockaddr.GetAllInterfaces_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetAllInterfaces() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetDefaultInterfacesGen = cel.Function("sockaddr.GetDefaultInterfaces", - cel.Overload("sockaddr.GetDefaultInterfaces_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetDefaultInterfaces() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetPrivateInterfacesGen = cel.Function("sockaddr.GetPrivateInterfaces", - cel.Overload("sockaddr.GetPrivateInterfaces_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetPrivateInterfaces() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetPublicInterfacesGen = cel.Function("sockaddr.GetPublicInterfaces", - cel.Overload("sockaddr.GetPublicInterfaces_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetPublicInterfaces() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrSortGen = cel.Function("sockaddr.Sort", - cel.Overload("sockaddr.Sort_string_sockaddr.IfAddrs", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Sort(args[0].Value().(string), args[1].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrExcludeGen = cel.Function("sockaddr.Exclude", - cel.Overload("sockaddr.Exclude_string_string_sockaddr.IfAddrs", - - []*cel.Type{ - cel.StringType, cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Exclude(args[0].Value().(string), args[1].Value().(string), args[2].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrIncludeGen = cel.Function("sockaddr.Include", - cel.Overload("sockaddr.Include_string_string_sockaddr.IfAddrs", - - []*cel.Type{ - cel.StringType, cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Include(args[0].Value().(string), args[1].Value().(string), args[2].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrAttrGen = cel.Function("sockaddr.Attr", - cel.Overload("sockaddr.Attr_string_interface{}", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Attr(args[0].Value().(string), args[1]) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrJoinGen = cel.Function("sockaddr.Join", - cel.Overload("sockaddr.Join_string_string_sockaddr.IfAddrs", - - []*cel.Type{ - cel.StringType, cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Join(args[0].Value().(string), args[1].Value().(string), args[2].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrLimitGen = cel.Function("sockaddr.Limit", - cel.Overload("sockaddr.Limit_uint_sockaddr.IfAddrs", - - []*cel.Type{ - cel.UintType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Limit(args[0].Value().(uint), args[1].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrOffsetGen = cel.Function("sockaddr.Offset", - cel.Overload("sockaddr.Offset_int_sockaddr.IfAddrs", - - []*cel.Type{ - cel.IntType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Offset(args[0].Value().(int), args[1].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrUniqueGen = cel.Function("sockaddr.Unique", - cel.Overload("sockaddr.Unique_string_sockaddr.IfAddrs", - - []*cel.Type{ - cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Unique(args[0].Value().(string), args[1].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrMathGen = cel.Function("sockaddr.Math", - cel.Overload("sockaddr.Math_string_string_sockaddr.IfAddrs", - - []*cel.Type{ - cel.StringType, cel.StringType, cel.DynType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.Math(args[0].Value().(string), args[1].Value().(string), args[2].Value().(sockaddr.IfAddrs)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetPrivateIPGen = cel.Function("sockaddr.GetPrivateIP", - cel.Overload("sockaddr.GetPrivateIP_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetPrivateIP() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetPrivateIPsGen = cel.Function("sockaddr.GetPrivateIPs", - cel.Overload("sockaddr.GetPrivateIPs_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetPrivateIPs() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetPublicIPGen = cel.Function("sockaddr.GetPublicIP", - cel.Overload("sockaddr.GetPublicIP_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetPublicIP() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetPublicIPsGen = cel.Function("sockaddr.GetPublicIPs", - cel.Overload("sockaddr.GetPublicIPs_", - nil, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetPublicIPs() - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetInterfaceIPGen = cel.Function("sockaddr.GetInterfaceIP", - cel.Overload("sockaddr.GetInterfaceIP_string", - - []*cel.Type{ - cel.StringType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetInterfaceIP(args[0].Value().(string)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) - -var sockaddrGetInterfaceIPsGen = cel.Function("sockaddr.GetInterfaceIPs", - cel.Overload("sockaddr.GetInterfaceIPs_string", - - []*cel.Type{ - cel.StringType, - }, - cel.DynType, - cel.FunctionBinding(func(args ...ref.Val) ref.Val { - - var x SockaddrFuncs - - a0, a1 := x.GetInterfaceIPs(args[0].Value().(string)) - return types.DefaultTypeAdapter.NativeToValue([]any{ - a0, a1, - }) - - }), - ), -) diff --git a/funcs/sockaddr_test.go b/funcs/sockaddr_test.go deleted file mode 100644 index 8843f3f02..000000000 --- a/funcs/sockaddr_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package funcs - -import ( - "context" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestCreateSockaddrFuncs(t *testing.T) { - t.Parallel() - - for i := 0; i < 10; i++ { - // Run this a bunch to catch race conditions - t.Run(strconv.Itoa(i), func(t *testing.T) { - t.Parallel() - - ctx := context.Background() - fmap := CreateSockaddrFuncs(ctx) - actual := fmap["sockaddr"].(func() interface{}) - - assert.Same(t, ctx, actual().(*SockaddrFuncs).ctx) - }) - } -} diff --git a/funcs/sprig.go b/funcs/sprig.go deleted file mode 100644 index 7bc5512c9..000000000 --- a/funcs/sprig.go +++ /dev/null @@ -1,16 +0,0 @@ -package funcs - -import ( - "context" - "github.com/Masterminds/sprig" - "text/template" -) - -func AddSprigFuncs(ctx context.Context, funcs template.FuncMap) { - sprigFuncs := sprig.TxtFuncMap() - for funcName := range sprigFuncs { - if _, ok := funcs[funcName]; !ok { - funcs[funcName] = sprigFuncs[funcName] - } - } -} diff --git a/funcs/strings.go b/funcs/strings.go index 0546e1541..998b8f9a8 100644 --- a/funcs/strings.go +++ b/funcs/strings.go @@ -12,8 +12,8 @@ import ( "unicode/utf8" "github.com/Masterminds/goutils" + "github.com/Masterminds/semver/v3" "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/internal/deprecated" "github.com/pkg/errors" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -49,7 +49,7 @@ func CreateStringFuncs(ctx context.Context) map[string]interface{} { f["title"] = ns.Title f["toUpper"] = ns.ToUpper f["toLower"] = ns.ToLower - f["trimSpace"] = ns.TrimSpace + f["trim"] = ns.TrimSpace f["indent"] = ns.Indent f["quote"] = ns.Quote f["shellQuote"] = ns.ShellQuote @@ -59,13 +59,53 @@ func CreateStringFuncs(ctx context.Context) map[string]interface{} { f["contains"] = strings.Contains f["hasPrefix"] = strings.HasPrefix f["hasSuffix"] = strings.HasSuffix + f["startsWith"] = strings.HasPrefix + f["endsWith"] = strings.HasSuffix f["split"] = strings.Split f["splitN"] = strings.SplitN f["trim"] = strings.Trim + f["humanDuration"] = gompstrings.HumanDuration + f["humanSize"] = gompstrings.HumanBytes + f["semver"] = gompstrings.Semver + f["semverCompare"] = gompstrings.SemverCompare return f } +func (ns StringFuncs) HumanDuration(in interface{}) (string, error) { + return gompstrings.HumanDuration(in), nil +} + +func (ns StringFuncs) HumanSize(in interface{}) (string, error) { + return gompstrings.HumanBytes(in), nil +} + +func (ns StringFuncs) Semver(in string) (*semver.Version, error) { + return gompstrings.Semver(in) +} + +func (ns StringFuncs) SemverMap(in string) (map[string]string, error) { + v, err := gompstrings.Semver(in) + if err != nil { + return nil, err + } + + res := map[string]string{ + "major": fmt.Sprint(v.Major()), + "minor": fmt.Sprint(v.Minor()), + "patch": fmt.Sprint(v.Patch()), + "prerelease": v.Prerelease(), + "metadata": v.Metadata(), + "original": v.Original(), + } + + return res, nil +} + +func (ns StringFuncs) SemverCompare(v1, v2 string) (bool, error) { + return gompstrings.SemverCompare(v1, v2) +} + // StringFuncs - type StringFuncs struct { ctx context.Context @@ -134,7 +174,6 @@ func (StringFuncs) Repeat(count int, s interface{}) (string, error) { // // Deprecated: use coll.Sort instead func (f *StringFuncs) Sort(list interface{}) ([]string, error) { - deprecated.WarnDeprecated(f.ctx, "strings.Sort is deprecated - use coll.Sort instead") switch v := list.(type) { case []string: diff --git a/funcs/strings_gen.go b/funcs/strings_gen.go index 150b00729..a4ec64a64 100644 --- a/funcs/strings_gen.go +++ b/funcs/strings_gen.go @@ -2,9 +2,93 @@ package funcs -import "github.com/google/cel-go/cel" -import "github.com/google/cel-go/common/types" -import "github.com/google/cel-go/common/types/ref" +import ( + "github.com/flanksource/gomplate/v3/conv" + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" +) + +var stringsHumanDurationGen = cel.Function("HumanDuration", + cel.Overload("HumanDuration_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x StringFuncs + + a0, a1 := x.HumanDuration(args[0]) + return types.DefaultTypeAdapter.NativeToValue([]any{ + a0, a1, + }) + + }), + ), +) + +var stringsHumanSizeGen = cel.Function("HumanSize", + cel.Overload("HumanSize_interface{}", + + []*cel.Type{ + cel.DynType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x StringFuncs + + a0, _ := x.HumanSize(conv.ToString(args[0])) // Never returns error + return types.String(a0) + }), + ), +) + +var stringsSemverGen = cel.Function("Semver", + cel.Overload("Semver_string", + + []*cel.Type{ + cel.StringType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x StringFuncs + + a0, a1 := x.SemverMap(args[0].Value().(string)) + if a1 != nil { + return types.String("") + } + + + return types.DefaultTypeAdapter.NativeToValue(a0) + }), + ), +) + +var stringsSemverCompareGen = cel.Function("SemverCompare", + cel.Overload("SemverCompare_string_string", + + []*cel.Type{ + cel.StringType, cel.StringType, + }, + cel.DynType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x StringFuncs + + a0, a1 := x.SemverCompare(args[0].Value().(string), args[1].Value().(string)) + if a1 != nil { + return types.Bool(false) + } + + return types.DefaultTypeAdapter.NativeToValue(a0) + + }), + ), +) var stringsAbbrevGen = cel.Function("Abbrev", cel.Overload("Abbrev_interface{}", diff --git a/funcs/test.go b/funcs/test.go index 97f0b5c8b..35f65f94d 100644 --- a/funcs/test.go +++ b/funcs/test.go @@ -117,3 +117,10 @@ func (f TestFuncs) IsKind(kind string, arg interface{}) bool { } return k == kind } + +func must(r interface{}, err error) interface{} { + if err != nil { + panic(err) + } + return r +} diff --git a/funcs/time.go b/funcs/time.go index 8bf92d8b3..071a8ea31 100644 --- a/funcs/time.go +++ b/funcs/time.go @@ -3,12 +3,12 @@ package funcs import ( "context" "fmt" + "os" "strconv" "strings" gotime "time" "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/env" "github.com/flanksource/gomplate/v3/time" ) @@ -105,7 +105,10 @@ func (TimeFuncs) Parse(layout string, value interface{}) (gotime.Time, error) { // ParseLocal - func (f TimeFuncs) ParseLocal(layout string, value interface{}) (gotime.Time, error) { - tz := env.Getenv("TZ", "Local") + tz := os.Getenv("TZ") + if tz == "" { + tz = "Local" + } return f.ParseInLocation(layout, tz, value) } diff --git a/gcp/meta.go b/gcp/meta.go deleted file mode 100644 index b2a20ac21..000000000 --- a/gcp/meta.go +++ /dev/null @@ -1,130 +0,0 @@ -package gcp - -import ( - "fmt" - "io" - "net/http" - "strconv" - "strings" - "sync" - "time" - - "github.com/flanksource/gomplate/v3/env" -) - -// DefaultEndpoint is the DNS name for the default GCP compute instance metadata service. -var DefaultEndpoint = "http://metadata.google.internal" - -var ( - // co is a ClientOptions populated from the environment. - co ClientOptions - // coInit ensures that `co` is only set once. - coInit sync.Once -) - -// ClientOptions contains various user-specifiable options for a MetaClient. -type ClientOptions struct { - Timeout time.Duration -} - -// GetClientOptions - Centralised reading of GCP_TIMEOUT -// ... but cannot use in vault/auth.go as different strconv.Atoi error handling -func GetClientOptions() ClientOptions { - coInit.Do(func() { - timeout := env.Getenv("GCP_TIMEOUT") - if timeout == "" { - timeout = "500" - } - - t, err := strconv.Atoi(timeout) - if err != nil { - panic(fmt.Errorf("invalid GCP_TIMEOUT value '%s' - must be an integer: %w", timeout, err)) - } - - co.Timeout = time.Duration(t) * time.Millisecond - }) - return co -} - -// MetaClient is used to access metadata accessible via the GCP compute instance -// metadata service version 1. -type MetaClient struct { - client *http.Client - cache map[string]string - endpoint string - options ClientOptions -} - -// NewMetaClient constructs a new MetaClient with the given ClientOptions. If the environment -// contains a variable named `GCP_META_ENDPOINT`, the client will address that, if not the -// value of `DefaultEndpoint` is used. -func NewMetaClient(options ClientOptions) *MetaClient { - endpoint := env.Getenv("GCP_META_ENDPOINT") - if endpoint == "" { - endpoint = DefaultEndpoint - } - - return &MetaClient{ - cache: make(map[string]string), - endpoint: endpoint, - options: options, - } -} - -// Meta retrieves a value from the GCP Instance Metadata Service, returning the given default -// if the service is unavailable or the requested URL does not exist. -func (c *MetaClient) Meta(key string, def ...string) (string, error) { - url := c.endpoint + "/computeMetadata/v1/instance/" + key - return c.retrieveMetadata(url, def...) -} - -// retrieveMetadata executes an HTTP request to the GCP Instance Metadata Service with the -// correct headers set, and extracts the returned value. -func (c *MetaClient) retrieveMetadata(url string, def ...string) (string, error) { - if value, ok := c.cache[url]; ok { - return value, nil - } - - if c.client == nil { - timeout := c.options.Timeout - if timeout == 0 { - timeout = 500 * time.Millisecond - } - c.client = &http.Client{Timeout: timeout} - } - - request, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return returnDefault(def), nil - } - request.Header.Add("Metadata-Flavor", "Google") - - resp, err := c.client.Do(request) - if err != nil { - return returnDefault(def), nil - } - - // nolint: errcheck - defer resp.Body.Close() - if resp.StatusCode > 399 { - return returnDefault(def), nil - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read response body from %s: %w", url, err) - } - value := strings.TrimSpace(string(body)) - c.cache[url] = value - - return value, nil -} - -// returnDefault returns the first element of the given slice (often taken from varargs) -// if there is one, or returns an empty string if the slice has no elements. -func returnDefault(def []string) string { - if len(def) > 0 { - return def[0] - } - return "" -} diff --git a/gencel/file.go b/gencel/file.go index c456abe41..ed960961e 100644 --- a/gencel/file.go +++ b/gencel/file.go @@ -1,6 +1,7 @@ package gencel import ( + "fmt" "go/ast" "log" "regexp" @@ -38,6 +39,8 @@ func (t *File) visitor(n ast.Node) bool { } func (t *File) handleFuncDecl(n *ast.FuncDecl) bool { + + fmt.Printf("handle: %s", n.Name.Name) for _, blf := range blacklistedFuncs { if blf.MatchString(n.Name.Name) { log.Printf("Ignoring func [%s]. Blacklisted pattern", n.Name.Name) diff --git a/gencel/generator.go b/gencel/generator.go index e0da650d3..37e481cbb 100644 --- a/gencel/generator.go +++ b/gencel/generator.go @@ -11,7 +11,6 @@ import ( "strings" "text/template" - "github.com/flanksource/commons/logger" "golang.org/x/tools/go/packages" ) @@ -42,10 +41,12 @@ func (g *Generator) ParsePkg(patterns ...string) { } pkgs, err := packages.Load(cfg, patterns...) if err != nil { - logger.Fatalf("failed to load packages: %v", err) + fmt.Printf("failed to load packages: %v", err) + os.Exit(1) } if len(pkgs) != 1 { - logger.Fatalf("expected 1 packages but found %d", len(pkgs)) + fmt.Printf("expected 1 packages but found %d", len(pkgs)) + os.Exit(1) } g.addPackage(pkgs[0]) @@ -65,10 +66,6 @@ func (g *Generator) addPackage(pkg *packages.Package) { g.pkg.baseDir = filepath.Dir(pkg.GoFiles[0]) for i, astFile := range pkg.Syntax { - if _, ok := exlusions[filepath.Base(pkg.GoFiles[i])]; ok { - logger.Infof("Excluding file: %s", pkg.GoFiles[i]) - continue - } g.pkg.files = append(g.pkg.files, &File{ file: astFile, @@ -105,7 +102,8 @@ func (g *Generator) generateExports() { outputName := filepath.Join(g.pkg.baseDir, "cel_gen_exports.go") err := os.WriteFile(outputName, g.format(), 0644) if err != nil { - logger.Fatalf("error writing to file: %v", err) + fmt.Printf("error writing to file: %v", err) + os.Exit(1) } } @@ -162,7 +160,8 @@ func (g *Generator) generateFile(file *File) { outputName := filepath.Join(filepath.Dir(file.path), fmt.Sprintf("%s_gen.go", fileName)) err := os.WriteFile(outputName, g.format(), 0644) if err != nil { - logger.Fatalf("%v", err) + fmt.Printf("%v", err) + os.Exit(1) } } @@ -189,7 +188,8 @@ func (g *Generator) renderHeader(pkgName string, imports ...PkgImport) { func (g *Generator) printf(format string, args ...interface{}) { _, err := fmt.Fprintf(&g.buf, format, args...) if err != nil { - logger.Fatalf("fmt.Fprintf(): %v", err) + fmt.Printf("fmt.Fprintf(): %v", err) + os.Exit(1) } } @@ -198,12 +198,15 @@ func (g *Generator) renderExport(model interface{}) { t, err := t.Parse(exportAllTemplate) if err != nil { - logger.Fatalf("instance template parse: %v", err) + fmt.Printf("instance template parse: %v", err) + os.Exit(1) } err = t.Execute(&g.buf, model) if err != nil { - logger.Fatalf("Execute: %v", err) + fmt.Printf("Execute: %v", err) + os.Exit(1) + } } @@ -212,26 +215,29 @@ func (g *Generator) render(model interface{}) { t, err := t.Parse(funcDefTemplate) if err != nil { - logger.Fatalf("instance template parse: %v", err) + fmt.Printf("instance template parse: %v", err) + os.Exit(1) } t, err = t.Parse(funcBodyTemplate) if err != nil { - logger.Fatalf("instance template parse: %v", err) + fmt.Printf("instance template parse: %v", err) + os.Exit(1) + } err = t.Execute(&g.buf, model) if err != nil { - logger.Fatalf("Execute: %v", err) - return + fmt.Printf("Execute: %v", err) + os.Exit(1) } } func (g *Generator) format() []byte { src, err := format.Source(g.buf.Bytes()) if err != nil { - logger.Debugf("warning: internal error: invalid Go generated: %s", err) - logger.Debugf("warning: compile the package to analyze the error") + fmt.Printf("warning: internal error: invalid Go generated: %s", err) + fmt.Printf("warning: compile the package to analyze the error") return g.buf.Bytes() } return src @@ -240,18 +246,7 @@ func (g *Generator) format() []byte { // Some imports are difficult to infer. // We hardcode some imports for some files here. var importConf = map[string][]PkgImport{ - "time.go": {{alias: "gotime", importPath: "time"}}, - "sockaddr.go": {{alias: "sockaddr", importPath: "github.com/hashicorp/go-sockaddr"}}, -} - -// List of files that should be excluded. -// We don't generate cel functions for these files. -var exlusions = map[string]struct{}{ - "aws.go": {}, - "base64.go": {}, - "env.go": {}, - "gcp.go": {}, - "net.go": {}, + "time.go": {{alias: "gotime", importPath: "time"}}, } // List of files that shouldn't be namespaced. @@ -262,4 +257,5 @@ var exlusions = map[string]struct{}{ var notNamespaced = map[string]struct{}{ "coll.go": {}, "strings.go": {}, + "k8s.go": {}, } diff --git a/go.mod b/go.mod index 01ab71aff..3903e2f74 100644 --- a/go.mod +++ b/go.mod @@ -1,33 +1,24 @@ module github.com/flanksource/gomplate/v3 -go 1.20 +go 1.19 require ( github.com/Masterminds/goutils v1.1.1 - github.com/Masterminds/sprig v2.22.0+incompatible - github.com/Shopify/ejson v1.3.3 - github.com/apparentlymart/go-cidr v1.1.0 - github.com/aws/aws-sdk-go v1.44.234 - github.com/flanksource/commons v1.10.0 - github.com/go-git/go-billy/v5 v5.4.1 - github.com/go-git/go-git/v5 v5.6.1 - github.com/google/cel-go v0.13.0 + github.com/Masterminds/semver/v3 v3.2.1 + github.com/flanksource/is-healthy v0.0.0-20230705092916-3b4cf510c5fc + github.com/google/cel-go v0.16.0 github.com/google/uuid v1.3.0 github.com/gosimple/slug v1.13.1 github.com/hairyhenderson/toml v0.4.2-0.20210923231440-40456b8e66cf - github.com/hashicorp/go-sockaddr v1.0.2 - github.com/itchyny/gojq v0.12.10 - github.com/joho/godotenv v1.5.1 + github.com/itchyny/gojq v0.12.13 github.com/pkg/errors v0.9.1 - github.com/rs/zerolog v1.29.0 - github.com/spf13/afero v1.9.5 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 github.com/ugorji/go/codec v1.2.11 - gocloud.dev v0.29.0 - golang.org/x/crypto v0.7.0 - golang.org/x/text v0.8.0 + golang.org/x/text v0.11.0 golang.org/x/tools v0.7.0 gotest.tools/v3 v3.4.0 + k8s.io/apimachinery v0.27.3 + sigs.k8s.io/yaml v1.3.0 ) // TODO: replace with gopkg.in/yaml.v3 after https://github.com/go-yaml/yaml/pull/862 @@ -35,83 +26,36 @@ require ( require github.com/hairyhenderson/yaml v0.0.0-20220618171115-2d35fca545ce require ( - cloud.google.com/go v0.110.0 // indirect - cloud.google.com/go/compute v1.19.0 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect - cloud.google.com/go/storage v1.30.1 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230331115716-d34776aa93ec // indirect - github.com/acomagu/bufpipe v1.0.4 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2 v1.17.7 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/config v1.18.19 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.18 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.60 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 // indirect - github.com/aws/aws-sdk-go-v2/service/s3 v1.31.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 // indirect - github.com/aws/smithy-go v1.13.5 // indirect - github.com/cloudflare/circl v1.3.2 // indirect + github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/wire v0.5.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.8.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/gosimple/unidecode v1.0.1 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/huandu/xstrings v1.4.0 // indirect - github.com/imdario/mergo v0.3.15 // indirect github.com/itchyny/timefmt-go v0.1.5 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/sergi/go-diff v1.3.1 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - github.com/skeema/knownhosts v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - go.opencensus.io v0.24.0 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.24.0 // indirect + github.com/yuin/gopher-lua v1.1.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.114.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633 // indirect - google.golang.org/grpc v1.54.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.27.3 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect + layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index 26f262d36..972cfb1ad 100644 --- a/go.sum +++ b/go.sum @@ -1,2966 +1,151 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.82.0/go.mod h1:vlKccHJGuFBFufnAnuB08dfEH9Y3H7dzDzRECFdC2TA= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.109.0/go.mod h1:2sYycXt75t/CSB5R9M2wPU1tJmire7AQZTPtITcGBVE= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.2/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.0/go.mod h1:eF3Qsw58iX/bkKtVjMTYpH0LRjQ2goDkjkNQTlzq/ZM= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= -contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= -contrib.go.opencensus.io/exporter/stackdriver v0.13.14/go.mod h1:5pSSGY0Bhuk7waTHuDf4aQ8D2DrhgETRo9fy6k3Xlzc= -contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= -github.com/Azure/azure-amqp-common-go/v3 v3.2.3/go.mod h1:7rPmbSfszeovxGfc5fSAXE4ehlXQZHpMja2OtxC2Tas= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v63.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v66.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.2/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.1/go.mod h1:DffdKW9RFqa5VgmsjUOsS7UE7eiA5iAvYUs63bhKQ0M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.9.0/go.mod h1:EAyXOW1F6BTJPiK2pDvmnvxOHPxoTYWoqBeIlql+QhI= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= -github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.2.0/go.mod h1:R6+0udeRV8iYSTVuT5RT7If4sc46K5Bz3ZKrmvZQF7U= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= -github.com/Azure/go-amqp v0.17.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= -github.com/Azure/go-amqp v0.18.1/go.mod h1:+bg0x3ce5+Q3ahCEXnCsGG3ETpDQe3MEVnOuT2ywPwc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.25/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/GoogleCloudPlatform/cloudsql-proxy v1.33.2/go.mod h1:uqoR4sJc63p7ugW8a/vsEspOsNuehbi7ptS2CHCyOnY= -github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= -github.com/ProtonMail/go-crypto v0.0.0-20230331115716-d34776aa93ec h1:eQusauqzE1cAFR5hGnwkuSmFxKoy3+j9/cVaDeYfjjs= -github.com/ProtonMail/go-crypto v0.0.0-20230331115716-d34776aa93ec/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/ejson v1.3.3 h1:dPzgmvFhUPTJIzwdF5DaqbwW1dWaoR8ADKRdSTy6Mss= -github.com/Shopify/ejson v1.3.3/go.mod h1:VZMUtDzvBW/PAXRUF5fzp1ffb1ucT8MztrZXXLYZurw= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= -github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= -github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.156/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go v1.44.187/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go v1.44.200/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go v1.44.234 h1:8YbQ5AhpgV/cC7jYX8qS34Am/vcn2ZoIFJ1qIgwOL+0= -github.com/aws/aws-sdk-go v1.44.234/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= -github.com/aws/aws-sdk-go-v2 v1.17.4/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2 v1.17.7 h1:CLSjnhJSTSogvqUGhIC6LqFKATMRexcxLZ0i/Nzk9Eg= -github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.18.12/go.mod h1:J36fOhj1LQBr+O4hJCiT8FwVvieeoSGOtPuvhKlsNu8= -github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw= -github.com/aws/aws-sdk-go-v2/config v1.18.19/go.mod h1:XvTmGMY8d52ougvakOv1RpiTLPz9dlG/OQHsKU/cMmY= -github.com/aws/aws-sdk-go-v2/credentials v1.13.12/go.mod h1:37HG2MBroXK3jXfxVGtbM2J48ra2+Ltu+tmwr/jO0KA= -github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1hD6l3+RWFQABET4c= -github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.22/go.mod h1:YGSIJyQ6D6FjKMQh16hVFSIUD54L4F7zTGePqYMYYJU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.51/go.mod h1:7Grl2gV+dx9SWrUIgwwlUvU40t7+lOSbx34XwfmsTkY= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.60 h1:BRLcU36boYxw6BPOEvwJbDPuCtP7FqMhXMFk2NM6poM= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.60/go.mod h1:HLWzCoNyzaPkOOs9yZ3muJ91lSk8O9DJbJw5aKAWWHY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28/go.mod h1:3lwChorpIM/BhImY/hy+Z6jekmN92cXGPI1QJasVPYY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 h1:sJLYcS+eZn5EeNINGHSCRAwUJMFVqklwkH36Vbyai7M= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22/go.mod h1:EqK7gVrIGAHyZItrD1D8B0ilgwMD1GiWAmbU4u/JHNk= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 h1:1mnRASEKnkqsntcxHaysxwgVoUUp5dkiB+l3llKnqyg= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.29/go.mod h1:TwuqRBGzxjQJIwH16/fOZodwXt2Zxa9/cwJC5ke4j7s= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.19/go.mod h1:8W88sW3PjamQpKFUQvHWWKay6ARsNvZnzU7+a4apubw= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23/go.mod h1:uIiFgURZbACBEQJfqTZPb/jxO7R+9LeoHUFudtIdeQI= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.23/go.mod h1:1jcUfF+FAOEwtIcNiHPaV4TSoZqkUIPzrohmD7fb95c= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 h1:CeuSeq/8FnYpPtnuIeLQEEvDv9zUjneuYi8EghMBdwQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26/go.mod h1:2UqAAwMUXKeRkAHIlDJqvMVgOWkUi/AUXPk/YIe+Dg4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.22/go.mod h1:xt0Au8yPIwYXf/GYPy/vl4K3CgwhfQMYbrH7DlUUIws= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 h1:5LHn8JQ0qvjD9L9JhMtylnkcw7j05GDZqM9Oin6hpr0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25/go.mod h1:/95IA+0lMnzW6XzqYJRpjjsAbKEORVeO0anQqjd2CNU= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.22/go.mod h1:QFVbqK54XArazLvn2wvWMRBi/jGrWii46qbr5DyPGjc= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 h1:e2ooMhpYGhDnBfSvIyusvAwX7KexuZaHbQY2Dyei7VU= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0/go.mod h1:bh2E0CXKZsQN+faiKVqC40vfNMAWheoULBCnEgO9K+8= -github.com/aws/aws-sdk-go-v2/service/kms v1.20.2/go.mod h1:vdqtUOdVuf5ooy+hJ2GnzqNo94xiAA9s1xbZ1hQgRE0= -github.com/aws/aws-sdk-go-v2/service/s3 v1.30.2/go.mod h1:SXDHd6fI2RhqB7vmAzyYQCTQnpZrIprVJvYxpzW3JAM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.31.1 h1:PJH4I+qYjPXclKRbVCW47iYUvtXEh1u6YmDhn5J8VQE= -github.com/aws/aws-sdk-go-v2/service/s3 v1.31.1/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.18.3/go.mod h1:hqPcyOuLU6yWIbLy3qMnQnmidgKuIEwqIlW6+chYnog= -github.com/aws/aws-sdk-go-v2/service/sns v1.20.2/go.mod h1:VN2n9SOMS1lNbh5YD7o+ho0/rgfifSrK//YYNiVVF5E= -github.com/aws/aws-sdk-go-v2/service/sqs v1.20.2/go.mod h1:1ttxGjUHZliCQMpPss1sU5+Ph/5NvdMFRzr96bv8gm0= -github.com/aws/aws-sdk-go-v2/service/ssm v1.35.2/go.mod h1:VLSz2SHUKYFSOlXB/GlXoLU6KPYQJAbw7I20TDJdyws= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.1/go.mod h1:IgV8l3sj22nQDd5qcAGY0WenwCzCphqdbFOpfktZPrI= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.1/go.mod h1:O1YSOg3aekZibh2SngvCRRG+cRHKKlYgxf/JBF/Kr/k= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6/go.mod h1:Lh/bc9XUf8CfOY6Jp5aIkQtN+j1mc+nExc+KXj9jx2s= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.3/go.mod h1:b+psTJn33Q4qGoDaM7ZiOVVG8uVjGI6HaZ8WBHdgDgU= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 h1:bWNgNdRko2x6gqa0blfATqAZKZokPIeM1vfmQt2pnvM= -github.com/aws/aws-sdk-go-v2/service/sts v1.18.7/go.mod h1:JuTnSoeePXmMVe9G8NcjjwgOKEfZ4cOjMuT2IBT/2eI= -github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= -github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/circl v1.3.2 h1:VWp8dY3yH69fdM7lM6A1+NhhVoDu9vqK0jOgmkQHFWk= -github.com/cloudflare/circl v1.3.2/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= 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/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/digitalocean/godo v1.78.0/go.mod h1:GBmu8MkjZmNARE7IXRPmkbbnocNN8+uBm0xbEVw2LCs= -github.com/digitalocean/godo v1.95.0/go.mod h1:NRpFznZFvhHjBoqZAaOD3khVzsJ3EibzKqFL4R60dmA= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.23+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKBAG3Klr9cn7N+LcYc82AZ2S7+cA= -github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flanksource/commons v1.10.0 h1:Mc+fzxq1rOJ08lapF0cc0bo9ZKNDxA7/81q2D/5jt0Q= -github.com/flanksource/commons v1.10.0/go.mod h1:HpVjPtNe7v0UPk97kO/uUhOrYQ8yFD/mGglrTCkc9Ag= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= -github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= -github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= -github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= -github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ= -github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= -github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= -github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/flanksource/is-healthy v0.0.0-20230705092916-3b4cf510c5fc h1:CPUNUw2pHnlF4ucBHx44vLTcCa4FlEEu6PkNo5rCvD4= +github.com/flanksource/is-healthy v0.0.0-20230705092916-3b4cf510c5fc/go.mod h1:4pQhmF+TnVqJroQKY8wSnSp+T18oLson6YQ2M0qPHfQ= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.23.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= -github.com/go-openapi/runtime v0.25.0/go.mod h1:Ux6fikcHXyyob6LNWxtE96hWwjBPYF0DXgVFuMTneOs= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.7/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-openapi/validate v0.22.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.13.0 h1:z+8OBOcmh7IeKyqwT/6IlnMvy621fYUqnTVPEdegGlU= -github.com/google/cel-go v0.13.0/go.mod h1:K2hpQgEjDp18J76a2DKFRlPBPpgRZgi6EbnpDgIhJ8s= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= +github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE= -github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk= -github.com/google/go-replayers/httpreplay v1.1.1 h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY= -github.com/google/go-replayers/httpreplay v1.1.1/go.mod h1:gN9GeLIs7l6NUoVaSSnv2RiqK1NiwAmD0MrKeC9IIks= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= -github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20220318212150-b2ab0324ddda/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20230111200839-76d1ae5aea2b/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= -github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gophercloud/gophercloud v0.24.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c= -github.com/gophercloud/gophercloud v1.1.1/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q= github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= -github.com/grafana/regexp v0.0.0-20220304095617-2e8d9baf4ac2/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.1/go.mod h1:G+WkljZi4mflcqVxYSgvt8MNctRQHjEH8ubKtt1Ka3w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/hairyhenderson/toml v0.4.2-0.20210923231440-40456b8e66cf h1:I1sbT4ZbIt9i+hB1zfKw2mE8C12TuGxPiW7YmtLbPa4= github.com/hairyhenderson/toml v0.4.2-0.20210923231440-40456b8e66cf/go.mod h1:jDHmWDKZY6MIIYltYYfW4Rs7hQ50oS4qf/6spSiZAxY= github.com/hairyhenderson/yaml v0.0.0-20220618171115-2d35fca545ce h1:cVkYhlWAxwuS2/Yp6qPtcl0fGpcWxuZNonywHZ6/I+s= github.com/hairyhenderson/yaml v0.0.0-20220618171115-2d35fca545ce/go.mod h1:7TyiGlHI+IO+iJbqRZ82QbFtvgj/AIcFm5qc9DLn7Kc= -github.com/hanwen/go-fuse/v2 v2.2.0/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= -github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/api v1.18.0/go.mod h1:owRRGJ9M5xReDC5nfT8FTJrNAPbT4NM6p/k+d03q2v4= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= -github.com/hashicorp/consul/sdk v0.13.0/go.mod h1:0hs/l5fOVhJy/VdcoaNqUSi2AUs95eF5WKtv+EYIQqE= -github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= -github.com/hashicorp/nomad/api v0.0.0-20230124213148-69fd1a0e4bf7/go.mod h1:xYYd4dybIhRhhzDemKx7Ddt8CvCosgrEek8YM7/cF0A= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hetznercloud/hcloud-go v1.33.1/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME= -github.com/hetznercloud/hcloud-go v1.39.0/go.mod h1:mepQwR6va27S3UQthaEPGS86jtzSY9xWL1e9dyxXpgA= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= -github.com/ionos-cloud/sdk-go/v6 v6.1.3/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME= -github.com/itchyny/gojq v0.12.10 h1:6TcS0VYWS6wgntpF/4tnrzwdCMjiTxRAxIqZWfDsDQU= -github.com/itchyny/gojq v0.12.10/go.mod h1:o3FT8Gkbg/geT4pLI0tF3hvip5F3Y/uskjRz9OYa38g= +github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= +github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= -github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= -github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= -github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/kolo/xmlrpc v0.0.0-20201022064351-38db28db192b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= -github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/linode/linodego v1.4.0/go.mod h1:PVsRxSlOiJyvG4/scTszpmZDTdgS+to3X6eS8pRrWI8= -github.com/linode/linodego v1.12.0/go.mod h1:NJlzvlNtdMRRkXb0oN6UWzUkj6t+IBsyveHgZ5Ppjyk= -github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/microsoft/ApplicationInsights-Go v0.4.4/go.mod h1:fKRUseBqkw6bDiXTs3ESTiU/4YTIHsQS4W3fP2ieF4U= -github.com/microsoft/go-mssqldb v0.18.0/go.mod h1:ukJCBnnzLzpVF0qYRT+eg1e+eSwjeQ7IvenUv8QPook= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.48/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= -github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= -github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= -github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= -github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= -github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= -github.com/ovh/go-ovh v1.3.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/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= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/alertmanager v0.24.0/go.mod h1:r6fy/D7FRuZh5YbnX6J3MBY0eI4Pb5yPYS7/bPSXXqI= -github.com/prometheus/alertmanager v0.25.0/go.mod h1:MEZ3rFVHqKZsw7IcNS/m4AWZeXThmJhumpiWR4eHU/w= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.38.0/go.mod h1:MBXfmBQZrK5XpbCkjofnXs96LD2QQ7fEq4C0xjC/yec= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/common/assets v0.1.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= -github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= -github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= -github.com/prometheus/exporter-toolkit v0.7.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= -github.com/prometheus/exporter-toolkit v0.8.2/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/prometheus v0.35.0/go.mod h1:7HaLx5kEPKJ0GDgbODG0fZgXbQ8K/XjZNJXQmbmgQlY= -github.com/prometheus/prometheus v0.42.0/go.mod h1:Pfqb/MLnnR2KK+0vchiaH39jXxvLMBk+3lnIGP4N7Vk= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rakyll/embedmd v0.0.0-20171029212350-c8060a0752a2/go.mod h1:7jOTMgqac46PZcF54q6l2hkLEG8op93fZu61KmxWDV4= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= -github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.12/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/shoenig/test v0.6.0/go.mod h1:xYtyGBC5Q3kzCNyJg/SjgNpfAa2kvmgA0i5+lQso8x0= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0= -github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.31.0/go.mod h1:PFmBsWbldL1kiWZk9+0LBZz2brhByaGsvp6pRICMlPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.37.0/go.mod h1:+ARmXlUlc51J7sZeCBkBJNdHGySrdOzgzxp6VWRWM1U= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel v1.6.0/go.mod h1:bfJD2DZVw0LBxghOTlgnlI0CV3hLDu9XF/QKOUXMTQQ= -go.opentelemetry.io/otel v1.6.1/go.mod h1:blzUabWHkX6LJewxvadmzafgh/wnvBSDBdOuwkAtrWQ= -go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE= -go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.6.1/go.mod h1:NEu79Xo32iVb+0gVNV8PMd7GoWqnyDXRlj04yFjqz40= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.6.1/go.mod h1:YJ/JbY5ag/tSQFXzH3mtDmHqzF3aFn3DI/aB1n7pt4w= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2/go.mod h1:5Qn6qvgkMsLDX+sYK64rHb1FPhpn0UtxF+ouX1uhyJE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.6.1/go.mod h1:UJJXJj0rltNIemDMwkOJyggsvyMG9QHfJeFH0HS5JjM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2/go.mod h1:jWZUM2MWhWCJ9J9xVbRx7tzK1mXKpAlze4CeulycwVY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.6.1/go.mod h1:DAKwdo06hFLc0U88O10x4xnb5sc7dDRDqRuiN+io8JE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2/go.mod h1:GZWSQQky8AgdJj50r1KJm8oiQiIPaAX7uZCFQX9GzC8= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/metric v0.28.0/go.mod h1:TrzsfQAmQaB1PDcdhBauLMk7nyyg9hm+GoQq/ekE9Iw= -go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= -go.opentelemetry.io/otel/sdk v1.6.1/go.mod h1:IVYrddmFZ+eJqu2k38qD3WezFR2pymCzm8tdxyh3R4E= -go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys= -go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= -go.opentelemetry.io/otel/trace v1.6.0/go.mod h1:qs7BrU5cZ8dXQHBGxHMOxwME/27YH2qEp4/+tZLLwJE= -go.opentelemetry.io/otel/trace v1.6.1/go.mod h1:RkFRM1m0puWIq10oxImnGEduNBzxiN7TXluRBtE+5j0= -go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= -go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= -go.opentelemetry.io/proto/otlp v0.12.1/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -gocloud.dev v0.29.0 h1:fBy0jwJSmxs0IjT0fE32MO+Mj+307VZQwyHaTyFZbC4= -gocloud.dev v0.29.0/go.mod h1:E3dAjji80g+lIkq4CQeF/BTWqv1CBeTftmOb+gpyapQ= -golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= +github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp v0.0.0-20230124195608-d38c7dcee874/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20220921155015-db77216a4ee9/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= -google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.104.0/go.mod h1:JCspTXJbBxa5ySXw4UgUqVer7DfVxbvc/CTUFqAED5U= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221205194025-8222ab48f5fc/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0= -google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633 h1:0BOZf6qNozI3pkN3fJLwNubheHJYHhMh91GRFOWWK08= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.1/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 h1:m8v1xLLLzMe1m5P+gCTF8nJB9epwZQUBERm20Oy1poQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/telebot.v3 v3.0.0/go.mod h1:7rExV8/0mDDNu9epSrDm/8j22KLaActH1Tbee6YjzWg= -gopkg.in/telebot.v3 v3.1.2/go.mod h1:GJKwwWqp9nSkIVN51eRKU78aB5f5OnQuWdwiIZfPbko= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= -k8s.io/api v0.23.5/go.mod h1:Na4XuKng8PXJ2JsploYYrivXrINeTaycCGcYgF91Xm8= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= -k8s.io/apimachinery v0.23.5/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= -k8s.io/client-go v0.23.5/go.mod h1:flkeinTO1CirYgzMPRWxUCnV0G4Fbu2vLhYCObnt/r4= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +k8s.io/api v0.27.3 h1:yR6oQXXnUEBWEWcvPWS0jQL575KoAboQPfJAuKNrw5Y= +k8s.io/api v0.27.3/go.mod h1:C4BNvZnQOF7JA/0Xed2S+aUyJSfTGkGFxLXz9MnpIpg= +k8s.io/apimachinery v0.27.3 h1:Ubye8oBufD04l9QnNtW05idcOe9Z3GQN8+7PqmuVcUM= +k8s.io/apimachinery v0.27.3/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf h1:rRz0YsF7VXj9fXRF6yQgFI7DzST+hsI3TeFSGupntu0= +layeh.com/gopher-json v0.0.0-20201124131017-552bb3c4c3bf/go.mod h1:ivKkcY8Zxw5ba0jldhZCYYQfGdb2K6u9tbYK1AwMIBc= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/config/configfile.go b/internal/config/configfile.go deleted file mode 100644 index d9e617087..000000000 --- a/internal/config/configfile.go +++ /dev/null @@ -1,652 +0,0 @@ -package config - -import ( - "bytes" - "context" - "fmt" - "io" - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/flanksource/gomplate/v3/internal/iohelpers" - "github.com/hairyhenderson/yaml" - "github.com/pkg/errors" -) - -// Parse a config file -func Parse(in io.Reader) (*Config, error) { - out := &Config{} - dec := yaml.NewDecoder(in) - err := dec.Decode(out) - if err != nil && err != io.EOF { - return out, err - } - return out, nil -} - -// Config - configures the gomplate execution -type Config struct { - Stdin io.Reader `yaml:"-"` - Stdout io.Writer `yaml:"-"` - Stderr io.Writer `yaml:"-"` - - DataSources map[string]DataSource `yaml:"datasources,omitempty"` - Context map[string]DataSource `yaml:"context,omitempty"` - Plugins map[string]PluginConfig `yaml:"plugins,omitempty"` - Templates Templates `yaml:"templates,omitempty"` - - // Extra HTTP headers not attached to pre-defined datsources. Potentially - // used by datasources defined in the template. - ExtraHeaders map[string]http.Header `yaml:"-"` - - // internal use only, can't be injected in YAML - PostExecInput io.Reader `yaml:"-"` - - Input string `yaml:"in,omitempty"` - InputDir string `yaml:"inputDir,omitempty"` - InputFiles []string `yaml:"inputFiles,omitempty,flow"` - ExcludeGlob []string `yaml:"excludes,omitempty"` - - OutputDir string `yaml:"outputDir,omitempty"` - OutputMap string `yaml:"outputMap,omitempty"` - OutputFiles []string `yaml:"outputFiles,omitempty,flow"` - OutMode string `yaml:"chmod,omitempty"` - - LDelim string `yaml:"leftDelim,omitempty"` - RDelim string `yaml:"rightDelim,omitempty"` - - PostExec []string `yaml:"postExec,omitempty,flow"` - - PluginTimeout time.Duration `yaml:"pluginTimeout,omitempty"` - - ExecPipe bool `yaml:"execPipe,omitempty"` - SuppressEmpty bool `yaml:"suppressEmpty,omitempty"` - Experimental bool `yaml:"experimental,omitempty"` -} - -var experimentalCtxKey = struct{}{} - -func SetExperimental(ctx context.Context) context.Context { - return context.WithValue(ctx, experimentalCtxKey, true) -} - -func ExperimentalEnabled(ctx context.Context) bool { - v, ok := ctx.Value(experimentalCtxKey).(bool) - return ok && v -} - -// mergeDataSources - use d as defaults, and override with values from o -func mergeDataSources(d, o map[string]DataSource) map[string]DataSource { - for k, v := range o { - c, ok := d[k] - if ok { - d[k] = c.mergeFrom(v) - } else { - d[k] = v - } - } - return d -} - -// DataSource - datasource configuration -type DataSource struct { - URL *url.URL `yaml:"-"` - Header http.Header `yaml:"header,omitempty,flow"` -} - -// UnmarshalYAML - satisfy the yaml.Umarshaler interface - URLs aren't -// well supported, and anyway we need to do some extra parsing -func (d *DataSource) UnmarshalYAML(value *yaml.Node) error { - type raw struct { - Header http.Header - URL string - } - r := raw{} - err := value.Decode(&r) - if err != nil { - return err - } - u, err := ParseSourceURL(r.URL) - if err != nil { - return fmt.Errorf("could not parse datasource URL %q: %w", r.URL, err) - } - *d = DataSource{ - URL: u, - Header: r.Header, - } - return nil -} - -// MarshalYAML - satisfy the yaml.Marshaler interface - URLs aren't -// well supported, and anyway we need to do some extra parsing -func (d DataSource) MarshalYAML() (interface{}, error) { - type raw struct { - Header http.Header - URL string - } - r := raw{ - URL: d.URL.String(), - Header: d.Header, - } - return r, nil -} - -// mergeFrom - use this as default, and override with values from o -func (d DataSource) mergeFrom(o DataSource) DataSource { - if o.URL != nil { - d.URL = o.URL - } - if d.Header == nil { - d.Header = o.Header - } else { - for k, v := range o.Header { - d.Header[k] = v - } - } - return d -} - -type PluginConfig struct { - Cmd string - Timeout time.Duration - Pipe bool -} - -// UnmarshalYAML - satisfy the yaml.Umarshaler interface - plugin configs can -// either be a plain string (to specify only the name), or a map with a name, -// timeout, and pipe flag. -func (p *PluginConfig) UnmarshalYAML(value *yaml.Node) error { - if value.Kind == yaml.ScalarNode { - s := "" - err := value.Decode(&s) - if err != nil { - return err - } - - *p = PluginConfig{Cmd: s} - return nil - } - - if value.Kind != yaml.MappingNode { - return fmt.Errorf("plugin config must be a string or map") - } - - type raw struct { - Cmd string - Timeout time.Duration - Pipe bool - } - r := raw{} - err := value.Decode(&r) - if err != nil { - return err - } - - *p = PluginConfig(r) - - return nil -} - -// MergeFrom - use this Config as the defaults, and override it with any -// non-zero values from the other Config -// -// Note that Input/InputDir/InputFiles will override each other, as well as -// OutputDir/OutputFiles. -func (c *Config) MergeFrom(o *Config) *Config { - switch { - case !isZero(o.Input): - c.Input = o.Input - c.InputDir = "" - c.InputFiles = nil - c.OutputDir = "" - case !isZero(o.InputDir): - c.Input = "" - c.InputDir = o.InputDir - c.InputFiles = nil - case !isZero(o.InputFiles): - if !(len(o.InputFiles) == 1 && o.InputFiles[0] == "-") { - c.Input = "" - c.InputFiles = o.InputFiles - c.InputDir = "" - c.OutputDir = "" - } - } - - if !isZero(o.OutputMap) { - c.OutputDir = "" - c.OutputFiles = nil - c.OutputMap = o.OutputMap - } - if !isZero(o.OutputDir) { - c.OutputDir = o.OutputDir - c.OutputFiles = nil - c.OutputMap = "" - } - if !isZero(o.OutputFiles) { - c.OutputDir = "" - c.OutputFiles = o.OutputFiles - c.OutputMap = "" - } - if !isZero(o.ExecPipe) { - c.ExecPipe = o.ExecPipe - c.PostExec = o.PostExec - c.OutputFiles = o.OutputFiles - } - if !isZero(o.ExcludeGlob) { - c.ExcludeGlob = o.ExcludeGlob - } - if !isZero(o.OutMode) { - c.OutMode = o.OutMode - } - if !isZero(o.LDelim) { - c.LDelim = o.LDelim - } - if !isZero(o.RDelim) { - c.RDelim = o.RDelim - } - if c.Templates == nil { - c.Templates = o.Templates - } else { - mergeDataSources(c.Templates, o.Templates) - } - if c.DataSources == nil { - c.DataSources = o.DataSources - } else { - mergeDataSources(c.DataSources, o.DataSources) - } - if c.Context == nil { - c.Context = o.Context - } else { - mergeDataSources(c.Context, o.Context) - } - if len(o.Plugins) > 0 { - for k, v := range o.Plugins { - c.Plugins[k] = v - } - } - - return c -} - -// ParseDataSourceFlags - sets DataSources, Context, and Templates fields from -// the key=value format flags as provided at the command-line -// Unreferenced headers will be set in c.ExtraHeaders -func (c *Config) ParseDataSourceFlags(datasources, contexts, templates, headers []string) error { - err := c.parseResources(datasources, contexts, templates) - if err != nil { - return err - } - - hdrs, err := parseHeaderArgs(headers) - if err != nil { - return err - } - - for k, v := range hdrs { - if d, ok := c.Context[k]; ok { - d.Header = v - c.Context[k] = d - delete(hdrs, k) - } - if d, ok := c.DataSources[k]; ok { - d.Header = v - c.DataSources[k] = d - delete(hdrs, k) - } - if t, ok := c.Templates[k]; ok { - t.Header = v - c.Templates[k] = t - delete(hdrs, k) - } - } - if len(hdrs) > 0 { - c.ExtraHeaders = hdrs - } - return nil -} - -func (c *Config) parseResources(datasources, contexts, templates []string) error { - for _, d := range datasources { - k, ds, err := parseDatasourceArg(d) - if err != nil { - return err - } - if c.DataSources == nil { - c.DataSources = map[string]DataSource{} - } - c.DataSources[k] = ds - } - for _, d := range contexts { - k, ds, err := parseDatasourceArg(d) - if err != nil { - return err - } - if c.Context == nil { - c.Context = map[string]DataSource{} - } - c.Context[k] = ds - } - for _, t := range templates { - k, ds, err := parseTemplateArg(t) - if err != nil { - return err - } - if c.Templates == nil { - c.Templates = map[string]DataSource{} - } - c.Templates[k] = ds - } - - return nil -} - -// ParsePluginFlags - sets the Plugins field from the -// key=value format flags as provided at the command-line -func (c *Config) ParsePluginFlags(plugins []string) error { - for _, plugin := range plugins { - parts := strings.SplitN(plugin, "=", 2) - if len(parts) < 2 { - return fmt.Errorf("plugin requires both name and path") - } - if c.Plugins == nil { - c.Plugins = map[string]PluginConfig{} - } - c.Plugins[parts[0]] = PluginConfig{Cmd: parts[1]} - } - return nil -} - -func Cut(s, sep string) (before, after string, found bool) { - if i := strings.Index(s, sep); i >= 0 { - return s[:i], s[i+len(sep):], true - } - return s, "", false -} - -func parseDatasourceArg(value string) (alias string, ds DataSource, err error) { - alias, u, _ := Cut(value, "=") - if u == "" { - u = alias - alias, _, _ = Cut(value, ".") - if path.Base(u) != u { - err = fmt.Errorf("invalid argument (%s): must provide an alias with files not in working directory", value) - return alias, ds, err - } - } - - ds.URL, err = ParseSourceURL(u) - - return alias, ds, err -} - -func parseHeaderArgs(headerArgs []string) (map[string]http.Header, error) { - headers := make(map[string]http.Header) - for _, v := range headerArgs { - ds, name, value, err := splitHeaderArg(v) - if err != nil { - return nil, err - } - if _, ok := headers[ds]; !ok { - headers[ds] = make(http.Header) - } - headers[ds][name] = append(headers[ds][name], strings.TrimSpace(value)) - } - return headers, nil -} - -func splitHeaderArg(arg string) (datasourceAlias, name, value string, err error) { - parts := strings.SplitN(arg, "=", 2) - if len(parts) != 2 { - err = fmt.Errorf("invalid datasource-header option '%s'", arg) - return "", "", "", err - } - datasourceAlias = parts[0] - name, value, err = splitHeader(parts[1]) - return datasourceAlias, name, value, err -} - -func splitHeader(header string) (name, value string, err error) { - parts := strings.SplitN(header, ":", 2) - if len(parts) != 2 { - err = fmt.Errorf("invalid HTTP Header format '%s'", header) - return "", "", err - } - name = http.CanonicalHeaderKey(parts[0]) - value = parts[1] - return name, value, nil -} - -// Validate the Config -func (c Config) Validate() (err error) { - err = notTogether( - []string{"in", "inputFiles", "inputDir"}, - c.Input, c.InputFiles, c.InputDir) - if err == nil { - err = notTogether( - []string{"outputFiles", "outputDir", "outputMap"}, - c.OutputFiles, c.OutputDir, c.OutputMap) - } - if err == nil { - err = notTogether( - []string{"outputDir", "outputMap", "execPipe"}, - c.OutputDir, c.OutputMap, c.ExecPipe) - } - - if err == nil { - err = mustTogether("outputDir", "inputDir", - c.OutputDir, c.InputDir) - } - - if err == nil { - err = mustTogether("outputMap", "inputDir", - c.OutputMap, c.InputDir) - } - - if err == nil { - f := len(c.InputFiles) - if f == 0 && c.Input != "" { - f = 1 - } - o := len(c.OutputFiles) - if f != o && !c.ExecPipe { - err = fmt.Errorf("must provide same number of 'outputFiles' (%d) as 'in' or 'inputFiles' (%d) options", o, f) - } - } - - if err == nil { - if c.ExecPipe && len(c.PostExec) == 0 { - err = fmt.Errorf("execPipe may only be used with a postExec command") - } - } - - if err == nil { - if c.ExecPipe && (len(c.OutputFiles) > 0 && c.OutputFiles[0] != "-") { - err = fmt.Errorf("must not set 'outputFiles' when using 'execPipe'") - } - } - - return err -} - -func notTogether(names []string, values ...interface{}) error { - found := "" - for i, value := range values { - if isZero(value) { - continue - } - if found != "" { - return fmt.Errorf("only one of these options is supported at a time: '%s', '%s'", - found, names[i]) - } - found = names[i] - } - return nil -} - -func mustTogether(left, right string, lValue, rValue interface{}) error { - if !isZero(lValue) && isZero(rValue) { - return fmt.Errorf("these options must be set together: '%s', '%s'", - left, right) - } - - return nil -} - -func isZero(value interface{}) bool { - switch v := value.(type) { - case string: - return v == "" - case []string: - return len(v) == 0 - case bool: - return !v - default: - return false - } -} - -// ApplyDefaults - any defaults changed here should be added to cmd.InitFlags as -// well for proper help/usage display. -func (c *Config) ApplyDefaults() { - if c.Stdout == nil { - c.Stdout = os.Stdout - } - if c.Stderr == nil { - c.Stderr = os.Stderr - } - if c.Stdin == nil { - c.Stdin = os.Stdin - } - - if c.InputDir != "" && c.OutputDir == "" && c.OutputMap == "" { - c.OutputDir = "." - } - if c.Input == "" && c.InputDir == "" && len(c.InputFiles) == 0 { - c.InputFiles = []string{"-"} - } - if c.OutputDir == "" && c.OutputMap == "" && len(c.OutputFiles) == 0 && !c.ExecPipe { - c.OutputFiles = []string{"-"} - } - if c.LDelim == "" { - c.LDelim = "{{" - } - if c.RDelim == "" { - c.RDelim = "}}" - } - - if c.ExecPipe { - pipe := &bytes.Buffer{} - c.PostExecInput = pipe - c.OutputFiles = []string{"-"} - - // --exec-pipe redirects standard out to the out pipe - c.Stdout = pipe - } else { - c.PostExecInput = c.Stdin - } - - if c.PluginTimeout == 0 { - c.PluginTimeout = 5 * time.Second - } -} - -// GetMode - parse an os.FileMode out of the string, and let us know if it's an override or not... -func (c *Config) GetMode() (os.FileMode, bool, error) { - modeOverride := c.OutMode != "" - m, err := strconv.ParseUint("0"+c.OutMode, 8, 32) - if err != nil { - return 0, false, err - } - mode := iohelpers.NormalizeFileMode(os.FileMode(m)) - if mode == 0 && c.Input != "" { - mode = iohelpers.NormalizeFileMode(0644) - } - return mode, modeOverride, nil -} - -// String - -func (c *Config) String() string { - out := &strings.Builder{} - out.WriteString("---\n") - enc := yaml.NewEncoder(out) - enc.SetIndent(2) - - // dereferenced copy so we can truncate input for display - c2 := *c - if len(c2.Input) >= 11 { - c2.Input = c2.Input[0:8] + "..." - } - - err := enc.Encode(c2) - if err != nil { - return err.Error() - } - return out.String() -} - -// ParseSourceURL parses a datasource URL value, which may be '-' (for stdin://), -// or it may be a Windows path (with driver letter and back-slack separators) or -// UNC, or it may be relative. It also might just be a regular absolute URL... -// In all cases it returns a correct URL for the value. -func ParseSourceURL(value string) (*url.URL, error) { - if value == "-" { - value = "stdin://" - } - value = filepath.ToSlash(value) - // handle absolute Windows paths - volName := "" - if volName = filepath.VolumeName(value); volName != "" { - // handle UNCs - if len(volName) > 2 { - value = "file:" + value - } else { - value = "file:///" + value - } - } - srcURL, err := url.Parse(value) - if err != nil { - return nil, err - } - - if volName != "" && len(srcURL.Path) >= 3 { - if srcURL.Path[0] == '/' && srcURL.Path[2] == ':' { - srcURL.Path = srcURL.Path[1:] - } - } - - if !srcURL.IsAbs() { - srcURL, err = absFileURL(value) - if err != nil { - return nil, err - } - } - return srcURL, nil -} - -func absFileURL(value string) (*url.URL, error) { - wd, err := os.Getwd() - if err != nil { - return nil, errors.Wrapf(err, "can't get working directory") - } - wd = filepath.ToSlash(wd) - baseURL := &url.URL{ - Scheme: "file", - Path: wd + "/", - } - relURL, err := url.Parse(value) - if err != nil { - return nil, fmt.Errorf("can't parse value %s as URL: %w", value, err) - } - resolved := baseURL.ResolveReference(relURL) - // deal with Windows drive letters - if !strings.HasPrefix(wd, "/") && resolved.Path[2] == ':' { - resolved.Path = resolved.Path[1:] - } - return resolved, nil -} diff --git a/internal/config/configfile_test.go b/internal/config/configfile_test.go deleted file mode 100644 index a5e452b60..000000000 --- a/internal/config/configfile_test.go +++ /dev/null @@ -1,935 +0,0 @@ -package config - -import ( - "net/http" - "net/url" - "os" - "path" - "path/filepath" - "runtime" - "strings" - "testing" - "time" - - "github.com/flanksource/gomplate/v3/internal/iohelpers" - "github.com/hairyhenderson/yaml" - "github.com/stretchr/testify/assert" -) - -func TestParseConfigFile(t *testing.T) { - t.Parallel() - in := "in: hello world\n" - expected := &Config{ - Input: "hello world", - } - cf, err := Parse(strings.NewReader(in)) - assert.NoError(t, err) - assert.Equal(t, expected, cf) - - in = `in: hello world -outputFiles: [out.txt] -chmod: 644 - -datasources: - data: - url: file:///data.json - moredata: - url: https://example.com/more.json - header: - Authorization: ["Bearer abcd1234"] - -context: - .: - url: file:///data.json - -plugins: - foo: - cmd: echo - pipe: true - -templates: - foo: - url: file:///tmp/foo.t - -pluginTimeout: 2s -` - expected = &Config{ - Input: "hello world", - OutputFiles: []string{"out.txt"}, - DataSources: map[string]DataSource{ - "data": { - URL: mustURL("file:///data.json"), - }, - "moredata": { - URL: mustURL("https://example.com/more.json"), - Header: map[string][]string{ - "Authorization": {"Bearer abcd1234"}, - }, - }, - }, - Context: map[string]DataSource{ - ".": { - URL: mustURL("file:///data.json"), - }, - }, - OutMode: "644", - Plugins: map[string]PluginConfig{ - "foo": {Cmd: "echo", Pipe: true}, - }, - Templates: Templates{"foo": DataSource{URL: mustURL("file:///tmp/foo.t")}}, - PluginTimeout: 2 * time.Second, - } - - cf, err = Parse(strings.NewReader(in)) - assert.NoError(t, err) - assert.EqualValues(t, expected, cf) -} - -func mustURL(s string) *url.URL { - u, err := url.Parse(s) - if err != nil { - panic(err) - } - // handle the case where it's a relative URL - just like in parseSourceURL. - if !u.IsAbs() { - u, err = absFileURL(s) - if err != nil { - panic(err) - } - } - return u -} - -func TestValidate(t *testing.T) { - t.Parallel() - assert.NoError(t, validateConfig("")) - - assert.Error(t, validateConfig(`in: foo -inputFiles: [bar] -`)) - assert.Error(t, validateConfig(`inputDir: foo -inputFiles: [bar] -`)) - assert.Error(t, validateConfig(`inputDir: foo -in: bar -`)) - - assert.Error(t, validateConfig(`outputDir: foo -outputFiles: [bar] -`)) - - assert.Error(t, validateConfig(`in: foo -outputFiles: [bar, baz] -`)) - - assert.Error(t, validateConfig(`inputFiles: [foo] -outputFiles: [bar, baz] -`)) - - assert.Error(t, validateConfig(`outputDir: foo -outputFiles: [bar] -`)) - - assert.Error(t, validateConfig(`outputDir: foo -`)) - - assert.Error(t, validateConfig(`outputMap: foo -`)) - - assert.Error(t, validateConfig(`outputMap: foo -outputFiles: [bar] -`)) - - assert.Error(t, validateConfig(`inputDir: foo -outputDir: bar -outputMap: bar -`)) - - assert.Error(t, validateConfig(`execPipe: true -`)) - assert.Error(t, validateConfig(`execPipe: true -postExec: "" -`)) - - assert.NoError(t, validateConfig(`execPipe: true -postExec: [echo, foo] -`)) - - assert.Error(t, validateConfig(`execPipe: true -outputFiles: [foo] -postExec: [echo] -`)) - - assert.NoError(t, validateConfig(`execPipe: true -inputFiles: ['-'] -postExec: [echo] -`)) - - assert.Error(t, validateConfig(`inputDir: foo -execPipe: true -outputDir: foo -postExec: [echo] -`)) - - assert.Error(t, validateConfig(`inputDir: foo -execPipe: true -outputMap: foo -postExec: [echo] -`)) -} - -func validateConfig(c string) error { - in := strings.NewReader(c) - cfg, err := Parse(in) - if err != nil { - return err - } - err = cfg.Validate() - return err -} - -func TestMergeFrom(t *testing.T) { - t.Parallel() - cfg := &Config{ - Input: "hello world", - DataSources: map[string]DataSource{ - "data": { - URL: mustURL("file:///data.json"), - }, - "moredata": { - URL: mustURL("https://example.com/more.json"), - Header: http.Header{ - "Authorization": {"Bearer abcd1234"}, - }, - }, - }, - Context: map[string]DataSource{ - "foo": { - URL: mustURL("https://example.com/foo.yaml"), - Header: http.Header{ - "Accept": {"application/yaml"}, - }, - }, - }, - OutMode: "644", - } - other := &Config{ - OutputFiles: []string{"out.txt"}, - DataSources: map[string]DataSource{ - "data": { - Header: http.Header{ - "Accept": {"foo/bar"}, - }, - }, - }, - Context: map[string]DataSource{ - "foo": { - Header: http.Header{ - "Accept": {"application/json"}, - }, - }, - "bar": {URL: mustURL("stdin:///")}, - }, - } - expected := &Config{ - Input: "hello world", - OutputFiles: []string{"out.txt"}, - DataSources: map[string]DataSource{ - "data": { - URL: mustURL("file:///data.json"), - Header: http.Header{ - "Accept": {"foo/bar"}, - }, - }, - "moredata": { - URL: mustURL("https://example.com/more.json"), - Header: http.Header{ - "Authorization": {"Bearer abcd1234"}, - }, - }, - }, - Context: map[string]DataSource{ - "foo": { - URL: mustURL("https://example.com/foo.yaml"), - Header: http.Header{ - "Accept": {"application/json"}, - }, - }, - "bar": {URL: mustURL("stdin:///")}, - }, - OutMode: "644", - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) - - cfg = &Config{ - Input: "hello world", - } - other = &Config{ - InputFiles: []string{"in.tmpl", "in2.tmpl"}, - OutputFiles: []string{"out", "out2"}, - } - expected = &Config{ - InputFiles: []string{"in.tmpl", "in2.tmpl"}, - OutputFiles: []string{"out", "out2"}, - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) - - cfg = &Config{ - Input: "hello world", - OutputFiles: []string{"out", "out2"}, - } - other = &Config{ - InputDir: "in/", - OutputDir: "out/", - } - expected = &Config{ - InputDir: "in/", - OutputDir: "out/", - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) - - cfg = &Config{ - Input: "hello world", - OutputFiles: []string{"out"}, - } - other = &Config{ - Input: "hi", - ExecPipe: true, - PostExec: []string{"cat"}, - } - expected = &Config{ - Input: "hi", - ExecPipe: true, - PostExec: []string{"cat"}, - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) - - cfg = &Config{ - Input: "hello world", - OutputFiles: []string{"-"}, - Plugins: map[string]PluginConfig{ - "sleep": {Cmd: "echo"}, - }, - PluginTimeout: 500 * time.Microsecond, - } - other = &Config{ - InputFiles: []string{"-"}, - OutputFiles: []string{"-"}, - Plugins: map[string]PluginConfig{ - "sleep": {Cmd: "sleep.sh"}, - }, - } - expected = &Config{ - Input: "hello world", - OutputFiles: []string{"-"}, - Plugins: map[string]PluginConfig{ - "sleep": {Cmd: "sleep.sh"}, - }, - PluginTimeout: 500 * time.Microsecond, - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) - - cfg = &Config{ - Input: "hello world", - OutMode: "644", - } - other = &Config{ - OutputFiles: []string{"out.txt"}, - Context: map[string]DataSource{ - "foo": { - URL: mustURL("https://example.com/foo.yaml"), - Header: http.Header{ - "Accept": {"application/json"}, - }, - }, - "bar": {URL: mustURL("stdin:///")}, - }, - DataSources: map[string]DataSource{ - "data": { - URL: mustURL("file:///data.json"), - }, - "moredata": { - URL: mustURL("https://example.com/more.json"), - Header: http.Header{ - "Authorization": {"Bearer abcd1234"}, - }, - }, - }, - } - expected = &Config{ - Input: "hello world", - OutputFiles: []string{"out.txt"}, - Context: map[string]DataSource{ - "foo": { - URL: mustURL("https://example.com/foo.yaml"), - Header: http.Header{ - "Accept": {"application/json"}, - }, - }, - "bar": {URL: mustURL("stdin:///")}, - }, - DataSources: map[string]DataSource{ - "data": { - URL: mustURL("file:///data.json"), - }, - "moredata": { - URL: mustURL("https://example.com/more.json"), - Header: http.Header{ - "Authorization": {"Bearer abcd1234"}, - }, - }, - }, - OutMode: "644", - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) - - // test template merging & a few other things - cfg = &Config{ - InputDir: "indir/", - ExcludeGlob: []string{"*.txt"}, - Templates: Templates{ - "foo": { - URL: mustURL("file:///foo.yaml"), - }, - "bar": { - URL: mustURL("stdin:///"), - Header: http.Header{"Accept": {"application/json"}}, - }, - }, - } - other = &Config{ - ExcludeGlob: []string{"*.yaml"}, - OutputMap: "${ .in }.out", - OutMode: "600", - LDelim: "${", - RDelim: "}", - Templates: Templates{ - "foo": {URL: mustURL("https://example.com/foo.yaml")}, - "baz": {URL: mustURL("vault:///baz")}, - }, - } - expected = &Config{ - InputDir: "indir/", - ExcludeGlob: []string{"*.yaml"}, - OutputMap: "${ .in }.out", - OutMode: "600", - LDelim: "${", - RDelim: "}", - Templates: Templates{ - "foo": {URL: mustURL("https://example.com/foo.yaml")}, - "bar": { - URL: mustURL("stdin:///"), - Header: http.Header{"Accept": {"application/json"}}, - }, - "baz": {URL: mustURL("vault:///baz")}, - }, - } - - assert.EqualValues(t, expected, cfg.MergeFrom(other)) -} - -func TestParseDataSourceFlags(t *testing.T) { - t.Parallel() - cfg := &Config{} - err := cfg.ParseDataSourceFlags(nil, nil, nil, nil) - assert.NoError(t, err) - assert.EqualValues(t, &Config{}, cfg) - - cfg = &Config{} - err = cfg.ParseDataSourceFlags([]string{"foo/bar/baz.json"}, nil, nil, nil) - assert.Error(t, err) - - cfg = &Config{} - err = cfg.ParseDataSourceFlags([]string{"baz=foo/bar/baz.json"}, nil, nil, nil) - assert.NoError(t, err) - expected := &Config{ - DataSources: map[string]DataSource{ - "baz": {URL: mustURL("foo/bar/baz.json")}, - }, - } - assert.EqualValues(t, expected, cfg, "expected: %+v\nactual: %+v\n", expected, cfg) - - cfg = &Config{} - err = cfg.ParseDataSourceFlags( - []string{"baz=foo/bar/baz.json"}, - nil, - nil, - []string{"baz=Accept: application/json"}) - assert.NoError(t, err) - assert.EqualValues(t, &Config{ - DataSources: map[string]DataSource{ - "baz": { - URL: mustURL("foo/bar/baz.json"), - Header: http.Header{ - "Accept": {"application/json"}, - }, - }, - }, - }, cfg) - - cfg = &Config{} - err = cfg.ParseDataSourceFlags( - []string{"baz=foo/bar/baz.json"}, - []string{"foo=http://example.com"}, - nil, - []string{"foo=Accept: application/json", - "bar=Authorization: Basic xxxxx"}) - assert.NoError(t, err) - assert.EqualValues(t, &Config{ - DataSources: map[string]DataSource{ - "baz": {URL: mustURL("foo/bar/baz.json")}, - }, - Context: map[string]DataSource{ - "foo": { - URL: mustURL("http://example.com"), - Header: http.Header{ - "Accept": {"application/json"}, - }, - }, - }, - ExtraHeaders: map[string]http.Header{ - "bar": {"Authorization": {"Basic xxxxx"}}, - }, - }, cfg) - - cfg = &Config{} - err = cfg.ParseDataSourceFlags( - nil, - nil, - []string{"foo=http://example.com", "file.tmpl", "tmpldir/"}, - []string{"foo=Accept: application/json", - "bar=Authorization: Basic xxxxx"}) - assert.NoError(t, err) - assert.EqualValues(t, &Config{ - Templates: Templates{ - "foo": { - URL: mustURL("http://example.com"), - Header: http.Header{"Accept": {"application/json"}}, - }, - "file.tmpl": {URL: mustURL("file.tmpl")}, - "tmpldir/": {URL: mustURL("tmpldir/")}, - }, - ExtraHeaders: map[string]http.Header{ - "bar": {"Authorization": {"Basic xxxxx"}}, - }, - }, cfg) -} - -func TestParsePluginFlags(t *testing.T) { - t.Parallel() - cfg := &Config{} - err := cfg.ParsePluginFlags(nil) - assert.NoError(t, err) - - cfg = &Config{} - err = cfg.ParsePluginFlags([]string{"foo=bar"}) - assert.NoError(t, err) - assert.EqualValues(t, &Config{Plugins: map[string]PluginConfig{"foo": {Cmd: "bar"}}}, cfg) -} - -func TestConfigString(t *testing.T) { - c := &Config{} - c.ApplyDefaults() - - expected := `--- -inputFiles: ['-'] -outputFiles: ['-'] -leftDelim: '{{' -rightDelim: '}}' -pluginTimeout: 5s -` - assert.Equal(t, expected, c.String()) - - c = &Config{ - LDelim: "L", - RDelim: "R", - Input: "foo", - OutputFiles: []string{"-"}, - Templates: Templates{ - "foo": {URL: mustURL("https://www.example.com/foo.tmpl")}, - "bar": {URL: mustURL("/tmp/bar.t")}, - }, - } - expected = `--- -in: foo -outputFiles: ['-'] -leftDelim: L -rightDelim: R -templates: - foo: - url: https://www.example.com/foo.tmpl - bar: - url: file:///tmp/bar.t -` - assert.YAMLEq(t, expected, c.String()) - - c = &Config{ - LDelim: "L", - RDelim: "R", - Input: "long input that should be truncated", - OutputFiles: []string{"-"}, - Templates: Templates{ - "foo": {URL: mustURL("https://www.example.com/foo.tmpl")}, - "bar": {URL: mustURL("/tmp/bar.t")}, - }, - } - expected = `--- -in: long inp... -outputFiles: ['-'] -leftDelim: L -rightDelim: R -templates: - foo: - url: https://www.example.com/foo.tmpl - bar: - url: file:///tmp/bar.t -` - assert.YAMLEq(t, expected, c.String()) - - c = &Config{ - InputDir: "in/", - OutputDir: "out/", - } - expected = `--- -inputDir: in/ -outputDir: out/ -` - - assert.Equal(t, expected, c.String()) - - c = &Config{ - InputDir: "in/", - OutputMap: "{{ .in }}", - } - expected = `--- -inputDir: in/ -outputMap: '{{ .in }}' -` - - assert.Equal(t, expected, c.String()) - - c = &Config{ - PluginTimeout: 500 * time.Millisecond, - } - expected = `--- -pluginTimeout: 500ms -` - - assert.Equal(t, expected, c.String()) - - c = &Config{ - Plugins: map[string]PluginConfig{ - "foo": { - Cmd: "bar", - Pipe: true, - }, - }, - } - expected = `--- -plugins: - foo: - cmd: bar - timeout: 0s - pipe: true -` - - assert.Equal(t, expected, c.String()) -} - -func TestApplyDefaults(t *testing.T) { - t.Parallel() - cfg := &Config{} - - cfg.ApplyDefaults() - assert.EqualValues(t, []string{"-"}, cfg.InputFiles) - assert.EqualValues(t, []string{"-"}, cfg.OutputFiles) - assert.Empty(t, cfg.OutputDir) - assert.Equal(t, "{{", cfg.LDelim) - assert.Equal(t, "}}", cfg.RDelim) - - cfg = &Config{ - InputDir: "in", - } - - cfg.ApplyDefaults() - assert.Empty(t, cfg.InputFiles) - assert.Empty(t, cfg.OutputFiles) - assert.Equal(t, ".", cfg.OutputDir) - assert.Equal(t, "{{", cfg.LDelim) - assert.Equal(t, "}}", cfg.RDelim) - - cfg = &Config{ - Input: "foo", - LDelim: "<", - RDelim: ">", - } - - cfg.ApplyDefaults() - assert.Empty(t, cfg.InputFiles) - assert.EqualValues(t, []string{"-"}, cfg.OutputFiles) - assert.Empty(t, cfg.OutputDir) - assert.Equal(t, "<", cfg.LDelim) - assert.Equal(t, ">", cfg.RDelim) - - cfg = &Config{ - Input: "foo", - ExecPipe: true, - } - - cfg.ApplyDefaults() - assert.Empty(t, cfg.InputFiles) - assert.EqualValues(t, []string{"-"}, cfg.OutputFiles) - assert.Empty(t, cfg.OutputDir) - assert.True(t, cfg.ExecPipe) - - cfg = &Config{ - InputDir: "foo", - OutputMap: "bar", - } - - cfg.ApplyDefaults() - assert.Empty(t, cfg.InputFiles) - assert.Empty(t, cfg.Input) - assert.Empty(t, cfg.OutputFiles) - assert.Empty(t, cfg.OutputDir) - assert.False(t, cfg.ExecPipe) - assert.Equal(t, "bar", cfg.OutputMap) -} - -func TestGetMode(t *testing.T) { - c := &Config{} - m, o, err := c.GetMode() - assert.NoError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0), m) - assert.False(t, o) - - c = &Config{OutMode: "755"} - m, o, err = c.GetMode() - assert.NoError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0o755), m) - assert.True(t, o) - - c = &Config{OutMode: "0755"} - m, o, err = c.GetMode() - assert.NoError(t, err) - assert.Equal(t, iohelpers.NormalizeFileMode(0o755), m) - assert.True(t, o) - - c = &Config{OutMode: "foo"} - _, _, err = c.GetMode() - assert.Error(t, err) -} - -func TestParseHeaderArgs(t *testing.T) { - args := []string{ - "foo=Accept: application/json", - "bar=Authorization: Bearer supersecret", - } - expected := map[string]http.Header{ - "foo": { - "Accept": {"application/json"}, - }, - "bar": { - "Authorization": {"Bearer supersecret"}, - }, - } - parsed, err := parseHeaderArgs(args) - assert.NoError(t, err) - assert.Equal(t, expected, parsed) - - _, err = parseHeaderArgs([]string{"foo"}) - assert.Error(t, err) - - _, err = parseHeaderArgs([]string{"foo=bar"}) - assert.Error(t, err) - - args = []string{ - "foo=Accept: application/json", - "foo=Foo: bar", - "foo=foo: baz", - "foo=fOO: qux", - "bar=Authorization: Bearer supersecret", - } - expected = map[string]http.Header{ - "foo": { - "Accept": {"application/json"}, - "Foo": {"bar", "baz", "qux"}, - }, - "bar": { - "Authorization": {"Bearer supersecret"}, - }, - } - parsed, err = parseHeaderArgs(args) - assert.NoError(t, err) - assert.Equal(t, expected, parsed) -} - -func TestParseSourceURL(t *testing.T) { - expected := &url.URL{ - Scheme: "http", - Host: "example.com", - Path: "/foo.json", - RawQuery: "bar", - } - u, err := ParseSourceURL("http://example.com/foo.json?bar") - assert.NoError(t, err) - assert.EqualValues(t, expected, u) - - expected = &url.URL{Scheme: "stdin"} - u, err = ParseSourceURL("-") - assert.NoError(t, err) - assert.EqualValues(t, expected, u) - - wd, err := os.Getwd() - assert.NoError(t, err) - expected = &url.URL{ - Scheme: "file", - Path: path.Join(filepath.ToSlash(wd), "foo/bar.json"), - } - u, err = ParseSourceURL("./foo/bar.json") - assert.NoError(t, err) - assert.EqualValues(t, expected, u) -} - -func TestAbsFileURL(t *testing.T) { - cwd, _ := os.Getwd() - // make this pass on Windows - cwd = filepath.ToSlash(cwd) - expected := &url.URL{ - Scheme: "file", - Host: "", - Path: "/tmp/foo", - } - u, err := absFileURL("/tmp/foo") - assert.NoError(t, err) - assert.EqualValues(t, expected, u) - - expected = &url.URL{ - Scheme: "file", - Host: "", - Path: cwd + "/tmp/foo", - } - u, err = absFileURL("tmp/foo") - assert.NoError(t, err) - assert.EqualValues(t, expected, u) - - expected = &url.URL{ - Scheme: "file", - Host: "", - Path: cwd + "/tmp/foo", - RawQuery: "q=p", - } - u, err = absFileURL("tmp/foo?q=p") - assert.NoError(t, err) - assert.EqualValues(t, expected, u) -} - -func TestParseDatasourceArgNoAlias(t *testing.T) { - alias, ds, err := parseDatasourceArg("foo.json") - assert.NoError(t, err) - assert.Equal(t, "foo", alias) - assert.Equal(t, "file", ds.URL.Scheme) - - _, _, err = parseDatasourceArg("../foo.json") - assert.Error(t, err) - - _, _, err = parseDatasourceArg("ftp://example.com/foo.yml") - assert.Error(t, err) -} - -func TestParseDatasourceArgWithAlias(t *testing.T) { - alias, ds, err := parseDatasourceArg("data=foo.json") - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "file", ds.URL.Scheme) - assert.True(t, ds.URL.IsAbs()) - - alias, ds, err = parseDatasourceArg("data=/otherdir/foo.json") - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "file", ds.URL.Scheme) - assert.True(t, ds.URL.IsAbs()) - assert.Equal(t, "/otherdir/foo.json", ds.URL.Path) - - if runtime.GOOS == "windows" { - alias, ds, err = parseDatasourceArg("data=foo.json") - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "file", ds.URL.Scheme) - assert.True(t, ds.URL.IsAbs()) - assert.Equalf(t, byte(':'), ds.URL.Path[1], "Path was %s", ds.URL.Path) - - alias, ds, err = parseDatasourceArg(`data=\otherdir\foo.json`) - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "file", ds.URL.Scheme) - assert.True(t, ds.URL.IsAbs()) - assert.Equal(t, `/otherdir/foo.json`, ds.URL.Path) - - alias, ds, err = parseDatasourceArg("data=C:\\windowsdir\\foo.json") - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "file", ds.URL.Scheme) - assert.True(t, ds.URL.IsAbs()) - assert.Equal(t, "C:/windowsdir/foo.json", ds.URL.Path) - - alias, ds, err = parseDatasourceArg("data=\\\\somehost\\share\\foo.json") - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "file", ds.URL.Scheme) - assert.Equal(t, "somehost", ds.URL.Host) - assert.True(t, ds.URL.IsAbs()) - assert.Equal(t, "/share/foo.json", ds.URL.Path) - } - - alias, ds, err = parseDatasourceArg("data=sftp://example.com/blahblah/foo.json") - assert.NoError(t, err) - assert.Equal(t, "data", alias) - assert.Equal(t, "sftp", ds.URL.Scheme) - assert.True(t, ds.URL.IsAbs()) - assert.Equal(t, "/blahblah/foo.json", ds.URL.Path) - - alias, ds, err = parseDatasourceArg("merged=merge:./foo.yaml|http://example.com/bar.json%3Ffoo=bar") - assert.NoError(t, err) - assert.Equal(t, "merged", alias) - assert.Equal(t, "merge", ds.URL.Scheme) - assert.Equal(t, "./foo.yaml|http://example.com/bar.json%3Ffoo=bar", ds.URL.Opaque) -} - -func TestPluginConfig_UnmarshalYAML(t *testing.T) { - in := `foo` - out := PluginConfig{} - err := yaml.Unmarshal([]byte(in), &out) - assert.NoError(t, err) - assert.EqualValues(t, PluginConfig{Cmd: "foo"}, out) - - in = `[foo, bar]` - out = PluginConfig{} - err = yaml.Unmarshal([]byte(in), &out) - assert.Error(t, err) - - in = `cmd: foo` - out = PluginConfig{} - err = yaml.Unmarshal([]byte(in), &out) - assert.NoError(t, err) - assert.EqualValues(t, PluginConfig{Cmd: "foo"}, out) - - in = `cmd: foo -timeout: 10ms -pipe: true -` - out = PluginConfig{} - err = yaml.Unmarshal([]byte(in), &out) - assert.NoError(t, err) - assert.EqualValues(t, PluginConfig{ - Cmd: "foo", - Timeout: time.Duration(10) * time.Millisecond, - Pipe: true, - }, out) -} diff --git a/internal/config/types.go b/internal/config/types.go deleted file mode 100644 index b05759b45..000000000 --- a/internal/config/types.go +++ /dev/null @@ -1,94 +0,0 @@ -package config - -import ( - "fmt" - "net/http" - - "github.com/hairyhenderson/yaml" -) - -// Templates - a map of templates. We can't just use map[string]DataSource, -// because we need to be able to marshal both the old (array of '[k=]v' strings) -// and the new (proper map) formats. -// -// Note that templates use the DataSource type, since they have the exact same -// shape. -// TODO: get rid of this and just use map[string]DataSource once the legacy -// [k=]v array format is no longer supported -type Templates map[string]DataSource - -// UnmarshalYAML - satisfy the yaml.Umarshaler interface -func (t *Templates) UnmarshalYAML(value *yaml.Node) error { - // first attempt to unmarshal as a map[string]DataSource - m := map[string]DataSource{} - err := value.Decode(m) - if err == nil { - *t = m - return nil - } - - // if that fails, try to unmarshal as an array of '[k=]v' strings - err = t.unmarshalYAMLArray(value) - if err != nil { - return fmt.Errorf("could not unmarshal templates as map or array: %w", err) - } - - return nil -} - -func (t *Templates) unmarshalYAMLArray(value *yaml.Node) error { - a := []string{} - err := value.Decode(&a) - if err != nil { - return fmt.Errorf("could not unmarshal templates as array: %w", err) - } - - ts := Templates{} - for _, s := range a { - alias, pth, _ := Cut(s, "=") - if pth == "" { - // when alias is omitted, the path and alias are identical - pth = alias - } - - u, err := ParseSourceURL(pth) - if err != nil { - return fmt.Errorf("could not parse template URL %q: %w", pth, err) - } - - ts[alias] = DataSource{ - URL: u, - } - } - - *t = ts - - return nil -} - -func (t Templates) MarshalYAML() (interface{}, error) { - type rawTemplate struct { - Header http.Header `yaml:"header,omitempty,flow"` - URL string `yaml:"url"` - } - - m := map[string]rawTemplate{} - for k, v := range t { - m[k] = rawTemplate{ - Header: v.Header, - URL: v.URL.String(), - } - } - return m, nil -} - -func parseTemplateArg(value string) (alias string, ds DataSource, err error) { - alias, u, _ := Cut(value, "=") - if u == "" { - u = alias - } - - ds.URL, err = ParseSourceURL(u) - - return alias, ds, err -} diff --git a/internal/config/types_test.go b/internal/config/types_test.go deleted file mode 100644 index 49225afbe..000000000 --- a/internal/config/types_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package config - -import ( - "net/http" - "testing" - - "github.com/hairyhenderson/yaml" - "github.com/stretchr/testify/assert" -) - -func TestTemplates_UnmarshalYAML(t *testing.T) { - in := `t: - url: foo/bar/helloworld.tmpl -templatedir: - url: templatedir/ -dir: - url: foo/bar/ -mytemplate.t: - url: mytemplate.t -remote: - url: https://example.com/foo/bar/helloworld.tmpl - header: - Accept: [text/plain, text/template]` - out := Templates{} - err := yaml.Unmarshal([]byte(in), &out) - assert.NoError(t, err) - assert.EqualValues(t, Templates{ - "t": {URL: mustURL("foo/bar/helloworld.tmpl")}, - "templatedir": {URL: mustURL("templatedir/")}, - "dir": {URL: mustURL("foo/bar/")}, - "mytemplate.t": {URL: mustURL("mytemplate.t")}, - "remote": { - URL: mustURL("https://example.com/foo/bar/helloworld.tmpl"), - Header: http.Header{"Accept": {"text/plain", "text/template"}}, - }, - }, out) - - // legacy array format - in = `- t=foo/bar/helloworld.tmpl -- templatedir/ -- dir=foo/bar/ -- mytemplate.t -- remote=https://example.com/foo/bar/helloworld.tmpl` - out = Templates{} - err = yaml.Unmarshal([]byte(in), &out) - assert.NoError(t, err) - assert.EqualValues(t, Templates{ - "t": {URL: mustURL("foo/bar/helloworld.tmpl")}, - "templatedir/": {URL: mustURL("templatedir/")}, - "dir": {URL: mustURL("foo/bar/")}, - "mytemplate.t": {URL: mustURL("mytemplate.t")}, - "remote": {URL: mustURL("https://example.com/foo/bar/helloworld.tmpl")}, - }, out) - - // invalid format - in = `"neither an array nor a map"` - out = Templates{} - err = yaml.Unmarshal([]byte(in), &out) - assert.Error(t, err) - - // invalid URL - in = `- t="not a:valid url"` - out = Templates{} - err = yaml.Unmarshal([]byte(in), &out) - assert.Error(t, err) -} - -func TestParseTemplateArg(t *testing.T) { - data := []struct { - ds DataSource - in string - alias string - }{ - {in: "t=foo/bar/helloworld.tmpl", alias: "t", ds: DataSource{URL: mustURL("foo/bar/helloworld.tmpl")}}, - {in: "templatedir/", alias: "templatedir/", ds: DataSource{URL: mustURL("templatedir/")}}, - {in: "dir=foo/bar/", alias: "dir", ds: DataSource{URL: mustURL("foo/bar/")}}, - {in: "mytemplate.t", alias: "mytemplate.t", ds: DataSource{URL: mustURL("mytemplate.t")}}, - {in: "remote=https://example.com/foo/bar/helloworld.tmpl", - alias: "remote", ds: DataSource{URL: mustURL("https://example.com/foo/bar/helloworld.tmpl")}}, - } - - for _, d := range data { - alias, ds, err := parseTemplateArg(d.in) - assert.NoError(t, err) - assert.Equal(t, d.alias, alias) - assert.EqualValues(t, d.ds, ds) - } -} diff --git a/internal/deprecated/deprecated.go b/internal/deprecated/deprecated.go deleted file mode 100644 index c453ebbe1..000000000 --- a/internal/deprecated/deprecated.go +++ /dev/null @@ -1,14 +0,0 @@ -package deprecated - -import ( - "context" - - "github.com/rs/zerolog" -) - -// WarnDeprecated - use this to warn about deprecated template functions or -// datasources -func WarnDeprecated(ctx context.Context, msg string) { - logger := zerolog.Ctx(ctx) - logger.Warn().Msgf("Deprecated: %s", msg) -} diff --git a/k8s/cel_gen_exports.go b/k8s/cel_gen_exports.go new file mode 100644 index 000000000..4dd6b4efa --- /dev/null +++ b/k8s/cel_gen_exports.go @@ -0,0 +1,24 @@ +// Code generated by gencel. DO NOT EDIT. + +package k8s + +import "log" +import "github.com/google/cel-go/common/types/ref" +import "github.com/google/cel-go/cel" + +func transferSlice[K any](arg ref.Val) []K { + list, ok := arg.Value().([]ref.Val) + if !ok { + log.Printf("Not a list %T\n", arg.Value()) + return nil + } + + var out = make([]K, len(list)) + for i, val := range list { + out[i] = val.Value().(K) + } + + return out +} + +var CelEnvOption = []cel.EnvOption{} diff --git a/k8s/k8s.go b/k8s/k8s.go new file mode 100644 index 000000000..044f24942 --- /dev/null +++ b/k8s/k8s.go @@ -0,0 +1,98 @@ +package k8s + +import ( + "encoding/json" + "fmt" + + "github.com/flanksource/is-healthy/pkg/health" + "github.com/flanksource/is-healthy/pkg/lua" + "github.com/google/cel-go/common/types" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/yaml" +) + +type HealthStatus struct { + Status string `json:"status,omitempty"` + Message string `json:"message,omitempty"` + OK bool `json:"ok,omitempty"` +} + +func GetUnstructuredMap(in interface{}) []byte { + x := GetUnstructured(in) + b, _ := json.Marshal(x) + return b +} + +func GetUnstructured(in interface{}) *unstructured.Unstructured { + var err error + obj := make(map[string]interface{}) + + switch v := in.(type) { + case string: + err = yaml.Unmarshal([]byte(v), &obj) + case []byte: + err = yaml.Unmarshal(v, &obj) + case types.Bytes: + err = yaml.Unmarshal(v, &obj) + case map[string]interface{}: + obj = v + case unstructured.Unstructured: + obj = v.Object + default: + var data []byte + if data, err = yaml.Marshal(in); err == nil { + err = yaml.Unmarshal(data, &obj) + } + } + + if err != nil { + return nil + } + + return &unstructured.Unstructured{Object: obj} +} + +func IsHealthy(in interface{}) bool { + return GetHealth(in).OK +} + +func GetStatus(in interface{}) string { + health := GetHealth(in) + return fmt.Sprintf("%s: %s", health.Status, health.Message) +} + +func GetHealth(in interface{}) HealthStatus { + var err error + obj := GetUnstructured(in) + + if obj == nil { + return HealthStatus{ + OK: false, + Status: "Error", + Message: "Invalid spec", + } + } + + _health, err := health.GetResourceHealth(obj, lua.ResourceHealthOverrides{}) + if err != nil { + return HealthStatus{ + OK: false, + Status: "Error", + Message: err.Error(), + } + } + + if _health == nil { + return HealthStatus{ + OK: false, + Status: "Missing", + Message: "No health check found", + } + } + + return HealthStatus{ + OK: _health.Status == health.HealthStatusHealthy || _health.Status == health.HealthStatusProgressing, + Status: string(_health.Status), + Message: _health.Message, + } +} diff --git a/k8s/k8s_test.go b/k8s/k8s_test.go new file mode 100644 index 000000000..22ae6ecfa --- /dev/null +++ b/k8s/k8s_test.go @@ -0,0 +1,33 @@ +package k8s + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +// test IsHealthy with a kubernetes pod spec in running mode +func TestIsHealthySvc(t *testing.T) { + r := GetHealth(TestHealthy) + assert.Equal(t, true, r.OK) + assert.Equal(t, "Healthy", r.Status) +} + +func TestIsHealthyPod(t *testing.T) { + r := GetHealth(TestUnhealthy) + assert.Equal(t, false, r.OK) + assert.Equal(t, "Degraded", r.Status) +} + +func TestIsHealthyAppset(t *testing.T) { + r := GetHealth(TestLuaStatus) + assert.Equal(t, false, r.OK) + assert.Equal(t, "Degraded", r.Status) + assert.Equal(t, "found less than two generators, Merge requires two or more", r.Message) +} + +func TestIsHealthySvcPending(t *testing.T) { + r := GetHealth(TestProgressing) + assert.Equal(t, true, r.OK) + assert.Equal(t, "Progressing", r.Status) +} diff --git a/k8s/testdata.go b/k8s/testdata.go new file mode 100644 index 000000000..3559f021f --- /dev/null +++ b/k8s/testdata.go @@ -0,0 +1,175 @@ +package k8s + +var TestHealthy = ` +apiVersion: v1 +kind: Service +metadata: + name: argocd-server +spec: + clusterIP: 100.69.46.185 + externalTrafficPolicy: Cluster + ports: + - name: http + nodePort: 30354 + port: 80 + protocol: TCP + targetPort: 8080 + - name: https + nodePort: 31866 + port: 443 + protocol: TCP + targetPort: 8080 + selector: + app: argocd-server + sessionAffinity: None + type: LoadBalancer +status: + loadBalancer: + ingress: + - hostname: abc123.us-west-2.elb.amazonaws.com +` + +var TestProgressing = ` +apiVersion: v1 +kind: Service +metadata: + name: argo-artifacts +spec: + clusterIP: 10.105.70.181 + externalTrafficPolicy: Cluster + ports: + - name: service + nodePort: 32667 + port: 9000 + protocol: TCP + targetPort: 9000 + selector: + app: minio + release: argo-artifacts + sessionAffinity: None + type: LoadBalancer +status: + loadBalancer: {} +` + +var TestUnhealthy = ` +apiVersion: v1 +kind: Pod +metadata: + creationTimestamp: 2018-12-02T09:19:36Z + name: my-pod + namespace: argocd + resourceVersion: "151454" + selfLink: /api/v1/namespaces/argocd/pods/my-pod + uid: 63674389-f613-11e8-a057-fe5f49266390 +spec: + containers: + - command: + - sh + - -c + - exit 1 + image: alpine:latest + imagePullPolicy: Always + name: main + resources: {} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: default-token-f9jvj + readOnly: true + dnsPolicy: ClusterFirst + nodeName: minikube + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccount: default + serviceAccountName: default + terminationGracePeriodSeconds: 30 + tolerations: + - effect: NoExecute + key: node.kubernetes.io/not-ready + operator: Exists + tolerationSeconds: 300 + - effect: NoExecute + key: node.kubernetes.io/unreachable + operator: Exists + tolerationSeconds: 300 + volumes: + - name: default-token-f9jvj + secret: + defaultMode: 420 + secretName: default-token-f9jvj +status: + conditions: + - lastProbeTime: null + lastTransitionTime: 2018-12-02T09:19:36Z + status: "True" + type: Initialized + - lastProbeTime: null + lastTransitionTime: 2018-12-02T09:19:36Z + message: 'containers with unready status: [main]' + reason: ContainersNotReady + status: "False" + type: Ready + - lastProbeTime: null + lastTransitionTime: 2018-12-02T09:19:36Z + status: "True" + type: PodScheduled + containerStatuses: + - containerID: docker://c3aa0064b95a26045999b99c268e715a1c64201e816f1279ac06638778547bb8 + image: alpine:latest + imageID: docker-pullable://alpine@sha256:621c2f39f8133acb8e64023a94dbdf0d5ca81896102b9e57c0dc184cadaf5528 + lastState: + terminated: + containerID: docker://c3aa0064b95a26045999b99c268e715a1c64201e816f1279ac06638778547bb8 + exitCode: 1 + finishedAt: 2018-12-02T09:20:25Z + reason: Error + startedAt: 2018-12-02T09:20:25Z + name: main + ready: false + restartCount: 3 + state: + waiting: + message: Back-off 40s restarting failed container=main pod=my-pod_argocd(63674389-f613-11e8-a057-fe5f49266390) + reason: CrashLoopBackOff + hostIP: 192.168.64.41 + phase: Running + podIP: 172.17.0.9 + qosClass: BestEffort + startTime: 2018-12-02T09:19:36Z +` + +var TestLuaStatus = ` +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: cluster-git + namespace: argocd +spec: + generators: + - merge: + generators: [] + mergeKeys: + - server + template: + metadata: + name: '{{name}}' + spec: + destination: + namespace: default + server: '{{server}}' + project: default + source: + path: helm-guestbook + repoURL: https://github.com/argoproj/argocd-example-apps/ + targetRevision: HEAD +status: + conditions: + - lastTransitionTime: "2021-11-12T14:28:01Z" + message: found less than two generators, Merge requires two or more + reason: ApplicationGenerationFromParamsError + status: "True" + type: ErrorOccurred +` diff --git a/net/net.go b/net/net.go deleted file mode 100644 index 2d291d2c3..000000000 --- a/net/net.go +++ /dev/null @@ -1,70 +0,0 @@ -// Package net contains functions to help with network-oriented lookups -package net - -import ( - "net" -) - -// LookupIP - -func LookupIP(name string) (string, error) { - i, err := LookupIPs(name) - if err != nil { - return "", err - } - if len(i) == 0 { - return "", nil - } - return i[0], nil -} - -// LookupIPs - -func LookupIPs(name string) ([]string, error) { - srcIPs, err := net.LookupIP(name) - if err != nil { - return nil, err - } - var ips []string - for _, v := range srcIPs { - if v.To4() != nil && !contains(ips, v.String()) { - ips = append(ips, v.String()) - } - } - return ips, nil -} - -func contains(a []string, s string) bool { - for _, v := range a { - if v == s { - return true - } - } - return false -} - -// LookupCNAME - -func LookupCNAME(name string) (string, error) { - return net.LookupCNAME(name) -} - -// LookupTXT - -func LookupTXT(name string) ([]string, error) { - return net.LookupTXT(name) -} - -// LookupSRV - -func LookupSRV(name string) (*net.SRV, error) { - srvs, err := LookupSRVs(name) - if err != nil { - return nil, err - } - return srvs[0], nil -} - -// LookupSRVs - -func LookupSRVs(name string) ([]*net.SRV, error) { - _, addrs, err := net.LookupSRV("", "", name) - if err != nil { - return nil, err - } - return addrs, nil -} diff --git a/net/net_test.go b/net/net_test.go deleted file mode 100644 index 4e569a443..000000000 --- a/net/net_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package net - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func must(r interface{}, err error) interface{} { - if err != nil { - panic(err) - } - return r -} -func TestLookupIP(t *testing.T) { - assert.Equal(t, "127.0.0.1", must(LookupIP("localhost"))) - assert.Equal(t, "93.184.216.34", must(LookupIP("example.com"))) -} - -func TestLookupIPs(t *testing.T) { - assert.Equal(t, []string{"127.0.0.1"}, must(LookupIPs("localhost"))) - assert.Equal(t, []string{"93.184.216.34"}, must(LookupIPs("example.com"))) -} - -func TestLookupTXT(t *testing.T) { - assert.NotEmpty(t, must(LookupTXT("example.com"))) -} - -func TestLookupCNAME(t *testing.T) { - assert.Equal(t, "hairyhenderson.ca.", must(LookupCNAME("www.hairyhenderson.ca."))) -} - -func TestLookupSRV(t *testing.T) { - srv, err := LookupSRV("_sip._udp.sip.voice.google.com") - assert.NoError(t, err) - assert.Equal(t, uint16(5060), srv.Port) -} diff --git a/plugins.go b/plugins.go deleted file mode 100644 index d874ac711..000000000 --- a/plugins.go +++ /dev/null @@ -1,175 +0,0 @@ -package gomplate - -import ( - "bytes" - "context" - "fmt" - "io" - "os" - "os/exec" - "os/signal" - "path/filepath" - "runtime" - "text/template" - "time" - - "github.com/flanksource/gomplate/v3/conv" - "github.com/flanksource/gomplate/v3/internal/config" -) - -// bindPlugins creates custom plugin functions for each plugin specified by -// the config, and adds them to the given funcMap. Uses the configuration's -// PluginTimeout as the default plugin Timeout. Errors if a function name is -// duplicated. -func bindPlugins(ctx context.Context, cfg *config.Config, funcMap template.FuncMap) error { - for k, v := range cfg.Plugins { - if _, ok := funcMap[k]; ok { - return fmt.Errorf("function %q is already bound, and can not be overridden", k) - } - - // default the timeout to the one in the config - timeout := cfg.PluginTimeout - if v.Timeout != 0 { - timeout = v.Timeout - } - - funcMap[k] = PluginFunc(ctx, v.Cmd, PluginOpts{ - Timeout: timeout, - Pipe: v.Pipe, - Stderr: cfg.Stderr, - }) - } - - return nil -} - -// PluginOpts are options for controlling plugin function execution -type PluginOpts struct { - // Stderr can be set to redirect the plugin's stderr to a custom writer. - // Defaults to os.Stderr. - Stderr io.Writer - - // Timeout is the maximum amount of time to wait for the plugin to complete. - // Defaults to 5 seconds. - Timeout time.Duration - - // Pipe indicates whether the last argument should be piped to the plugin's - // stdin (true) or processed as a commandline argument (false) - Pipe bool -} - -// PluginFunc creates a template function that runs an external process - either -// a shell script or commandline executable. -func PluginFunc(ctx context.Context, cmd string, opts PluginOpts) func(...interface{}) (interface{}, error) { - timeout := opts.Timeout - if timeout == 0 { - timeout = 5 * time.Second - } - - stderr := opts.Stderr - if stderr == nil { - stderr = os.Stderr - } - - plugin := &plugin{ - ctx: ctx, - path: cmd, - timeout: timeout, - pipe: opts.Pipe, - stderr: stderr, - } - - return plugin.run -} - -// plugin represents a custom function that binds to an external process to be executed -type plugin struct { - ctx context.Context - stderr io.Writer - path string - timeout time.Duration - pipe bool -} - -// builds a command that's appropriate for running scripts -func (p *plugin) buildCommand(a []string) (name string, args []string) { - switch filepath.Ext(p.path) { - case ".ps1": - a = append([]string{"-File", p.path}, a...) - return findPowershell(), a - case ".cmd", ".bat": - a = append([]string{"/c", p.path}, a...) - return "cmd.exe", a - default: - return p.path, a - } -} - -// finds the appropriate powershell command for the platform - prefers -// PowerShell Core (`pwsh`), but on Windows if it's not found falls back to -// Windows PowerShell (`powershell`). -func findPowershell() string { - if runtime.GOOS != "windows" { - return "pwsh" - } - - _, err := exec.LookPath("pwsh") - if err != nil { - return "powershell" - } - return "pwsh" -} - -func (p *plugin) run(args ...interface{}) (interface{}, error) { - a := conv.ToStrings(args...) - - name, a := p.buildCommand(a) - - ctx, cancel := context.WithTimeout(p.ctx, p.timeout) - defer cancel() - - var stdin *bytes.Buffer - if p.pipe && len(a) > 0 { - stdin = bytes.NewBufferString(a[len(a)-1]) - a = a[:len(a)-1] - } - - c := exec.CommandContext(ctx, name, a...) - if stdin != nil { - c.Stdin = stdin - } - - c.Stderr = p.stderr - outBuf := &bytes.Buffer{} - c.Stdout = outBuf - - start := time.Now() - err := c.Start() - if err != nil { - return nil, err - } - - // make sure all signals are propagated - sigs := make(chan os.Signal, 1) - signal.Notify(sigs) - go func() { - select { - case sig := <-sigs: - // Pass signals to the sub-process - if c.Process != nil { - // nolint: gosec - _ = c.Process.Signal(sig) - } - case <-ctx.Done(): - } - }() - - err = c.Wait() - elapsed := time.Since(start) - - if ctx.Err() != nil { - err = fmt.Errorf("plugin timed out after %v: %w", elapsed, ctx.Err()) - } - - return outBuf.String(), err -} diff --git a/plugins_test.go b/plugins_test.go deleted file mode 100644 index 852c992ef..000000000 --- a/plugins_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package gomplate - -import ( - "bytes" - "context" - "fmt" - "os" - "strings" - "testing" - "text/template" - "time" - - "github.com/flanksource/gomplate/v3/internal/config" - "github.com/stretchr/testify/assert" -) - -func TestBindPlugins(t *testing.T) { - ctx := context.Background() - fm := template.FuncMap{} - cfg := &config.Config{ - Plugins: map[string]config.PluginConfig{}, - } - err := bindPlugins(ctx, cfg, fm) - assert.NoError(t, err) - assert.EqualValues(t, template.FuncMap{}, fm) - - cfg.Plugins = map[string]config.PluginConfig{"foo": {Cmd: "bar"}} - err = bindPlugins(ctx, cfg, fm) - assert.NoError(t, err) - assert.Contains(t, fm, "foo") - - err = bindPlugins(ctx, cfg, fm) - assert.ErrorContains(t, err, "already bound") -} - -func TestBuildCommand(t *testing.T) { - ctx := context.Background() - data := []struct { - name, path string - args []string - expected []string - }{ - {"foo", "foo", nil, []string{"foo"}}, - {"foo", "foo", []string{"bar"}, []string{"foo", "bar"}}, - {"foo", "foo.bat", nil, []string{"cmd.exe", "/c", "foo.bat"}}, - {"foo", "foo.cmd", []string{"bar"}, []string{"cmd.exe", "/c", "foo.cmd", "bar"}}, - {"foo", "foo.ps1", []string{"bar", "baz"}, []string{"pwsh", "-File", "foo.ps1", "bar", "baz"}}, - } - for _, d := range data { - p := &plugin{ - ctx: ctx, - path: d.path, - } - name, args := p.buildCommand(d.args) - actual := append([]string{name}, args...) - assert.EqualValues(t, d.expected, actual) - } -} - -func TestRun(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - stderr := &bytes.Buffer{} - p := &plugin{ - ctx: ctx, - timeout: 500 * time.Millisecond, - stderr: stderr, - path: "echo", - } - out, err := p.run("foo") - assert.NoError(t, err) - assert.Equal(t, "", stderr.String()) - assert.Equal(t, "foo", strings.TrimSpace(out.(string))) -} - -func ExamplePluginFunc() { - ctx := context.Background() - - // PluginFunc creates a template function that runs an arbitrary command. - f := PluginFunc(ctx, "echo", PluginOpts{}) - - // The function can be used in a template, but here we'll just run it - // directly. This is equivalent to running 'echo foo bar' - out, err := f("foo", "bar") - if err != nil { - panic(err) - } - fmt.Println(out) - - // Output: - // foo bar -} - -func ExamplePluginFunc_with_template() { - ctx := context.Background() - - f := PluginFunc(ctx, "echo", PluginOpts{}) - - // PluginFunc is intended for use with gomplate, but can be used in any - // text/template by adding it to the FuncMap. - tmpl := template.New("new").Funcs(template.FuncMap{"echo": f}) - - tmpl, err := tmpl.Parse(`{{ echo "baz" "qux" }}`) - if err != nil { - panic(err) - } - - err = tmpl.Execute(os.Stdout, nil) - if err != nil { - panic(err) - } - - // Output: - // baz qux -} diff --git a/strings/bytes.go b/strings/bytes.go new file mode 100644 index 000000000..e9f3493aa --- /dev/null +++ b/strings/bytes.go @@ -0,0 +1,114 @@ +/* +Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved. + +This project contains software that is Copyright (c) 2013-2015 Pivotal Software, Inc. + +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. + +This project may include a number of subcomponents with separate +copyright notices and license terms. Your use of these subcomponents +is subject to the terms and conditions of each subcomponent's license, +as noted in the LICENSE file. +*/ + +package strings + +import ( + "fmt" + "strconv" + "strings" + + "github.com/google/cel-go/common/types" +) + +const ( + BYTE = 1 << (10 * iota) + KILOBYTE + MEGABYTE + GIGABYTE + TERABYTE + PETABYTE + EXABYTE +) + +// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available: +// +// E: Exabyte +// P: Petabyte +// T: Terabyte +// G: Gigabyte +// M: Megabyte +// K: Kilobyte +// B: Byte +// +// The unit that results in the smallest number greater than or equal to 1 is always chosen. +// Input is the size in bytes. +func HumanBytes(size interface{}) string { + unit := "" + var bytes uint64 + var err error + switch t := size.(type) { + case types.Int: + bytes = uint64(t) + case uint: + bytes = uint64(t) + case uint64: + bytes = t + case int: + bytes = uint64(t) + case int64: + bytes = uint64(t) + case float64: + bytes = uint64(t) + case float32: + bytes = uint64(t) + case string: + bytes, err = strconv.ParseUint(t, 10, 64) + if err != nil { + return "NaN" + } + default: + return fmt.Sprintf("unknown type: %v = %t", size, size) + } + + value := float64(bytes) + + switch { + case bytes >= EXABYTE: + unit = "E" + value = value / EXABYTE + case bytes >= PETABYTE: + unit = "P" + value = value / PETABYTE + case bytes >= TERABYTE: + unit = "T" + value = value / TERABYTE + case bytes >= GIGABYTE: + unit = "G" + value = value / GIGABYTE + case bytes >= MEGABYTE: + unit = "M" + value = value / MEGABYTE + case bytes >= KILOBYTE: + unit = "K" + value = value / KILOBYTE + case bytes >= BYTE: + unit = "B" + case bytes == 0: + return "0B" + } + + result := strconv.FormatFloat(value, 'f', 1, 64) + result = strings.TrimSuffix(result, ".0") + return result + unit +} diff --git a/strings/bytes_test.go b/strings/bytes_test.go new file mode 100644 index 000000000..4db15f30c --- /dev/null +++ b/strings/bytes_test.go @@ -0,0 +1,28 @@ +package strings + +import "testing" + +func TestByteSizeFormating(t *testing.T) { + tests := []struct { + Bytes uint64 + Humanized string + }{ + {0, "0B"}, + {10, "10B"}, + {1023, "1023B"}, + {1024, "1K"}, + {1024 * 1024, "1M"}, + {1024*1024 + 53, "1M"}, + {5 * 1024 * 1024, "5M"}, + {1 * 1024 * 1024 * 1024, "1G"}, + {1 * 1024 * 1024 * 1024 * 1024, "1T"}, + {10 * 1024 * 1024 * 1024 * 1024, "10T"}, + {10 * 1024 * 1024 * 1024 * 1024 * 1024, "10P"}, + {10 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, "10E"}, + } + for _, tc := range tests { + if HumanBytes(tc.Bytes) != tc.Humanized { + t.Errorf("Failed for test case %v ", tc) + } + } +} diff --git a/strings/cel_gen_exports.go b/strings/cel_gen_exports.go new file mode 100644 index 000000000..78445bea5 --- /dev/null +++ b/strings/cel_gen_exports.go @@ -0,0 +1,32 @@ +// Code generated by gencel. DO NOT EDIT. + +package strings + +import "log" +import "github.com/google/cel-go/common/types/ref" +import "github.com/google/cel-go/cel" + +func transferSlice[K any](arg ref.Val) []K { + list, ok := arg.Value().([]ref.Val) + if !ok { + log.Printf("Not a list %T\n", arg.Value()) + return nil + } + + var out = make([]K, len(list)) + for i, val := range list { + out[i] = val.Value().(K) + } + + return out +} + +var CelEnvOption = []cel.EnvOption{ + durationStringGen, + durationNanosecondsGen, + durationSecondsGen, + durationHoursGen, + durationDaysGen, + durationWeeksGen, + durationMinutesGen, +} diff --git a/strings/duration.go b/strings/duration.go new file mode 100644 index 000000000..e3a8522b5 --- /dev/null +++ b/strings/duration.go @@ -0,0 +1,426 @@ +// MIT License +// Copyright Wijnand Modderman-Lenstra (maze.io) + +// 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. + +// FORKED from https://git.maze.io/go/duration/src/branch/master/duration.go + +// Package duration contains routines to parse standard units of time. +package strings + +import ( + "errors" + "strings" + "time" +) + +// Duration is a standard unit of time. +type Duration time.Duration + +// String returns a string representing the duration in the form "3d1h3m". +// Leading zero units are omitted. As a special case, durations less than one +// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure +// that the leading digit is non-zero. Duration more than a day or more than a +// week lose granularity and are truncated to resp. days-hours-minutes and +// weeks-days-hours. The zero duration formats as 0s. +func (d Duration) String() string { + // Largest time is 2540400h10m10.000000000s + var buf [32]byte + w := len(buf) + + u := uint64(d) + neg := d < 0 + if neg { + u = -u + } + + if u < uint64(Second) { + // Special case: if duration is smaller than a second, + // use smaller units, like 1.2ms + var prec int + w-- + buf[w] = 's' + w-- + switch { + case u == 0: + return "0s" + case u < uint64(Microsecond): + // print nanoseconds + prec = 0 + buf[w] = 'n' + case u < uint64(Millisecond): + // print microseconds + prec = 3 + // U+00B5 'µ' micro sign == 0xC2 0xB5 + w-- // Need room for two bytes. + copy(buf[w:], "µ") + default: + // print milliseconds + prec = 6 + buf[w] = 'm' + } + w, u = fmtFrac(buf[:w], u, prec) + w = fmtInt(buf[:w], u) + + } else if u > uint64(Week) { + // Special case: if duration is larger than a week, + // use bigger units like 4w3d2h + w-- + buf[w] = 'h' + + u /= uint64(Hour) + + // u is now integer hours + w = fmtInt(buf[:w], u%24) + u /= 24 + + // u is now integer days + if u > 0 { + w-- + buf[w] = 'd' + w = fmtInt(buf[:w], u%7) + u /= 7 + + // u is now integer weeks + // Stop at hours because days can be different lengths. + if u > 0 { + w-- + buf[w] = 'w' + w = fmtInt(buf[:w], u) + } + } + + } else if u > uint64(Day) { + // Special case: if duration is larger than a day, + // use bigger units like 3d2h6m + w-- + buf[w] = 'm' + + u /= uint64(Minute) + + // u is now integer minutes + w = fmtInt(buf[:w], u%60) + u /= 60 + + // u is now integer hours + if u > 0 { + w-- + buf[w] = 'h' + w = fmtInt(buf[:w], u%24) + u /= 24 + + // u is now integer weeks + if u > 0 { + w-- + buf[w] = 'd' + w = fmtInt(buf[:w], u) + } + } + + } else { + w-- + buf[w] = 's' + + w, u = fmtFrac(buf[:w], u, 9) + + // u is now integer seconds + w = fmtInt(buf[:w], u%60) + u /= 60 + + // u is now integer minutes + if u > 0 { + w-- + buf[w] = 'm' + w = fmtInt(buf[:w], u%60) + u /= 60 + + // u is now integer hours + // Stop at hours because days can be different lengths. + if u > 0 { + w-- + buf[w] = 'h' + w = fmtInt(buf[:w], u) + } + } + } + + if neg { + w-- + buf[w] = '-' + } + + return strings.ReplaceAll(strings.ReplaceAll(string(buf[w:]), "0s", ""), "0m", "") +} + +// fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the +// tail of buf, omitting trailing zeros. it omits the decimal +// point too when the fraction is 0. It returns the index where the +// output bytes begin and the value v/10**prec. +func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) { + // Omit trailing zeros up to and including decimal point. + w := len(buf) + print := false + for i := 0; i < prec; i++ { + digit := v % 10 + print = print || digit != 0 + if print { + w-- + buf[w] = byte(digit) + '0' + } + v /= 10 + } + if print { + w-- + buf[w] = '.' + } + return w, v +} + +// fmtInt formats v into the tail of buf. +// It returns the index where the output begins. +func fmtInt(buf []byte, v uint64) int { + w := len(buf) + if v == 0 { + w-- + buf[w] = '0' + } else { + for v > 0 { + w-- + buf[w] = byte(v%10) + '0' + v /= 10 + } + } + return w +} + +// Nanoseconds returns the duration as an integer nanosecond count. +func (d Duration) Nanoseconds() int64 { return int64(d) } + +// Seconds returns the duration as a floating point number of seconds. +func (d Duration) Seconds() float64 { + sec := d / Second + nsec := d % Second + return float64(sec) + float64(nsec)*1e-9 +} + +// Hours returns the duration as a floating point number of hours. +func (d Duration) Hours() float64 { + hour := d / Hour + nsec := d % Hour + return float64(hour) + float64(nsec)*(1e-9/60/60) +} + +// Days returns the duration as a floating point number of days. +func (d Duration) Days() float64 { + hour := d / Hour + nsec := d % Hour + return float64(hour) + float64(nsec)*(1e-9/60/60/24) +} + +// Weeks returns the duration as a floating point number of days. +func (d Duration) Weeks() float64 { + hour := d / Hour + nsec := d % Hour + return float64(hour) + float64(nsec)*(1e-9/60/60/24/7) +} + +// Minutes returns the duration as a floating point number of minutes. +func (d Duration) Minutes() float64 { + min := d / Minute + nsec := d % Minute + return float64(min) + float64(nsec)*(1e-9/60) +} + +// Standard unit of time. +var ( + Nanosecond = Duration(time.Nanosecond) + Microsecond = Duration(time.Microsecond) + Millisecond = Duration(time.Millisecond) + Second = Duration(time.Second) + Minute = Duration(time.Minute) + Hour = Duration(time.Hour) + Day = Hour * 24 + Week = Day * 7 + Fortnight = Week * 2 + Month = Day * 30 // Approximation + Year = Day * 365 // Approximation + Decade = Year * 10 // Approximation + Century = Year * 100 // Approximation + Millennium = Year * 1000 // Approximation +) + +var errLeadingInt = errors.New("duration: bad [0-9]*") // never printed +// leadingInt consumes the leading [0-9]* from s. +func leadingInt(s string) (x int64, rem string, err error) { + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + break + } + if x > (1<<63-1)/10 { + // overflow + return 0, "", errLeadingInt + } + x = x*10 + int64(c) - '0' + if x < 0 { + // overflow + return 0, "", errLeadingInt + } + } + return x, s[i:], nil +} + +var unitMap = map[string]int64{ + "ns": int64(Nanosecond), + "us": int64(Microsecond), + "µs": int64(Microsecond), // U+00B5 = micro symbol + "μs": int64(Microsecond), // U+03BC = Greek letter mu + "ms": int64(Millisecond), + "s": int64(Second), + "m": int64(Minute), + "h": int64(Hour), + "d": int64(Day), + "w": int64(Week), + "y": int64(Year), // Approximation +} + +// ParseDuration parses a duration string. +// A duration string is a possibly signed sequence of +// decimal numbers, each with optional fraction and a unit suffix, +// such as "300ms", "-1.5h" or "2h45m". +// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h", "d", "w", "y". +func parseDuration(s string) (Duration, error) { + // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ + orig := s + var d int64 + neg := false + + // Consume [-+]? + if s != "" { + c := s[0] + if c == '-' || c == '+' { + neg = c == '-' + s = s[1:] + } + } + // Special case: if all that is left is "0", this is zero. + if s == "0" { + return 0, nil + } + if s == "" { + return 0, errors.New("time: invalid duration " + orig) + } + for s != "" { + var ( + v, f int64 // integers before, after decimal point + scale float64 = 1 // value = v + f/scale + ) + + var err error + + // The next character must be [0-9.] + if !(s[0] == '.' || '0' <= s[0] && s[0] <= '9') { + return 0, errors.New("time: invalid duration " + orig) + } + // Consume [0-9]* + pl := len(s) + v, s, err = leadingInt(s) + if err != nil { + return 0, errors.New("time: invalid duration " + orig) + } + pre := pl != len(s) // whether we consumed anything before a period + // Consume (\.[0-9]*)? + post := false + if s != "" && s[0] == '.' { + s = s[1:] + pl := len(s) + f, s, err = leadingInt(s) + if err != nil { + return 0, errors.New("time: invalid duration " + orig) + } + for n := pl - len(s); n > 0; n-- { + scale *= 10 + } + post = pl != len(s) + } + if !pre && !post { + // no digits (e.g. ".s" or "-.s") + return 0, errors.New("time: invalid duration " + orig) + } + + // Consume unit. + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c == '.' || '0' <= c && c <= '9' { + break + } + } + if i == 0 { + return 0, errors.New("time: missing unit in duration " + orig) + } + u := s[:i] + s = s[i:] + unit, ok := unitMap[u] + if !ok { + return 0, errors.New("time: unknown unit " + u + " in duration " + orig) + } + if v > (1<<63-1)/unit { + // overflow + return 0, errors.New("time: invalid duration " + orig) + } + v *= unit + if f > 0 { + // float64 is needed to be nanosecond accurate for fractions of hours. + // v >= 0 && (f*unit/scale) <= 3.6e+12 (ns/h, h is the largest unit) + v += int64(float64(f) * (float64(unit) / scale)) + if v < 0 { + // overflow + return 0, errors.New("time: invalid duration " + orig) + } + } + d += v + if d < 0 { + // overflow + return 0, errors.New("time: invalid duration " + orig) + } + } + + if neg { + d = -d + } + return Duration(d), nil +} + +// Returns a string representing of a duration in the form "3d1h3m". +// +// Leading zero units are omitted. As a special case, durations less than one +// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure +// that the leading digit is non-zero. Duration more than a day or more than a +// week lose granularity and are truncated to resp. days-hours-minutes and +// weeks-days-hours. The zero duration formats as 0s. +func HumanDuration(duration interface{}) string { + switch v := duration.(type) { + case int64: + return Duration(time.Duration(int64(v))).String() + case float64: + return Duration(time.Duration(int64(v))).String() + case time.Duration: + return Duration(v).String() + } + return "" +} + +func ParseDuration(val string) (*time.Duration, error) { + d, err := parseDuration(val) + if err != nil { + return nil, err + } + t := time.Duration(d) + return &t, err +} diff --git a/strings/duration_gen.go b/strings/duration_gen.go new file mode 100644 index 000000000..acd18066e --- /dev/null +++ b/strings/duration_gen.go @@ -0,0 +1,105 @@ +// Code generated by gencel. DO NOT EDIT. + +package strings + +import "github.com/google/cel-go/cel" +import "github.com/google/cel-go/common/types" +import "github.com/google/cel-go/common/types/ref" + +var durationStringGen = cel.Function("duration.String", + cel.Overload("duration.String_", + nil, + cel.StringType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.String()) + + }), + ), +) + +var durationNanosecondsGen = cel.Function("duration.Nanoseconds", + cel.Overload("duration.Nanoseconds_", + nil, + cel.IntType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.Nanoseconds()) + + }), + ), +) + +var durationSecondsGen = cel.Function("duration.Seconds", + cel.Overload("duration.Seconds_", + nil, + cel.DoubleType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.Seconds()) + + }), + ), +) + +var durationHoursGen = cel.Function("duration.Hours", + cel.Overload("duration.Hours_", + nil, + cel.DoubleType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.Hours()) + + }), + ), +) + +var durationDaysGen = cel.Function("duration.Days", + cel.Overload("duration.Days_", + nil, + cel.DoubleType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.Days()) + + }), + ), +) + +var durationWeeksGen = cel.Function("duration.Weeks", + cel.Overload("duration.Weeks_", + nil, + cel.DoubleType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.Weeks()) + + }), + ), +) + +var durationMinutesGen = cel.Function("duration.Minutes", + cel.Overload("duration.Minutes_", + nil, + cel.DoubleType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + + var x Duration + + return types.DefaultTypeAdapter.NativeToValue(x.Minutes()) + + }), + ), +) diff --git a/strings/duration_test.go b/strings/duration_test.go new file mode 100644 index 000000000..555d2cc13 --- /dev/null +++ b/strings/duration_test.go @@ -0,0 +1,34 @@ +package strings + +import ( + "testing" + "time" +) + +func TestHumanizeDuration(t *testing.T) { + tests := []struct { + Duration interface{} + Humanized string + }{ + {5 * time.Nanosecond, "5ns"}, + {5 * time.Millisecond, "5ms"}, + {5 * time.Second, "5s"}, + {(5 * time.Second).Nanoseconds(), "5s"}, + {75 * time.Second, "1m15s"}, + {121 * time.Second, "2m1s"}, + {431 * time.Second, "7m11s"}, + {65 * time.Minute, "1h5m"}, + {125 * time.Minute, "2h5m"}, + {23 * time.Hour, "23h"}, + {32 * time.Hour, "1d8h"}, + {49 * time.Hour, "2d1h"}, + {320 * time.Hour, "1w6d8h"}, + {3200 * time.Hour, "19w0d8h"}, + } + + for _, tc := range tests { + if HumanDuration(tc.Duration) != tc.Humanized { + t.Errorf("Failed for test case %v != %v", tc, HumanDuration(tc.Duration)) + } + } +} diff --git a/strings/semver.go b/strings/semver.go new file mode 100644 index 000000000..248974ce8 --- /dev/null +++ b/strings/semver.go @@ -0,0 +1,23 @@ +package strings + +import ( + sv2 "github.com/Masterminds/semver/v3" +) + +func SemverCompare(constraint, version string) (bool, error) { + c, err := sv2.NewConstraint(constraint) + if err != nil { + return false, err + } + + v, err := sv2.NewVersion(version) + if err != nil { + return false, err + } + + return c.Check(v), nil +} + +func Semver(version string) (*sv2.Version, error) { + return sv2.NewVersion(version) +} diff --git a/strings/semver_test.go b/strings/semver_test.go new file mode 100644 index 000000000..e50dbb905 --- /dev/null +++ b/strings/semver_test.go @@ -0,0 +1,13 @@ +package strings + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSemverCompare(t *testing.T) { + v, err := SemverCompare("1.2.3", "1.2.3") + assert.NoError(t, err) + assert.Equal(t, true, v) +} diff --git a/template.go b/template.go new file mode 100644 index 000000000..726d8a712 --- /dev/null +++ b/template.go @@ -0,0 +1,110 @@ +package gomplate + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "strings" + gotemplate "text/template" + + "github.com/flanksource/gomplate/v3/funcs" + "github.com/google/cel-go/cel" +) + +var funcMap gotemplate.FuncMap + +func init() { + funcMap = CreateFuncs(context.Background()) +} + +type Template struct { + Template string `yaml:"template,omitempty" json:"template,omitempty"` + JSONPath string `yaml:"jsonPath,omitempty" json:"jsonPath,omitempty"` + Expression string `yaml:"expr,omitempty" json:"expr,omitempty"` + Javascript string `yaml:"javascript,omitempty" json:"javascript,omitempty"` +} + +func (t Template) IsEmpty() bool { + return t.Template == "" && t.JSONPath == "" && t.Expression == "" && t.Javascript == "" +} + +func RunTemplate(environment map[string]interface{}, template Template) (string, error) { + // javascript + if template.Javascript != "" { + // // FIXME: whitelist allowed files + // vm := otto.New() + // for k, v := range environment { + // if err := vm.Set(k, v); err != nil { + // return "", errors.Wrapf(err, "error setting %s", k) + // } + // } + + // if err != nil { + // return "", errors.Wrapf(err, "error setting findConfigItem function") + // } + + // out, err := vm.Run(template.Javascript) + // if err != nil { + // return "", errors.Wrapf(err, "failed to run javascript") + // } + + // if s, err := out.ToString(); err != nil { + // return "", errors.Wrapf(err, "failed to cast output to string") + // } else { + // return s, nil + // } + } + + // gotemplate + if template.Template != "" { + tpl := gotemplate.New("") + tpl, err := tpl.Funcs(funcMap).Parse(template.Template) + if err != nil { + return "", err + } + + // marshal data from interface{} to map[string]interface{} + data, _ := json.Marshal(environment) + unstructured := make(map[string]interface{}) + if err := json.Unmarshal(data, &unstructured); err != nil { + return "", err + } + + var buf bytes.Buffer + if err := tpl.Execute(&buf, unstructured); err != nil { + return "", fmt.Errorf("error executing template %s: %v", strings.Split(template.Template, "\n")[0], err) + } + return strings.TrimSpace(buf.String()), nil + } + + // cel-go + if template.Expression != "" { + var opts = funcs.CelEnvOption + for k := range environment { + opts = append(opts, cel.Variable(k, cel.AnyType)) + } + + env, err := cel.NewEnv(opts...) + if err != nil { + return "", err + } + + ast, issues := env.Compile(template.Expression) + if issues != nil && issues.Err() != nil { + return "", issues.Err() + } + + prg, err := env.Program(ast, cel.Globals(environment)) + if err != nil { + return "", err + } + out, _, err := prg.Eval(environment) + if err != nil { + return "", err + } + return fmt.Sprintf("%v", out.Value()), nil + } + + return "", nil +} diff --git a/template_test.go b/template_test.go new file mode 100644 index 000000000..bea119baf --- /dev/null +++ b/template_test.go @@ -0,0 +1,67 @@ +package gomplate + +import ( + "testing" + "time" + + "github.com/flanksource/gomplate/v3/k8s" + "github.com/stretchr/testify/assert" +) + +func TestGomplate(t *testing.T) { + tests := []struct { + env map[string]interface{} + template string + out string + }{ + {map[string]interface{}{"hello": "world"}, "{{ .hello }}", "world"}, + {map[string]interface{}{"age": 75 * time.Second}, "{{ .age | humanDuration }}", "1m15s"}, + {map[string]interface{}{"healthySvc": k8s.GetUnstructured(k8s.TestHealthy)}, "{{ (.healthySvc | isHealthy) }}", "true"}, + {map[string]interface{}{"healthySvc": k8s.GetUnstructured(k8s.TestLuaStatus)}, "{{ (.healthySvc | getStatus) }}", "Degraded: found less than two generators, Merge requires two or more"}, + {map[string]interface{}{"healthySvc": k8s.GetUnstructured(k8s.TestHealthy)}, "{{ (.healthySvc | getHealth).Status }}", "Healthy"}, + {map[string]interface{}{"size": 123456}, "{{ .size | humanSize }}", "120.6K"}, + {map[string]interface{}{"v": "1.2.3-beta.1+c0ff33"}, "{{ (.v | semver).Prerelease }}", "beta.1"}, + {map[string]interface{}{"old": "1.2.3", "new": "1.2.3"}, "{{ .old | semverCompare .new }}", "true"}, + {map[string]interface{}{"old": "1.2.3", "new": "1.2.4"}, "{{ .old | semverCompare .new }}", "false"}, + } + + for _, tc := range tests { + t.Run(tc.template, func(t *testing.T) { + out, err := RunTemplate(tc.env, Template{ + Template: tc.template, + }) + assert.ErrorIs(t, err, nil) + assert.Equal(t, tc.out, out) + }) + } +} + +func TestCel(t *testing.T) { + tests := []struct { + env map[string]interface{} + expression string + out string + }{ + {nil, `math.Add([1,2,3,4,5])`, "15"}, + {map[string]interface{}{"hello": "world"}, "hello", "world"}, + {map[string]interface{}{"age": 75 * time.Second}, "age", "1m15s"}, + {map[string]interface{}{"healthySvc": k8s.GetUnstructuredMap(k8s.TestHealthy)}, "IsHealthy(healthySvc)", "true"}, + {map[string]interface{}{"healthySvc": k8s.GetUnstructuredMap(k8s.TestLuaStatus)}, "GetStatus(healthySvc)", "Degraded: found less than two generators, Merge requires two or more"}, + {map[string]interface{}{"healthySvc": k8s.GetUnstructuredMap(k8s.TestHealthy)}, "GetHealth(healthySvc).status", "Healthy"}, + {map[string]interface{}{"size": "123456"}, "HumanSize(size)", "120.6K"}, + {map[string]interface{}{"size": 123456}, "HumanSize(size)", "120.6K"}, + {map[string]interface{}{"v": "1.2.3-beta.1+c0ff33"}, "Semver(v).prerelease", "beta.1"}, + {map[string]interface{}{"old": "1.2.3", "new": "1.2.3"}, "SemverCompare(new, old)", "true"}, + {map[string]interface{}{"old": "1.2.3", "new": "1.2.4"}, "SemverCompare(new, old)", "false"}, + } + + for _, tc := range tests { + t.Run(tc.expression, func(t *testing.T) { + out, err := RunTemplate(tc.env, Template{ + Expression: tc.expression, + }) + assert.ErrorIs(t, nil, err) + assert.Equal(t, tc.out, out) + }) + } +} diff --git a/time/time.go b/time/time.go index cc421e538..1a4e986d5 100644 --- a/time/time.go +++ b/time/time.go @@ -2,9 +2,8 @@ package time import ( + "os" "time" - - "github.com/flanksource/gomplate/v3/env" ) // ZoneName - a convenience function for determining the current timezone's name @@ -20,11 +19,15 @@ func ZoneOffset() int { } func zone() (string, int) { + + tz := os.Getenv("TZ") + if tz == "" { + tz = "Local" + } // re-read TZ env var in case it's changed since the process started. // This may happen in certain rare instances when this is being called as a // library, or in a test. It allows for a bit more flexibility too, as // changing time.Local is prone to data races. - tz := env.Getenv("TZ", "Local") loc, err := time.LoadLocation(tz) if err != nil { loc = time.Local