1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

(Feature) (ML) Storage S3 sidecar implementation - GT-529 (#1512)

* (Feature) (ML) Storage S3 sidecar implementation
This commit is contained in:
Nikita Vaniasin 2023-11-29 13:31:03 +01:00 committed by GitHub
parent cbf5e65e8b
commit b421395047
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 2648 additions and 3 deletions

View file

@ -17,12 +17,13 @@
- (Bugfix) Handle optional taints for Storage Operator
- (Bugfix) Fix Early Connections for 3.10+
- (Maintenance) yamlfmt as CI Step
- (Maintenance) Expose Context in OperatorV2 Item Handler
- (Maintenance) Expose Context in OperatorV2 Item Handler
- (Feature) Improve K8S Mock for UT
- (Feature) (ML) Introduce basic Conditions
- (Improvement) Raise memory requests for init containers to 50mi
- (Feature) (ML) Metadata Service Implementation
- (Feature) License Manager for ML Deployment
- (Feature) (ML) Storage S3 sidecar implementation
## [1.2.35](https://github.com/arangodb/kube-arangodb/tree/1.2.35) (2023-11-06)
- (Maintenance) Update go-driver to v1.6.0, update IsNotFound() checks

39
cmd/ml.go Normal file
View file

@ -0,0 +1,39 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package cmd
import (
"github.com/spf13/cobra"
)
var (
cmdML = &cobra.Command{
Use: "ml",
Run: func(cmd *cobra.Command, args []string) {
},
Hidden: true,
}
)
func init() {
cmdMain.AddCommand(cmdML)
}

87
cmd/ml_storage.go Normal file
View file

@ -0,0 +1,87 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package cmd
import (
"context"
"os"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/arangodb/kube-arangodb/pkg/ml/storage"
"github.com/arangodb/kube-arangodb/pkg/util"
)
var (
cmdMLStorage = &cobra.Command{
Use: "storage",
Run: func(cmd *cobra.Command, args []string) {
},
Hidden: true,
}
cmdMLStorageS3 = &cobra.Command{
Use: "s3",
Short: "Run a GRPC service implementing the arangodb.operator.ml.storage.v1 API. Enterprise Edition only",
Run: cmdMLStorageS3Run,
}
cmdMLStorageS3Options struct {
storage.ServiceConfig
}
)
func init() {
cmdML.AddCommand(cmdMLStorage)
cmdMLStorage.AddCommand(cmdMLStorageS3)
f := cmdMLStorageS3.PersistentFlags()
f.StringVar(&cmdMLStorageS3Options.ListenAddress, "server.address", "", "Address the GRPC service will listen on (IP:port)")
f.StringVar(&cmdMLStorageS3Options.S3.Endpoint, "s3.endpoint", "", "Endpoint of S3 API implementation")
f.StringVar(&cmdMLStorageS3Options.S3.CACrtFile, "s3.ca-crt", "", "Path to file containing CA certificate to validate endpoint connection")
f.StringVar(&cmdMLStorageS3Options.S3.CAKeyFile, "s3.ca-key", "", "Path to file containing keyfile to validate endpoint connection")
f.BoolVar(&cmdMLStorageS3Options.S3.AllowInsecure, "s3.allow-insecure", false, "If set to true, the Endpoint certificates won't be checked")
f.BoolVar(&cmdMLStorageS3Options.S3.DisableSSL, "s3.disable-ssl", false, "If set to true, the SSL won't be used when connecting to Endpoint")
f.StringVar(&cmdMLStorageS3Options.S3.Region, "s3.region", "", "Region")
f.StringVar(&cmdMLStorageS3Options.S3.BucketName, "s3.bucket", "", "Bucket name")
f.StringVar(&cmdMLStorageS3Options.S3.AccessKeyFile, "s3.access-key", "", "Path to file containing S3 AccessKey")
f.StringVar(&cmdMLStorageS3Options.S3.SecretKeyFile, "s3.secret-key", "", "Path to file containing S3 SecretKey")
}
func cmdMLStorageS3Run(cmd *cobra.Command, _ []string) {
if err := cmdMLStorageS3RunE(cmd); err != nil {
log.Error().Err(err).Msgf("Fatal")
os.Exit(1)
}
}
func cmdMLStorageS3RunE(_ *cobra.Command) error {
ctx := util.CreateSignalContext(context.Background())
svc, err := storage.NewService(ctx, storage.StorageTypeS3Proxy, cmdMLStorageS3Options.ServiceConfig)
if err != nil {
return err
}
return svc.Run(ctx)
}

4
go.mod
View file

@ -35,6 +35,7 @@ require (
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.3.0
github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15
github.com/josephburnett/jd v1.6.1
github.com/julienschmidt/httprouter v1.3.0
@ -62,6 +63,7 @@ require (
k8s.io/apimachinery v0.25.13
k8s.io/client-go v0.25.13
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
sigs.k8s.io/yaml v1.2.0
)
@ -94,7 +96,6 @@ require (
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
@ -127,7 +128,6 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.70.1 // indirect
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)

379
pkg/api/common/v1/common.pb.go generated Normal file
View file

@ -0,0 +1,379 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.21.1
// source: pkg/api/common/v1/common.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Empty message
type Empty struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Empty) Reset() {
*x = Empty{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Empty) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) {
return file_pkg_api_common_v1_common_proto_rawDescGZIP(), []int{0}
}
// Response for single boolean.
type YesOrNo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Result bool `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"`
}
func (x *YesOrNo) Reset() {
*x = YesOrNo{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *YesOrNo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*YesOrNo) ProtoMessage() {}
func (x *YesOrNo) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use YesOrNo.ProtoReflect.Descriptor instead.
func (*YesOrNo) Descriptor() ([]byte, []int) {
return file_pkg_api_common_v1_common_proto_rawDescGZIP(), []int{1}
}
func (x *YesOrNo) GetResult() bool {
if x != nil {
return x.Result
}
return false
}
// Semantic version number.
type Version struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Major version (increasing may break APIs)
Major int32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
// Minor version (increased for new features)
Minor int32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"`
// Patch version (increased for fixes)
Patch int32 `protobuf:"varint,3,opt,name=patch,proto3" json:"patch,omitempty"`
}
func (x *Version) Reset() {
*x = Version{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Version) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Version) ProtoMessage() {}
func (x *Version) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Version.ProtoReflect.Descriptor instead.
func (*Version) Descriptor() ([]byte, []int) {
return file_pkg_api_common_v1_common_proto_rawDescGZIP(), []int{2}
}
func (x *Version) GetMajor() int32 {
if x != nil {
return x.Major
}
return 0
}
func (x *Version) GetMinor() int32 {
if x != nil {
return x.Minor
}
return 0
}
func (x *Version) GetPatch() int32 {
if x != nil {
return x.Patch
}
return 0
}
// KeyValuePair specifies a key-value pair.
type KeyValuePair struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The key.
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
// The value.
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *KeyValuePair) Reset() {
*x = KeyValuePair{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *KeyValuePair) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*KeyValuePair) ProtoMessage() {}
func (x *KeyValuePair) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_common_v1_common_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use KeyValuePair.ProtoReflect.Descriptor instead.
func (*KeyValuePair) Descriptor() ([]byte, []int) {
return file_pkg_api_common_v1_common_proto_rawDescGZIP(), []int{3}
}
func (x *KeyValuePair) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *KeyValuePair) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
var File_pkg_api_common_v1_common_proto protoreflect.FileDescriptor
var file_pkg_api_common_v1_common_proto_rawDesc = []byte{
0x0a, 0x1e, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x1b, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x22, 0x07, 0x0a,
0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x07, 0x59, 0x65, 0x73, 0x4f, 0x72, 0x4e,
0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
0x08, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x4b, 0x0a, 0x07, 0x56, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69,
0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x22, 0x36, 0x0a, 0x0c, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x35,
0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x61,
0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x2d, 0x61, 0x72, 0x61, 0x6e, 0x67,
0x6f, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_pkg_api_common_v1_common_proto_rawDescOnce sync.Once
file_pkg_api_common_v1_common_proto_rawDescData = file_pkg_api_common_v1_common_proto_rawDesc
)
func file_pkg_api_common_v1_common_proto_rawDescGZIP() []byte {
file_pkg_api_common_v1_common_proto_rawDescOnce.Do(func() {
file_pkg_api_common_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_api_common_v1_common_proto_rawDescData)
})
return file_pkg_api_common_v1_common_proto_rawDescData
}
var file_pkg_api_common_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_pkg_api_common_v1_common_proto_goTypes = []interface{}{
(*Empty)(nil), // 0: arangodb.operator.common.v1.Empty
(*YesOrNo)(nil), // 1: arangodb.operator.common.v1.YesOrNo
(*Version)(nil), // 2: arangodb.operator.common.v1.Version
(*KeyValuePair)(nil), // 3: arangodb.operator.common.v1.KeyValuePair
}
var file_pkg_api_common_v1_common_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_pkg_api_common_v1_common_proto_init() }
func file_pkg_api_common_v1_common_proto_init() {
if File_pkg_api_common_v1_common_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_pkg_api_common_v1_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Empty); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_common_v1_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*YesOrNo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_common_v1_common_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Version); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_common_v1_common_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*KeyValuePair); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pkg_api_common_v1_common_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_pkg_api_common_v1_common_proto_goTypes,
DependencyIndexes: file_pkg_api_common_v1_common_proto_depIdxs,
MessageInfos: file_pkg_api_common_v1_common_proto_msgTypes,
}.Build()
File_pkg_api_common_v1_common_proto = out.File
file_pkg_api_common_v1_common_proto_rawDesc = nil
file_pkg_api_common_v1_common_proto_goTypes = nil
file_pkg_api_common_v1_common_proto_depIdxs = nil
}

