From 067e55f8cc781e2e1cfd8f8a00f3cccd8fec22cf Mon Sep 17 00:00:00 2001 From: wlan0 Date: Mon, 5 Apr 2021 15:08:03 -0700 Subject: [PATCH] Major refactor and bugfixes - Requires changes to API from this PR github.com/kubernetes-sigs/container-object-storage-interface-api/pull/35 - Requires changes to API from this PR github.com/kubernetes-sigs/container-object-storage-interface-spec/pull/25 --- .../Dockerfile => Dockerfile | 2 +- Dockerfile.sample-driver | 6 - Makefile | 2 +- cmd/minio-cosi-driver/cmd.go | 73 ++ cmd/minio-cosi-driver/main.go | 44 ++ .../app/objectstorage-sidecar.go | 109 --- cmd/objectstorage-sidecar/cmd.go | 101 +++ cmd/objectstorage-sidecar/main.go | 52 +- cmd/sample-driver/Dockerfile | 6 - cmd/sample-driver/driver-server.go | 136 ---- cmd/sample-driver/identity-server.go | 53 -- cmd/sample-driver/sample-driver.go | 127 --- go.mod | 27 +- go.sum | 438 +---------- hack/add-license-header.sh | 22 + pkg/bucket/bucket_controller.go | 200 +++++ pkg/bucket/bucket_controller_test.go | 187 +++++ pkg/bucketaccess/bucketaccess_controller.go | 254 ++++++ .../bucketaccess_controller_test.go | 235 ++++++ pkg/controller/bucket/bucket_controller.go | 208 ----- .../bucket/bucket_controller_test.go | 534 ------------- .../bucketaccess/bucket_access_controller.go | 270 ------- .../bucket_access_controller_test.go | 740 ------------------ pkg/grpcclient/client.go | 139 ---- pkg/grpcserver/server.go | 139 ---- pkg/provisioner/client.go | 70 ++ pkg/provisioner/interceptors.go | 46 ++ pkg/provisioner/provisioner.go | 111 +++ pkg/provisioner/server.go | 67 ++ pkg/sampledriver/driver.go | 22 + pkg/sampledriver/identity.go | 42 + pkg/sampledriver/provisioner.go | 49 ++ resources/deployment.yaml | 16 +- resources/secret.yaml | 4 +- 34 files changed, 1629 insertions(+), 2902 deletions(-) rename cmd/objectstorage-sidecar/Dockerfile => Dockerfile (79%) delete mode 100644 Dockerfile.sample-driver create mode 100644 cmd/minio-cosi-driver/cmd.go create mode 100644 cmd/minio-cosi-driver/main.go delete mode 100644 cmd/objectstorage-sidecar/app/objectstorage-sidecar.go create mode 100644 cmd/objectstorage-sidecar/cmd.go delete mode 100644 cmd/sample-driver/Dockerfile delete mode 100644 cmd/sample-driver/driver-server.go delete mode 100644 cmd/sample-driver/identity-server.go delete mode 100644 cmd/sample-driver/sample-driver.go create mode 100755 hack/add-license-header.sh create mode 100644 pkg/bucket/bucket_controller.go create mode 100644 pkg/bucket/bucket_controller_test.go create mode 100644 pkg/bucketaccess/bucketaccess_controller.go create mode 100644 pkg/bucketaccess/bucketaccess_controller_test.go delete mode 100644 pkg/controller/bucket/bucket_controller.go delete mode 100644 pkg/controller/bucket/bucket_controller_test.go delete mode 100644 pkg/controller/bucketaccess/bucket_access_controller.go delete mode 100644 pkg/controller/bucketaccess/bucket_access_controller_test.go delete mode 100644 pkg/grpcclient/client.go delete mode 100644 pkg/grpcserver/server.go create mode 100644 pkg/provisioner/client.go create mode 100644 pkg/provisioner/interceptors.go create mode 100644 pkg/provisioner/provisioner.go create mode 100644 pkg/provisioner/server.go create mode 100644 pkg/sampledriver/driver.go create mode 100644 pkg/sampledriver/identity.go create mode 100644 pkg/sampledriver/provisioner.go diff --git a/cmd/objectstorage-sidecar/Dockerfile b/Dockerfile similarity index 79% rename from cmd/objectstorage-sidecar/Dockerfile rename to Dockerfile index 78f5ebc..0a44b73 100644 --- a/cmd/objectstorage-sidecar/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM gcr.io/distroless/static:latest -LABEL maintainers="Kubernetes Authors" +LABEL maintainers="Kubernetes COSI Authors" LABEL description="Object Storage Sidecar" COPY ./bin/objectstorage-sidecar objectstorage-sidecar diff --git a/Dockerfile.sample-driver b/Dockerfile.sample-driver deleted file mode 100644 index 0a8ee41..0000000 --- a/Dockerfile.sample-driver +++ /dev/null @@ -1,6 +0,0 @@ -FROM gcr.io/distroless/static:latest -LABEL maintainers="Kubernetes Authors" -LABEL description="Object Storage Sidecar Sample Driver" - -COPY ./bin/sample-driver /sample-driver -ENTRYPOINT ["/sample-driver"] diff --git a/Makefile b/Makefile index c26fe7e..d98e7a8 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -CMDS=objectstorage-sidecar sample-driver +CMDS=objectstorage-sidecar minio-cosi-driver all: reltools build .PHONY: reltools diff --git a/cmd/minio-cosi-driver/cmd.go b/cmd/minio-cosi-driver/cmd.go new file mode 100644 index 0000000..69d243e --- /dev/null +++ b/cmd/minio-cosi-driver/cmd.go @@ -0,0 +1,73 @@ +// Copyright 2021 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "flag" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/provisioner" + "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/sampledriver" + + "k8s.io/klog/v2" +) + +const provisionerName = "minio.objectstorage.k8s.io" + +var ( + driverAddress = "unix:///var/lib/cosi/cosi.sock" +) + +var cmd = &cobra.Command{ + Use: "minio-cosi-driver", + Short: "K8s COSI driver for MinIO object storage", + SilenceErrors: true, + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + return run(cmd.Context(), args) + }, + DisableFlagsInUseLine: true, +} + +func init() { + viper.AutomaticEnv() + + flag.Set("alsologtostderr", "true") + kflags := flag.NewFlagSet("klog", flag.ExitOnError) + klog.InitFlags(kflags) + + persistentFlags := cmd.PersistentFlags() + persistentFlags.AddGoFlagSet(kflags) + + stringFlag := persistentFlags.StringVarP + stringFlag(&driverAddress, + "driver-addr", + "d", + driverAddress, + "path to unix domain socket where driver should listen") + + viper.BindPFlags(cmd.PersistentFlags()) +} + +func run(ctx context.Context, args []string) error { + identityServer, bucketProvisioner := sampledriver.NewDriver(provisionerName) + server, err := provisioner.NewDefaultCOSIProvisionerServer(driverAddress, identityServer, bucketProvisioner) + if err != nil { + return err + } + return server.Run(ctx) +} diff --git a/cmd/minio-cosi-driver/main.go b/cmd/minio-cosi-driver/main.go new file mode 100644 index 0000000..abce3c7 --- /dev/null +++ b/cmd/minio-cosi-driver/main.go @@ -0,0 +1,44 @@ +// Copyright 2021 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "os" + "os/signal" + "syscall" + "time" + + "k8s.io/klog/v2" +) + +func main() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + go func() { + sig := <-sigs + klog.InfoS("Signal received", "type", sig) + cancel() + <-time.After(30 * time.Second) + os.Exit(1) + }() + + if err := cmd.ExecuteContext(ctx); err != nil { + klog.ErrorS(err, "Exiting on error") + } +} diff --git a/cmd/objectstorage-sidecar/app/objectstorage-sidecar.go b/cmd/objectstorage-sidecar/app/objectstorage-sidecar.go deleted file mode 100644 index cc5aac9..0000000 --- a/cmd/objectstorage-sidecar/app/objectstorage-sidecar.go +++ /dev/null @@ -1,109 +0,0 @@ -package app - -import ( - "context" - "os" - "time" - - "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/controller/bucket" - "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/controller/bucketaccess" - "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/grpcclient" - - osspec "sigs.k8s.io/container-object-storage-interface-spec" - - "github.com/spf13/cobra" - - "google.golang.org/grpc" - - "k8s.io/klog/v2" -) - -const ( - // Interval of logging connection errors - connectionLoggingInterval = 10 * time.Second - defaultDriverAddress = "tcp://0.0.0.0:9000" -) - -// SidecarOptions defines the options for running the sidecar -type SidecarOptions struct { - driverAddress string -} - -// NewSidecarOptions returns an initialized SidecarOptions instance -func NewSidecarOptions() *SidecarOptions { - return &SidecarOptions{driverAddress: defaultDriverAddress} -} - -// Run starts the sidecar with the configured options -func (so *SidecarOptions) Run() { - klog.Infof("attempting to open a gRPC connection with: %q", so.driverAddress) - grpcClient, err := grpcclient.NewGRPCClient(so.driverAddress, []grpc.DialOption{}, nil) - if err != nil { - klog.Errorf("error creating GRPC Client: %v", err) - os.Exit(1) - } - - grpcConn, err := grpcClient.ConnectWithLogging(connectionLoggingInterval) - if err != nil { - klog.Errorf("error connecting to COSI driver: %v", err) - os.Exit(1) - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - klog.Infof("creating provisioner client") - provisionerClient := osspec.NewProvisionerClient(grpcConn) - identityClient := osspec.NewIdentityClient(grpcConn) - - klog.Infof("discovering driver name") - req := osspec.ProvisionerGetInfoRequest{} - rsp, err := identityClient.ProvisionerGetInfo(ctx, &req) - if err != nil { - klog.Errorf("error calling ProvisionerGetInfo: %v", err) - os.Exit(1) - } - - // TODO: go routine with health check to vendor driver - - provisionerName := rsp.Name - // TODO: Register provisioner using internal type - klog.Info("This sidecar is working with the driver identified as: ", provisionerName) - - so.startControllers(ctx, provisionerName, provisionerClient) - <-ctx.Done() -} - -func (so *SidecarOptions) startControllers(ctx context.Context, name string, client osspec.ProvisionerClient) { - bucketController, err := bucket.NewBucketController(name, client) - if err != nil { - klog.Fatalf("Error creating bucket controller: %v", err) - } - - bucketAccessController, err := bucketaccess.NewBucketAccessController(name, client) - if err != nil { - klog.Fatalf("Error creating bucket access controller: %v", err) - } - - go bucketController.Run(ctx) - go bucketAccessController.Run(ctx) -} - -// NewControllerManagerCommand creates a *cobra.Command object with default parameters -func NewControllerManagerCommand() *cobra.Command { - opts := NewSidecarOptions() - - cmd := &cobra.Command{ - Use: "objectstorage-sidecar", - DisableFlagsInUseLine: true, - Short: "", - Long: ``, - Run: func(cmd *cobra.Command, args []string) { - opts.Run() - }, - } - - cmd.Flags().StringVarP(&opts.driverAddress, "connect-address", "c", opts.driverAddress, "The address that the sidecar should connect to") - - return cmd -} diff --git a/cmd/objectstorage-sidecar/cmd.go b/cmd/objectstorage-sidecar/cmd.go new file mode 100644 index 0000000..7555947 --- /dev/null +++ b/cmd/objectstorage-sidecar/cmd.go @@ -0,0 +1,101 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "context" + "flag" + + "sigs.k8s.io/container-object-storage-interface-api/controller" + "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/bucket" + "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/bucketaccess" + "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/provisioner" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "k8s.io/klog/v2" +) + +const DefaultProvisionerName = "provisioner.objectstorage.k8s.io" + +var ( + driverAddress = "unix:///var/lib/cosi/cosi.sock" + provisionerName = "" + kubeconfig = "" + debug = false +) + +var cmd = &cobra.Command{ + Use: "objectstorage-sidecar", + Short: "provisioner that interacts with cosi drivers to manage buckets and bucketAccesses", + SilenceErrors: true, + SilenceUsage: true, + RunE: func(cmd *cobra.Command, args []string) error { + return run(cmd.Context(), args) + }, + DisableFlagsInUseLine: true, +} + +func init() { + viper.AutomaticEnv() + + flag.Set("alsologtostderr", "true") + kflags := flag.NewFlagSet("klog", flag.ExitOnError) + klog.InitFlags(kflags) + + persistentFlags := cmd.PersistentFlags() + persistentFlags.AddGoFlagSet(kflags) + + stringFlag := persistentFlags.StringVarP + boolFlag := persistentFlags.BoolVarP + + stringFlag(&kubeconfig, "kubeconfig", "", kubeconfig, "path to kubeconfig file") + stringFlag(&driverAddress, "driver-addr", "d", driverAddress, "path to unix domain socket where driver is listening") + stringFlag(&provisionerName, "provisioner", "p", DefaultProvisionerName, "The name of the provisioner") + + boolFlag(&debug, "debug", "g", debug, "Logs all grpc requests and responses") + + viper.BindPFlags(cmd.PersistentFlags()) +} + +func run(ctx context.Context, args []string) error { + if provisionerName == "" { + provisionerName = DefaultProvisionerName + } + + ctrl, err := controller.NewDefaultObjectStorageController("cosi", provisionerName, 40) + if err != nil { + return err + } + + klog.V(3).InfoS("Attempting connection to driver", "address", driverAddress) + cosiClient, err := provisioner.NewDefaultCOSIProvisionerClient(ctx, driverAddress, debug) + if err != nil { + return err + } + klog.V(3).InfoS("Successfully connected to driver") + + ctrl.AddBucketListener(bucket.NewBucketListener(provisionerName, cosiClient)) + + bal, err := bucketaccess.NewBucketAccessListener(provisionerName, cosiClient) + if err != nil { + return err + } + ctrl.AddBucketAccessListener(bal) + + return ctrl.Run(ctx) +} diff --git a/cmd/objectstorage-sidecar/main.go b/cmd/objectstorage-sidecar/main.go index a2317e3..643eb0a 100644 --- a/cmd/objectstorage-sidecar/main.go +++ b/cmd/objectstorage-sidecar/main.go @@ -1,30 +1,46 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package main import ( + "context" "os" + "os/signal" + "syscall" + "time" - "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/cmd/objectstorage-sidecar/app" + "k8s.io/klog/v2" ) func main() { - command := app.NewControllerManagerCommand() - if err := command.Execute(); err != nil { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + go func() { + sig := <-sigs + klog.InfoS("Signal received", "type", sig) + cancel() + <-time.After(30 * time.Second) os.Exit(1) + }() + + if err := cmd.ExecuteContext(ctx); err != nil { + klog.ErrorS(err, "Exiting on error") } } diff --git a/cmd/sample-driver/Dockerfile b/cmd/sample-driver/Dockerfile deleted file mode 100644 index 1d8c977..0000000 --- a/cmd/sample-driver/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM gcr.io/distroless/static:latest -LABEL maintainers="Kubernetes Authors" -LABEL description="Object Storage Sample Driver" - -COPY ./bin/sample-driver sample-driver -ENTRYPOINT ["/sample-driver"] diff --git a/cmd/sample-driver/driver-server.go b/cmd/sample-driver/driver-server.go deleted file mode 100644 index 00d2cdf..0000000 --- a/cmd/sample-driver/driver-server.go +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "fmt" - - "github.com/minio/minio-go" - "github.com/minio/minio/pkg/auth" - "github.com/minio/minio/pkg/bucket/policy" - "github.com/minio/minio/pkg/bucket/policy/condition" - iampolicy "github.com/minio/minio/pkg/iam/policy" - "github.com/minio/minio/pkg/madmin" - - "golang.org/x/net/context" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "k8s.io/klog/v2" - - cosi "sigs.k8s.io/container-object-storage-interface-spec" -) - -type DriverServer struct { - S3Client *minio.Client - S3AdminClient *madmin.AdminClient -} - -func (ds DriverServer) ProvisionerCreateBucket(ctx context.Context, req *cosi.ProvisionerCreateBucketRequest) (*cosi.ProvisionerCreateBucketResponse, error) { - klog.Infof("Using minio to create Backend Bucket") - - s3 := req.Protocol.GetS3() - if s3 == nil { - return nil, status.Error(codes.Unavailable, "Driver is missing protocol") - } - - err := ds.S3Client.MakeBucket(s3.BucketName, "") - if err != nil { - // Check to see if the bucket already exists - exists, errBucketExists := ds.S3Client.BucketExists(s3.BucketName) - if errBucketExists == nil && exists { - klog.Info("Backend Bucket already exists", s3.BucketName) - return &cosi.ProvisionerCreateBucketResponse{}, nil - } else { - klog.Error(err) - return &cosi.ProvisionerCreateBucketResponse{}, err - } - } - klog.Info("Successfully created Backend Bucket", s3.BucketName) - - return &cosi.ProvisionerCreateBucketResponse{}, nil -} - -func (ds *DriverServer) ProvisionerDeleteBucket(ctx context.Context, req *cosi.ProvisionerDeleteBucketRequest) (*cosi.ProvisionerDeleteBucketResponse, error) { - s3 := req.Protocol.GetS3() - if s3 == nil { - return nil, status.Error(codes.Unavailable, "Driver is missing protocol") - } - - if err := ds.S3Client.RemoveBucket(s3.BucketName); err != nil { - klog.Info("failed to delete bucket", s3.BucketName) - return nil, err - } - - return &cosi.ProvisionerDeleteBucketResponse{}, nil -} - -func (ds *DriverServer) ProvisionerGrantBucketAccess(ctx context.Context, req *cosi.ProvisionerGrantBucketAccessRequest) (*cosi.ProvisionerGrantBucketAccessResponse, error) { - creds, err := auth.GetNewCredentials() - if err != nil { - klog.Error("failed to generate new credentails") - return nil, err - } - - s3 := req.Protocol.GetS3() - if s3 == nil { - return nil, status.Error(codes.Unavailable, "Driver is missing protocol") - } - - if err := ds.S3AdminClient.AddUser(context.Background(), creds.AccessKey, creds.SecretKey); err != nil { - klog.Error("failed to create user", err) - return nil, err - } - - // Create policy - p := iampolicy.Policy{ - Version: iampolicy.DefaultVersion, - Statements: []iampolicy.Statement{ - iampolicy.NewStatement( - policy.Allow, - iampolicy.NewActionSet("s3:*"), - iampolicy.NewResourceSet(iampolicy.NewResource(s3.BucketName+"/*", "")), - condition.NewFunctions(), - )}, - } - - if err := ds.S3AdminClient.AddCannedPolicy(context.Background(), "s3:*", &p); err != nil { - klog.Error("failed to add canned policy", err) - return nil, err - } - - if err := ds.S3AdminClient.SetPolicy(context.Background(), "s3:*", creds.AccessKey, false); err != nil { - klog.Error("failed to set policy", err) - return nil, err - } - - return &cosi.ProvisionerGrantBucketAccessResponse{ - Principal: req.Principal, - CredentialsFileContents: fmt.Sprintf("[default]\naws_access_key %s\naws_secret_key %s", creds.AccessKey, creds.SecretKey), - CredentialsFilePath: ".aws/credentials", - }, nil -} - -func (ds *DriverServer) ProvisionerRevokeBucketAccess(ctx context.Context, req *cosi.ProvisionerRevokeBucketAccessRequest) (*cosi.ProvisionerRevokeBucketAccessResponse, error) { - - // revokes user access to bucket - if err := ds.S3AdminClient.RemoveUser(ctx, req.GetPrincipal()); err != nil { - klog.Error("falied to Revoke Bucket Access") - return nil, err - } - return &cosi.ProvisionerRevokeBucketAccessResponse{}, nil -} diff --git a/cmd/sample-driver/identity-server.go b/cmd/sample-driver/identity-server.go deleted file mode 100644 index 6438221..0000000 --- a/cmd/sample-driver/identity-server.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "fmt" - - "github.com/minio/minio-go" - "github.com/minio/minio/pkg/madmin" - "golang.org/x/net/context" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - cosi "sigs.k8s.io/container-object-storage-interface-spec" -) - -var ( - PROVISIONER_NAME = "sample-provisioner.objectstorage.k8s.io" - VERSION = "dev" -) - -type IdentityServer struct { - Name, Version string - S3Client *minio.Client - S3AdminClient *madmin.AdminClient -} - -func (id *IdentityServer) ProvisionerGetInfo(context.Context, *cosi.ProvisionerGetInfoRequest) (*cosi.ProvisionerGetInfoResponse, error) { - if id.Name == "" { - return nil, status.Error(codes.Unavailable, "Driver name not configured") - } - - if id.Version == "" { - return nil, status.Error(codes.Unavailable, "Driver is missing version") - } - rsp := &cosi.ProvisionerGetInfoResponse{} - rsp.Name = fmt.Sprintf("%s-%s", id.Name, id.Version) - return rsp, nil -} diff --git a/cmd/sample-driver/sample-driver.go b/cmd/sample-driver/sample-driver.go deleted file mode 100644 index af1c2b1..0000000 --- a/cmd/sample-driver/sample-driver.go +++ /dev/null @@ -1,127 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "context" - "flag" - "fmt" - "os" - "os/signal" - "strings" - "syscall" - - "github.com/minio/minio-go" - "github.com/minio/minio/pkg/madmin" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "k8s.io/klog/v2" - - "sigs.k8s.io/container-object-storage-interface-provisioner-sidecar/pkg/grpcserver" -) - -var ( - cosiAddress = "tcp://0.0.0.0:9000" - s3Endpoint = "tcp://0.0.0.0:9000" - accessKey = "AKIAIOSFODNN7EXAMPLE" - secretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" - ctx context.Context -) - -var cmd = &cobra.Command{ - Use: os.Args[0], - Short: "sample provisoner for provisioning bucket instance to the backend bucket", - SilenceErrors: true, - SilenceUsage: true, - RunE: func(c *cobra.Command, args []string) error { - return run(args, cosiAddress) - }, - DisableFlagsInUseLine: true, - Version: VERSION, -} - -func init() { - viper.AutomaticEnv() - - cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine) - flag.Set("logtostderr", "true") - - strFlag := func(c *cobra.Command, ptr *string, name string, short string, dfault string, desc string) { - c.PersistentFlags(). - StringVarP(ptr, name, short, dfault, desc) - } - strFlag(cmd, &cosiAddress, "listen-address", "", cosiAddress, "The address for the driver to listen on") - strFlag(cmd, &s3Endpoint, "s3-endpoint", "", "", "S3-endpont") - strFlag(cmd, &accessKey, "access-key", "", "", "S3-AccessKey") - strFlag(cmd, &secretKey, "secret-key", "", "", "S3-SecretKey") - hideFlag := func(name string) { - cmd.PersistentFlags().MarkHidden(name) - } - hideFlag("alsologtostderr") - hideFlag("log_backtrace_at") - hideFlag("log_dir") - hideFlag("logtostderr") - hideFlag("master") - hideFlag("stderrthreshold") - hideFlag("vmodule") - - // Substitute _ for - - replacer := strings.NewReplacer("-", "_") - viper.SetEnvKeyReplacer(replacer) - - // suppress the incorrect prefix in glog output - flag.CommandLine.Parse([]string{}) - viper.BindPFlags(cmd.PersistentFlags()) - - var cancel context.CancelFunc - - ctx, cancel = context.WithCancel(context.Background()) - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGSEGV) - - go func() { - s := <-sigs - cancel() - klog.Error(fmt.Sprintf("%s %s", s.String(), "Signal received. Exiting")) - }() - -} - -func main() { - if err := cmd.Execute(); err != nil { - klog.Fatal(err.Error()) - - } -} - -func run(args []string, endpoint string) error { - // Initialize minio client object. - minioClient, err := minio.New(s3Endpoint, accessKey, secretKey, false) - if err != nil { - klog.Fatalln(err) - } - minioAdminClient, err := madmin.New(s3Endpoint, accessKey, secretKey, false) - if err != nil { - klog.Fatalln(err) - } - cds := DriverServer{S3Client: minioClient, S3AdminClient: minioAdminClient} - ids := IdentityServer{Name: PROVISIONER_NAME, Version: VERSION} - s := grpcserver.NewNonBlockingGRPCServer() - s.Start(endpoint, &cds, &ids) - s.Wait() - return nil -} diff --git a/go.mod b/go.mod index 39df6eb..64d00fe 100644 --- a/go.mod +++ b/go.mod @@ -3,20 +3,27 @@ module sigs.k8s.io/container-object-storage-interface-provisioner-sidecar go 1.15 require ( - github.com/go-ini/ini v1.62.0 // indirect - github.com/kubernetes-csi/csi-lib-utils v0.9.0 - github.com/minio/minio v0.0.0-20210112204746-e09196d62633 - github.com/minio/minio-go v6.0.14+incompatible + github.com/google/go-cmp v0.5.2 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pkg/errors v0.9.1 - github.com/spf13/cobra v0.0.5 - github.com/spf13/viper v1.3.2 - golang.org/x/net v0.0.0-20201216054612-986b41b23924 - golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 + github.com/smartystreets/assertions v1.1.1 // indirect + github.com/spf13/cobra v1.1.3 + github.com/spf13/viper v1.7.0 + github.com/stretchr/testify v1.6.1 // indirect + golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 // indirect + golang.org/x/net v0.0.0-20201216054612-986b41b23924 // indirect + golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/grpc v1.35.0 + gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect + gopkg.in/ini.v1 v1.57.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect k8s.io/api v0.19.4 k8s.io/apimachinery v0.19.4 k8s.io/client-go v0.19.4 k8s.io/klog/v2 v2.2.0 - sigs.k8s.io/container-object-storage-interface-api v0.0.0-20210308183412-eb167f7cca3c - sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210224211525-dfa3af562c18 + sigs.k8s.io/container-object-storage-interface-api v0.0.0-20210330175159-2cdabb1a5dc7 + sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210330184956-b0de747ccee4 ) diff --git a/go.sum b/go.sum index 4bd17b2..e6dd379 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,6 @@ 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.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -9,36 +8,27 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -git.apache.org/thrift.git v0.13.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= -github.com/Azure/azure-storage-blob-go v0.10.0/go.mod h1:ep1edmW+kNQx4UfWM9heESNmQdijykocJ0YOxmMX8SE= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/adal v0.9.1/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 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 v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -46,63 +36,32 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.27.2/go.mod h1:g5s5osgELxgM+Md9Qni9rzo7Rbt+vvFQI4bt/Mc93II= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= -github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk= 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/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= 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.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.35.20/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/bcicen/jstream v1.0.1/go.mod h1:9ielPxqFry7Y4Tg3j4BfjPocfJ3TbsRtXOAYXYmRuAQ= -github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= 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/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/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/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/colinmarc/hdfs/v2 v2.1.1/go.mod h1:M3x+k8UKKmxtFu++uAZ0OtDU8jR3jnaZIAc6yK4Ue0c= -github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= -github.com/coredns/coredns v1.4.0/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= +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-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 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= @@ -111,43 +70,30 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/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 v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA= 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/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 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/dswarbrick/smart v0.0.0-20190505152634-909a45200d6d h1:QK8IYltsNy+5QZcDFbVkyInrs98/wHy1tfUTGG91sps= -github.com/dswarbrick/smart v0.0.0-20190505152634-909a45200d6d/go.mod h1:apXo4PA/BgBPrt66j0N45O2stlBTRowdip2igwcUWVc= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-resiliency v1.2.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/eclipse/paho.mqtt.golang v1.3.0/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= 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.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -155,14 +101,6 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.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/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -170,22 +108,15 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +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-ini/ini v1.62.0 h1:7VJT/ZXjzqSrvtraFp4ONq80hTcRQth1c9ZnQ3uNQvU= -github.com/go-ini/ini v1.62.0/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.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= 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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= -github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -236,17 +167,11 @@ github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72P github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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= @@ -257,7 +182,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb 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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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= @@ -268,20 +192,15 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU 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 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -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/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= 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/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.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -307,46 +226,27 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.6.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/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.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 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/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.1/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/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 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.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.2.0/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= @@ -357,35 +257,20 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= -github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jcmturner/gofork v0.0.0-20180107083740-2aebee971930/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/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 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -393,250 +278,125 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X 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/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/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/klauspost/readahead v1.3.1/go.mod h1:AH9juHzNH7xqdqFHrMRSHeH2Ps+vFf+kblDqzPFiLJg= -github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/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 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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/kubernetes-csi/csi-lib-utils v0.9.0 h1:TbuDmxoVqM+fvVkzG/7sShyX/8jUln0ElLHuETcsQJI= -github.com/kubernetes-csi/csi-lib-utils v0.9.0/go.mod h1:8E2jVUX9j3QgspwHXa6LwyN7IHQDjW9jX3kwoWnSC+M= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/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 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= 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.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-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/minio/cli v1.22.0/go.mod h1:bYxnK0uS629N3Bq+AOZZ+6lwF77Sodk4+UL9vNuXhOY= -github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= -github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= -github.com/minio/minio v0.0.0-20210112204746-e09196d62633 h1:N90Nw/JSwaKOg4sHN6AhMkg6/91axNFOao4/K8JJ3K8= -github.com/minio/minio v0.0.0-20210112204746-e09196d62633/go.mod h1:mD4TRSEetR2LyRBs9oKqi5ynFQDyW49vPPLCdP///EY= -github.com/minio/minio-go v6.0.14+incompatible h1:fnV+GD28LeqdN6vT2XdGKW8Qe/IfjJDswNVuni6km9o= -github.com/minio/minio-go v6.0.14+incompatible/go.mod h1:7guKYtitv8dktvNUGrhzmNlA5wrAABTQXCoesZdFQO8= -github.com/minio/minio-go/v7 v7.0.7-0.20210105224719-8dddba43079f h1:XMEV9mP1TMX/lPvhnEH5vAr4AKfF+A9vycTninVcgOA= -github.com/minio/minio-go/v7 v7.0.7-0.20210105224719-8dddba43079f/go.mod h1:pEZBUa+L2m9oECoIA6IcSK8bv/qggtQVLovjeKK5jYc= -github.com/minio/selfupdate v0.3.1/go.mod h1:b8ThJzzH7u2MkF6PcIra7KaXO9Khf6alWPvMSyTDCFM= -github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/simdjson-go v0.1.5/go.mod h1:oKURrZZEBtqObgJrSjN1Ln2n9MJj2icuBTkeJzZnvSI= -github.com/minio/sio v0.2.1/go.mod h1:8b0yPp2avGThviy/+OCJBI6OMpvxoUuiLvE6F1lebhw= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -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 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk= -github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 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 v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU= -github.com/nats-io/nats-streaming-server v0.19.0/go.mod h1:oqrRqpMg84aiPDyroTornjVWNYJKh+6ozh2Mgt8dslE= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nats-io/stan.go v0.7.0/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU= -github.com/ncw/directio v1.0.5 h1:JSUBhdjEvVaJvOoyPAbcW0fnd0tvRXD76wEfZ1KcQz4= -github.com/ncw/directio v1.0.5/go.mod h1:rX/pKEYkOXBGOggmcyJeJGloCkleSvphPx2eV3t6ROk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nsqio/go-nsq v1.0.8/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +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/olivere/elastic/v7 v7.0.22/go.mod h1:VDexNy9NjmtAkrjNoI7tImv7FR4tf5zUA3ickqu5Pc8= 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.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= 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.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.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -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-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= 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/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +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.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +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.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -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/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 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/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/secure-io/sio-go v0.3.0 h1:QKGb6rGJeiExac9wSWxnWPYo8O8OFN7lxXQvHshX6vo= -github.com/secure-io/sio-go v0.3.0/go.mod h1:D3KmXgKETffyYxBdFRN+Hpd2WzhzqS0EQwT3XWsAcBU= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v3.20.11+incompatible h1:LJr4ZQK4mPpIV5gOa4jCOKOGb4ty4DZO54I4FGqIpto= -github.com/shirou/gopsutil v3.20.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= -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/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +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 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -644,66 +404,41 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn 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.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/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-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= 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/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 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= -github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 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/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.0.0-20201125193152-8a03d2e9614b/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= -golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -711,26 +446,20 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/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-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/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 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 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= @@ -747,8 +476,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc 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.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= @@ -759,9 +486,7 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r 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-20190125091013-d26f9f9a57f3/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 h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -772,21 +497,12 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20191002035440-2ec189313ef0/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-20191112182307-2180aed22343/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-20200202094626-16171245cfb2/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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/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-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY= golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -800,71 +516,46 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20180926160741-c2ed4eda69e7/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/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-20190209173611-3b5209105503/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-20190321052220-f7bb7a8bee54/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-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-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/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-20190726091711-fc99dfbffb4e/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-20190924154521-2837fb4f24fe/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-20191112214154-59a1497f0cea/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-20191220142924-d4481acd189f/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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/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-20200519105757-fe76b779f299/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 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= 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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 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.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -875,7 +566,6 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/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-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -886,7 +576,6 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 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-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -894,38 +583,27 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/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-20191119224855-298f0cb1881e/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-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/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-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.5.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.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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= @@ -933,33 +611,24 @@ google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpC google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/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-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/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-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= 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.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 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.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.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -974,73 +643,54 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/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 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= -gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= -gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= -gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= -gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= -gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= -gopkg.in/ldap.v3 v3.0.3/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= -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.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 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/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= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= -k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo= k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0= k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg= k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q= -k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU= k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8= k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA= k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14= -k8s.io/component-base v0.19.0/go.mod h1:dKsY8BxkA+9dZIAh2aWJLL/UdASFDNtGYTCItL4LM7Y= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= @@ -1052,7 +702,6 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20200923155610-8b5066479488 h1:mNpvQf4lkIHNOXCoM+Veu/UXwA56Yx1J7hY1Tvcs/oM= k8s.io/kube-openapi v0.0.0-20200923155610-8b5066479488/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= @@ -1061,12 +710,12 @@ k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= -sigs.k8s.io/container-object-storage-interface-api v0.0.0-20210308183412-eb167f7cca3c h1:GANfOgppBbhCKqGFDVnuluhJ5km8gqNDatXn5ULGUt8= -sigs.k8s.io/container-object-storage-interface-api v0.0.0-20210308183412-eb167f7cca3c/go.mod h1:yMgeGQDROJIdY1jymECN2ptefmQ4+e3EQB/S8gyIE0o= -sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210224211525-dfa3af562c18 h1:TIx7kV6/3ZSQ5BETBx1QG1Va28zv1LZAvqRjs28n8ss= -sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210224211525-dfa3af562c18/go.mod h1:kafkL5l/lTUrZXhVi/9p1GzpEE/ts29BkWkL3Ao33WU= +sigs.k8s.io/container-object-storage-interface-api v0.0.0-20210330175159-2cdabb1a5dc7 h1:M2ZMhWdq9Az8TFj8G6ZffFUpR4XG7Qy8h8ZGsZhi9Xg= +sigs.k8s.io/container-object-storage-interface-api v0.0.0-20210330175159-2cdabb1a5dc7/go.mod h1:5n4lNKN4uOMW2NTqJ9r8qRAiqh5dZRZB7CNOkFihLfM= +sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210329232956-3bbacbbc9c19/go.mod h1:kafkL5l/lTUrZXhVi/9p1GzpEE/ts29BkWkL3Ao33WU= +sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210330184956-b0de747ccee4 h1:U+M87V77xKotSub2dqNlmxHMbb30QeC7wwTWdPGAhSI= +sigs.k8s.io/container-object-storage-interface-spec v0.0.0-20210330184956-b0de747ccee4/go.mod h1:kafkL5l/lTUrZXhVi/9p1GzpEE/ts29BkWkL3Ao33WU= sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhvlJtrvDcwIpm+uhDvp63Bl72xYJtoOE= sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= @@ -1076,4 +725,3 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/hack/add-license-header.sh b/hack/add-license-header.sh new file mode 100755 index 0000000..7378803 --- /dev/null +++ b/hack/add-license-header.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +cat > /tmp/LICENSE_TEMPLATE << EOF +Copyright 2021 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +You may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +EOF + +# install addlicense +GO111MODULE=off go get github.com/google/addlicense + +# apply license to all go files +find . | grep .go$ | xargs addlicense -f /tmp/LICENSE_TEMPLATE diff --git a/pkg/bucket/bucket_controller.go b/pkg/bucket/bucket_controller.go new file mode 100644 index 0000000..5c9e2fb --- /dev/null +++ b/pkg/bucket/bucket_controller.go @@ -0,0 +1,200 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bucket + +import ( + "context" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilversion "k8s.io/apimachinery/pkg/util/version" + kube "k8s.io/client-go/kubernetes" + "k8s.io/klog/v2" + + "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" + buckets "sigs.k8s.io/container-object-storage-interface-api/clientset" + bucketapi "sigs.k8s.io/container-object-storage-interface-api/clientset/typed/objectstorage.k8s.io/v1alpha1" + cosi "sigs.k8s.io/container-object-storage-interface-spec" + + "github.com/pkg/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// BucketListener manages Bucket objects +type BucketListener struct { + provisionerClient cosi.ProvisionerClient + provisionerName string + + kubeClient kube.Interface + bucketClient buckets.Interface + kubeVersion *utilversion.Version +} + +// NewBucketListener returns a resource handler for Bucket objects +func NewBucketListener(provisionerName string, client cosi.ProvisionerClient) *BucketListener { + bl := &BucketListener{ + provisionerName: provisionerName, + provisionerClient: client, + } + + return bl +} + +// Add attempts to create a bucket for a given bucket. This function must be idempotent +// Return values +// nil - Bucket successfully provisioned +// non-nil err - Internal error [requeue'd with exponential backoff] +func (b *BucketListener) Add(ctx context.Context, inputBucket *v1alpha1.Bucket) error { + bucket := inputBucket.DeepCopy() + + klog.V(3).InfoS("Add Bucket", + "name", bucket.Name, + "bucketclass", bucket.Spec.BucketClassName, + ) + + if !strings.EqualFold(bucket.Spec.Provisioner, b.provisionerName) { + klog.V(5).InfoS("Skipping bucket for provisiner", + "bucket", bucket.Name, + "provisioner", bucket.Spec.Provisioner, + ) + return nil + } + + if bucket.Status.BucketAvailable { + klog.V(5).InfoS("BucketExists", + "bucket", bucket.Name, + "provisioner", bucket.Spec.Provisioner, + ) + return nil + } + + proto, err := bucket.Spec.Protocol.ConvertToExternal() + if err != nil { + klog.ErrorS(err, "Invalid protocol", + "bucket", bucket.Name) + + return errors.Wrap(err, "Failed to parse protocol for API") + } + + req := &cosi.ProvisionerCreateBucketRequest{ + Parameters: bucket.Spec.Parameters, + Protocol: proto, + Name: bucket.Name, + } + + rsp, err := b.provisionerClient.ProvisionerCreateBucket(ctx, req) + if err != nil { + if status.Code(err) != codes.AlreadyExists { + klog.ErrorS(err, "Failed to create bucket", + "bucket", bucket.Name) + return errors.Wrap(err, "Failed to create bucket") + } + } + + bucket.Spec.BucketID = rsp.BucketId + bucket.Status.Message = "Bucket Provisioned" + bucket.Status.BucketAvailable = true + + // if this step fails, then controller will retry with backoff + if _, err := b.Buckets().Update(ctx, bucket, metav1.UpdateOptions{}); err != nil { + klog.ErrorS(err, "Failed to update bucket", + "bucket", bucket.Name) + return errors.Wrap(err, "Failed to update bucket") + } + + return nil +} + +// Update attempts to reconcile changes to a given bucket. This function must be idempotent +// Return values +// nil - Bucket successfully reconciled +// non-nil err - Internal error [requeue'd with exponential backoff] +func (b *BucketListener) Update(ctx context.Context, old, new *v1alpha1.Bucket) error { + klog.V(3).InfoS("Update Bucket", + "name", old.Name) + + return nil +} + +// Delete attemps to delete a bucket. This function must be idempotent +// Return values +// nil - Bucket successfully deleted +// non-nil err - Internal error [requeue'd with exponential backoff] +func (b *BucketListener) Delete(ctx context.Context, inputBucket *v1alpha1.Bucket) error { + bucket := inputBucket.DeepCopy() + + klog.V(3).InfoS("Delete Bucket", + "name", bucket.Name, + "bucketclass", bucket.Spec.BucketClassName, + ) + + if !strings.EqualFold(bucket.Spec.Provisioner, b.provisionerName) { + klog.V(5).InfoS("Skipping bucket for provisiner", + "bucket", bucket.Name, + "provisioner", bucket.Spec.Provisioner, + ) + return nil + } + + req := &cosi.ProvisionerDeleteBucketRequest{ + BucketId: bucket.Spec.BucketID, + } + + if _, err := b.provisionerClient.ProvisionerDeleteBucket(ctx, req); err != nil { + if status.Code(err) != codes.NotFound { + klog.ErrorS(err, "Failed to delete bucket", + "bucket", bucket.Name, + ) + return err + } + } + + bucket.Status.BucketAvailable = false + + // if this step fails, then controller will retry with backoff + if _, err := b.Buckets().Update(ctx, bucket, metav1.UpdateOptions{}); err != nil { + klog.ErrorS(err, "Failed to update bucket", + "bucket", bucket.Name) + return errors.Wrap(err, "Failed to update bucket") + } + + return nil +} + +func (b *BucketListener) Buckets() bucketapi.BucketInterface { + if b.bucketClient != nil { + return b.bucketClient.ObjectstorageV1alpha1().Buckets() + } + panic("uninitialized listener") +} + +// InitializeKubeClient initializes the kubernetes client +func (b *BucketListener) InitializeKubeClient(k kube.Interface) { + b.kubeClient = k + + serverVersion, err := k.Discovery().ServerVersion() + if err != nil { + klog.ErrorS(err, "Cannot determine server version") + } else { + b.kubeVersion = utilversion.MustParseSemantic(serverVersion.GitVersion) + } +} + +// InitializeBucketClient initializes the object storage bucket client +func (b *BucketListener) InitializeBucketClient(bc buckets.Interface) { + b.bucketClient = bc +} diff --git a/pkg/bucket/bucket_controller_test.go b/pkg/bucket/bucket_controller_test.go new file mode 100644 index 0000000..5fbff0c --- /dev/null +++ b/pkg/bucket/bucket_controller_test.go @@ -0,0 +1,187 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bucket + +import ( + "context" + "reflect" + "testing" + + "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" + fakebucketclientset "sigs.k8s.io/container-object-storage-interface-api/clientset/fake" + cosi "sigs.k8s.io/container-object-storage-interface-spec" + fakespec "sigs.k8s.io/container-object-storage-interface-spec/fake" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilversion "k8s.io/apimachinery/pkg/util/version" + "k8s.io/apimachinery/pkg/version" + fakediscovery "k8s.io/client-go/discovery/fake" + fakekubeclientset "k8s.io/client-go/kubernetes/fake" + + "google.golang.org/grpc" +) + +func TestInitializeKubeClient(t *testing.T) { + client := fakekubeclientset.NewSimpleClientset() + fakeDiscovery, ok := client.Discovery().(*fakediscovery.FakeDiscovery) + if !ok { + t.Fatalf("Couldn't convert Discovery() to *FakeDiscovery") + } + + fakeVersion := &version.Info{ + GitVersion: "v1.0.0", + } + fakeDiscovery.FakedServerVersion = fakeVersion + + bl := BucketListener{} + bl.InitializeKubeClient(client) + + if bl.kubeClient == nil { + t.Errorf("KubeClient was nil") + } + + expected := utilversion.MustParseSemantic(fakeVersion.GitVersion) + if !reflect.DeepEqual(expected, bl.kubeVersion) { + t.Errorf("Expected %+v, but got %+v", expected, bl.kubeVersion) + } +} + +func TestInitializeBucketClient(t *testing.T) { + client := fakebucketclientset.NewSimpleClientset() + + bl := BucketListener{} + bl.InitializeBucketClient(client) + + if bl.bucketClient == nil { + t.Errorf("BucketClient was nil") + } +} + +func TestAddWrongProvisioner(t *testing.T) { + provisioner := "provisioner1" + mpc := struct{ fakespec.FakeProvisionerClient }{} + mpc.FakeProvisionerCreateBucket = func(ctx context.Context, + in *cosi.ProvisionerCreateBucketRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerCreateBucketResponse, error) { + t.Errorf("grpc client called") + return nil, nil + } + + bl := BucketListener{ + provisionerName: provisioner, + provisionerClient: &mpc, + } + + b := v1alpha1.Bucket{ + Spec: v1alpha1.BucketSpec{ + Provisioner: "provisioner2", + }, + } + ctx := context.TODO() + err := bl.Add(ctx, &b) + if err != nil { + t.Errorf("Error returned: %+v", err) + } +} + +func TestDeleteWrongProvisioner(t *testing.T) { + provisioner := "provisioner1" + mpc := struct{ fakespec.FakeProvisionerClient }{} + mpc.FakeProvisionerDeleteBucket = func(ctx context.Context, + in *cosi.ProvisionerDeleteBucketRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerDeleteBucketResponse, error) { + t.Errorf("grpc client called") + return nil, nil + } + + bl := BucketListener{ + provisionerName: provisioner, + provisionerClient: &mpc, + } + + b := v1alpha1.Bucket{ + Spec: v1alpha1.BucketSpec{ + Provisioner: "provisioner2", + }, + } + ctx := context.TODO() + err := bl.Delete(ctx, &b) + if err != nil { + t.Errorf("error returned: %+v", err) + } +} + +func TestBucketDeletion(t *testing.T) { + provisioner := "provisioner1" + bucketId := "bucket1" + mpc := struct{ fakespec.FakeProvisionerClient }{} + + testCases := []struct { + name string + setFields func(*v1alpha1.Bucket) + deleteFunc func(ctx context.Context, + in *cosi.ProvisionerDeleteBucketRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerDeleteBucketResponse, error) + }{ + { + name: "BucketDeletion", + setFields: func(b *v1alpha1.Bucket) { + b.Spec.BucketID = bucketId + }, + deleteFunc: func(ctx context.Context, + req *cosi.ProvisionerDeleteBucketRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerDeleteBucketResponse, error) { + inBucketId := req.BucketId + if inBucketId != bucketId { + t.Errorf("expected %s, got %s", bucketId, inBucketId) + } + return &cosi.ProvisionerDeleteBucketResponse{}, nil + }, + }, + } + + for _, tc := range testCases { + b := v1alpha1.Bucket{ + Spec: v1alpha1.BucketSpec{ + Provisioner: provisioner, + }, + Status: v1alpha1.BucketStatus{ + BucketAvailable: true, + }, + } + + ctx := context.TODO() + client := fakebucketclientset.NewSimpleClientset(&b) + mpc.FakeProvisionerDeleteBucket = tc.deleteFunc + bl := BucketListener{ + provisionerName: provisioner, + provisionerClient: &mpc, + bucketClient: client, + } + + tc.setFields(&b) + t.Logf(tc.name) + err := bl.Delete(ctx, &b) + if err != nil { + t.Errorf("Error running TestBucketDeletion: %v", err) + } + + updatedB, _ := client.ObjectstorageV1alpha1().Buckets().Get(ctx, b.Name, metav1.GetOptions{}) + if updatedB.Status.BucketAvailable != false { + t.Errorf("Expected %t, got %t", false, b.Status.BucketAvailable) + } + } +} diff --git a/pkg/bucketaccess/bucketaccess_controller.go b/pkg/bucketaccess/bucketaccess_controller.go new file mode 100644 index 0000000..0d392de --- /dev/null +++ b/pkg/bucketaccess/bucketaccess_controller.go @@ -0,0 +1,254 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bucketaccess + +import ( + "context" + "os" + "strings" + + corev1 "k8s.io/api/core/v1" + kubeerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilversion "k8s.io/apimachinery/pkg/util/version" + kube "k8s.io/client-go/kubernetes" + kubecorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/klog/v2" + + "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" + buckets "sigs.k8s.io/container-object-storage-interface-api/clientset" + bucketapi "sigs.k8s.io/container-object-storage-interface-api/clientset/typed/objectstorage.k8s.io/v1alpha1" + cosi "sigs.k8s.io/container-object-storage-interface-spec" + + "github.com/pkg/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const ( + CredentialsFilePath = "CredentialsFilePath" + CredentialsFileContents = "CredentialsFileContents" +) + +// BucketAccessListener manages Bucket objects +type BucketAccessListener struct { + provisionerClient cosi.ProvisionerClient + provisionerName string + + kubeClient kube.Interface + bucketClient buckets.Interface + kubeVersion *utilversion.Version + + namespace string +} + +// NewBucketAccessListener returns a resource handler for BucketAccess objects +func NewBucketAccessListener(provisionerName string, client cosi.ProvisionerClient) (*BucketAccessListener, error) { + ns := os.Getenv("POD_NAMESPACE") + if ns == "" { + return nil, errors.New("POD_NAMESPACE env var cannot be empty") + } + + return &BucketAccessListener{ + provisionerName: provisionerName, + provisionerClient: client, + namespace: ns, + }, nil +} + +// Add attempts to provision credentials to access a given bucket. This function must be idempotent +// Return values +// nil - BucketAccess successfully granted +// non-nil err - Internal error [requeue'd with exponential backoff] +func (bal *BucketAccessListener) Add(ctx context.Context, inputBucketAccess *v1alpha1.BucketAccess) error { + bucketAccess := inputBucketAccess.DeepCopy() + + bucketName := bucketAccess.Spec.BucketName + klog.V(3).InfoS("Add BucketAccess", + "name", bucketAccess.Name, + "bucket", bucketName, + ) + + if bucketAccess.Spec.MintedSecretName != "" { + klog.V(5).InfoS("AccessAlreadyGranted", + "bucketAccess", bucketAccess.Name, + "bucket", bucketName, + ) + return nil + } + + bucket, err := bal.Buckets().Get(ctx, bucketName, metav1.GetOptions{}) + if err != nil { + klog.ErrorS(err, "Failed to fetch bucket", "bucket", bucketName) + return errors.Wrap(err, "Failed to fetch bucket") + } + + if !strings.EqualFold(bucket.Spec.Provisioner, bal.provisionerName) { + klog.V(5).InfoS("Skipping bucketaccess for provisiner", + "bucketAccess", bucketAccess.Name, + "provisioner", bucket.Spec.Provisioner, + ) + return nil + } + + if bucketAccess.Status.AccessGranted { + klog.V(5).InfoS("AccessAlreadyGranted", + "bucketaccess", bucketAccess.Name, + "bucket", bucket.Name, + ) + return nil + } + + if bucket.Spec.BucketID == "" { + err := errors.New("BucketID cannot be empty") + klog.ErrorS(err, + "Invalid arguments", + "bucket", bucket.Name, + "bucketAccess", bucketAccess.Name, + ) + return errors.Wrap(err, "Invalid arguments") + } + + req := &cosi.ProvisionerGrantBucketAccessRequest{ + BucketId: bucket.Spec.BucketID, + AccountName: bucketAccess.Name, + AccessPolicy: bucketAccess.Spec.PolicyActionsConfigMapData, + } + + // This needs to be idempotent + rsp, err := bal.provisionerClient.ProvisionerGrantBucketAccess(ctx, req) + if err != nil { + if status.Code(err) != codes.AlreadyExists { + klog.ErrorS(err, + "Failed to grant access", + "bucketAccess", bucketAccess.Name, + "bucket", bucket.Name, + ) + return errors.Wrap(err, "failed to grant access") + } + + } + ns := bal.namespace + mintedSecretName := "ba-" + string(bucketAccess.UID) + if _, err := bal.Secrets(ns).Get(ctx, mintedSecretName, metav1.GetOptions{}); err != nil { + if !kubeerrors.IsNotFound(err) { + klog.ErrorS(err, + "Failed to create secrets", + "bucketAccess", bucketAccess.Name, + "bucket", bucket.Name) + return errors.Wrap(err, "failed to fetch secrets") + } + + // if secret doesn't exist, create it + credentialsFileContents := rsp.CredentialsFileContents + credentialsFilePath := rsp.CredentialsFilePath + + if _, err := bal.Secrets(ns).Create(ctx, &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: mintedSecretName, + Namespace: ns, + }, + StringData: map[string]string{ + CredentialsFilePath: credentialsFilePath, + CredentialsFileContents: credentialsFileContents, + }, + Type: corev1.SecretTypeOpaque, + }, metav1.CreateOptions{}); err != nil { + if !kubeerrors.IsAlreadyExists(err) { + klog.ErrorS(err, + "Failed to create minted secret", + "bucketAccess", bucketAccess.Name, + "bucket", bucket.Name) + return errors.Wrap(err, "Failed to create minted secret") + } + } + } + + bucketAccess.Spec.AccountID = rsp.AccountId + bucketAccess.Status.AccessGranted = true + bucketAccess.Spec.MintedSecretName = mintedSecretName + + // if this step fails, then controller will retry with backoff + if _, err := bal.BucketAccesses().Update(ctx, bucketAccess, metav1.UpdateOptions{}); err != nil { + klog.ErrorS(err, "Failed to update BucketAccess", + "bucketAccess", bucketAccess.Name, + "bucket", bucket.Name) + return errors.Wrap(err, "Failed to update BucketAccess") + } + + return nil +} + +// Update attempts to reconcile changes to a given bucketAccess. This function must be idempotent +// Return values +// nil - BucketAccess successfully reconciled +// non-nil err - Internal error [requeue'd with exponential backoff] +func (bal *BucketAccessListener) Update(ctx context.Context, old, new *v1alpha1.BucketAccess) error { + klog.V(3).InfoS("Update BucketAccess", + "name", old.Name) + + return nil +} + +// Delete attemps to delete a bucketAccess. This function must be idempotent +// Return values +// nil - BucketAccess successfully deleted +// non-nil err - Internal error [requeue'd with exponential backoff] +func (bal *BucketAccessListener) Delete(ctx context.Context, bucketAccess *v1alpha1.BucketAccess) error { + klog.V(3).InfoS("Delete BucketAccess", + "name", bucketAccess.Name, + "bucket", bucketAccess.Spec.BucketName, + ) + return nil +} + +func (b *BucketAccessListener) Secrets(ns string) kubecorev1.SecretInterface { + if b.kubeClient != nil { + return b.kubeClient.CoreV1().Secrets(ns) + } + panic("uninitialized listener") +} + +func (b *BucketAccessListener) BucketAccesses() bucketapi.BucketAccessInterface { + if b.bucketClient != nil { + return b.bucketClient.ObjectstorageV1alpha1().BucketAccesses() + } + panic("uninitialized listener") +} + +func (b *BucketAccessListener) Buckets() bucketapi.BucketInterface { + if b.bucketClient != nil { + return b.bucketClient.ObjectstorageV1alpha1().Buckets() + } + panic("uninitialized listener") +} + +// InitializeKubeClient initializes the kubernetes client +func (b *BucketAccessListener) InitializeKubeClient(k kube.Interface) { + b.kubeClient = k + + serverVersion, err := k.Discovery().ServerVersion() + if err != nil { + klog.ErrorS(err, "Cannot determine server version") + } else { + b.kubeVersion = utilversion.MustParseSemantic(serverVersion.GitVersion) + } +} + +// InitializeBucketClient initializes the object storage bucket client +func (b *BucketAccessListener) InitializeBucketClient(bc buckets.Interface) { + b.bucketClient = bc +} diff --git a/pkg/bucketaccess/bucketaccess_controller_test.go b/pkg/bucketaccess/bucketaccess_controller_test.go new file mode 100644 index 0000000..e1571c9 --- /dev/null +++ b/pkg/bucketaccess/bucketaccess_controller_test.go @@ -0,0 +1,235 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package bucketaccess + +import ( + "context" + "reflect" + "strings" + "testing" + + "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" + fakebucketclientset "sigs.k8s.io/container-object-storage-interface-api/clientset/fake" + cosi "sigs.k8s.io/container-object-storage-interface-spec" + fakespec "sigs.k8s.io/container-object-storage-interface-spec/fake" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + utilversion "k8s.io/apimachinery/pkg/util/version" + "k8s.io/apimachinery/pkg/version" + fakediscovery "k8s.io/client-go/discovery/fake" + fakekubeclientset "k8s.io/client-go/kubernetes/fake" + + "google.golang.org/grpc" +) + +func TestInitializeKubeClient(t *testing.T) { + client := fakekubeclientset.NewSimpleClientset() + fakeDiscovery, ok := client.Discovery().(*fakediscovery.FakeDiscovery) + if !ok { + t.Fatalf("couldn't convert Discovery() to *FakeDiscovery") + } + + fakeVersion := &version.Info{ + GitVersion: "v1.0.0", + } + fakeDiscovery.FakedServerVersion = fakeVersion + + bal := BucketAccessListener{} + bal.InitializeKubeClient(client) + + if bal.kubeClient == nil { + t.Errorf("KubeClient was nil") + } + + expected := utilversion.MustParseSemantic(fakeVersion.GitVersion) + if !reflect.DeepEqual(expected, bal.kubeVersion) { + t.Errorf("Expected %+v, but got %+v", expected, bal.kubeVersion) + } +} + +func TestInitializeBucketClient(t *testing.T) { + client := fakebucketclientset.NewSimpleClientset() + + bal := BucketAccessListener{} + bal.InitializeBucketClient(client) + + if bal.bucketClient == nil { + t.Errorf("BucketClient not initialized, expected not nil") + } +} + +func TestAddWrongProvisioner(t *testing.T) { + provisioner := "provisioner1" + bucketName := "bucket1" + bucketId := "bucketId1" + accountId := "accountId1" + bucketAccessRequestName := "bar1" + policy := "policy1" + + mpc := struct{ fakespec.FakeProvisionerClient }{} + mpc.FakeProvisionerGrantBucketAccess = func(ctx context.Context, + in *cosi.ProvisionerGrantBucketAccessRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerGrantBucketAccessResponse, error) { + t.Errorf("grpc client called") + return &cosi.ProvisionerGrantBucketAccessResponse{ + AccountId: accountId, + }, nil + } + + b := v1alpha1.Bucket{ + ObjectMeta: metav1.ObjectMeta{ + Name: bucketName, + }, + Spec: v1alpha1.BucketSpec{ + Provisioner: provisioner + "-invalid", + Protocol: v1alpha1.Protocol{}, + BucketID: bucketId, + }, + } + + ba := v1alpha1.BucketAccess{ + Spec: v1alpha1.BucketAccessSpec{ + BucketName: bucketName, + BucketAccessRequest: &corev1.ObjectReference{ + Name: bucketAccessRequestName, + }, + PolicyActionsConfigMapData: policy, + }, + } + client := fakebucketclientset.NewSimpleClientset(&ba, &b) + kubeClient := fakekubeclientset.NewSimpleClientset() + bal := BucketAccessListener{ + provisionerName: provisioner, + provisionerClient: &mpc, + bucketClient: client, + kubeClient: kubeClient, + } + + ctx := context.TODO() + err := bal.Add(ctx, &ba) + if err != nil { + t.Errorf("Error returned: %+v", err) + } +} + +func TestAddBucketAccess(t *testing.T) { + provisioner := "provisioner" + bucketName := "bucket1" + bucketId := "bucketId1" + bucketAccessRequestName := "bar1" + + policy := "policy1" + accountId := "account1" + credsContents := "credsContents" + credsFile := "credsFile" + ns := "testns" + mpc := struct{ fakespec.FakeProvisionerClient }{} + + testCases := []struct { + name string + setFields func(ba *v1alpha1.BucketAccess) + grantFunc func(ctx context.Context, + in *cosi.ProvisionerGrantBucketAccessRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerGrantBucketAccessResponse, error) + }{ + { + name: "TestAddBucketAccess", + setFields: func(ba *v1alpha1.BucketAccess) { + + }, + grantFunc: func(ctx context.Context, + req *cosi.ProvisionerGrantBucketAccessRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerGrantBucketAccessResponse, error) { + + return &cosi.ProvisionerGrantBucketAccessResponse{ + AccountId: accountId, + CredentialsFileContents: credsContents, + CredentialsFilePath: credsFile, + }, nil + }, + }, + } + + for _, tc := range testCases { + b := v1alpha1.Bucket{ + ObjectMeta: metav1.ObjectMeta{ + Name: bucketName, + }, + Spec: v1alpha1.BucketSpec{ + Provisioner: provisioner, + Protocol: v1alpha1.Protocol{}, + BucketID: bucketId, + }, + } + + ba := v1alpha1.BucketAccess{ + Spec: v1alpha1.BucketAccessSpec{ + BucketName: bucketName, + BucketAccessRequest: &corev1.ObjectReference{ + Name: bucketAccessRequestName, + }, + PolicyActionsConfigMapData: policy, + }, + } + + ctx := context.TODO() + tc.setFields(&ba) + + client := fakebucketclientset.NewSimpleClientset(&ba, &b) + kubeClient := fakekubeclientset.NewSimpleClientset() + mpc.FakeProvisionerGrantBucketAccess = tc.grantFunc + + bal := BucketAccessListener{ + provisionerName: provisioner, + provisionerClient: &mpc, + bucketClient: client, + kubeClient: kubeClient, + namespace: ns, + } + + t.Logf(tc.name) + err := bal.Add(ctx, &ba) + if err != nil { + t.Errorf("Add returned: %+v", err) + } + + updatedBA, _ := bal.BucketAccesses().Get(ctx, ba.Name, metav1.GetOptions{}) + if updatedBA.Status.AccessGranted != true { + t.Errorf("Expected %t, got %t", true, ba.Status.AccessGranted) + } + if !strings.EqualFold(updatedBA.Spec.AccountID, accountId) { + t.Errorf("Expected %s, got %s", accountId, updatedBA.Spec.AccountID) + } + + secretName := "ba-" + string(ba.UID) + secret, err := bal.Secrets(ns).Get(ctx, secretName, metav1.GetOptions{}) + if err != nil { + t.Fatalf("minted secret creation failed: %v", err) + } + + if secret.StringData["CredentialsFilePath"] != credsFile { + t.Errorf("Expected %s, got %s", + credsFile, + secret.StringData["CredentialsFilePath"]) + } + if secret.StringData["CredentialsFileContents"] != credsContents { + t.Errorf("Expected %s, got %s", + credsContents, + secret.StringData["CredentialsFileContents"]) + } + } +} diff --git a/pkg/controller/bucket/bucket_controller.go b/pkg/controller/bucket/bucket_controller.go deleted file mode 100644 index 4dfb6b6..0000000 --- a/pkg/controller/bucket/bucket_controller.go +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bucket - -import ( - "context" - "fmt" - "github.com/pkg/errors" - "strings" - "time" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilversion "k8s.io/apimachinery/pkg/util/version" - - kubeclientset "k8s.io/client-go/kubernetes" - "k8s.io/client-go/util/retry" - "k8s.io/client-go/util/workqueue" - - "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" - bucketclientset "sigs.k8s.io/container-object-storage-interface-api/clientset" - "sigs.k8s.io/container-object-storage-interface-api/controller" - - osspec "sigs.k8s.io/container-object-storage-interface-spec" - - "k8s.io/klog/v2" - - "golang.org/x/time/rate" -) - -// bucketListener manages Bucket objects -type bucketListener struct { - kubeClient kubeclientset.Interface - bucketClient bucketclientset.Interface - provisionerClient osspec.ProvisionerClient - - // The name of the provisioner for which this controller dynamically - // provisions buckets. - provisionerName string - kubeVersion *utilversion.Version -} - -// NewBucketController returns a controller that manages Bucket objects -func NewBucketController(provisionerName string, client osspec.ProvisionerClient) (*controller.ObjectStorageController, error) { - rateLimit := workqueue.NewMaxOfRateLimiter( - workqueue.NewItemExponentialFailureRateLimiter(5*time.Second, 60*time.Minute), - &workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)}, - ) - - identity := fmt.Sprintf("objectstorage-sidecar-%s", provisionerName) - bc, err := controller.NewObjectStorageController(identity, "bucket-controller", 5, rateLimit) - if err != nil { - return nil, err - } - - bl := bucketListener{ - provisionerName: provisionerName, - provisionerClient: client, - } - bc.AddBucketListener(&bl) - - return bc, nil -} - -// InitializeKubeClient initializes the kubernetes client -func (bl *bucketListener) InitializeKubeClient(k kubeclientset.Interface) { - bl.kubeClient = k - - serverVersion, err := k.Discovery().ServerVersion() - if err != nil { - klog.Errorf("unable to get server version: %v", err) - } else { - bl.kubeVersion = utilversion.MustParseSemantic(serverVersion.GitVersion) - } -} - -// InitializeBucketClient initializes the object storage bucket client -func (bl *bucketListener) InitializeBucketClient(bc bucketclientset.Interface) { - bl.bucketClient = bc -} - -// Add will call the provisioner and add a bucket -func (bl *bucketListener) Add(ctx context.Context, obj *v1alpha1.Bucket) error { - klog.Infof("bucketListener: add called for bucket %s", obj.Name) - - // Verify this bucket is for this provisioner - if !strings.EqualFold(obj.Spec.Provisioner, bl.provisionerName) { - return nil - } - - req := osspec.ProvisionerCreateBucketRequest{ - Parameters: bl.getParams(obj), - } - if req.Parameters == nil { - req.Parameters = make(map[string]string) - } - - proto, err := obj.Spec.Protocol.ConvertToExternal() - if err != nil { - return errors.Wrap(err, "failed to parse protocol for API") - } - req.Protocol = proto - - req.Parameters["ProtocolVersion"] = obj.Spec.Protocol.Version - - if obj.Spec.AnonymousAccessMode.Private { - req.AnonymousBucketAccessMode = osspec.AnonymousBucketAccessMode_Private - } else if obj.Spec.AnonymousAccessMode.PublicReadOnly { - req.AnonymousBucketAccessMode = osspec.AnonymousBucketAccessMode_ReadOnly - } else if obj.Spec.AnonymousAccessMode.PublicReadWrite { - req.AnonymousBucketAccessMode = osspec.AnonymousBucketAccessMode_ReadWrite - } else if obj.Spec.AnonymousAccessMode.PublicWriteOnly { - req.AnonymousBucketAccessMode = osspec.AnonymousBucketAccessMode_WriteOnly - } - - // TODO set grpc timeout - rsp, err := bl.provisionerClient.ProvisionerCreateBucket(ctx, &req) - if err != nil { - klog.Errorf("error calling ProvisionerCreateBucket: %v", err) - return err - } - klog.V(1).Infof("provisioner returned create bucket response %v", rsp) - - // TODO update the bucket protocol in the bucket spec - - // update bucket availability to true - return bl.updateStatus(ctx, obj.Name, "Bucket Provisioned", true) -} - -// Update does nothing -func (bl *bucketListener) Update(ctx context.Context, old, new *v1alpha1.Bucket) error { - klog.Infof("bucketListener: update called for bucket %s", old.Name) - return nil -} - -// Delete will call the provisioner and delete a bucket -func (bl *bucketListener) Delete(ctx context.Context, obj *v1alpha1.Bucket) error { - klog.Infof("bucketListener: delete called for bucket %s", obj.Name) - - // Verify this bucket is for this provisioner - if !strings.EqualFold(obj.Spec.Provisioner, bl.provisionerName) { - return nil - } - - req := osspec.ProvisionerDeleteBucketRequest{ - Parameters: bl.getParams(obj), - } - if req.Parameters == nil { - req.Parameters = make(map[string]string) - } - - proto, err := obj.Spec.Protocol.ConvertToExternal() - if err != nil { - return errors.Wrap(err, "failed to parse protocol for API") - } - req.Protocol = proto - - req.Parameters["ProtocolVersion"] = obj.Spec.Protocol.Version - - // TODO set grpc timeout - rsp, err := bl.provisionerClient.ProvisionerDeleteBucket(ctx, &req) - if err != nil { - klog.Errorf("error calling ProvisionerDeleteBucket: %v", err) - obj.Status.Message = "Bucket Deleting" - obj.Status.BucketAvailable = false - _, err = bl.bucketClient.ObjectstorageV1alpha1().Buckets().UpdateStatus(ctx, obj, metav1.UpdateOptions{}) - return err - } - klog.Infof("provisioner returned delete bucket response %v", rsp) - - // update bucket availability to false - return bl.updateStatus(ctx, obj.Name, "Bucket Deleted", false) -} - -func (bl *bucketListener) updateStatus(ctx context.Context, name, msg string, state bool) error { - err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - bucket, err := bl.bucketClient.ObjectstorageV1alpha1().Buckets().Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return err - } - bucket.Status.Message = msg - bucket.Status.BucketAvailable = state - _, err = bl.bucketClient.ObjectstorageV1alpha1().Buckets().UpdateStatus(ctx, bucket, metav1.UpdateOptions{}) - return err - }) - return err -} - -func (bl *bucketListener) getParams(obj *v1alpha1.Bucket) map[string]string { - params := map[string]string{} - if obj.Spec.Parameters != nil { - params = obj.Spec.Parameters - } - return params -} diff --git a/pkg/controller/bucket/bucket_controller_test.go b/pkg/controller/bucket/bucket_controller_test.go deleted file mode 100644 index 90657a2..0000000 --- a/pkg/controller/bucket/bucket_controller_test.go +++ /dev/null @@ -1,534 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bucket - -import ( - "context" - "reflect" - "testing" - - "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" - - fakebucketclientset "sigs.k8s.io/container-object-storage-interface-api/clientset/fake" - - osspec "sigs.k8s.io/container-object-storage-interface-spec" - fakespec "sigs.k8s.io/container-object-storage-interface-spec/fake" - - corev1 "k8s.io/api/core/v1" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilversion "k8s.io/apimachinery/pkg/util/version" - "k8s.io/apimachinery/pkg/version" - - fakediscovery "k8s.io/client-go/discovery/fake" - fakekubeclientset "k8s.io/client-go/kubernetes/fake" - - "google.golang.org/grpc" -) - -func TestInitializeKubeClient(t *testing.T) { - client := fakekubeclientset.NewSimpleClientset() - fakeDiscovery, ok := client.Discovery().(*fakediscovery.FakeDiscovery) - if !ok { - t.Fatalf("couldn't convert Discovery() to *FakeDiscovery") - } - - fakeVersion := &version.Info{ - GitVersion: "v1.0.0", - } - fakeDiscovery.FakedServerVersion = fakeVersion - - bl := bucketListener{} - bl.InitializeKubeClient(client) - - if bl.kubeClient == nil { - t.Errorf("kubeClient was nil") - } - - expected := utilversion.MustParseSemantic(fakeVersion.GitVersion) - if !reflect.DeepEqual(expected, bl.kubeVersion) { - t.Errorf("expected %+v, but got %+v", expected, bl.kubeVersion) - } -} - -func TestInitializeBucketClient(t *testing.T) { - client := fakebucketclientset.NewSimpleClientset() - - bl := bucketListener{} - bl.InitializeBucketClient(client) - - if bl.bucketClient == nil { - t.Errorf("bucketClient was nil") - } -} - -func TestAddWrongProvisioner(t *testing.T) { - provisioner := "provisioner1" - mpc := struct{ fakespec.FakeProvisionerClient }{} - mpc.FakeProvisionerCreateBucket = func(ctx context.Context, in *osspec.ProvisionerCreateBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerCreateBucketResponse, error) { - t.Errorf("grpc client called") - return nil, nil - } - - bl := bucketListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - } - - b := v1alpha1.Bucket{ - Spec: v1alpha1.BucketSpec{ - Provisioner: "provisioner2", - }, - } - ctx := context.TODO() - err := bl.Add(ctx, &b) - if err != nil { - t.Errorf("error returned: %+v", err) - } -} - -func TestAddValidProtocols(t *testing.T) { - provisioner := "provisioner1" - protocolVersion := "proto1" - anonAccess := "BUCKET_PRIVATE" - bucketName := "bucket1" - s3 := v1alpha1.S3Protocol{ - BucketName: "bucket1", - Endpoint: "127.0.0.1", - Region: "region1", - SignatureVersion: v1alpha1.S3SignatureVersionV2, - } - gcs := v1alpha1.GCSProtocol{ - BucketName: "bucket1", - PrivateKeyName: "keyName1", - ProjectID: "id1", - ServiceAccount: "account1", - } - azure := v1alpha1.AzureProtocol{ - ContainerName: "bucket1", - StorageAccount: "account1", - } - mpc := struct{ fakespec.FakeProvisionerClient }{} - - testCases := []struct { - name string - protocolName v1alpha1.ProtocolName - setProtocol func(b *v1alpha1.Bucket) - createFunc func(ctx context.Context, in *osspec.ProvisionerCreateBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerCreateBucketResponse, error) - params map[string]string - }{ - { - name: "S3", - protocolName: v1alpha1.ProtocolNameS3, - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &s3 - }, - createFunc: func(ctx context.Context, req *osspec.ProvisionerCreateBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerCreateBucketResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != s3.BucketName { - t.Errorf("expected %s, got %s", s3.BucketName, in.BucketName) - } - if in.Region != s3.Region { - t.Errorf("expected %s, got %s", s3.Region, in.Region) - } - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(s3.SignatureVersion) { - t.Errorf("expected %s, got %s", s3.SignatureVersion, sigver) - } - if in.Endpoint != s3.Endpoint { - t.Errorf("expected %s, got %s", in.Endpoint, in.Endpoint) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerCreateBucketResponse{}, nil - }, - }, - { - name: "GCS", - protocolName: v1alpha1.ProtocolNameGCS, - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.GCS = &gcs - }, - createFunc: func(ctx context.Context, req *osspec.ProvisionerCreateBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerCreateBucketResponse, error) { - in := req.Protocol.GetGcs() - if in.BucketName != gcs.BucketName { - t.Errorf("expected %s, got %s", gcs.BucketName, in.BucketName) - } - if in.ServiceAccount != gcs.ServiceAccount { - t.Errorf("expected %s, got %s", gcs.ServiceAccount, in.ServiceAccount) - } - if in.PrivateKeyName != gcs.PrivateKeyName { - t.Errorf("expected %s, got %s", gcs.PrivateKeyName, in.PrivateKeyName) - } - if in.ProjectId != gcs.ProjectID { - t.Errorf("expected %s, got %s", gcs.ProjectID, in.ProjectId) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerCreateBucketResponse{}, nil - }, - }, - { - name: "AzureBlob", - protocolName: v1alpha1.ProtocolNameAzure, - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.AzureBlob = &azure - }, - createFunc: func(ctx context.Context, req *osspec.ProvisionerCreateBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerCreateBucketResponse, error) { - in := req.Protocol.GetAzureBlob() - if in.ContainerName != azure.ContainerName { - t.Errorf("expected %s, got %s", azure.ContainerName, in.ContainerName) - } - if in.StorageAccount != azure.StorageAccount { - t.Errorf("expected %s, got %s", azure.StorageAccount, in.StorageAccount) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerCreateBucketResponse{}, nil - }, - }, - { - name: "AnonymousAccessMode", - protocolName: v1alpha1.ProtocolNameAzure, - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.AzureBlob = &azure - }, - createFunc: func(ctx context.Context, req *osspec.ProvisionerCreateBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerCreateBucketResponse, error) { - in := req.Protocol.GetAzureBlob() - if in.ContainerName != azure.ContainerName { - t.Errorf("expected %s, got %s", azure.ContainerName, in.ContainerName) - } - if in.StorageAccount != azure.StorageAccount { - t.Errorf("expected %s, got %s", azure.StorageAccount, in.StorageAccount) - } - aMode := osspec.AnonymousBucketAccessMode(osspec.AnonymousBucketAccessMode_value[anonAccess]) - if req.AnonymousBucketAccessMode != aMode { - t.Errorf("expected %s, got %s", aMode, req.AnonymousBucketAccessMode) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerCreateBucketResponse{}, nil - }, - }, - } - - for _, tc := range testCases { - b := v1alpha1.Bucket{ - ObjectMeta: metav1.ObjectMeta{ - Name: bucketName, - }, - Spec: v1alpha1.BucketSpec{ - Provisioner: provisioner, - Protocol: v1alpha1.Protocol{ - Name: tc.protocolName, - Version: protocolVersion, - }, - Parameters: tc.params, - }, - } - - ctx := context.TODO() - client := fakebucketclientset.NewSimpleClientset(&b) - kubeClient := fakekubeclientset.NewSimpleClientset() - mpc.FakeProvisionerCreateBucket = tc.createFunc - bl := bucketListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - bucketClient: client, - kubeClient: kubeClient, - } - - tc.setProtocol(&b) - t.Logf(tc.name) - err := bl.Add(ctx, &b) - if err != nil { - t.Errorf("add returned: %+v", err) - } - - updatedB, _ := client.ObjectstorageV1alpha1().Buckets().Get(ctx, b.Name, metav1.GetOptions{}) - if updatedB.Status.BucketAvailable != true { - t.Errorf("expected %t, got %t", true, b.Status.BucketAvailable) - } - } -} - -func TestDeleteWrongProvisioner(t *testing.T) { - provisioner := "provisioner1" - mpc := struct{ fakespec.FakeProvisionerClient }{} - mpc.FakeProvisionerDeleteBucket = func(ctx context.Context, in *osspec.ProvisionerDeleteBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerDeleteBucketResponse, error) { - t.Errorf("grpc client called") - return nil, nil - } - - bl := bucketListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - } - - b := v1alpha1.Bucket{ - Spec: v1alpha1.BucketSpec{ - Provisioner: "provisioner2", - }, - } - ctx := context.TODO() - err := bl.Delete(ctx, &b) - if err != nil { - t.Errorf("error returned: %+v", err) - } -} - -func TestDeleteValidProtocols(t *testing.T) { - provisioner := "provisioner1" - region := "region1" - bucketName := "bucket1" - protocolVersion := "proto1" - sigVersion := v1alpha1.S3SignatureVersion(v1alpha1.S3SignatureVersionV2) - account := "account1" - keyName := "keyName1" - projID := "id1" - endpoint := "endpoint1" - mpc := struct{ fakespec.FakeProvisionerClient }{} - extraParamName := "ParamName" - extraParamValue := "ParamValue" - - testCases := []struct { - name string - setProtocol func(b *v1alpha1.Bucket) - protocolName v1alpha1.ProtocolName - deleteFunc func(ctx context.Context, in *osspec.ProvisionerDeleteBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerDeleteBucketResponse, error) - params map[string]string - }{ - { - name: "S3", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - deleteFunc: func(ctx context.Context, req *osspec.ProvisionerDeleteBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerDeleteBucketResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerDeleteBucketResponse{}, nil - }, - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "GCS", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.GCS = &v1alpha1.GCSProtocol{ - ServiceAccount: account, - PrivateKeyName: keyName, - ProjectID: projID, - BucketName: bucketName, - } - }, - protocolName: v1alpha1.ProtocolNameGCS, - deleteFunc: func(ctx context.Context, req *osspec.ProvisionerDeleteBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerDeleteBucketResponse, error) { - in := req.Protocol.GetGcs() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.ServiceAccount != account { - t.Errorf("expected %s, got %s", region, in.ServiceAccount) - } - if in.PrivateKeyName != keyName { - t.Errorf("expected %s, got %s", region, in.PrivateKeyName) - } - if in.ProjectId != projID { - t.Errorf("expected %s, got %s", region, in.ProjectId) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerDeleteBucketResponse{}, nil - }, - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "AzureBlob", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.AzureBlob = &v1alpha1.AzureProtocol{ - StorageAccount: account, - ContainerName: bucketName, - } - }, - protocolName: v1alpha1.ProtocolNameAzure, - deleteFunc: func(ctx context.Context, req *osspec.ProvisionerDeleteBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerDeleteBucketResponse, error) { - in := req.Protocol.GetAzureBlob() - if in.ContainerName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.ContainerName) - } - if in.StorageAccount != account { - t.Errorf("expected %s, got %s", region, in.StorageAccount) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerDeleteBucketResponse{}, nil - }, - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "Empty parameters", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - deleteFunc: func(ctx context.Context, req *osspec.ProvisionerDeleteBucketRequest, opts ...grpc.CallOption) (*osspec.ProvisionerDeleteBucketResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - if req.Parameters["ProtocolVersion"] != protocolVersion { - t.Errorf("expected %s, got %s", protocolVersion, req.Parameters["ProtocolVersion"]) - } - return &osspec.ProvisionerDeleteBucketResponse{}, nil - }, - params: nil, - }, - } - - for _, tc := range testCases { - b := v1alpha1.Bucket{ - Spec: v1alpha1.BucketSpec{ - Provisioner: provisioner, - Protocol: v1alpha1.Protocol{ - Name: tc.protocolName, - Version: protocolVersion, - }, - Parameters: tc.params, - }, - Status: v1alpha1.BucketStatus{ - BucketAvailable: true, - }, - } - - ctx := context.TODO() - client := fakebucketclientset.NewSimpleClientset(&b) - mpc.FakeProvisionerDeleteBucket = tc.deleteFunc - bl := bucketListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - bucketClient: client, - } - - tc.setProtocol(&b) - t.Logf(tc.name) - err := bl.Delete(ctx, &b) - if err != nil { - t.Errorf("delete returned: %+v", err) - } - - updatedB, _ := client.ObjectstorageV1alpha1().Buckets().Get(ctx, b.Name, metav1.GetOptions{}) - if updatedB.Status.BucketAvailable != false { - t.Errorf("expected %t, got %t", false, b.Status.BucketAvailable) - } - } -} - -func TestDeleteInvalidProtocol(t *testing.T) { - const ( - protocolName v1alpha1.ProtocolName = "invalid" - ) - - bucketName := "bucket1" - provisioner := "provisioner1" - - bl := bucketListener{ - provisionerName: provisioner, - } - - b := v1alpha1.Bucket{ - Spec: v1alpha1.BucketSpec{ - BucketRequest: &corev1.ObjectReference{ - Name: bucketName, - }, - Provisioner: provisioner, - Protocol: v1alpha1.Protocol{ - Name: protocolName, - }, - }, - } - - ctx := context.TODO() - err := bl.Delete(ctx, &b) - if err == nil { - t.Errorf("invalidProtocol: no error returned") - } -} diff --git a/pkg/controller/bucketaccess/bucket_access_controller.go b/pkg/controller/bucketaccess/bucket_access_controller.go deleted file mode 100644 index 37c6db5..0000000 --- a/pkg/controller/bucketaccess/bucket_access_controller.go +++ /dev/null @@ -1,270 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bucketaccess - -import ( - "context" - "fmt" - "github.com/pkg/errors" - "strings" - "time" - - corev1 "k8s.io/api/core/v1" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - utilversion "k8s.io/apimachinery/pkg/util/version" - - kubeclientset "k8s.io/client-go/kubernetes" - "k8s.io/client-go/util/retry" - "k8s.io/client-go/util/workqueue" - - "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" - bucketclientset "sigs.k8s.io/container-object-storage-interface-api/clientset" - "sigs.k8s.io/container-object-storage-interface-api/controller" - - osspec "sigs.k8s.io/container-object-storage-interface-spec" - - "k8s.io/klog/v2" - - "golang.org/x/time/rate" -) - -func generateSecretName(uid types.UID) string { - return fmt.Sprintf("ba-%s", string(uid)) -} - -// bucketAccessListener manages BucketAccess objects -type bucketAccessListener struct { - kubeClient kubeclientset.Interface - bucketAccessClient bucketclientset.Interface - provisionerClient osspec.ProvisionerClient - - // The name of the provisioner for which this controller handles - // bucket access. - provisionerName string - kubeVersion *utilversion.Version -} - -// NewBucketAccessController returns a controller that manages BucketAccess objects -func NewBucketAccessController(provisionerName string, client osspec.ProvisionerClient) (*controller.ObjectStorageController, error) { - rateLimit := workqueue.NewMaxOfRateLimiter( - workqueue.NewItemExponentialFailureRateLimiter(5*time.Second, 60*time.Minute), - &workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)}, - ) - - identity := fmt.Sprintf("objectstorage-sidecar-%s", provisionerName) - bc, err := controller.NewObjectStorageController(identity, "bucket-access-controller", 5, rateLimit) - if err != nil { - return nil, err - } - - bal := bucketAccessListener{ - provisionerName: provisionerName, - provisionerClient: client, - } - bc.AddBucketAccessListener(&bal) - - return bc, nil -} - -// InitializeKubeClient initializes the kubernetes client -func (bal *bucketAccessListener) InitializeKubeClient(k kubeclientset.Interface) { - bal.kubeClient = k - - serverVersion, err := k.Discovery().ServerVersion() - if err != nil { - klog.Errorf("unable to get server version: %v", err) - } else { - bal.kubeVersion = utilversion.MustParseSemantic(serverVersion.GitVersion) - } -} - -// InitializeBucketClient initializes the object storage bucket client -func (bal *bucketAccessListener) InitializeBucketClient(bc bucketclientset.Interface) { - bal.bucketAccessClient = bc -} - -// Add will call the provisioner to grant permissions -func (bal *bucketAccessListener) Add(ctx context.Context, obj *v1alpha1.BucketAccess) error { - klog.Infof("bucketAccessListener: add called for bucket access %s", obj.Name) - - // Verify this bucket access is for this provisioner - if !strings.EqualFold(obj.Spec.Provisioner, bal.provisionerName) { - return nil - } - - bucketInstanceName := obj.Spec.BucketInstanceName - bucket, err := bal.bucketAccessClient.ObjectstorageV1alpha1().Buckets().Get(ctx, bucketInstanceName, metav1.GetOptions{}) - if err != nil { - return fmt.Errorf("unable to get bucket instance %s: %+v", bucketInstanceName, err) - } - - req := osspec.ProvisionerGrantBucketAccessRequest{ - Principal: obj.Spec.Principal, - AccessPolicy: obj.Spec.PolicyActionsConfigMapData, - Parameters: bal.getParams(obj), - } - - if req.Parameters == nil { - req.Parameters = make(map[string]string) - } - - proto, err := bucket.Spec.Protocol.ConvertToExternal() - if err != nil { - return errors.Wrap(err, "failed to parse protocol for API") - } - req.Protocol = proto - - // TODO set grpc timeout - rsp, err := bal.provisionerClient.ProvisionerGrantBucketAccess(ctx, &req) - if err != nil { - klog.Errorf("error calling ProvisionerGrantBucketAccess: %v", err) - return err - } - klog.Infof("provisioner returned grant bucket access response %v", rsp) - - // Only update the principal in the BucketAccess if it wasn't set because - // that means that the provisioner created one - if len(obj.Spec.Principal) == 0 && obj.Spec.ServiceAccount == nil { - err = bal.updatePrincipal(ctx, obj.Name, rsp) - if err != nil { - return err - } - } - - // Only create the secret with credentials if serviveAccount isn't set. - // If serviceAccount is set then authorization happens out of band in the - // cloud provider - if obj.Spec.ServiceAccount == nil { - secret := corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: generateSecretName(obj.UID), - }, - StringData: map[string]string{ - "CredentialsFilePath": rsp.CredentialsFilePath, - "CredentialsFileContents": rsp.CredentialsFileContents, - }, - Type: corev1.SecretTypeOpaque, - } - - // It's unlikely but should probably handle retries on rare case of collision - _, err = bal.kubeClient.CoreV1().Secrets("objectstorage-system").Create(ctx, &secret, metav1.CreateOptions{}) - if err != nil { - return err - } - - // TODO update the mintedSecretName in the BA - } - - // update bucket access status to granted - return bal.updateStatus(ctx, obj.Name, "Permissions Granted", true) -} - -// Update does nothing -func (bal *bucketAccessListener) Update(ctx context.Context, old, new *v1alpha1.BucketAccess) error { - klog.Infof("bucketAccessListener: update called for bucket %s", old.Name) - return nil -} - -// Delete will call the provisioner to revoke permissions -func (bal *bucketAccessListener) Delete(ctx context.Context, obj *v1alpha1.BucketAccess) error { - klog.Infof("bucketAccessListener: delete called for bucket access %s", obj.Name) - - // Verify this bucket access is for this provisioner - if !strings.EqualFold(obj.Spec.Provisioner, bal.provisionerName) { - return nil - } - - bucketInstanceName := obj.Spec.BucketInstanceName - bucket, err := bal.bucketAccessClient.ObjectstorageV1alpha1().Buckets().Get(ctx, bucketInstanceName, metav1.GetOptions{}) - if err != nil { - return fmt.Errorf("unable to get bucket instance %s: %+v", bucketInstanceName, err) - } - - req := osspec.ProvisionerRevokeBucketAccessRequest{ - Principal: obj.Spec.Principal, - Parameters: bal.getParams(obj), - } - - if req.Parameters == nil { - req.Parameters = make(map[string]string) - } - - proto, err := bucket.Spec.Protocol.ConvertToExternal() - if err != nil { - return errors.Wrap(err, "failed to parse protocol for API") - } - req.Protocol = proto - - // TODO set grpc timeout - rsp, err := bal.provisionerClient.ProvisionerRevokeBucketAccess(ctx, &req) - if err != nil { - klog.Errorf("error calling ProvisionerRevokeBucketAccess: %v", err) - return err - } - klog.Infof("provisioner returned revoke bucket access response %v", rsp) - - // Delete the secret - if obj.Spec.ServiceAccount == nil { - // TODO get the minted secret name from the BA - - // It's unlikely but should probably handle retries on rare case of collision - err = bal.kubeClient.CoreV1().Secrets("objectstorage-system").Delete(ctx, generateSecretName(obj.UID), metav1.DeleteOptions{}) - if err != nil { - return err - } - } - - // Update bucket access status to revoked - return bal.updateStatus(ctx, obj.Name, "Permissions Revoked", false) -} - -func (bal *bucketAccessListener) updateStatus(ctx context.Context, name, msg string, state bool) error { - err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - bucketAccess, err := bal.bucketAccessClient.ObjectstorageV1alpha1().BucketAccesses().Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return err - } - bucketAccess.Status.Message = msg - bucketAccess.Status.AccessGranted = state - _, err = bal.bucketAccessClient.ObjectstorageV1alpha1().BucketAccesses().UpdateStatus(ctx, bucketAccess, metav1.UpdateOptions{}) - return err - }) - return err -} - -func (bal *bucketAccessListener) updatePrincipal(ctx context.Context, name string, resp *osspec.ProvisionerGrantBucketAccessResponse) error { - err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - bucketAccess, err := bal.bucketAccessClient.ObjectstorageV1alpha1().BucketAccesses().Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return err - } - bucketAccess.Spec.Principal = resp.Principal - _, err = bal.bucketAccessClient.ObjectstorageV1alpha1().BucketAccesses().Update(ctx, bucketAccess, metav1.UpdateOptions{}) - return err - }) - return err -} - -func (bal *bucketAccessListener) getParams(obj *v1alpha1.BucketAccess) map[string]string { - params := map[string]string{} - if obj.Spec.Parameters != nil { - params = obj.Spec.Parameters - } - return params -} diff --git a/pkg/controller/bucketaccess/bucket_access_controller_test.go b/pkg/controller/bucketaccess/bucket_access_controller_test.go deleted file mode 100644 index 1612114..0000000 --- a/pkg/controller/bucketaccess/bucket_access_controller_test.go +++ /dev/null @@ -1,740 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package bucketaccess - -import ( - "context" - "reflect" - "strings" - "testing" - - "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage.k8s.io/v1alpha1" - fakebucketclientset "sigs.k8s.io/container-object-storage-interface-api/clientset/fake" - - osspec "sigs.k8s.io/container-object-storage-interface-spec" - fakespec "sigs.k8s.io/container-object-storage-interface-spec/fake" - - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilversion "k8s.io/apimachinery/pkg/util/version" - "k8s.io/apimachinery/pkg/version" - - fakediscovery "k8s.io/client-go/discovery/fake" - fakekubeclientset "k8s.io/client-go/kubernetes/fake" - - "google.golang.org/grpc" -) - -func TestInitializeKubeClient(t *testing.T) { - client := fakekubeclientset.NewSimpleClientset() - fakeDiscovery, ok := client.Discovery().(*fakediscovery.FakeDiscovery) - if !ok { - t.Fatalf("couldn't convert Discovery() to *FakeDiscovery") - } - - fakeVersion := &version.Info{ - GitVersion: "v1.0.0", - } - fakeDiscovery.FakedServerVersion = fakeVersion - - bal := bucketAccessListener{} - bal.InitializeKubeClient(client) - - if bal.kubeClient == nil { - t.Errorf("kubeClient was nil") - } - - expected := utilversion.MustParseSemantic(fakeVersion.GitVersion) - if !reflect.DeepEqual(expected, bal.kubeVersion) { - t.Errorf("expected %+v, but got %+v", expected, bal.kubeVersion) - } -} - -func TestInitializeBucketClient(t *testing.T) { - client := fakebucketclientset.NewSimpleClientset() - - bal := bucketAccessListener{} - bal.InitializeBucketClient(client) - - if bal.bucketAccessClient == nil { - t.Errorf("bucketClient was nil") - } -} - -func TestAddWrongProvisioner(t *testing.T) { - provisioner := "provisioner1" - mpc := struct{ fakespec.FakeProvisionerClient }{} - mpc.FakeProvisionerGrantBucketAccess = func(ctx context.Context, in *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - t.Errorf("grpc client called") - return nil, nil - } - - bal := bucketAccessListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - } - - ba := v1alpha1.BucketAccess{ - Spec: v1alpha1.BucketAccessSpec{ - Provisioner: "provisioner2", - }, - } - ctx := context.TODO() - err := bal.Add(ctx, &ba) - if err != nil { - t.Errorf("error returned: %+v", err) - } -} - -func TestAdd(t *testing.T) { - provisioner := "provisioner1" - region := "region1" - bucketName := "bucket1" - principal := "principal1" - protocolVersion := "proto1" - sigVersion := v1alpha1.S3SignatureVersion(v1alpha1.S3SignatureVersionV2) - account := "account1" - keyName := "keyName1" - projID := "id1" - endpoint := "endpoint1" - instanceName := "instance" - credsContents := "credsContents" - credsFile := "credsFile" - generatedPrincipal := "driverPrincipal" - sa := "serviceAccount" - mpc := struct{ fakespec.FakeProvisionerClient }{} - extraParamName := "ParamName" - extraParamValue := "ParamValue" - - testCases := []struct { - name string - setProtocol func(b *v1alpha1.Bucket) - protocolName v1alpha1.ProtocolName - grantFunc func(ctx context.Context, in *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) - principal string - serviceAccount string - params map[string]string - }{ - { - name: "S3", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - grantFunc: func(ctx context.Context, req *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - // TODO do we need to check ProtocolVersion here? If so, from where? - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerGrantBucketAccessResponse{ - Principal: principal, - CredentialsFileContents: credsContents, - CredentialsFilePath: credsFile, - }, nil - }, - principal: principal, - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "GCS", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.GCS = &v1alpha1.GCSProtocol{ - ServiceAccount: account, - PrivateKeyName: keyName, - ProjectID: projID, - BucketName: bucketName, - } - }, - protocolName: v1alpha1.ProtocolNameGCS, - grantFunc: func(ctx context.Context, req *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - in := req.Protocol.GetGcs() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - if in.ServiceAccount != account { - t.Errorf("expected %s, got %s", account, in.ServiceAccount) - } - if in.PrivateKeyName != keyName { - t.Errorf("expected %s, got %s", keyName, in.PrivateKeyName) - } - if in.ProjectId != projID { - t.Errorf("expected %s, got %s", projID, in.ProjectId) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerGrantBucketAccessResponse{ - Principal: principal, - CredentialsFileContents: credsContents, - CredentialsFilePath: credsFile, - }, nil - }, - principal: principal, - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "AzureBlob", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.AzureBlob = &v1alpha1.AzureProtocol{ - StorageAccount: account, - ContainerName: bucketName, - } - }, - protocolName: v1alpha1.ProtocolNameAzure, - grantFunc: func(ctx context.Context, req *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - in := req.Protocol.GetAzureBlob() - if in.ContainerName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.ContainerName) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - if in.StorageAccount != account { - t.Errorf("expected %s, got %s", account, in.StorageAccount) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerGrantBucketAccessResponse{ - Principal: principal, - CredentialsFileContents: credsContents, - CredentialsFilePath: credsFile, - }, nil - }, - principal: principal, - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "No Principal", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - grantFunc: func(ctx context.Context, in *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - return &osspec.ProvisionerGrantBucketAccessResponse{ - Principal: generatedPrincipal, - CredentialsFileContents: credsContents, - CredentialsFilePath: credsFile, - }, nil - }, - principal: "", - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "ServiceAccount exists", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - grantFunc: func(ctx context.Context, in *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - return &osspec.ProvisionerGrantBucketAccessResponse{ - Principal: principal, - CredentialsFileContents: credsContents, - CredentialsFilePath: credsFile, - }, nil - }, - principal: principal, - serviceAccount: sa, - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "Empty parameters", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - grantFunc: func(ctx context.Context, req *osspec.ProvisionerGrantBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerGrantBucketAccessResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - // TODO do we need to check ProtocolVersion here? If so, from where? - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - return &osspec.ProvisionerGrantBucketAccessResponse{ - Principal: principal, - CredentialsFileContents: credsContents, - CredentialsFilePath: credsFile, - }, nil - }, - principal: principal, - serviceAccount: "", - params: nil, - }, - } - - for _, tc := range testCases { - b := v1alpha1.Bucket{ - ObjectMeta: metav1.ObjectMeta{ - Name: instanceName, - }, - Spec: v1alpha1.BucketSpec{ - Provisioner: provisioner, - Protocol: v1alpha1.Protocol{ - Name: tc.protocolName, - Version: protocolVersion, - }, - }, - } - - ba := v1alpha1.BucketAccess{ - Spec: v1alpha1.BucketAccessSpec{ - BucketInstanceName: instanceName, - Provisioner: provisioner, - Principal: tc.principal, - Parameters: tc.params, - }, - } - - if len(tc.serviceAccount) > 0 { - ba.Spec.ServiceAccount = &corev1.ObjectReference{ - Name: tc.serviceAccount, - } - } - - ctx := context.TODO() - tc.setProtocol(&b) - client := fakebucketclientset.NewSimpleClientset(&ba, &b) - kubeClient := fakekubeclientset.NewSimpleClientset() - mpc.FakeProvisionerGrantBucketAccess = tc.grantFunc - bal := bucketAccessListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - bucketAccessClient: client, - kubeClient: kubeClient, - } - - t.Logf(tc.name) - err := bal.Add(ctx, &ba) - if err != nil { - t.Errorf("add returned: %+v", err) - } - - updatedBA, _ := client.ObjectstorageV1alpha1().BucketAccesses().Get(ctx, ba.Name, metav1.GetOptions{}) - if updatedBA.Status.AccessGranted != true { - t.Errorf("expected %t, got %t", true, ba.Status.AccessGranted) - } - if len(tc.principal) <= 0 { - if !strings.EqualFold(updatedBA.Spec.Principal, generatedPrincipal) { - t.Errorf("expected %s, got %s", generatedPrincipal, updatedBA.Spec.Principal) - } - } - - secretName := generateSecretName(ba.UID) - secret, err := kubeClient.CoreV1().Secrets("objectstorage-system").Get(ctx, secretName, metav1.GetOptions{}) - if len(tc.serviceAccount) > 0 { - if err == nil { - t.Errorf("secret should not have been created") - } - } else { - if secret.StringData["CredentialsFilePath"] != credsFile { - t.Errorf("expected %s, got %s", credsFile, secret.StringData["CredentialsFilePath"]) - } - if secret.StringData["CredentialsFileContents"] != credsContents { - t.Errorf("expected %s, got %s", credsContents, secret.StringData["CredentialsFileContents"]) - } - } - } -} - -func TestDeleteWrongProvisioner(t *testing.T) { - provisioner := "provisioner1" - mpc := struct{ fakespec.FakeProvisionerClient }{} - mpc.FakeProvisionerRevokeBucketAccess = func(ctx context.Context, in *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) { - t.Errorf("grpc client called") - return nil, nil - } - - bal := bucketAccessListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - } - - ba := v1alpha1.BucketAccess{ - Spec: v1alpha1.BucketAccessSpec{ - Provisioner: "provisioner2", - }, - } - ctx := context.TODO() - err := bal.Delete(ctx, &ba) - if err != nil { - t.Errorf("error returned: %+v", err) - } -} - -func TestDelete(t *testing.T) { - provisioner := "provisioner1" - region := "region1" - bucketName := "bucket1" - principal := "principal1" - protocolVersion := "proto1" - sigVersion := v1alpha1.S3SignatureVersionV2 - account := "account1" - keyName := "keyName1" - projID := "id1" - endpoint := "endpoint1" - instanceName := "instance" - mpc := struct{ fakespec.FakeProvisionerClient }{} - extraParamName := "ParamName" - extraParamValue := "ParamValue" - - testCases := []struct { - name string - setProtocol func(b *v1alpha1.Bucket) - protocolName v1alpha1.ProtocolName - revokeFunc func(ctx context.Context, in *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) - serviceAccount string - params map[string]string - }{ - { - name: "S3", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - revokeFunc: func(ctx context.Context, req *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - // TODO do we need to check ProtocolVersion here? If so, from where? - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerRevokeBucketAccessResponse{}, nil - }, - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "GCS", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.GCS = &v1alpha1.GCSProtocol{ - ServiceAccount: account, - PrivateKeyName: keyName, - ProjectID: projID, - BucketName: bucketName, - } - }, - protocolName: v1alpha1.ProtocolNameGCS, - revokeFunc: func(ctx context.Context, req *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) { - in := req.Protocol.GetGcs() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - if in.ServiceAccount != account { - t.Errorf("expected %s, got %s", account, in.ServiceAccount) - } - if in.PrivateKeyName != keyName { - t.Errorf("expected %s, got %s", keyName, in.PrivateKeyName) - } - if in.ProjectId != projID { - t.Errorf("expected %s, got %s", projID, in.ProjectId) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerRevokeBucketAccessResponse{}, nil - }, - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "AzureBlob", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.AzureBlob = &v1alpha1.AzureProtocol{ - StorageAccount: account, - ContainerName: bucketName, - } - }, - protocolName: v1alpha1.ProtocolNameAzure, - revokeFunc: func(ctx context.Context, req *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) { - in := req.Protocol.GetAzureBlob() - if in.ContainerName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.ContainerName) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - if in.StorageAccount != account { - t.Errorf("expected %s, got %s", account, in.StorageAccount) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerRevokeBucketAccessResponse{}, nil - }, - serviceAccount: "", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "service account exists", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - revokeFunc: func(ctx context.Context, req *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - // TODO do we need to check ProtocolVersion here? If so, from where? - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - if req.Parameters[extraParamName] != extraParamValue { - t.Errorf("expected %s, got %s", extraParamValue, req.Parameters[extraParamName]) - } - return &osspec.ProvisionerRevokeBucketAccessResponse{}, nil - }, - serviceAccount: "serviceAccount", - params: map[string]string{ - extraParamName: extraParamValue, - }, - }, - { - name: "Empty parameters", - setProtocol: func(b *v1alpha1.Bucket) { - b.Spec.Protocol.S3 = &v1alpha1.S3Protocol{ - Region: region, - SignatureVersion: sigVersion, - BucketName: bucketName, - Endpoint: endpoint, - } - }, - protocolName: v1alpha1.ProtocolNameS3, - revokeFunc: func(ctx context.Context, req *osspec.ProvisionerRevokeBucketAccessRequest, opts ...grpc.CallOption) (*osspec.ProvisionerRevokeBucketAccessResponse, error) { - in := req.Protocol.GetS3() - if in.BucketName != bucketName { - t.Errorf("expected %s, got %s", bucketName, in.BucketName) - } - if in.Region != region { - t.Errorf("expected %s, got %s", region, in.Region) - } - if req.Principal != principal { - t.Errorf("expected %s, got %s", principal, req.Principal) - } - // TODO do we need to check ProtocolVersion here? If so, from where? - sigver, ok := osspec.S3SignatureVersion_name[int32(in.SignatureVersion)] - if !ok { - sigver = osspec.S3SignatureVersion_name[int32(osspec.S3SignatureVersion_UnknownSignature)] - } - if sigver != string(sigVersion) { - t.Errorf("expected %s, got %s", sigVersion, sigver) - } - if in.Endpoint != endpoint { - t.Errorf("expected %s, got %s", endpoint, in.Endpoint) - } - return &osspec.ProvisionerRevokeBucketAccessResponse{}, nil - }, - serviceAccount: "", - params: nil, - }, - } - - for _, tc := range testCases { - b := v1alpha1.Bucket{ - ObjectMeta: metav1.ObjectMeta{ - Name: instanceName, - }, - Spec: v1alpha1.BucketSpec{ - Provisioner: provisioner, - Protocol: v1alpha1.Protocol{ - Name: tc.protocolName, - Version: protocolVersion, - }, - }, - } - - ba := v1alpha1.BucketAccess{ - Spec: v1alpha1.BucketAccessSpec{ - BucketInstanceName: instanceName, - Provisioner: provisioner, - Principal: principal, - Parameters: tc.params, - }, - Status: v1alpha1.BucketAccessStatus{ - AccessGranted: true, - }, - } - - if len(tc.serviceAccount) > 0 { - ba.Spec.ServiceAccount = &corev1.ObjectReference{ - Name: tc.serviceAccount, - } - } - secretName := generateSecretName(ba.UID) - secret := v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: "objectstorage-system", - }, - Type: v1.SecretTypeOpaque, - } - - t.Logf(tc.name) - ctx := context.TODO() - tc.setProtocol(&b) - client := fakebucketclientset.NewSimpleClientset(&ba, &b) - kubeClient := fakekubeclientset.NewSimpleClientset(&secret) - mpc.FakeProvisionerRevokeBucketAccess = tc.revokeFunc - bal := bucketAccessListener{ - provisionerName: provisioner, - provisionerClient: &mpc, - bucketAccessClient: client, - kubeClient: kubeClient, - } - - err := bal.Delete(ctx, &ba) - if err != nil { - t.Errorf("delete returned: %+v", err) - } - - updatedBA, _ := client.ObjectstorageV1alpha1().BucketAccesses().Get(ctx, ba.Name, metav1.GetOptions{}) - if updatedBA.Status.AccessGranted != false { - t.Errorf("expected %t, got %t", false, ba.Status.AccessGranted) - } - - _, err = kubeClient.CoreV1().Secrets("objectstorage-system").Get(ctx, secretName, metav1.GetOptions{}) - if len(tc.serviceAccount) == 0 { - if err == nil { - t.Errorf("secret should not exist") - } - } - } -} diff --git a/pkg/grpcclient/client.go b/pkg/grpcclient/client.go deleted file mode 100644 index 25016a3..0000000 --- a/pkg/grpcclient/client.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package grpcclient - -import ( - "context" - "errors" - "net" - "strings" - "time" - - "google.golang.org/grpc" - - "k8s.io/klog/v2" -) - -type options struct { - reconnect func() bool -} - -// Option is the type of all optional parameters for Connect. -type Option func(o *options) - -type GRPCClient struct { - serverAddress string - dialOptions []grpc.DialOption -} - -// NewGRPCClient creates a new GRPCClient -func NewGRPCClient(address string, dialOptions []grpc.DialOption, connectOptions []Option) (*GRPCClient, error) { - var o options - for _, option := range connectOptions { - option(&o) - } - - dialOptions = append(dialOptions, - grpc.WithInsecure(), // Don't use TLS, it's usually local Unix domain socket in a container. - grpc.WithBackoffMaxDelay(time.Second), // Retry every second after failure. - grpc.WithBlock(), // Block until connection succeeds. - ) - - unixPrefix := "unix://" - if strings.HasPrefix(address, "tcp://") { - address = address[6:] - } - if strings.HasPrefix(address, "/") { - // It looks like filesystem path. - address = unixPrefix + address - } - - if strings.HasPrefix(address, unixPrefix) { - // state variables for the custom dialer - haveConnected := false - lostConnection := false - reconnect := true - - dialOptions = append(dialOptions, grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { - if haveConnected && !lostConnection { - // We have detected a loss of connection for the first time. Decide what to do... - // Record this once. TODO (?): log at regular time intervals. - klog.Errorf("Lost connection to %s.", address) - // Inform caller and let it decide? Default is to reconnect. - if o.reconnect != nil { - reconnect = o.reconnect() - } - lostConnection = true - } - if !reconnect { - return nil, errors.New("connection lost, reconnecting disabled") - } - conn, err := net.DialTimeout("unix", address[len(unixPrefix):], timeout) - if err == nil { - // Connection restablished. - haveConnected = true - lostConnection = false - } - return conn, err - })) - } else if o.reconnect != nil { - return nil, errors.New("OnConnectionLoss callback only supported for unix:// addresses") - } - - return &GRPCClient{serverAddress: address, dialOptions: dialOptions}, nil -} - -// Connect connects to the grpc server -func (c *GRPCClient) ConnectWithLogging(interval time.Duration) (*grpc.ClientConn, error) { - klog.Infof("Connecting to %s", c.serverAddress) - - grpcLogFunc := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - klog.Infof("GRPC call: %s", method) - klog.Infof("GRPC request: %s", req) - err := invoker(ctx, method, req, reply, cc, opts...) - klog.Infof("GRPC response: %s", reply) - klog.Infof("GRPC error: %v", err) - return err - } - - // Log all messages - c.dialOptions = append(c.dialOptions, grpc.WithChainUnaryInterceptor(grpcLogFunc)) - - // Connect in background. - var conn *grpc.ClientConn - var err error - ready := make(chan bool) - go func() { - conn, err = grpc.Dial(c.serverAddress, c.dialOptions...) - close(ready) - }() - - // Log error every connectionLoggingInterval - ticker := time.NewTicker(interval) - defer ticker.Stop() - - // Wait until Dial() succeeds. - for { - select { - case <-ticker.C: - klog.Warningf("Still connecting to %s", c.serverAddress) - - case <-ready: - return conn, err - } - } -} diff --git a/pkg/grpcserver/server.go b/pkg/grpcserver/server.go deleted file mode 100644 index a78901e..0000000 --- a/pkg/grpcserver/server.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2020 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package grpcserver - -import ( - "fmt" - "net" - "os" - "strings" - "sync" - - "github.com/kubernetes-csi/csi-lib-utils/protosanitizer" - "golang.org/x/net/context" - "google.golang.org/grpc" - - osi "sigs.k8s.io/container-object-storage-interface-spec" - - "k8s.io/klog/v2" -) - -// Defines Non blocking GRPC server interfaces -type NonBlockingGRPCServer interface { - // Start services at the endpoint - Start(endpoint string, cds osi.ProvisionerServer, ids osi.IdentityServer) - // Waits for the service to stop - Wait() - // Stops the service gracefully - Stop() - // Stops the service forcefully - ForceStop() -} - -func NewNonBlockingGRPCServer() NonBlockingGRPCServer { - return &nonBlockingGRPCServer{} -} - -// NonBlocking server -type nonBlockingGRPCServer struct { - wg sync.WaitGroup - server *grpc.Server -} - -func logGRPC(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - klog.Infof("GRPC call: %s", info.FullMethod) - klog.Infof("GRPC request: %s", protosanitizer.StripSecrets(req)) - resp, err := handler(ctx, req) - if err != nil { - klog.Errorf("GRPC error: %v", err) - } else { - klog.Infof("GRPC response: %s", protosanitizer.StripSecrets(resp)) - } - return resp, err -} - -func ParseEndpoint(ep string) (string, string, error) { - if strings.HasPrefix(strings.ToLower(ep), "unix://") || strings.HasPrefix(strings.ToLower(ep), "tcp://") { - s := strings.SplitN(ep, "://", 2) - if s[1] != "" { - return s[0], s[1], nil - } - } - return "", "", fmt.Errorf("Invalid endpoint: %v", ep) -} - -func (s *nonBlockingGRPCServer) Start(endpoint string, cds osi.ProvisionerServer, ids osi.IdentityServer) { - - s.wg.Add(1) - - go s.serve(endpoint, cds, ids) - - return -} - -func (s *nonBlockingGRPCServer) Wait() { - s.wg.Wait() -} - -func (s *nonBlockingGRPCServer) Stop() { - s.server.GracefulStop() -} - -func (s *nonBlockingGRPCServer) ForceStop() { - s.server.Stop() -} - -func (s *nonBlockingGRPCServer) serve(endpoint string, driver osi.ProvisionerServer, identity osi.IdentityServer) { - - proto, addr, err := ParseEndpoint(endpoint) - if err != nil { - klog.Fatal(err.Error()) - } - - if proto == "unix" { - addr = "/" + addr - if err := os.Remove(addr); err != nil && !os.IsNotExist(err) { - klog.Fatalf("Failed to remove %s, error: %s", addr, err.Error()) - } - } - klog.Infof("Create listener on %s", endpoint) - - //listener, err := net.Listen("tcp", fmt.Sprintf(":%d", osi-port)) - listener, err := net.Listen(proto, addr) - if err != nil { - klog.Fatalf("Failed to listen: %v", err) - } - - opts := []grpc.ServerOption{ - grpc.UnaryInterceptor(logGRPC), - } - server := grpc.NewServer(opts...) - s.server = server - - klog.Infof("Registering CosiControllerServer") - if driver != nil { - osi.RegisterProvisionerServer(server, driver) - } - if identity != nil { - osi.RegisterIdentityServer(server, identity) - } - - klog.Infof("Listening for connections on address: %#v", listener.Addr()) - - server.Serve(listener) - -} diff --git a/pkg/provisioner/client.go b/pkg/provisioner/client.go new file mode 100644 index 0000000..ab68930 --- /dev/null +++ b/pkg/provisioner/client.go @@ -0,0 +1,70 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package provisioner + +import ( + "context" + + "google.golang.org/grpc" + cosi "sigs.k8s.io/container-object-storage-interface-spec" +) + +var ( + _ cosi.IdentityClient = &COSIProvisionerClient{} + _ cosi.ProvisionerClient = &COSIProvisionerClient{} +) + +type COSIProvisionerClient struct { + address string + conn *grpc.ClientConn + identityClient cosi.IdentityClient + provisionerClient cosi.ProvisionerClient +} + +func (c *COSIProvisionerClient) ProvisionerGetInfo(ctx context.Context, + in *cosi.ProvisionerGetInfoRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerGetInfoResponse, error) { + + return c.identityClient.ProvisionerGetInfo(ctx, in, opts...) +} + +func (c *COSIProvisionerClient) ProvisionerCreateBucket(ctx context.Context, + in *cosi.ProvisionerCreateBucketRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerCreateBucketResponse, error) { + + return c.provisionerClient.ProvisionerCreateBucket(ctx, in, opts...) +} + +func (c *COSIProvisionerClient) ProvisionerDeleteBucket(ctx context.Context, + in *cosi.ProvisionerDeleteBucketRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerDeleteBucketResponse, error) { + + return c.provisionerClient.ProvisionerDeleteBucket(ctx, in, opts...) +} + +func (c *COSIProvisionerClient) ProvisionerGrantBucketAccess(ctx context.Context, + in *cosi.ProvisionerGrantBucketAccessRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerGrantBucketAccessResponse, error) { + + return c.provisionerClient.ProvisionerGrantBucketAccess(ctx, in, opts...) +} + +func (c *COSIProvisionerClient) ProvisionerRevokeBucketAccess(ctx context.Context, + in *cosi.ProvisionerRevokeBucketAccessRequest, + opts ...grpc.CallOption) (*cosi.ProvisionerRevokeBucketAccessResponse, error) { + + return c.provisionerClient.ProvisionerRevokeBucketAccess(ctx, in, opts...) +} diff --git a/pkg/provisioner/interceptors.go b/pkg/provisioner/interceptors.go new file mode 100644 index 0000000..77d4353 --- /dev/null +++ b/pkg/provisioner/interceptors.go @@ -0,0 +1,46 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package provisioner + +import ( + "context" + "encoding/json" + "time" + + "google.golang.org/grpc" + "k8s.io/klog/v2" +) + +func apiLogger(ctx context.Context, api string, + req, resp interface{}, + grpcConn *grpc.ClientConn, + apiCall grpc.UnaryInvoker, + opts ...grpc.CallOption) error { + + if jsonReq, err := json.MarshalIndent(req, "", " "); err != nil { + klog.InfoS("Request", "api", api, "req", string(jsonReq)) + } + + start := time.Now() + err := apiCall(ctx, api, req, resp, grpcConn, opts...) + end := time.Now() + + if jsonRes, err := json.MarshalIndent(resp, "", " "); err != nil { + klog.InfoS("Response", "api", api, "elapsed", end.Sub(start), "resp", jsonRes) + } + + return err +} diff --git a/pkg/provisioner/provisioner.go b/pkg/provisioner/provisioner.go new file mode 100644 index 0000000..6f34be0 --- /dev/null +++ b/pkg/provisioner/provisioner.go @@ -0,0 +1,111 @@ +/* Copyright 2021 The Kubernetes Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package provisioner + +import ( + "context" + "net/url" + "time" + + "github.com/pkg/errors" + "google.golang.org/grpc" + + "k8s.io/klog/v2" + cosi "sigs.k8s.io/container-object-storage-interface-spec" +) + +const ( + maxGrpcBackoff = 30 * time.Second + grpcDialTimeout = 30 * time.Second +) + +func NewDefaultCOSIProvisionerClient(ctx context.Context, address string, debug bool) (*COSIProvisionerClient, error) { + dialOpts := []grpc.DialOption{ + grpc.WithInsecure(), // strictly restricting to local Unix domain socket + grpc.WithBackoffMaxDelay(maxGrpcBackoff), + grpc.WithBlock(), // block until connection succeeds + grpc.WithTimeout(grpcDialTimeout), + } + + interceptors := []grpc.UnaryClientInterceptor{} + + if debug { + interceptors = append(interceptors, apiLogger) + } + return NewCOSIProvisionerClient(ctx, address, dialOpts, interceptors) +} + +// NewCOSIProvisionerClient creates a new GRPCClient that only supports unix domain sockets +func NewCOSIProvisionerClient(ctx context.Context, address string, dialOpts []grpc.DialOption, interceptors []grpc.UnaryClientInterceptor) (*COSIProvisionerClient, error) { + addr, err := url.Parse(address) + if err != nil { + return nil, err + } + + if addr.Scheme != "unix" { + err := errors.New("Address must be a unix domain socket") + klog.ErrorS(err, "Unsupported scheme", "expected", "unix", "found", addr.Scheme) + return nil, errors.Wrap(err, "Invalid argument") + } + + for _, interceptor := range interceptors { + dialOpts = append(dialOpts, grpc.WithChainUnaryInterceptor(interceptor)) + } + + conn, err := grpc.DialContext(ctx, address, dialOpts...) + if err != nil { + klog.ErrorS(err, "Connection failed", "address", address) + return nil, err + } + + return &COSIProvisionerClient{ + address: address, + conn: conn, + identityClient: cosi.NewIdentityClient(conn), + provisionerClient: cosi.NewProvisionerClient(conn), + }, nil +} + +func NewDefaultCOSIProvisionerServer(address string, + identityServer cosi.IdentityServer, + provisionerServer cosi.ProvisionerServer) (*COSIProvisionerServer, error) { + + return NewCOSIProvisionerServer(address, identityServer, provisionerServer, []grpc.ServerOption{}) +} + +func NewCOSIProvisionerServer(address string, + identityServer cosi.IdentityServer, + provisionerServer cosi.ProvisionerServer, + listenOpts []grpc.ServerOption) (*COSIProvisionerServer, error) { + + if identityServer == nil { + err := errors.New("Identity server cannot be nil") + klog.ErrorS(err, "Invalid argument") + return nil, err + } + if provisionerServer == nil { + err := errors.New("Provisioner server cannot be nil") + klog.ErrorS(err, "Invalid argument") + return nil, err + } + + return &COSIProvisionerServer{ + address: address, + identityServer: identityServer, + provisionerServer: provisionerServer, + listenOpts: listenOpts, + }, nil +} diff --git a/pkg/provisioner/server.go b/pkg/provisioner/server.go new file mode 100644 index 0000000..dab572a --- /dev/null +++ b/pkg/provisioner/server.go @@ -0,0 +1,67 @@ +// Copyright 2021 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provisioner + +import ( + "context" + "net" + "net/url" + + "github.com/pkg/errors" + "google.golang.org/grpc" + + "k8s.io/klog/v2" + cosi "sigs.k8s.io/container-object-storage-interface-spec" +) + +type COSIProvisionerServer struct { + address string + identityServer cosi.IdentityServer + provisionerServer cosi.ProvisionerServer + + listenOpts []grpc.ServerOption +} + +func (s *COSIProvisionerServer) Run(ctx context.Context) error { + addr, err := url.Parse(s.address) + if err != nil { + return err + } + + if addr.Scheme != "unix" { + err := errors.New("Address must be a unix domain socket") + klog.ErrorS(err, "Unsupported scheme", "expected", "unix", "found", addr.Scheme) + return errors.Wrap(err, "Invalid argument") + } + + listenConfig := net.ListenConfig{} + listener, err := listenConfig.Listen(ctx, "unix", addr.Path) + if err != nil { + klog.ErrorS(err, "Failed to start server") + return errors.Wrap(err, "Failed to start server") + } + + server := grpc.NewServer(s.listenOpts...) + + if s.provisionerServer == nil || s.identityServer == nil { + err := errors.New("ProvisionerServer and identity server cannot be nil") + klog.ErrorS(err, "Invalid args") + return errors.Wrap(err, "Invalid args") + } + + cosi.RegisterIdentityServer(server, s.identityServer) + cosi.RegisterProvisionerServer(server, s.provisionerServer) + + return server.Serve(listener) +} diff --git a/pkg/sampledriver/driver.go b/pkg/sampledriver/driver.go new file mode 100644 index 0000000..d74a193 --- /dev/null +++ b/pkg/sampledriver/driver.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sampledriver + +func NewDriver(provisioner string) (*IdentityServer, *ProvisionerServer) { + return &IdentityServer{ + provisioner: provisioner, + }, &ProvisionerServer{ + provisioner: provisioner, + } +} diff --git a/pkg/sampledriver/identity.go b/pkg/sampledriver/identity.go new file mode 100644 index 0000000..c45fa89 --- /dev/null +++ b/pkg/sampledriver/identity.go @@ -0,0 +1,42 @@ +// Copyright 2021 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sampledriver + +import ( + "context" + + "k8s.io/klog/v2" + cosi "sigs.k8s.io/container-object-storage-interface-spec" + + "github.com/pkg/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type IdentityServer struct { + provisioner string +} + +func (id *IdentityServer) ProvisionerGetInfo(ctx context.Context, + req *cosi.ProvisionerGetInfoRequest) (*cosi.ProvisionerGetInfoResponse, error) { + + if id.provisioner == "" { + klog.ErrorS(errors.New("provisioner name cannot be empty"), "Invalid argument") + return nil, status.Error(codes.Unavailable, "Provisioner name not configured") + } + + return &cosi.ProvisionerGetInfoResponse{ + Name: id.provisioner, + }, nil +} diff --git a/pkg/sampledriver/provisioner.go b/pkg/sampledriver/provisioner.go new file mode 100644 index 0000000..b44cd58 --- /dev/null +++ b/pkg/sampledriver/provisioner.go @@ -0,0 +1,49 @@ +// Copyright 2021 The Kubernetes Authors. +// Licensed under the Apache License, Version 2.0 (the "License"); +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sampledriver + +import ( + "context" + + _ "k8s.io/klog/v2" + cosi "sigs.k8s.io/container-object-storage-interface-spec" +) + +type ProvisionerServer struct { + provisioner string +} + +func (s *ProvisionerServer) ProvisionerCreateBucket(ctx context.Context, + req *cosi.ProvisionerCreateBucketRequest) (*cosi.ProvisionerCreateBucketResponse, error) { + + return &cosi.ProvisionerCreateBucketResponse{}, nil +} + +func (s *ProvisionerServer) ProvisionerDeleteBucket(ctx context.Context, + req *cosi.ProvisionerDeleteBucketRequest) (*cosi.ProvisionerDeleteBucketResponse, error) { + + return &cosi.ProvisionerDeleteBucketResponse{}, nil +} + +func (s *ProvisionerServer) ProvisionerGrantBucketAccess(ctx context.Context, + req *cosi.ProvisionerGrantBucketAccessRequest) (*cosi.ProvisionerGrantBucketAccessResponse, error) { + + return &cosi.ProvisionerGrantBucketAccessResponse{}, nil +} + +func (s *ProvisionerServer) ProvisionerRevokeBucketAccess(ctx context.Context, + req *cosi.ProvisionerRevokeBucketAccessRequest) (*cosi.ProvisionerRevokeBucketAccessResponse, error) { + + return &cosi.ProvisionerRevokeBucketAccessResponse{}, nil +} diff --git a/resources/deployment.yaml b/resources/deployment.yaml index 6eac0fb..3f92421 100644 --- a/resources/deployment.yaml +++ b/resources/deployment.yaml @@ -34,11 +34,11 @@ spec: spec: serviceAccountName: objectstorage-provisioner-sa containers: - - name: objectstorage-sample-driver - image: quay.io/containerobjectstorage/objectstorage-sample-driver:latest + - name: minio-cosi-driver + image: quay.io/containerobjectstorage/minio-cosi-driver:latest args: - - "--listen-address=$(LISTEN_ADDRESS)" - - "--s3-endpoint=$(S3_ENDPOINT)" + - "--driver-addr=$(DRIVER_ADDRESS)" + - "--endpoint=$(ENDPOINT)" - "--access-key=$(ACCESS_KEY)" - "--secret-key=$(SECRET_KEY)" envFrom: @@ -47,10 +47,10 @@ spec: - name: objectstorage-provisioner-sidecar image: quay.io/containerobjectstorage/objectstorage-sidecar:latest args: - - "--connect-address=$(CONNECT_ADDRESS)" - env: - - name: CONNECT_ADDRESS + - "--driver-addr=$(DRIVER_ADDRESS)" + envFrom: + - name: DRIVER_ADDRESS valueFrom: secretKeyRef: name: objectstorage-provisioner - key: LISTEN_ADDRESS + key: DRIVER_ADDRESS diff --git a/resources/secret.yaml b/resources/secret.yaml index 69085e5..d7f96fa 100644 --- a/resources/secret.yaml +++ b/resources/secret.yaml @@ -10,9 +10,9 @@ metadata: app.kubernetes.io/name: container-object-storage-interface-provisioner type: Opaque stringData: - LISTEN_ADDRESS: tcp://0.0.0.0:9000 + DRIVER_ADDRESS: unix:///var/lib/cosi/cosi.sock data: # set to space - S3_ENDPOINT: IA== + ENDPOINT: IA== ACCESS_KEY: IA== SECRET_KEY: IA==