From def8e47f32052280ea06a78a5b58930e2fb61034 Mon Sep 17 00:00:00 2001 From: Louis Ruch Date: Thu, 30 Mar 2023 22:25:08 -0700 Subject: [PATCH] feat(storage): Add pluginInfo to storageBucket --- internal/daemon/worker/worker.go | 15 +++- .../storagebuckets/v1/storage_bucket.proto | 4 + internal/storage/plugin/client.go | 21 +++++ internal/storage/storage.go | 3 + .../storagebuckets/storage_bucket.pb.go | 84 ++++++++++++------- 5 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 internal/storage/plugin/client.go diff --git a/internal/daemon/worker/worker.go b/internal/daemon/worker/worker.go index b37735c148..2ee46f6a29 100644 --- a/internal/daemon/worker/worker.go +++ b/internal/daemon/worker/worker.go @@ -30,6 +30,7 @@ import ( "github.com/hashicorp/boundary/internal/observability/event" "github.com/hashicorp/boundary/internal/server" "github.com/hashicorp/boundary/internal/storage" + plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-secure-stdlib/base62" "github.com/hashicorp/go-secure-stdlib/mlock" @@ -78,7 +79,7 @@ type recorderCache any // create its reverseConnReceiver var reverseConnReceiverFactory func() reverseConnReceiver -var recordingStorageFactory func(ctx context.Context, path string) (storage.RecordingStorage, error) +var recordingStorageFactory func(ctx context.Context, path string, plgClients map[string]plgpb.StoragePluginServiceClient) (storage.RecordingStorage, error) var recorderCacheFactory func() recorderCache @@ -144,6 +145,8 @@ type Worker struct { // The storage for session recording RecordingStorage storage.RecordingStorage + enabledPlugins []base.EnabledPlugin + // downstream workers and routes to those workers downstreamWorkers downstreamers downstreamReceiver reverseConnReceiver @@ -210,7 +213,15 @@ func New(conf *Config) (*Worker, error) { } if w.conf.RawConfig.Worker.RecordingStoragePath != "" && recordingStorageFactory != nil { - s, err := recordingStorageFactory(w.baseContext, w.conf.RawConfig.Worker.RecordingStoragePath) + plgClients := make(map[string]plgpb.StoragePluginServiceClient) + for _, enabledPlugin := range w.enabledPlugins { + switch enabledPlugin { + // TODO(storage): Add mock plugin when enabled, also make sure to enable in dev mode + // TODO(storage): Add AWS storage plugin + } + } + + s, err := recordingStorageFactory(w.baseContext, w.conf.RawConfig.Worker.RecordingStoragePath, plgClients) if err != nil { return nil, fmt.Errorf("error create recording storage: %w", err) } diff --git a/internal/proto/controller/api/resources/storagebuckets/v1/storage_bucket.proto b/internal/proto/controller/api/resources/storagebuckets/v1/storage_bucket.proto index 1d67d5a0d8..a497b35df1 100644 --- a/internal/proto/controller/api/resources/storagebuckets/v1/storage_bucket.proto +++ b/internal/proto/controller/api/resources/storagebuckets/v1/storage_bucket.proto @@ -5,6 +5,7 @@ syntax = "proto3"; package controller.api.resources.storagebuckets.v1; +import "controller/api/resources/plugins/v1/plugin.proto"; import "controller/custom_options/v1/options.proto"; import "google/protobuf/struct.proto"; @@ -26,4 +27,7 @@ message StorageBucket { // Secrets specific to the storage bucket type. These are never output. google.protobuf.Struct secrets = 40 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. Plugin information for this resource. + resources.plugins.v1.PluginInfo plugin = 50; } diff --git a/internal/storage/plugin/client.go b/internal/storage/plugin/client.go new file mode 100644 index 0000000000..bdc8ad4190 --- /dev/null +++ b/internal/storage/plugin/client.go @@ -0,0 +1,21 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package plugin + +import ( + "context" + + wpbs "github.com/hashicorp/boundary/internal/gen/worker/servers/services" +) + +// StorageProxyClient provides a storage related functions that will be sent from a controller +// to a worker through a CommandClientProducer to a corresponding storage plugin. +type StorageProxyClient interface { + // OnCreateStorageBucket is a hook that runs when a storage bucket is created. + OnCreateStorageBucket(context.Context, *wpbs.OnCreateStorageBucketRequest) (*wpbs.OnCreateStorageBucketResponse, error) + // OnUpdateStorageBucket is a hook that runs when a storage bucket is updated. + OnUpdateStorageBucket(context.Context, *wpbs.OnUpdateStorageBucketRequest) (*wpbs.OnUpdateStorageBucketResponse, error) + // OnDeleteStorageBucket is a hook that runs when a storage bucket is deleted. + OnDeleteStorageBucket(context.Context, *wpbs.OnDeleteStorageBucketRequest) (*wpbs.OnDeleteStorageBucketResponse, error) +} diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 565f4f22cf..56c4379d59 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -7,11 +7,14 @@ import ( "context" "io" "io/fs" + + plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin" ) // RecordingStorage can be used to create a LocalFS usable for session recording. type RecordingStorage interface { NewLocalFS(ctx context.Context, bucket Bucket, _ ...Option) (FS, error) + PluginClients() map[string]plgpb.StoragePluginServiceClient } // Bucket is a resource that represents a bucket in an external object store diff --git a/sdk/pbs/controller/api/resources/storagebuckets/storage_bucket.pb.go b/sdk/pbs/controller/api/resources/storagebuckets/storage_bucket.pb.go index 32438c7727..1596b869fc 100644 --- a/sdk/pbs/controller/api/resources/storagebuckets/storage_bucket.pb.go +++ b/sdk/pbs/controller/api/resources/storagebuckets/storage_bucket.pb.go @@ -10,6 +10,7 @@ package storagebuckets import ( + plugins "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/plugins" _ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -42,6 +43,8 @@ type StorageBucket struct { Attributes *structpb.Struct `protobuf:"bytes,30,opt,name=attributes,proto3" json:"attributes,omitempty"` // @gotags: `class:"public"` // Secrets specific to the storage bucket type. These are never output. Secrets *structpb.Struct `protobuf:"bytes,40,opt,name=secrets,proto3" json:"secrets,omitempty"` + // Output only. Plugin information for this resource. + Plugin *plugins.PluginInfo `protobuf:"bytes,50,opt,name=plugin,proto3" json:"plugin,omitempty"` } func (x *StorageBucket) Reset() { @@ -104,6 +107,13 @@ func (x *StorageBucket) GetSecrets() *structpb.Struct { return nil } +func (x *StorageBucket) GetPlugin() *plugins.PluginInfo { + if x != nil { + return x.Plugin + } + return nil +} + var File_controller_api_resources_storagebuckets_v1_storage_bucket_proto protoreflect.FileDescriptor var file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_rawDesc = []byte{ @@ -113,31 +123,39 @@ var file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_rawDesc 0x72, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x2a, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x75, 0x63, - 0x6b, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x75, - 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, - 0x3d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x1e, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, - 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x37, - 0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x07, - 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x42, 0x5e, 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x67, 0x65, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x30, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, + 0x76, 0x31, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x02, 0x0a, 0x0d, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, + 0x75, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x12, 0x3d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, + 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x12, 0x37, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x28, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, + 0x52, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x47, 0x0a, 0x06, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x42, 0x5e, 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x75, 0x63, 0x6b, + 0x65, 0x74, 0x73, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x75, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -154,17 +172,19 @@ func file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_rawDes var file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_goTypes = []interface{}{ - (*StorageBucket)(nil), // 0: controller.api.resources.storagebuckets.v1.StorageBucket - (*structpb.Struct)(nil), // 1: google.protobuf.Struct + (*StorageBucket)(nil), // 0: controller.api.resources.storagebuckets.v1.StorageBucket + (*structpb.Struct)(nil), // 1: google.protobuf.Struct + (*plugins.PluginInfo)(nil), // 2: controller.api.resources.plugins.v1.PluginInfo } var file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_depIdxs = []int32{ 1, // 0: controller.api.resources.storagebuckets.v1.StorageBucket.attributes:type_name -> google.protobuf.Struct 1, // 1: controller.api.resources.storagebuckets.v1.StorageBucket.secrets:type_name -> google.protobuf.Struct - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 2, // 2: controller.api.resources.storagebuckets.v1.StorageBucket.plugin:type_name -> controller.api.resources.plugins.v1.PluginInfo + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_controller_api_resources_storagebuckets_v1_storage_bucket_proto_init() }