51
pkg/api/common/v1/common.proto generated Normal file
View file

@ -0,0 +1,51 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
syntax = "proto3";
package arangodb.operator.common.v1;
option go_package = "github.com/arangodb/kube-arangodb/pkg/api/common/v1";
// Empty message
message Empty {}
// Response for single boolean.
message YesOrNo {
bool result = 1;
}
// Semantic version number.
message Version {
// Major version (increasing may break APIs)
int32 major = 1;
// Minor version (increased for new features)
int32 minor = 2;
// Patch version (increased for fixes)
int32 patch = 3;
}
// KeyValuePair specifies a key-value pair.
message KeyValuePair {
// The key.
string key = 1;
// The value.
string value = 2;
}

126
pkg/api/common/v1/errors.go generated Normal file
View file

@ -0,0 +1,126 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package v1
import (
"errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// CauseFunc specifies the prototype of a function that must return the cause
// of the given error.
// If there is not underlying cause, the given error itself must be retured.
// If nil is passed, nil must be returned.
type CauseFunc = func(error) error
// Cause is the cause function used by the error helpers in this module.
func Cause(err error) error {
for err != nil {
if s, ok := status.FromError(err); ok {
return s.Err()
}
err = errors.Unwrap(err)
}
return nil
}
// IsCanceled returns true if the given error signals a request that was canceled. Typically by the caller.
func IsCanceled(err error) bool {
return status.Code(Cause(err)) == codes.Canceled
}
// Canceled creates a new error that signals a request that was canceled. Typically by the caller.
func Canceled(msg string, args ...interface{}) error {
if len(args) > 0 {
return status.Errorf(codes.Canceled, msg, args...)
}
return status.Error(codes.Canceled, msg)
}
// IsInvalidArgument returns true if the given error signals a request with invalid arguments.
func IsInvalidArgument(err error) bool {
return status.Code(Cause(err)) == codes.InvalidArgument
}
// InvalidArgument creates a new error that signals a request with invalid arguments.
func InvalidArgument(msg string, args ...interface{}) error {
if len(args) > 0 {
return status.Errorf(codes.InvalidArgument, msg, args...)
}
return status.Error(codes.InvalidArgument, msg)
}
// IsNotFound returns true if the given error signals a request to an object that is not found.
func IsNotFound(err error) bool {
return status.Code(Cause(err)) == codes.NotFound
}
// NotFound creates a new error that signals a request to an object that is not found.
func NotFound(msg string, args ...interface{}) error {
if len(args) > 0 {
return status.Errorf(codes.NotFound, msg, args...)
}
return status.Error(codes.NotFound, msg)
}
// IsAlreadyExists returns true if the given error signals a request to create an object that already exists.
func IsAlreadyExists(err error) bool {
return status.Code(Cause(err)) == codes.AlreadyExists
}
// AlreadyExists creates a new error that signals a request to create an object that already exists.
func AlreadyExists(msg string, args ...interface{}) error {
if len(args) > 0 {
return status.Errorf(codes.AlreadyExists, msg, args...)
}
return status.Error(codes.AlreadyExists, msg)
}
// IsPreconditionFailed returns true if the given error signals a precondition of the request has failed.
func IsPreconditionFailed(err error) bool {
return status.Code(Cause(err)) == codes.FailedPrecondition
}
// PreconditionFailed creates a new error that signals a request that a precondition of the call has failed.
func PreconditionFailed(msg string, args ...interface{}) error {
if len(args) > 0 {
return status.Errorf(codes.FailedPrecondition, msg, args...)
}
return status.Error(codes.FailedPrecondition, msg)
}
// IsUnavailable returns true if the given error signals an unavailable error.
// This is a most likely a transient condition and may be corrected
// by retrying with a backoff. Note that it is not always safe to retry
// non-idempotent operations.
func IsUnavailable(err error) bool {
return status.Code(Cause(err)) == codes.Unavailable
}
// Unavailable creates a new error that signals an unavailable service.
func Unavailable(msg string, args ...interface{}) error {
if len(args) > 0 {
return status.Errorf(codes.Unavailable, msg, args...)
}
return status.Error(codes.Unavailable, msg)
}

56
pkg/api/common/v1/errors_test.go generated Normal file
View file

@ -0,0 +1,56 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package v1
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestCommonErrorsWrapping(t *testing.T) {
errors := []struct {
name string
errorFunc func(string, ...interface{}) error
validationFunc func(error) bool
}{
{"Canceled", Canceled, IsCanceled},
{"InvalidArgument", InvalidArgument, IsInvalidArgument},
{"NotFound", NotFound, IsNotFound},
{"AlreadyExists", AlreadyExists, IsAlreadyExists},
{"PreconditionFailed", PreconditionFailed, IsPreconditionFailed},
{"Unavailable", Unavailable, IsUnavailable},
}
for idx, testCase := range errors {
t.Run(testCase.name, func(t *testing.T) {
e := testCase.errorFunc("%s error", testCase.name)
wrapped := fmt.Errorf("Wraps: %w", e)
wrapped2 := fmt.Errorf("Wraps another one: %w", wrapped)
for idx2 := range errors {
assert.Equal(t, idx == idx2, errors[idx2].validationFunc(e))
assert.Equal(t, idx == idx2, errors[idx2].validationFunc(wrapped), "wrapped error %s is not detected as an error", testCase.name)
assert.Equal(t, idx == idx2, errors[idx2].validationFunc(wrapped2), "wrapped error %s is not detected as an error", testCase.name)
}
})
}
}

54
pkg/api/common/v1/helper.go generated Normal file
View file

@ -0,0 +1,54 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package v1
// KeyValuePairList is a strong-typed list of KeyValuePair
type KeyValuePairList []*KeyValuePair
// GetValue gets the value for the requested key or nil if it doesn't exist
func (list KeyValuePairList) GetValue(key string) *string {
for _, kv := range list {
if kv.GetKey() == key {
v := kv.GetValue()
return &v
}
}
return nil
}
// UpsertPair update or insert the given value for the requested key
// Returns inserted (otherwise updated)
func (list *KeyValuePairList) UpsertPair(key, value string) bool {
if list == nil {
return false
}
for _, kv := range *list {
if kv.GetKey() == key {
kv.Value = value
return false
}
}
*list = append(*list, &KeyValuePair{
Key: key,
Value: value,
})
return true
}

824
pkg/api/ml/storage/v1/bucketservice.pb.go generated Normal file
View file

@ -0,0 +1,824 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.21.1
// source: pkg/api/ml/storage/v1/bucketservice.proto
package v1
import (
v1 "github.com/arangodb/kube-arangodb/pkg/api/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Request params for Bucket related calls
type BucketRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Key-value pairs stored at the providers (as labels/tags) during CreateBucket
Tags []*v1.KeyValuePair `protobuf:"bytes,10,rep,name=tags,proto3" json:"tags,omitempty"`
}
func (x *BucketRequest) Reset() {
*x = BucketRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *BucketRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BucketRequest) ProtoMessage() {}
func (x *BucketRequest) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BucketRequest.ProtoReflect.Descriptor instead.
func (*BucketRequest) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{0}
}
func (x *BucketRequest) GetTags() []*v1.KeyValuePair {
if x != nil {
return x.Tags
}
return nil
}
// Request params for Path related requests
type PathRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The path (Specify as "." to indicate the root folder)
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
}
func (x *PathRequest) Reset() {
*x = PathRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PathRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PathRequest) ProtoMessage() {}
func (x *PathRequest) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PathRequest.ProtoReflect.Descriptor instead.
func (*PathRequest) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{1}
}
func (x *PathRequest) GetPath() string {
if x != nil {
return x.Path
}
return ""
}
// Response from GetRepositoryURL request
type RepositoryURL struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The URL
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
// The URL without provider information
BucketPath string `protobuf:"bytes,2,opt,name=bucket_path,json=bucketPath,proto3" json:"bucket_path,omitempty"`
}
func (x *RepositoryURL) Reset() {
*x = RepositoryURL{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RepositoryURL) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RepositoryURL) ProtoMessage() {}
func (x *RepositoryURL) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RepositoryURL.ProtoReflect.Descriptor instead.
func (*RepositoryURL) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{2}
}
func (x *RepositoryURL) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
func (x *RepositoryURL) GetBucketPath() string {
if x != nil {
return x.BucketPath
}
return ""
}
// Response from GetPathSize request
type PathSize struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The size in bytes
SizeInBytes uint64 `protobuf:"varint,1,opt,name=size_in_bytes,json=sizeInBytes,proto3" json:"size_in_bytes,omitempty"`
// Number of files
NumberOfFiles uint32 `protobuf:"varint,2,opt,name=number_of_files,json=numberOfFiles,proto3" json:"number_of_files,omitempty"`
// Number of folders
NumberOfFolders uint32 `protobuf:"varint,3,opt,name=number_of_folders,json=numberOfFolders,proto3" json:"number_of_folders,omitempty"`
}
func (x *PathSize) Reset() {
*x = PathSize{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *PathSize) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PathSize) ProtoMessage() {}
func (x *PathSize) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PathSize.ProtoReflect.Descriptor instead.
func (*PathSize) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{3}
}
func (x *PathSize) GetSizeInBytes() uint64 {
if x != nil {
return x.SizeInBytes
}
return 0
}
func (x *PathSize) GetNumberOfFiles() uint32 {
if x != nil {
return x.NumberOfFiles
}
return 0
}
func (x *PathSize) GetNumberOfFolders() uint32 {
if x != nil {
return x.NumberOfFolders
}
return 0
}
// Response from GetObjectInfo request
type ObjectInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Indicates if the object is locked
IsLocked bool `protobuf:"varint,1,opt,name=is_locked,json=isLocked,proto3" json:"is_locked,omitempty"`
// Indicates the size of the object in bytes
SizeInBytes uint64 `protobuf:"varint,2,opt,name=size_in_bytes,json=sizeInBytes,proto3" json:"size_in_bytes,omitempty"`
// The timestamp this object has last been modified
LastUpdatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=last_updated_at,json=lastUpdatedAt,proto3" json:"last_updated_at,omitempty"`
}
func (x *ObjectInfo) Reset() {
*x = ObjectInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ObjectInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ObjectInfo) ProtoMessage() {}
func (x *ObjectInfo) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ObjectInfo.ProtoReflect.Descriptor instead.
func (*ObjectInfo) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{4}
}
func (x *ObjectInfo) GetIsLocked() bool {
if x != nil {
return x.IsLocked
}
return false
}
func (x *ObjectInfo) GetSizeInBytes() uint64 {
if x != nil {
return x.SizeInBytes
}
return 0
}
func (x *ObjectInfo) GetLastUpdatedAt() *timestamppb.Timestamp {
if x != nil {
return x.LastUpdatedAt
}
return nil
}
// Output message for ReadObject.
type ReadObjectChunk struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Raw output
Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
}
func (x *ReadObjectChunk) Reset() {
*x = ReadObjectChunk{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReadObjectChunk) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReadObjectChunk) ProtoMessage() {}
func (x *ReadObjectChunk) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReadObjectChunk.ProtoReflect.Descriptor instead.
func (*ReadObjectChunk) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{5}
}
func (x *ReadObjectChunk) GetChunk() []byte {
if x != nil {
return x.Chunk
}
return nil
}
// Input message for WriteObject
type WriteObjectChunk struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Base request params for Path related requests.
// This field cannot change during the stream.
Path *PathRequest `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
// Raw input
Chunk []byte `protobuf:"bytes,2,opt,name=chunk,proto3" json:"chunk,omitempty"`
// If set, the caller wants to send a next message with more input data.
// If not set, no more control message will be sent.
HasMore bool `protobuf:"varint,3,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"`
}
func (x *WriteObjectChunk) Reset() {
*x = WriteObjectChunk{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WriteObjectChunk) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WriteObjectChunk) ProtoMessage() {}
func (x *WriteObjectChunk) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WriteObjectChunk.ProtoReflect.Descriptor instead.
func (*WriteObjectChunk) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{6}
}
func (x *WriteObjectChunk) GetPath() *PathRequest {
if x != nil {
return x.Path
}
return nil
}
func (x *WriteObjectChunk) GetChunk() []byte {
if x != nil {
return x.Chunk
}
return nil
}
func (x *WriteObjectChunk) GetHasMore() bool {
if x != nil {
return x.HasMore
}
return false
}
// Output message for WriteObject
type WriteObjectControl struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// If set, the next chunk of input is allowed.
// If unset, the caller is expected to terminate the call.
AllowMoreOutput bool `protobuf:"varint,1,opt,name=allow_more_output,json=allowMoreOutput,proto3" json:"allow_more_output,omitempty"`
// Maximum number of bytes the caller is allowed to send in the next input chunk.
MaxChunkBytes int32 `protobuf:"varint,2,opt,name=max_chunk_bytes,json=maxChunkBytes,proto3" json:"max_chunk_bytes,omitempty"`
}
func (x *WriteObjectControl) Reset() {
*x = WriteObjectControl{}
if protoimpl.UnsafeEnabled {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *WriteObjectControl) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*WriteObjectControl) ProtoMessage() {}
func (x *WriteObjectControl) ProtoReflect() protoreflect.Message {
mi := &file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use WriteObjectControl.ProtoReflect.Descriptor instead.
func (*WriteObjectControl) Descriptor() ([]byte, []int) {
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP(), []int{7}
}
func (x *WriteObjectControl) GetAllowMoreOutput() bool {
if x != nil {
return x.AllowMoreOutput
}
return false
}
func (x *WriteObjectControl) GetMaxChunkBytes() int32 {
if x != nil {
return x.MaxChunkBytes
}
return 0
}
var File_pkg_api_ml_storage_v1_bucketservice_proto protoreflect.FileDescriptor
var file_pkg_api_ml_storage_v1_bucketservice_proto_rawDesc = []byte{
0x0a, 0x29, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x6c, 0x2f, 0x73, 0x74, 0x6f,
0x72, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1f, 0x61, 0x72, 0x61,
0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d,
0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1e, 0x70, 0x6b,
0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4e, 0x0a,
0x0d, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d,
0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61,
0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x21, 0x0a,
0x0b, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68,
0x22, 0x42, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x55, 0x52,
0x4c, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x75, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x70, 0x61,
0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74,
0x50, 0x61, 0x74, 0x68, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x50, 0x61, 0x74, 0x68, 0x53, 0x69, 0x7a,
0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x79, 0x74,
0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x69, 0x7a, 0x65, 0x49, 0x6e,
0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f,
0x6f, 0x66, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x0a,
0x11, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x66, 0x6f, 0x6c, 0x64, 0x65,
0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
0x4f, 0x66, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x0a, 0x4f, 0x62,
0x6a, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x6c,
0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4c,
0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x69, 0x6e,
0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x69,
0x7a, 0x65, 0x49, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0f, 0x6c, 0x61, 0x73,
0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d,
0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x27, 0x0a,
0x0f, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b,
0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x85, 0x01, 0x0a, 0x10, 0x57, 0x72, 0x69, 0x74, 0x65,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x40, 0x0a, 0x04, 0x70,
0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x72, 0x61, 0x6e,
0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c,
0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a,
0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68,
0x75, 0x6e, 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x6d, 0x6f, 0x72, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4d, 0x6f, 0x72, 0x65, 0x22, 0x68,
0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x6f,
0x72, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4d, 0x6f, 0x72, 0x65, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x62, 0x79,
0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x43, 0x68,
0x75, 0x6e, 0x6b, 0x42, 0x79, 0x74, 0x65, 0x73, 0x32, 0xa9, 0x08, 0x0a, 0x0d, 0x42, 0x75, 0x63,
0x6b, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x0d, 0x47, 0x65,
0x74, 0x41, 0x50, 0x49, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x61, 0x72,
0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
0x24, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x64, 0x0a, 0x0c, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x45,
0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x2e, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62,
0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f,
0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62,
0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x76, 0x31, 0x2e, 0x59, 0x65, 0x73, 0x4f, 0x72, 0x4e, 0x6f, 0x12, 0x62, 0x0a, 0x0c, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x2e, 0x2e, 0x61, 0x72,
0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e,
0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75,
0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72,
0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12,
0x62, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12,
0x2e, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x22, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x12, 0x70, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x6f, 0x72, 0x79, 0x55, 0x52, 0x4c, 0x12, 0x2c, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f,
0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73,
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62,
0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f,
0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
0x72, 0x79, 0x55, 0x52, 0x4c, 0x12, 0x5e, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50,
0x61, 0x74, 0x68, 0x12, 0x2c, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f,
0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61,
0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65,
0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x66, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68,
0x53, 0x69, 0x7a, 0x65, 0x12, 0x2c, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e,
0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72,
0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x29, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70,
0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x6e, 0x0a,
0x0a, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2c, 0x2e, 0x61, 0x72,
0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e,
0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61,
0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x61, 0x72, 0x61, 0x6e,
0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c,
0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x30, 0x01, 0x12, 0x79, 0x0a,
0x0b, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x31, 0x2e, 0x61,
0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72,
0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57,
0x72, 0x69, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a,
0x33, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61,
0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x28, 0x01, 0x30, 0x01, 0x12, 0x6a, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x2e, 0x61, 0x72, 0x61, 0x6e,
0x67, 0x6f, 0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c,
0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f,
0x64, 0x62, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x6d, 0x6c, 0x2e, 0x73,
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x49, 0x6e, 0x66, 0x6f, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x6b, 0x75, 0x62, 0x65,
0x2d, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x64, 0x62, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x6d, 0x6c, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescOnce sync.Once
file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescData = file_pkg_api_ml_storage_v1_bucketservice_proto_rawDesc
)
func file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescGZIP() []byte {
file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescOnce.Do(func() {
file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescData)
})
return file_pkg_api_ml_storage_v1_bucketservice_proto_rawDescData
}
var file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_pkg_api_ml_storage_v1_bucketservice_proto_goTypes = []interface{}{
(*BucketRequest)(nil), // 0: arangodb.operator.ml.storage.v1.BucketRequest
(*PathRequest)(nil), // 1: arangodb.operator.ml.storage.v1.PathRequest
(*RepositoryURL)(nil), // 2: arangodb.operator.ml.storage.v1.RepositoryURL
(*PathSize)(nil), // 3: arangodb.operator.ml.storage.v1.PathSize
(*ObjectInfo)(nil), // 4: arangodb.operator.ml.storage.v1.ObjectInfo
(*ReadObjectChunk)(nil), // 5: arangodb.operator.ml.storage.v1.ReadObjectChunk
(*WriteObjectChunk)(nil), // 6: arangodb.operator.ml.storage.v1.WriteObjectChunk
(*WriteObjectControl)(nil), // 7: arangodb.operator.ml.storage.v1.WriteObjectControl
(*v1.KeyValuePair)(nil), // 8: arangodb.operator.common.v1.KeyValuePair
(*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
(*v1.Empty)(nil), // 10: arangodb.operator.common.v1.Empty
(*v1.Version)(nil), // 11: arangodb.operator.common.v1.Version
(*v1.YesOrNo)(nil), // 12: arangodb.operator.common.v1.YesOrNo
}
var file_pkg_api_ml_storage_v1_bucketservice_proto_depIdxs = []int32{
8, // 0: arangodb.operator.ml.storage.v1.BucketRequest.tags:type_name -> arangodb.operator.common.v1.KeyValuePair
9, // 1: arangodb.operator.ml.storage.v1.ObjectInfo.last_updated_at:type_name -> google.protobuf.Timestamp
1, // 2: arangodb.operator.ml.storage.v1.WriteObjectChunk.path:type_name -> arangodb.operator.ml.storage.v1.PathRequest
10, // 3: arangodb.operator.ml.storage.v1.BucketService.GetAPIVersion:input_type -> arangodb.operator.common.v1.Empty
0, // 4: arangodb.operator.ml.storage.v1.BucketService.BucketExists:input_type -> arangodb.operator.ml.storage.v1.BucketRequest
0, // 5: arangodb.operator.ml.storage.v1.BucketService.CreateBucket:input_type -> arangodb.operator.ml.storage.v1.BucketRequest
0, // 6: arangodb.operator.ml.storage.v1.BucketService.DeleteBucket:input_type -> arangodb.operator.ml.storage.v1.BucketRequest
1, // 7: arangodb.operator.ml.storage.v1.BucketService.GetRepositoryURL:input_type -> arangodb.operator.ml.storage.v1.PathRequest
1, // 8: arangodb.operator.ml.storage.v1.BucketService.DeletePath:input_type -> arangodb.operator.ml.storage.v1.PathRequest
1, // 9: arangodb.operator.ml.storage.v1.BucketService.GetPathSize:input_type -> arangodb.operator.ml.storage.v1.PathRequest
1, // 10: arangodb.operator.ml.storage.v1.BucketService.ReadObject:input_type -> arangodb.operator.ml.storage.v1.PathRequest
6, // 11: arangodb.operator.ml.storage.v1.BucketService.WriteObject:input_type -> arangodb.operator.ml.storage.v1.WriteObjectChunk
1, // 12: arangodb.operator.ml.storage.v1.BucketService.GetObjectInfo:input_type -> arangodb.operator.ml.storage.v1.PathRequest
11, // 13: arangodb.operator.ml.storage.v1.BucketService.GetAPIVersion:output_type -> arangodb.operator.common.v1.Version
12, // 14: arangodb.operator.ml.storage.v1.BucketService.BucketExists:output_type -> arangodb.operator.common.v1.YesOrNo
10, // 15: arangodb.operator.ml.storage.v1.BucketService.CreateBucket:output_type -> arangodb.operator.common.v1.Empty
10, // 16: arangodb.operator.ml.storage.v1.BucketService.DeleteBucket:output_type -> arangodb.operator.common.v1.Empty
2, // 17: arangodb.operator.ml.storage.v1.BucketService.GetRepositoryURL:output_type -> arangodb.operator.ml.storage.v1.RepositoryURL
10, // 18: arangodb.operator.ml.storage.v1.BucketService.DeletePath:output_type -> arangodb.operator.common.v1.Empty
3, // 19: arangodb.operator.ml.storage.v1.BucketService.GetPathSize:output_type -> arangodb.operator.ml.storage.v1.PathSize
5, // 20: arangodb.operator.ml.storage.v1.BucketService.ReadObject:output_type -> arangodb.operator.ml.storage.v1.ReadObjectChunk
7, // 21: arangodb.operator.ml.storage.v1.BucketService.WriteObject:output_type -> arangodb.operator.ml.storage.v1.WriteObjectControl
4, // 22: arangodb.operator.ml.storage.v1.BucketService.GetObjectInfo:output_type -> arangodb.operator.ml.storage.v1.ObjectInfo
13, // [13:23] is the sub-list for method output_type
3, // [3:13] 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_pkg_api_ml_storage_v1_bucketservice_proto_init() }
func file_pkg_api_ml_storage_v1_bucketservice_proto_init() {
if File_pkg_api_ml_storage_v1_bucketservice_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BucketRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PathRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RepositoryURL); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PathSize); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ObjectInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReadObjectChunk); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WriteObjectChunk); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*WriteObjectControl); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_pkg_api_ml_storage_v1_bucketservice_proto_rawDesc,
NumEnums: 0,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_pkg_api_ml_storage_v1_bucketservice_proto_goTypes,
DependencyIndexes: file_pkg_api_ml_storage_v1_bucketservice_proto_depIdxs,
MessageInfos: file_pkg_api_ml_storage_v1_bucketservice_proto_msgTypes,
}.Build()
File_pkg_api_ml_storage_v1_bucketservice_proto = out.File
file_pkg_api_ml_storage_v1_bucketservice_proto_rawDesc = nil
file_pkg_api_ml_storage_v1_bucketservice_proto_goTypes = nil
file_pkg_api_ml_storage_v1_bucketservice_proto_depIdxs = nil
}

125
pkg/api/ml/storage/v1/bucketservice.proto generated Normal file
View file

@ -0,0 +1,125 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
syntax = "proto3";
package arangodb.operator.ml.storage.v1;
option go_package = "github.com/arangodb/kube-arangodb/pkg/api/ml/storage/v1";
import "pkg/api/common/v1/common.proto";
import "google/protobuf/timestamp.proto";
// BucketService is the API used to manage buckets.
service BucketService {
// Get the current API version of this service.
rpc GetAPIVersion(common.v1.Empty) returns (common.v1.Version);
// BucketExists checks if the specified bucket exists
rpc BucketExists(BucketRequest) returns (common.v1.YesOrNo);
// CreateBucket creates a bucket
rpc CreateBucket(BucketRequest) returns (common.v1.Empty);
// DeleteBucket deletes a bucket
// Notice that this deletes all data contained in the bucket as well
rpc DeleteBucket(BucketRequest) returns (common.v1.Empty);
// GetRepositoryURL get the URL needed to store/delete objects in a bucket
rpc GetRepositoryURL(PathRequest) returns (RepositoryURL);
// DeletePath deletes the specified path (recursively) from the provided bucket
rpc DeletePath(PathRequest) returns (common.v1.Empty);
// GetPathSize provides the size in bytes for the specified path from the provided bucket
rpc GetPathSize(PathRequest) returns (PathSize);
// ReadObject opens an object in the bucket and streams the existing data from the object into the client
rpc ReadObject(PathRequest) returns (stream ReadObjectChunk);
// WriteObject creates or opens an object in the bucket and allows the client to stream (additional) data into the object
rpc WriteObject(stream WriteObjectChunk) returns (stream WriteObjectControl);
// GetObjectInfo provides information for the specified object from the provided bucket
// A Not-Found error is returned if the object cannot be found
rpc GetObjectInfo(PathRequest) returns (ObjectInfo);
}
// Request params for Bucket related calls
message BucketRequest {
// Key-value pairs stored at the providers (as labels/tags) during CreateBucket
repeated common.v1.KeyValuePair tags = 10;
}
// Request params for Path related requests
message PathRequest {
// The path (Specify as "." to indicate the root folder)
string path = 3;
}
// Response from GetRepositoryURL request
message RepositoryURL {
// The URL
string url = 1;
// The URL without provider information
string bucket_path = 2;
}
// Response from GetPathSize request
message PathSize {
// The size in bytes
uint64 size_in_bytes = 1;
// Number of files
uint32 number_of_files = 2;
// Number of folders
uint32 number_of_folders = 3;
}
// Response from GetObjectInfo request
message ObjectInfo {
// Indicates if the object is locked
bool is_locked = 1;
// Indicates the size of the object in bytes
uint64 size_in_bytes = 2;
// The timestamp this object has last been modified
google.protobuf.Timestamp last_updated_at = 3;
}
// Output message for ReadObject.
message ReadObjectChunk {
// Raw output
bytes chunk = 1;
}
// Input message for WriteObject
message WriteObjectChunk {
// Base request params for Path related requests.
// This field cannot change during the stream.
PathRequest path = 1;
// Raw input
bytes chunk = 2;
// If set, the caller wants to send a next message with more input data.
// If not set, no more control message will be sent.
bool has_more = 3;
}
// Output message for WriteObject
message WriteObjectControl {
// If set, the next chunk of input is allowed.
// If unset, the caller is expected to terminate the call.
bool allow_more_output = 1;
// Maximum number of bytes the caller is allowed to send in the next input chunk.
int32 max_chunk_bytes = 2;
}

View file

@ -0,0 +1,514 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.21.1
// source: pkg/api/ml/storage/v1/bucketservice.proto
package v1
import (
context "context"
v1 "github.com/arangodb/kube-arangodb/pkg/api/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// BucketServiceClient is the client API for BucketService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type BucketServiceClient interface {
// Get the current API version of this service.
GetAPIVersion(ctx context.Context, in *v1.Empty, opts ...grpc.CallOption) (*v1.Version, error)
// BucketExists checks if the specified bucket exists
BucketExists(ctx context.Context, in *BucketRequest, opts ...grpc.CallOption) (*v1.YesOrNo, error)
// CreateBucket creates a bucket
CreateBucket(ctx context.Context, in *BucketRequest, opts ...grpc.CallOption) (*v1.Empty, error)
// DeleteBucket deletes a bucket
// Notice that this deletes all data contained in the bucket as well
DeleteBucket(ctx context.Context, in *BucketRequest, opts ...grpc.CallOption) (*v1.Empty, error)
// GetRepositoryURL get the URL needed to store/delete objects in a bucket
GetRepositoryURL(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*RepositoryURL, error)
// DeletePath deletes the specified path (recursively) from the provided bucket
DeletePath(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*v1.Empty, error)
// GetPathSize provides the size in bytes for the specified path from the provided bucket
GetPathSize(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*PathSize, error)
// ReadObject opens an object in the bucket and streams the existing data from the object into the client
ReadObject(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (BucketService_ReadObjectClient, error)
// WriteObject creates or opens an object in the bucket and allows the client to stream (additional) data into the object
WriteObject(ctx context.Context, opts ...grpc.CallOption) (BucketService_WriteObjectClient, error)
// GetObjectInfo provides information for the specified object from the provided bucket
// A Not-Found error is returned if the object cannot be found
GetObjectInfo(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*ObjectInfo, error)
}
type bucketServiceClient struct {
cc grpc.ClientConnInterface
}
func NewBucketServiceClient(cc grpc.ClientConnInterface) BucketServiceClient {
return &bucketServiceClient{cc}
}
func (c *bucketServiceClient) GetAPIVersion(ctx context.Context, in *v1.Empty, opts ...grpc.CallOption) (*v1.Version, error) {
out := new(v1.Version)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/GetAPIVersion", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) BucketExists(ctx context.Context, in *BucketRequest, opts ...grpc.CallOption) (*v1.YesOrNo, error) {
out := new(v1.YesOrNo)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/BucketExists", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) CreateBucket(ctx context.Context, in *BucketRequest, opts ...grpc.CallOption) (*v1.Empty, error) {
out := new(v1.Empty)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/CreateBucket", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) DeleteBucket(ctx context.Context, in *BucketRequest, opts ...grpc.CallOption) (*v1.Empty, error) {
out := new(v1.Empty)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/DeleteBucket", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) GetRepositoryURL(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*RepositoryURL, error) {
out := new(RepositoryURL)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/GetRepositoryURL", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) DeletePath(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*v1.Empty, error) {
out := new(v1.Empty)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/DeletePath", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) GetPathSize(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*PathSize, error) {
out := new(PathSize)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/GetPathSize", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bucketServiceClient) ReadObject(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (BucketService_ReadObjectClient, error) {
stream, err := c.cc.NewStream(ctx, &BucketService_ServiceDesc.Streams[0], "/arangodb.operator.ml.storage.v1.BucketService/ReadObject", opts...)
if err != nil {
return nil, err
}
x := &bucketServiceReadObjectClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type BucketService_ReadObjectClient interface {
Recv() (*ReadObjectChunk, error)
grpc.ClientStream
}
type bucketServiceReadObjectClient struct {
grpc.ClientStream
}
func (x *bucketServiceReadObjectClient) Recv() (*ReadObjectChunk, error) {
m := new(ReadObjectChunk)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *bucketServiceClient) WriteObject(ctx context.Context, opts ...grpc.CallOption) (BucketService_WriteObjectClient, error) {
stream, err := c.cc.NewStream(ctx, &BucketService_ServiceDesc.Streams[1], "/arangodb.operator.ml.storage.v1.BucketService/WriteObject", opts...)
if err != nil {
return nil, err
}
x := &bucketServiceWriteObjectClient{stream}
return x, nil
}
type BucketService_WriteObjectClient interface {
Send(*WriteObjectChunk) error
Recv() (*WriteObjectControl, error)
grpc.ClientStream
}
type bucketServiceWriteObjectClient struct {
grpc.ClientStream
}
func (x *bucketServiceWriteObjectClient) Send(m *WriteObjectChunk) error {
return x.ClientStream.SendMsg(m)
}
func (x *bucketServiceWriteObjectClient) Recv() (*WriteObjectControl, error) {
m := new(WriteObjectControl)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *bucketServiceClient) GetObjectInfo(ctx context.Context, in *PathRequest, opts ...grpc.CallOption) (*ObjectInfo, error) {
out := new(ObjectInfo)
err := c.cc.Invoke(ctx, "/arangodb.operator.ml.storage.v1.BucketService/GetObjectInfo", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// BucketServiceServer is the server API for BucketService service.
// All implementations must embed UnimplementedBucketServiceServer
// for forward compatibility
type BucketServiceServer interface {
// Get the current API version of this service.
GetAPIVersion(context.Context, *v1.Empty) (*v1.Version, error)
// BucketExists checks if the specified bucket exists
BucketExists(context.Context, *BucketRequest) (*v1.YesOrNo, error)
// CreateBucket creates a bucket
CreateBucket(context.Context, *BucketRequest) (*v1.Empty, error)
// DeleteBucket deletes a bucket
// Notice that this deletes all data contained in the bucket as well
DeleteBucket(context.Context, *BucketRequest) (*v1.Empty, error)
// GetRepositoryURL get the URL needed to store/delete objects in a bucket
GetRepositoryURL(context.Context, *PathRequest) (*RepositoryURL, error)
// DeletePath deletes the specified path (recursively) from the provided bucket
DeletePath(context.Context, *PathRequest) (*v1.Empty, error)
// GetPathSize provides the size in bytes for the specified path from the provided bucket
GetPathSize(context.Context, *PathRequest) (*PathSize, error)
// ReadObject opens an object in the bucket and streams the existing data from the object into the client
ReadObject(*PathRequest, BucketService_ReadObjectServer) error
// WriteObject creates or opens an object in the bucket and allows the client to stream (additional) data into the object
WriteObject(BucketService_WriteObjectServer) error
// GetObjectInfo provides information for the specified object from the provided bucket
// A Not-Found error is returned if the object cannot be found
GetObjectInfo(context.Context, *PathRequest) (*ObjectInfo, error)
mustEmbedUnimplementedBucketServiceServer()
}
// UnimplementedBucketServiceServer must be embedded to have forward compatible implementations.
type UnimplementedBucketServiceServer struct {
}
func (UnimplementedBucketServiceServer) GetAPIVersion(context.Context, *v1.Empty) (*v1.Version, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAPIVersion not implemented")
}
func (UnimplementedBucketServiceServer) BucketExists(context.Context, *BucketRequest) (*v1.YesOrNo, error) {
return nil, status.Errorf(codes.Unimplemented, "method BucketExists not implemented")
}
func (UnimplementedBucketServiceServer) CreateBucket(context.Context, *BucketRequest) (*v1.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateBucket not implemented")
}
func (UnimplementedBucketServiceServer) DeleteBucket(context.Context, *BucketRequest) (*v1.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteBucket not implemented")
}
func (UnimplementedBucketServiceServer) GetRepositoryURL(context.Context, *PathRequest) (*RepositoryURL, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRepositoryURL not implemented")
}
func (UnimplementedBucketServiceServer) DeletePath(context.Context, *PathRequest) (*v1.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeletePath not implemented")
}
func (UnimplementedBucketServiceServer) GetPathSize(context.Context, *PathRequest) (*PathSize, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPathSize not implemented")
}
func (UnimplementedBucketServiceServer) ReadObject(*PathRequest, BucketService_ReadObjectServer) error {
return status.Errorf(codes.Unimplemented, "method ReadObject not implemented")
}
func (UnimplementedBucketServiceServer) WriteObject(BucketService_WriteObjectServer) error {
return status.Errorf(codes.Unimplemented, "method WriteObject not implemented")
}
func (UnimplementedBucketServiceServer) GetObjectInfo(context.Context, *PathRequest) (*ObjectInfo, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetObjectInfo not implemented")
}
func (UnimplementedBucketServiceServer) mustEmbedUnimplementedBucketServiceServer() {}
// UnsafeBucketServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to BucketServiceServer will
// result in compilation errors.
type UnsafeBucketServiceServer interface {
mustEmbedUnimplementedBucketServiceServer()
}
func RegisterBucketServiceServer(s grpc.ServiceRegistrar, srv BucketServiceServer) {
s.RegisterService(&BucketService_ServiceDesc, srv)
}
func _BucketService_GetAPIVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).GetAPIVersion(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/GetAPIVersion",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).GetAPIVersion(ctx, req.(*v1.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_BucketExists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BucketRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).BucketExists(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/BucketExists",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).BucketExists(ctx, req.(*BucketRequest))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_CreateBucket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BucketRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).CreateBucket(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/CreateBucket",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).CreateBucket(ctx, req.(*BucketRequest))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_DeleteBucket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BucketRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).DeleteBucket(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/DeleteBucket",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).DeleteBucket(ctx, req.(*BucketRequest))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_GetRepositoryURL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PathRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).GetRepositoryURL(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/GetRepositoryURL",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).GetRepositoryURL(ctx, req.(*PathRequest))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_DeletePath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PathRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).DeletePath(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/DeletePath",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).DeletePath(ctx, req.(*PathRequest))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_GetPathSize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PathRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).GetPathSize(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/GetPathSize",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).GetPathSize(ctx, req.(*PathRequest))
}
return interceptor(ctx, in, info, handler)
}
func _BucketService_ReadObject_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(PathRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(BucketServiceServer).ReadObject(m, &bucketServiceReadObjectServer{stream})
}
type BucketService_ReadObjectServer interface {
Send(*ReadObjectChunk) error
grpc.ServerStream
}
type bucketServiceReadObjectServer struct {
grpc.ServerStream
}
func (x *bucketServiceReadObjectServer) Send(m *ReadObjectChunk) error {
return x.ServerStream.SendMsg(m)
}
func _BucketService_WriteObject_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(BucketServiceServer).WriteObject(&bucketServiceWriteObjectServer{stream})
}
type BucketService_WriteObjectServer interface {
Send(*WriteObjectControl) error
Recv() (*WriteObjectChunk, error)
grpc.ServerStream
}
type bucketServiceWriteObjectServer struct {
grpc.ServerStream
}
func (x *bucketServiceWriteObjectServer) Send(m *WriteObjectControl) error {
return x.ServerStream.SendMsg(m)
}
func (x *bucketServiceWriteObjectServer) Recv() (*WriteObjectChunk, error) {
m := new(WriteObjectChunk)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _BucketService_GetObjectInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PathRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(BucketServiceServer).GetObjectInfo(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/arangodb.operator.ml.storage.v1.BucketService/GetObjectInfo",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(BucketServiceServer).GetObjectInfo(ctx, req.(*PathRequest))
}
return interceptor(ctx, in, info, handler)
}
// BucketService_ServiceDesc is the grpc.ServiceDesc for BucketService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var BucketService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "arangodb.operator.ml.storage.v1.BucketService",
HandlerType: (*BucketServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetAPIVersion",
Handler: _BucketService_GetAPIVersion_Handler,
},
{
MethodName: "BucketExists",
Handler: _BucketService_BucketExists_Handler,
},
{
MethodName: "CreateBucket",
Handler: _BucketService_CreateBucket_Handler,
},
{
MethodName: "DeleteBucket",
Handler: _BucketService_DeleteBucket_Handler,
},
{
MethodName: "GetRepositoryURL",
Handler: _BucketService_GetRepositoryURL_Handler,
},
{
MethodName: "DeletePath",
Handler: _BucketService_DeletePath_Handler,
},
{
MethodName: "GetPathSize",
Handler: _BucketService_GetPathSize_Handler,
},
{
MethodName: "GetObjectInfo",
Handler: _BucketService_GetObjectInfo_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "ReadObject",
Handler: _BucketService_ReadObject_Handler,
ServerStreams: true,
},
{
StreamName: "WriteObject",
Handler: _BucketService_WriteObject_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "pkg/api/ml/storage/v1/bucketservice.proto",
}

25
pkg/api/ml/storage/v1/version.go generated Normal file
View file

@ -0,0 +1,25 @@
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package v1
const (
VersionMajor = 1
VersionMinor = 0
VersionPatch = 0
)

43
pkg/ml/storage/s3/s3.go Normal file
View file

@ -0,0 +1,43 @@
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package s3
import (
"context"
pb "github.com/arangodb/kube-arangodb/pkg/api/ml/storage/v1"
)
type Config struct {
Endpoint string
AllowInsecure bool
CACrtFile string
CAKeyFile string
DisableSSL bool
Region string
BucketName string
AccessKeyFile string // path to file containing S3 AccessKey
SecretKeyFile string // path to file containing S3 SecretKey
}
type ShutdownableBucketServiceServer interface {
pb.BucketServiceServer
Shutdown(cancelFunc context.CancelFunc)
}

View file

@ -0,0 +1,32 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
//go:build !enterprise
package storage
import (
"context"
"errors"
)
func NewService(_ context.Context, _ StorageType, _ ServiceConfig) (Service, error) {
return nil, errors.New("this service is available only in enterprise edition of operator")
}

42
pkg/ml/storage/service.go Normal file
View file

@ -0,0 +1,42 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package storage
import (
"context"
"github.com/arangodb/kube-arangodb/pkg/ml/storage/s3"
)
type StorageType string
const (
StorageTypeS3Proxy = StorageType("s3")
)
type ServiceConfig struct {
ListenAddress string
S3 s3.Config
}
type Service interface {
Run(ctx context.Context) error
}

View file

@ -44,6 +44,9 @@ const (
SecretUsername = "username" // Key in Secret.data used to store a username used for basic authentication
SecretPassword = "password" // Key in Secret.data used to store a password used for basic authentication
SecretCredentialsAccessKey = "accessKey" // Key in Secret used to store an S3 API access key
SecretCredentialsSecretKey = "secretKey" // Key in Secret used to store an S3 API secret key
SecretAccessPackageYaml = "accessPackage.yaml" // Key in Secret.data used to store a YAML encoded access package
FinalizerDeplRemoveChildFinalizers = "database.arangodb.com/remove-child-finalizers" // Finalizer added to ArangoDeployment, indicating the need to remove finalizers from all children

151
pkg/util/fwatch/watcher.go Normal file
View file

@ -0,0 +1,151 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package fwatch
import (
"context"
"fmt"
"os"
"sync"
"k8s.io/utils/inotify"
"github.com/arangodb/kube-arangodb/pkg/logging"
)
const (
inotifyEventsModification = inotify.InCreate | inotify.InDelete | inotify.InDeleteSelf |
inotify.InCloseWrite | inotify.InMove | inotify.InMove | inotify.InMoveSelf | inotify.InUnmount
)
type FileContentWatcher interface {
// Start a routine to watch for file content changes. It will be stopped when context finishes
Start(ctx context.Context)
// IsChanged returns true if file content has been changed since last read
IsChanged() bool
// ReadAll tries to read all content from file
ReadAll() ([]byte, error)
}
type fileContentWatcher struct {
isRunning bool
p string
w *inotify.Watcher
log logging.Logger
changed bool
lock sync.RWMutex
}
// NewFileContentWatcher returns FileContentWatcher, which tracks changes in file
// Returns error if filePath is a directory.
// Caller must Close() the watcher once work finished.
func NewFileContentWatcher(filePath string, log logging.Logger) (FileContentWatcher, error) {
watcher, err := inotify.NewWatcher()
if err != nil {
return nil, fmt.Errorf("unable to setup inotify: %s", err)
}
err = watcher.AddWatch(filePath, inotifyEventsModification)
if err != nil {
return nil, fmt.Errorf("unable to AddWatch: %s", err)
}
// This returns an *os.FileInfo type
fileInfo, err := os.Stat(filePath)
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("unexpected err while Stat: %s", err)
}
if fileInfo.IsDir() {
return nil, fmt.Errorf("can't operator on directories")
}
fw := &fileContentWatcher{p: filePath, w: watcher, log: log, changed: true}
return fw, nil
}
func (fw *fileContentWatcher) Start(ctx context.Context) {
fw.isRunning = true
go func() {
defer func() {
fw.isRunning = false
}()
defer fw.w.Close()
fw.log.Info("Starting to watch for file content")
for {
select {
case <-ctx.Done():
err := fw.w.Close()
if err != nil {
fw.log.Err(err).Info("error while closing inotify watcher")
}
return
case err := <-fw.w.Error:
fw.log.Err(err).Debug("error while watching for file content")
case e := <-fw.w.Event:
fw.log.Info("changed: %s", e.String())
fw.markAsChanged()
if e.Mask&inotify.InIgnored == 0 {
// IN_IGNORED can happen if file is deleted
// restart watch:
err := fw.w.RemoveWatch(fw.p)
if err != nil {
fw.log.Err(err).Warn("RemoveWatch failed")
}
err = fw.w.AddWatch(fw.p, inotifyEventsModification)
if err != nil {
fw.log.Err(err).Error("Could not start watch again after getting IN_IGNORED")
}
}
}
}
}()
}
func (fw *fileContentWatcher) markAsChanged() {
fw.lock.Lock()
defer fw.lock.Unlock()
fw.changed = true
}
func (fw *fileContentWatcher) IsChanged() bool {
fw.lock.RLock()
defer fw.lock.RUnlock()
return fw.changed
}
func (fw *fileContentWatcher) ReadAll() ([]byte, error) {
fw.lock.Lock()
defer fw.lock.Unlock()
result, err := os.ReadFile(fw.p)
if err != nil {
return nil, err
}
fw.changed = false
return result, nil
}

View file

@ -0,0 +1,93 @@
//
// DISCLAIMER
//
// Copyright 2023 ArangoDB GmbH, Cologne, Germany
//
// 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 holder is ArangoDB GmbH, Cologne, Germany
//
package fwatch
import (
"context"
"os"
"path/filepath"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/arangodb/kube-arangodb/pkg/logging"
)
func Test_FileContentWatcher(t *testing.T) {
tempDir := os.TempDir()
filePath := filepath.Join(tempDir, uuid.New().String())
data := []byte("12345\n6789")
err := os.WriteFile(filePath, data, 0644)
require.NoError(t, err)
defer os.Remove(filePath)
fileWatcher, err := NewFileContentWatcher(filePath, logging.Global().Get("test"))
require.NoError(t, err)
w := fileWatcher.(*fileContentWatcher)
ctx, cancel := context.WithCancel(context.Background())
w.Start(ctx)
require.True(t, w.isRunning)
// must be initialized as "changed":
time.Sleep(time.Millisecond * 100)
require.True(t, w.IsChanged())
// must read correctly and "changed" updated
dataAct, err := w.ReadAll()
require.NoError(t, err)
require.Equal(t, data, dataAct)
require.False(t, w.IsChanged())
// change content
newData := []byte("9876543210")
err = os.WriteFile(filePath, newData, 0644)
require.NoError(t, err)
time.Sleep(time.Millisecond * 100)
require.True(t, w.IsChanged())
// read and compare again
dataAct, err = w.ReadAll()
require.NoError(t, err)
require.Equal(t, newData, dataAct)
require.False(t, w.IsChanged())
// recreate file with old data
err = os.Remove(filePath)
require.NoError(t, err)
err = os.WriteFile(filePath, data, 0644)
require.NoError(t, err)
time.Sleep(time.Millisecond * 100)
require.True(t, w.IsChanged())
dataAct, err = w.ReadAll()
require.NoError(t, err)
require.Equal(t, data, dataAct)
require.False(t, w.IsChanged())
// cancel context: watchers should be stopped
cancel()
time.Sleep(time.Millisecond * 100)
require.False(t, w.isRunning)
}