From 39952962dd0cf1d884264ba8de5c75690cc437fb Mon Sep 17 00:00:00 2001 From: Adam Janikowski <12255597+ajanikow@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:33:03 +0100 Subject: [PATCH] [Feature] [Platform] Chart Integration (#1766) --- .golangci.yaml | 4 + CHANGELOG.md | 1 + integrations/scheduler/v2/chart.go | 111 +++++ integrations/scheduler/v2/chart_test.go | 269 +++++++++++ .../scheduler/v2/definition/chart.pb.go | 457 ++++++++++++++++++ .../scheduler/v2/definition/chart.proto | 59 +++ .../scheduler/v2/definition/definition.pb.go | 263 +++++----- .../scheduler/v2/definition/definition.proto | 11 + .../v2/definition/definition_grpc.pb.go | 144 +++++- .../scheduler/v2/definition/kubernetes.pb.go | 299 +++++++++++- .../scheduler/v2/definition/kubernetes.proto | 40 ++ integrations/scheduler/v2/errors.go | 44 ++ .../scheduler/v2/implementation_test.go | 40 +- integrations/scheduler/v2/kubernetes.go | 31 +- integrations/scheduler/v2/suite_test.go | 20 +- integrations/storage/v2/definition/helpers.go | 50 +- integrations/storage/v2/storage_test.go | 15 +- pkg/apis/shared/v1/data.go | 8 +- pkg/apis/shared/v1/data_test.go | 37 ++ .../generators/kubernetes/arango_platform.go | 5 + .../kubernetes/arango_platform_c.go | 73 +++ pkg/deployment/deployment_suite_test.go | 2 +- pkg/deployment/resources/arango_profiles.go | 5 +- pkg/util/grpc/stream.go | 87 ++++ pkg/util/json.go | 60 +++ pkg/util/k8sutil/helm/chart_manager.go | 252 ++++++++++ pkg/util/k8sutil/helm/chart_manager_test.go | 83 ++++ pkg/util/kclient/client_factory.go | 3 +- pkg/util/kclient/fake.go | 6 +- pkg/util/mod.go | 49 ++ pkg/util/next.go | 27 ++ pkg/util/refs.go | 29 -- 32 files changed, 2341 insertions(+), 243 deletions(-) create mode 100644 integrations/scheduler/v2/chart.go create mode 100644 integrations/scheduler/v2/chart_test.go create mode 100644 integrations/scheduler/v2/definition/chart.pb.go create mode 100644 integrations/scheduler/v2/definition/chart.proto create mode 100644 integrations/scheduler/v2/errors.go create mode 100644 pkg/apis/shared/v1/data_test.go create mode 100644 pkg/debug_package/generators/kubernetes/arango_platform_c.go create mode 100644 pkg/util/grpc/stream.go create mode 100644 pkg/util/json.go create mode 100644 pkg/util/k8sutil/helm/chart_manager.go create mode 100644 pkg/util/k8sutil/helm/chart_manager_test.go create mode 100644 pkg/util/mod.go create mode 100644 pkg/util/next.go diff --git a/.golangci.yaml b/.golangci.yaml index 4a55daca8..0e13e8a3f 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -45,6 +45,10 @@ linters-settings: pkg: github.com/arangodb/kube-arangodb/integrations/scheduler/v1 - alias: pbSchedulerV1 pkg: github.com/arangodb/kube-arangodb/integrations/scheduler/v1/definition + - alias: pbImplSchedulerV2 + pkg: github.com/arangodb/kube-arangodb/integrations/scheduler/v2 + - alias: pbSchedulerV2 + pkg: github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition - alias: pbImplSharedV1 pkg: github.com/arangodb/kube-arangodb/integrations/shared/v1 - alias: pbSharedV1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 907f12b23..029687bcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - (Maintenance) Extract GRPC Client Package - (Feature) (Platform) Chart - (Feature) (Scheduler) Deployment Scale Functionality +- (Feature) (Platform) Chart Integration ## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14) - (Feature) ArangoRoute CRD diff --git a/integrations/scheduler/v2/chart.go b/integrations/scheduler/v2/chart.go new file mode 100644 index 000000000..0107ba2ae --- /dev/null +++ b/integrations/scheduler/v2/chart.go @@ -0,0 +1,111 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 v2 + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + + pbSchedulerV2 "github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition" + platformApi "github.com/arangodb/kube-arangodb/pkg/apis/platform/v1alpha1" + "github.com/arangodb/kube-arangodb/pkg/util" +) + +func (i *implementation) ListCharts(req *pbSchedulerV2.SchedulerV2ListChartsRequest, server pbSchedulerV2.SchedulerV2_ListChartsServer) error { + ctx := server.Context() + + var ct string + + for { + resp, err := i.client.Client().Arango().PlatformV1alpha1().ArangoPlatformCharts(i.client.Namespace()).List(ctx, meta.ListOptions{ + Limit: util.OptionalType(req.Items, 128), + Continue: ct, + }) + if err != nil { + logger.Err(err).Warn("Unable to run action: ListCharts") + return asGRPCError(err) + } + + var res pbSchedulerV2.SchedulerV2ListChartsResponse + + for _, item := range resp.Items { + res.Charts = append(res.Charts, item.GetName()) + } + + if err := server.Send(&res); err != nil { + logger.Err(err).Warn("Unable to send action response: ListCharts") + return err + } + + if resp.Continue == "" { + return nil + } + + ct = resp.Continue + } +} + +func (i *implementation) GetChart(ctx context.Context, in *pbSchedulerV2.SchedulerV2GetChartRequest) (*pbSchedulerV2.SchedulerV2GetChartResponse, error) { + resp, err := i.client.Client().Arango().PlatformV1alpha1().ArangoPlatformCharts(i.client.Namespace()).Get(ctx, in.GetName(), meta.GetOptions{}) + if err != nil { + logger.Err(err).Warn("Unable to run action: GetChart") + return nil, asGRPCError(err) + } + + if !resp.Status.Conditions.IsTrue(platformApi.SpecValidCondition) { + return nil, status.Errorf(codes.Unavailable, "Chart Spec is invalid") + } + + if info := resp.Status.Info; info == nil { + return nil, status.Errorf(codes.Unavailable, "Chart Infos are missing") + } else { + if !info.Valid { + if msg := info.Message; msg == "" { + return nil, status.Errorf(codes.Unavailable, "Chart is not Valid") + } else { + return nil, status.Errorf(codes.Unavailable, "Chart is not Valid: %s", msg) + } + } else { + if details := info.Details; details == nil { + return nil, status.Errorf(codes.Unavailable, "Chart Details are missing") + } else { + return &pbSchedulerV2.SchedulerV2GetChartResponse{ + Chart: info.Definition, + Info: chartInfoDetailsAsInfo(details), + }, nil + } + } + } +} + +func chartInfoDetailsAsInfo(in *platformApi.ChartDetails) *pbSchedulerV2.SchedulerV2ChartInfo { + if in == nil { + return nil + } + + return &pbSchedulerV2.SchedulerV2ChartInfo{ + Name: in.Name, + Version: in.Version, + } +} diff --git a/integrations/scheduler/v2/chart_test.go b/integrations/scheduler/v2/chart_test.go new file mode 100644 index 000000000..512b6fcce --- /dev/null +++ b/integrations/scheduler/v2/chart_test.go @@ -0,0 +1,269 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 v2 + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + core "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + + pbSchedulerV2 "github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition" + api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" + platformApi "github.com/arangodb/kube-arangodb/pkg/apis/platform/v1alpha1" + "github.com/arangodb/kube-arangodb/pkg/util" + ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc" + "github.com/arangodb/kube-arangodb/pkg/util/tests" + "github.com/arangodb/kube-arangodb/pkg/util/tests/tgrpc" +) + +func Test_Chart_List(t *testing.T) { + ctx, c := context.WithCancel(context.Background()) + defer c() + + scheduler, h := InternalClient(t, ctx, func(c Configuration) Configuration { + c.Namespace = tests.FakeNamespace + c.Deployment = tests.FakeNamespace + return c + }) + + t.Run("Create Charts", func(t *testing.T) { + for i := 0; i < 1024; i++ { + _, err := h.Client().Arango().PlatformV1alpha1().ArangoPlatformCharts(tests.FakeNamespace).Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: fmt.Sprintf("chart-%05d", i), + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{ + Conditions: []api.Condition{ + { + Type: platformApi.SpecValidCondition, + Status: core.ConditionTrue, + }, + }, + Info: &platformApi.ChartStatusInfo{ + Definition: make([]byte, 128), + Valid: true, + Details: &platformApi.ChartDetails{ + Name: fmt.Sprintf("chart-%05d", i), + Version: "1.2.3", + }, + }, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + } + }) + + t.Run("Try to get", func(t *testing.T) { + _, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{ + Name: "chart-00010", + }) + require.NoError(t, err) + }) + + t.Run("List by 128", func(t *testing.T) { + wr, err := scheduler.ListCharts(ctx, &pbSchedulerV2.SchedulerV2ListChartsRequest{ + Items: util.NewType[int64](128), + }) + require.NoError(t, err) + + var items []string + + require.NoError(t, ugrpc.Recv[*pbSchedulerV2.SchedulerV2ListChartsResponse](wr, func(response *pbSchedulerV2.SchedulerV2ListChartsResponse) error { + items = append(items, response.GetCharts()...) + return nil + })) + + require.Len(t, items, 1024) + }) +} + +func Test_Chart_Get(t *testing.T) { + ctx, c := context.WithCancel(context.Background()) + defer c() + + scheduler, h := InternalClient(t, ctx, func(c Configuration) Configuration { + c.Namespace = tests.FakeNamespace + c.Deployment = tests.FakeNamespace + return c + }) + + z := h.Client().Arango().PlatformV1alpha1().ArangoPlatformCharts(tests.FakeNamespace) + + t1, err := z.Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: "test-1", + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{}, + }, meta.CreateOptions{}) + require.NoError(t, err) + + t2, err := z.Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: "test-2", + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{ + Conditions: []api.Condition{ + { + Type: platformApi.SpecValidCondition, + Status: core.ConditionTrue, + }, + }, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + + t3, err := z.Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: "test-3", + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{ + Conditions: []api.Condition{ + { + Type: platformApi.SpecValidCondition, + Status: core.ConditionTrue, + }, + }, + Info: &platformApi.ChartStatusInfo{ + Valid: false, + }, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + + t4, err := z.Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: "test-4", + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{ + Conditions: []api.Condition{ + { + Type: platformApi.SpecValidCondition, + Status: core.ConditionTrue, + }, + }, + Info: &platformApi.ChartStatusInfo{ + Valid: false, + Message: "Invalid XxX", + }, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + + t5, err := z.Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: "test-5", + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{ + Conditions: []api.Condition{ + { + Type: platformApi.SpecValidCondition, + Status: core.ConditionTrue, + }, + }, + Info: &platformApi.ChartStatusInfo{ + Definition: make([]byte, 128), + Valid: true, + }, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + + t6, err := z.Create(context.Background(), &platformApi.ArangoPlatformChart{ + ObjectMeta: meta.ObjectMeta{ + Name: "test-6", + Namespace: tests.FakeNamespace, + }, + Status: platformApi.ArangoPlatformChartStatus{ + Conditions: []api.Condition{ + { + Type: platformApi.SpecValidCondition, + Status: core.ConditionTrue, + }, + }, + Info: &platformApi.ChartStatusInfo{ + Definition: make([]byte, 128), + Valid: true, + Details: &platformApi.ChartDetails{ + Name: "test-6", + Version: "1.2.3", + }, + }, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + + t.Run("Missing", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: "test-0"}) + tgrpc.AsGRPCError(t, err).Code(t, codes.NotFound).Errorf(t, "NotFound: arangoplatformcharts.platform.arangodb.com \"test-0\" not found") + require.Nil(t, resp) + }) + + t.Run("Invalid Spec", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: t1.GetName()}) + tgrpc.AsGRPCError(t, err).Code(t, codes.Unavailable).Errorf(t, "Chart Spec is invalid") + require.Nil(t, resp) + }) + + t.Run("Invalid Info", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: t2.GetName()}) + tgrpc.AsGRPCError(t, err).Code(t, codes.Unavailable).Errorf(t, "Chart Infos are missing") + require.Nil(t, resp) + }) + + t.Run("Invalid", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: t3.GetName()}) + tgrpc.AsGRPCError(t, err).Code(t, codes.Unavailable).Errorf(t, "Chart is not Valid") + require.Nil(t, resp) + }) + + t.Run("Invalid with message", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: t4.GetName()}) + tgrpc.AsGRPCError(t, err).Code(t, codes.Unavailable).Errorf(t, "Chart is not Valid: Invalid XxX") + require.Nil(t, resp) + }) + + t.Run("Valid with missing details", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: t5.GetName()}) + tgrpc.AsGRPCError(t, err).Code(t, codes.Unavailable).Errorf(t, "Chart Details are missing") + require.Nil(t, resp) + }) + + t.Run("Valid with details", func(t *testing.T) { + resp, err := scheduler.GetChart(context.Background(), &pbSchedulerV2.SchedulerV2GetChartRequest{Name: t6.GetName()}) + require.NoError(t, err) + require.NotNil(t, resp) + require.Len(t, resp.Chart, 128) + require.NotNil(t, resp.Info) + require.EqualValues(t, "test-6", resp.Info.Name) + require.EqualValues(t, "1.2.3", resp.Info.Version) + }) +} diff --git a/integrations/scheduler/v2/definition/chart.pb.go b/integrations/scheduler/v2/definition/chart.pb.go new file mode 100644 index 000000000..77d22e830 --- /dev/null +++ b/integrations/scheduler/v2/definition/chart.pb.go @@ -0,0 +1,457 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 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: integrations/scheduler/v2/definition/chart.proto + +package definition + +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) +) + +// Chart Info +type SchedulerV2ChartInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Chart Name + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Chart Version + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *SchedulerV2ChartInfo) Reset() { + *x = SchedulerV2ChartInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2ChartInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2ChartInfo) ProtoMessage() {} + +func (x *SchedulerV2ChartInfo) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_chart_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 SchedulerV2ChartInfo.ProtoReflect.Descriptor instead. +func (*SchedulerV2ChartInfo) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{0} +} + +func (x *SchedulerV2ChartInfo) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *SchedulerV2ChartInfo) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +// SchedulerV2 ListCharts Request +type SchedulerV2ListChartsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Maximum items per batch + Items *int64 `protobuf:"varint,1,opt,name=items,proto3,oneof" json:"items,omitempty"` +} + +func (x *SchedulerV2ListChartsRequest) Reset() { + *x = SchedulerV2ListChartsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2ListChartsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2ListChartsRequest) ProtoMessage() {} + +func (x *SchedulerV2ListChartsRequest) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_chart_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 SchedulerV2ListChartsRequest.ProtoReflect.Descriptor instead. +func (*SchedulerV2ListChartsRequest) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{1} +} + +func (x *SchedulerV2ListChartsRequest) GetItems() int64 { + if x != nil && x.Items != nil { + return *x.Items + } + return 0 +} + +// SchedulerV2 ListCharts Response +type SchedulerV2ListChartsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of the charts + Charts []string `protobuf:"bytes,1,rep,name=charts,proto3" json:"charts,omitempty"` +} + +func (x *SchedulerV2ListChartsResponse) Reset() { + *x = SchedulerV2ListChartsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2ListChartsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2ListChartsResponse) ProtoMessage() {} + +func (x *SchedulerV2ListChartsResponse) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_chart_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 SchedulerV2ListChartsResponse.ProtoReflect.Descriptor instead. +func (*SchedulerV2ListChartsResponse) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{2} +} + +func (x *SchedulerV2ListChartsResponse) GetCharts() []string { + if x != nil { + return x.Charts + } + return nil +} + +// SchedulerV2 GetChart Request +type SchedulerV2GetChartRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Chart Name + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *SchedulerV2GetChartRequest) Reset() { + *x = SchedulerV2GetChartRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2GetChartRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2GetChartRequest) ProtoMessage() {} + +func (x *SchedulerV2GetChartRequest) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_chart_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 SchedulerV2GetChartRequest.ProtoReflect.Descriptor instead. +func (*SchedulerV2GetChartRequest) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{3} +} + +func (x *SchedulerV2GetChartRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// SchedulerV2 GetChart Response +type SchedulerV2GetChartResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Chart Data + Chart []byte `protobuf:"bytes,1,opt,name=chart,proto3" json:"chart,omitempty"` + // Chart Info + Info *SchedulerV2ChartInfo `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` +} + +func (x *SchedulerV2GetChartResponse) Reset() { + *x = SchedulerV2GetChartResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2GetChartResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2GetChartResponse) ProtoMessage() {} + +func (x *SchedulerV2GetChartResponse) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_chart_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 SchedulerV2GetChartResponse.ProtoReflect.Descriptor instead. +func (*SchedulerV2GetChartResponse) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{4} +} + +func (x *SchedulerV2GetChartResponse) GetChart() []byte { + if x != nil { + return x.Chart + } + return nil +} + +func (x *SchedulerV2GetChartResponse) GetInfo() *SchedulerV2ChartInfo { + if x != nil { + return x.Info + } + return nil +} + +var File_integrations_scheduler_v2_definition_chart_proto protoreflect.FileDescriptor + +var file_integrations_scheduler_v2_definition_chart_proto_rawDesc = []byte{ + 0x0a, 0x30, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, + 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x09, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x22, 0x44, 0x0a, + 0x14, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x43, 0x0a, 0x1c, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x56, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x48, 0x00, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x88, 0x01, 0x01, 0x42, 0x08, + 0x0a, 0x06, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x37, 0x0a, 0x1d, 0x53, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, + 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x63, 0x68, 0x61, 0x72, 0x74, + 0x73, 0x22, 0x30, 0x0a, 0x1a, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x22, 0x68, 0x0a, 0x1b, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x56, 0x32, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x72, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x43, 0x68, + 0x61, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x42, 0x48, 0x5a, + 0x46, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, + 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x66, + 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_integrations_scheduler_v2_definition_chart_proto_rawDescOnce sync.Once + file_integrations_scheduler_v2_definition_chart_proto_rawDescData = file_integrations_scheduler_v2_definition_chart_proto_rawDesc +) + +func file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP() []byte { + file_integrations_scheduler_v2_definition_chart_proto_rawDescOnce.Do(func() { + file_integrations_scheduler_v2_definition_chart_proto_rawDescData = protoimpl.X.CompressGZIP(file_integrations_scheduler_v2_definition_chart_proto_rawDescData) + }) + return file_integrations_scheduler_v2_definition_chart_proto_rawDescData +} + +var file_integrations_scheduler_v2_definition_chart_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_integrations_scheduler_v2_definition_chart_proto_goTypes = []interface{}{ + (*SchedulerV2ChartInfo)(nil), // 0: scheduler.SchedulerV2ChartInfo + (*SchedulerV2ListChartsRequest)(nil), // 1: scheduler.SchedulerV2ListChartsRequest + (*SchedulerV2ListChartsResponse)(nil), // 2: scheduler.SchedulerV2ListChartsResponse + (*SchedulerV2GetChartRequest)(nil), // 3: scheduler.SchedulerV2GetChartRequest + (*SchedulerV2GetChartResponse)(nil), // 4: scheduler.SchedulerV2GetChartResponse +} +var file_integrations_scheduler_v2_definition_chart_proto_depIdxs = []int32{ + 0, // 0: scheduler.SchedulerV2GetChartResponse.info:type_name -> scheduler.SchedulerV2ChartInfo + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_integrations_scheduler_v2_definition_chart_proto_init() } +func file_integrations_scheduler_v2_definition_chart_proto_init() { + if File_integrations_scheduler_v2_definition_chart_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2ChartInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2ListChartsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2ListChartsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2GetChartRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2GetChartResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_integrations_scheduler_v2_definition_chart_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_integrations_scheduler_v2_definition_chart_proto_goTypes, + DependencyIndexes: file_integrations_scheduler_v2_definition_chart_proto_depIdxs, + MessageInfos: file_integrations_scheduler_v2_definition_chart_proto_msgTypes, + }.Build() + File_integrations_scheduler_v2_definition_chart_proto = out.File + file_integrations_scheduler_v2_definition_chart_proto_rawDesc = nil + file_integrations_scheduler_v2_definition_chart_proto_goTypes = nil + file_integrations_scheduler_v2_definition_chart_proto_depIdxs = nil +} diff --git a/integrations/scheduler/v2/definition/chart.proto b/integrations/scheduler/v2/definition/chart.proto new file mode 100644 index 000000000..7dad5cffb --- /dev/null +++ b/integrations/scheduler/v2/definition/chart.proto @@ -0,0 +1,59 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 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 scheduler; + +option go_package = "github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition"; + +// Chart Info +message SchedulerV2ChartInfo { + // Chart Name + string name = 1; + // Chart Version + string version = 2; +} + +// SchedulerV2 ListCharts Request +message SchedulerV2ListChartsRequest { + // Maximum items per batch + optional int64 items = 1; +} + +// SchedulerV2 ListCharts Response +message SchedulerV2ListChartsResponse { + // List of the charts + repeated string charts =1; +} + +// SchedulerV2 GetChart Request +message SchedulerV2GetChartRequest { + // Chart Name + string name = 1; +} + +// SchedulerV2 GetChart Response +message SchedulerV2GetChartResponse { + // Chart Data + bytes chart = 1; + // Chart Info + SchedulerV2ChartInfo info = 2; +} \ No newline at end of file diff --git a/integrations/scheduler/v2/definition/definition.pb.go b/integrations/scheduler/v2/definition/definition.pb.go index c97b551d4..8f5de8e1c 100644 --- a/integrations/scheduler/v2/definition/definition.pb.go +++ b/integrations/scheduler/v2/definition/definition.pb.go @@ -47,113 +47,143 @@ var file_integrations_scheduler_v2_definition_definition_proto_rawDesc = []byte{ 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, - 0x65, 0x72, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x65, 0x72, 0x1a, 0x30, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x6c, 0x6d, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x64, - 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, - 0x76, 0x31, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x6d, - 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xb5, 0x08, 0x0a, 0x0b, 0x53, 0x63, - 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x12, 0x2f, 0x0a, 0x0f, 0x49, 0x6e, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0d, 0x2e, 0x73, - 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x05, 0x41, 0x6c, - 0x69, 0x76, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x4d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x21, 0x2e, 0x73, 0x63, 0x68, 0x65, + 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x6c, 0x6d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, + 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6b, 0x75, 0x62, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x69, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2f, + 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x82, 0x0b, 0x0a, 0x0b, + 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x12, 0x2f, 0x0a, 0x0f, 0x49, + 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0d, + 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0d, 0x2e, + 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x05, + 0x41, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x21, 0x2e, 0x73, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, + 0x72, 0x56, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, + 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x2e, 0x73, + 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x56, 0x32, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, + 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x56, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x24, 0x2e, 0x73, + 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x56, 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, + 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x07, 0x55, 0x70, 0x67, + 0x72, 0x61, 0x64, 0x65, 0x12, 0x24, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x55, 0x70, 0x67, 0x72, + 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x56, 0x32, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x5c, 0x0a, 0x09, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x26, + 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, + 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x55, 0x6e, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4d, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x21, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, + 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x54, + 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x56, 0x32, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, + 0x0a, 0x14, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, - 0x32, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x73, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, - 0x65, 0x72, 0x56, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x2e, 0x73, 0x63, 0x68, - 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, - 0x56, 0x32, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, - 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, - 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x56, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x24, 0x2e, 0x73, 0x63, 0x68, - 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, - 0x56, 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, - 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x07, 0x55, 0x70, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x12, 0x24, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, - 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, - 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x5c, 0x0a, 0x09, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x26, 0x2e, 0x73, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, - 0x65, 0x72, 0x56, 0x32, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, - 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x55, 0x6e, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, - 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x21, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, - 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x54, 0x65, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, - 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, - 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, - 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, - 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x13, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x12, 0x30, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, - 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x32, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, + 0x13, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x4b, 0x75, 0x62, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x65, 0x73, 0x47, 0x65, 0x74, 0x12, 0x2a, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x50, 0x49, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x4b, 0x75, 0x62, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x47, 0x65, 0x74, 0x12, 0x2a, 0x2e, 0x73, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, + 0x56, 0x32, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, + 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4b, 0x75, + 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x19, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x65, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x36, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x73, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, + 0x32, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x61, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, 0x73, + 0x12, 0x27, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, + 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x73, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, + 0x32, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x12, 0x25, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x72, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, - 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, - 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4b, 0x75, 0x62, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x48, 0x5a, 0x46, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, - 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x48, 0x5a, 0x46, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var file_integrations_scheduler_v2_definition_definition_proto_goTypes = []interface{}{ - (*definition.Empty)(nil), // 0: shared.Empty - (*SchedulerV2ListRequest)(nil), // 1: scheduler.SchedulerV2ListRequest - (*SchedulerV2StatusRequest)(nil), // 2: scheduler.SchedulerV2StatusRequest - (*SchedulerV2StatusObjectsRequest)(nil), // 3: scheduler.SchedulerV2StatusObjectsRequest - (*SchedulerV2InstallRequest)(nil), // 4: scheduler.SchedulerV2InstallRequest - (*SchedulerV2UpgradeRequest)(nil), // 5: scheduler.SchedulerV2UpgradeRequest - (*SchedulerV2UninstallRequest)(nil), // 6: scheduler.SchedulerV2UninstallRequest - (*SchedulerV2TestRequest)(nil), // 7: scheduler.SchedulerV2TestRequest - (*SchedulerV2DiscoverAPIResourcesRequest)(nil), // 8: scheduler.SchedulerV2DiscoverAPIResourcesRequest - (*SchedulerV2DiscoverAPIResourceRequest)(nil), // 9: scheduler.SchedulerV2DiscoverAPIResourceRequest - (*SchedulerV2KubernetesGetRequest)(nil), // 10: scheduler.SchedulerV2KubernetesGetRequest - (*SchedulerV2ListResponse)(nil), // 11: scheduler.SchedulerV2ListResponse - (*SchedulerV2StatusResponse)(nil), // 12: scheduler.SchedulerV2StatusResponse - (*SchedulerV2StatusObjectsResponse)(nil), // 13: scheduler.SchedulerV2StatusObjectsResponse - (*SchedulerV2InstallResponse)(nil), // 14: scheduler.SchedulerV2InstallResponse - (*SchedulerV2UpgradeResponse)(nil), // 15: scheduler.SchedulerV2UpgradeResponse - (*SchedulerV2UninstallResponse)(nil), // 16: scheduler.SchedulerV2UninstallResponse - (*SchedulerV2TestResponse)(nil), // 17: scheduler.SchedulerV2TestResponse - (*SchedulerV2DiscoverAPIResourcesResponse)(nil), // 18: scheduler.SchedulerV2DiscoverAPIResourcesResponse - (*SchedulerV2DiscoverAPIResourceResponse)(nil), // 19: scheduler.SchedulerV2DiscoverAPIResourceResponse - (*SchedulerV2KubernetesGetResponse)(nil), // 20: scheduler.SchedulerV2KubernetesGetResponse + (*definition.Empty)(nil), // 0: shared.Empty + (*SchedulerV2ListRequest)(nil), // 1: scheduler.SchedulerV2ListRequest + (*SchedulerV2StatusRequest)(nil), // 2: scheduler.SchedulerV2StatusRequest + (*SchedulerV2StatusObjectsRequest)(nil), // 3: scheduler.SchedulerV2StatusObjectsRequest + (*SchedulerV2InstallRequest)(nil), // 4: scheduler.SchedulerV2InstallRequest + (*SchedulerV2UpgradeRequest)(nil), // 5: scheduler.SchedulerV2UpgradeRequest + (*SchedulerV2UninstallRequest)(nil), // 6: scheduler.SchedulerV2UninstallRequest + (*SchedulerV2TestRequest)(nil), // 7: scheduler.SchedulerV2TestRequest + (*SchedulerV2DiscoverAPIResourcesRequest)(nil), // 8: scheduler.SchedulerV2DiscoverAPIResourcesRequest + (*SchedulerV2DiscoverAPIResourceRequest)(nil), // 9: scheduler.SchedulerV2DiscoverAPIResourceRequest + (*SchedulerV2KubernetesGetRequest)(nil), // 10: scheduler.SchedulerV2KubernetesGetRequest + (*SchedulerV2KubernetesPermissionCheckRequest)(nil), // 11: scheduler.SchedulerV2KubernetesPermissionCheckRequest + (*SchedulerV2ListChartsRequest)(nil), // 12: scheduler.SchedulerV2ListChartsRequest + (*SchedulerV2GetChartRequest)(nil), // 13: scheduler.SchedulerV2GetChartRequest + (*SchedulerV2ListResponse)(nil), // 14: scheduler.SchedulerV2ListResponse + (*SchedulerV2StatusResponse)(nil), // 15: scheduler.SchedulerV2StatusResponse + (*SchedulerV2StatusObjectsResponse)(nil), // 16: scheduler.SchedulerV2StatusObjectsResponse + (*SchedulerV2InstallResponse)(nil), // 17: scheduler.SchedulerV2InstallResponse + (*SchedulerV2UpgradeResponse)(nil), // 18: scheduler.SchedulerV2UpgradeResponse + (*SchedulerV2UninstallResponse)(nil), // 19: scheduler.SchedulerV2UninstallResponse + (*SchedulerV2TestResponse)(nil), // 20: scheduler.SchedulerV2TestResponse + (*SchedulerV2DiscoverAPIResourcesResponse)(nil), // 21: scheduler.SchedulerV2DiscoverAPIResourcesResponse + (*SchedulerV2DiscoverAPIResourceResponse)(nil), // 22: scheduler.SchedulerV2DiscoverAPIResourceResponse + (*SchedulerV2KubernetesGetResponse)(nil), // 23: scheduler.SchedulerV2KubernetesGetResponse + (*SchedulerV2KubernetesPermissionCheckResponse)(nil), // 24: scheduler.SchedulerV2KubernetesPermissionCheckResponse + (*SchedulerV2ListChartsResponse)(nil), // 25: scheduler.SchedulerV2ListChartsResponse + (*SchedulerV2GetChartResponse)(nil), // 26: scheduler.SchedulerV2GetChartResponse } var file_integrations_scheduler_v2_definition_definition_proto_depIdxs = []int32{ 0, // 0: scheduler.SchedulerV2.InvalidateCache:input_type -> shared.Empty @@ -168,20 +198,26 @@ var file_integrations_scheduler_v2_definition_definition_proto_depIdxs = []int32 8, // 9: scheduler.SchedulerV2.DiscoverAPIResources:input_type -> scheduler.SchedulerV2DiscoverAPIResourcesRequest 9, // 10: scheduler.SchedulerV2.DiscoverAPIResource:input_type -> scheduler.SchedulerV2DiscoverAPIResourceRequest 10, // 11: scheduler.SchedulerV2.KubernetesGet:input_type -> scheduler.SchedulerV2KubernetesGetRequest - 0, // 12: scheduler.SchedulerV2.InvalidateCache:output_type -> shared.Empty - 0, // 13: scheduler.SchedulerV2.Alive:output_type -> shared.Empty - 11, // 14: scheduler.SchedulerV2.List:output_type -> scheduler.SchedulerV2ListResponse - 12, // 15: scheduler.SchedulerV2.Status:output_type -> scheduler.SchedulerV2StatusResponse - 13, // 16: scheduler.SchedulerV2.StatusObjects:output_type -> scheduler.SchedulerV2StatusObjectsResponse - 14, // 17: scheduler.SchedulerV2.Install:output_type -> scheduler.SchedulerV2InstallResponse - 15, // 18: scheduler.SchedulerV2.Upgrade:output_type -> scheduler.SchedulerV2UpgradeResponse - 16, // 19: scheduler.SchedulerV2.Uninstall:output_type -> scheduler.SchedulerV2UninstallResponse - 17, // 20: scheduler.SchedulerV2.Test:output_type -> scheduler.SchedulerV2TestResponse - 18, // 21: scheduler.SchedulerV2.DiscoverAPIResources:output_type -> scheduler.SchedulerV2DiscoverAPIResourcesResponse - 19, // 22: scheduler.SchedulerV2.DiscoverAPIResource:output_type -> scheduler.SchedulerV2DiscoverAPIResourceResponse - 20, // 23: scheduler.SchedulerV2.KubernetesGet:output_type -> scheduler.SchedulerV2KubernetesGetResponse - 12, // [12:24] is the sub-list for method output_type - 0, // [0:12] is the sub-list for method input_type + 11, // 12: scheduler.SchedulerV2.KubernetesPermissionCheck:input_type -> scheduler.SchedulerV2KubernetesPermissionCheckRequest + 12, // 13: scheduler.SchedulerV2.ListCharts:input_type -> scheduler.SchedulerV2ListChartsRequest + 13, // 14: scheduler.SchedulerV2.GetChart:input_type -> scheduler.SchedulerV2GetChartRequest + 0, // 15: scheduler.SchedulerV2.InvalidateCache:output_type -> shared.Empty + 0, // 16: scheduler.SchedulerV2.Alive:output_type -> shared.Empty + 14, // 17: scheduler.SchedulerV2.List:output_type -> scheduler.SchedulerV2ListResponse + 15, // 18: scheduler.SchedulerV2.Status:output_type -> scheduler.SchedulerV2StatusResponse + 16, // 19: scheduler.SchedulerV2.StatusObjects:output_type -> scheduler.SchedulerV2StatusObjectsResponse + 17, // 20: scheduler.SchedulerV2.Install:output_type -> scheduler.SchedulerV2InstallResponse + 18, // 21: scheduler.SchedulerV2.Upgrade:output_type -> scheduler.SchedulerV2UpgradeResponse + 19, // 22: scheduler.SchedulerV2.Uninstall:output_type -> scheduler.SchedulerV2UninstallResponse + 20, // 23: scheduler.SchedulerV2.Test:output_type -> scheduler.SchedulerV2TestResponse + 21, // 24: scheduler.SchedulerV2.DiscoverAPIResources:output_type -> scheduler.SchedulerV2DiscoverAPIResourcesResponse + 22, // 25: scheduler.SchedulerV2.DiscoverAPIResource:output_type -> scheduler.SchedulerV2DiscoverAPIResourceResponse + 23, // 26: scheduler.SchedulerV2.KubernetesGet:output_type -> scheduler.SchedulerV2KubernetesGetResponse + 24, // 27: scheduler.SchedulerV2.KubernetesPermissionCheck:output_type -> scheduler.SchedulerV2KubernetesPermissionCheckResponse + 25, // 28: scheduler.SchedulerV2.ListCharts:output_type -> scheduler.SchedulerV2ListChartsResponse + 26, // 29: scheduler.SchedulerV2.GetChart:output_type -> scheduler.SchedulerV2GetChartResponse + 15, // [15:30] is the sub-list for method output_type + 0, // [0:15] 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 @@ -192,6 +228,7 @@ func file_integrations_scheduler_v2_definition_definition_proto_init() { if File_integrations_scheduler_v2_definition_definition_proto != nil { return } + file_integrations_scheduler_v2_definition_chart_proto_init() file_integrations_scheduler_v2_definition_helm_proto_init() file_integrations_scheduler_v2_definition_kubernetes_proto_init() type x struct{} diff --git a/integrations/scheduler/v2/definition/definition.proto b/integrations/scheduler/v2/definition/definition.proto index 284d1bf51..8d8426c1e 100644 --- a/integrations/scheduler/v2/definition/definition.proto +++ b/integrations/scheduler/v2/definition/definition.proto @@ -22,6 +22,7 @@ syntax = "proto3"; package scheduler; +import "integrations/scheduler/v2/definition/chart.proto"; import "integrations/scheduler/v2/definition/helm.proto"; import "integrations/scheduler/v2/definition/kubernetes.proto"; import "integrations/shared/v1/definition/empty.proto"; @@ -57,5 +58,15 @@ service SchedulerV2 { // Gets Kubernetes objects from the API rpc KubernetesGet(SchedulerV2KubernetesGetRequest) returns (SchedulerV2KubernetesGetResponse); + + // Checks if principal can take an action + rpc KubernetesPermissionCheck(SchedulerV2KubernetesPermissionCheckRequest) + returns (SchedulerV2KubernetesPermissionCheckResponse); + + // Lists installed ArangoPlatform Charts + rpc ListCharts(SchedulerV2ListChartsRequest) returns (stream SchedulerV2ListChartsResponse); + + // Gets Installed ArangoDB Chart + rpc GetChart(SchedulerV2GetChartRequest) returns (SchedulerV2GetChartResponse); } diff --git a/integrations/scheduler/v2/definition/definition_grpc.pb.go b/integrations/scheduler/v2/definition/definition_grpc.pb.go index 75805fdf8..122f3bf76 100644 --- a/integrations/scheduler/v2/definition/definition_grpc.pb.go +++ b/integrations/scheduler/v2/definition/definition_grpc.pb.go @@ -47,6 +47,12 @@ type SchedulerV2Client interface { DiscoverAPIResource(ctx context.Context, in *SchedulerV2DiscoverAPIResourceRequest, opts ...grpc.CallOption) (*SchedulerV2DiscoverAPIResourceResponse, error) // Gets Kubernetes objects from the API KubernetesGet(ctx context.Context, in *SchedulerV2KubernetesGetRequest, opts ...grpc.CallOption) (*SchedulerV2KubernetesGetResponse, error) + // Checks if principal can take an action + KubernetesPermissionCheck(ctx context.Context, in *SchedulerV2KubernetesPermissionCheckRequest, opts ...grpc.CallOption) (*SchedulerV2KubernetesPermissionCheckResponse, error) + // Lists installed ArangoPlatform Charts + ListCharts(ctx context.Context, in *SchedulerV2ListChartsRequest, opts ...grpc.CallOption) (SchedulerV2_ListChartsClient, error) + // Gets Installed ArangoDB Chart + GetChart(ctx context.Context, in *SchedulerV2GetChartRequest, opts ...grpc.CallOption) (*SchedulerV2GetChartResponse, error) } type schedulerV2Client struct { @@ -165,6 +171,56 @@ func (c *schedulerV2Client) KubernetesGet(ctx context.Context, in *SchedulerV2Ku return out, nil } +func (c *schedulerV2Client) KubernetesPermissionCheck(ctx context.Context, in *SchedulerV2KubernetesPermissionCheckRequest, opts ...grpc.CallOption) (*SchedulerV2KubernetesPermissionCheckResponse, error) { + out := new(SchedulerV2KubernetesPermissionCheckResponse) + err := c.cc.Invoke(ctx, "/scheduler.SchedulerV2/KubernetesPermissionCheck", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *schedulerV2Client) ListCharts(ctx context.Context, in *SchedulerV2ListChartsRequest, opts ...grpc.CallOption) (SchedulerV2_ListChartsClient, error) { + stream, err := c.cc.NewStream(ctx, &SchedulerV2_ServiceDesc.Streams[0], "/scheduler.SchedulerV2/ListCharts", opts...) + if err != nil { + return nil, err + } + x := &schedulerV2ListChartsClient{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 SchedulerV2_ListChartsClient interface { + Recv() (*SchedulerV2ListChartsResponse, error) + grpc.ClientStream +} + +type schedulerV2ListChartsClient struct { + grpc.ClientStream +} + +func (x *schedulerV2ListChartsClient) Recv() (*SchedulerV2ListChartsResponse, error) { + m := new(SchedulerV2ListChartsResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *schedulerV2Client) GetChart(ctx context.Context, in *SchedulerV2GetChartRequest, opts ...grpc.CallOption) (*SchedulerV2GetChartResponse, error) { + out := new(SchedulerV2GetChartResponse) + err := c.cc.Invoke(ctx, "/scheduler.SchedulerV2/GetChart", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // SchedulerV2Server is the server API for SchedulerV2 service. // All implementations must embed UnimplementedSchedulerV2Server // for forward compatibility @@ -193,6 +249,12 @@ type SchedulerV2Server interface { DiscoverAPIResource(context.Context, *SchedulerV2DiscoverAPIResourceRequest) (*SchedulerV2DiscoverAPIResourceResponse, error) // Gets Kubernetes objects from the API KubernetesGet(context.Context, *SchedulerV2KubernetesGetRequest) (*SchedulerV2KubernetesGetResponse, error) + // Checks if principal can take an action + KubernetesPermissionCheck(context.Context, *SchedulerV2KubernetesPermissionCheckRequest) (*SchedulerV2KubernetesPermissionCheckResponse, error) + // Lists installed ArangoPlatform Charts + ListCharts(*SchedulerV2ListChartsRequest, SchedulerV2_ListChartsServer) error + // Gets Installed ArangoDB Chart + GetChart(context.Context, *SchedulerV2GetChartRequest) (*SchedulerV2GetChartResponse, error) mustEmbedUnimplementedSchedulerV2Server() } @@ -236,6 +298,15 @@ func (UnimplementedSchedulerV2Server) DiscoverAPIResource(context.Context, *Sche func (UnimplementedSchedulerV2Server) KubernetesGet(context.Context, *SchedulerV2KubernetesGetRequest) (*SchedulerV2KubernetesGetResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method KubernetesGet not implemented") } +func (UnimplementedSchedulerV2Server) KubernetesPermissionCheck(context.Context, *SchedulerV2KubernetesPermissionCheckRequest) (*SchedulerV2KubernetesPermissionCheckResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method KubernetesPermissionCheck not implemented") +} +func (UnimplementedSchedulerV2Server) ListCharts(*SchedulerV2ListChartsRequest, SchedulerV2_ListChartsServer) error { + return status.Errorf(codes.Unimplemented, "method ListCharts not implemented") +} +func (UnimplementedSchedulerV2Server) GetChart(context.Context, *SchedulerV2GetChartRequest) (*SchedulerV2GetChartResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetChart not implemented") +} func (UnimplementedSchedulerV2Server) mustEmbedUnimplementedSchedulerV2Server() {} // UnsafeSchedulerV2Server may be embedded to opt out of forward compatibility for this service. @@ -465,6 +536,63 @@ func _SchedulerV2_KubernetesGet_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _SchedulerV2_KubernetesPermissionCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SchedulerV2KubernetesPermissionCheckRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SchedulerV2Server).KubernetesPermissionCheck(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/scheduler.SchedulerV2/KubernetesPermissionCheck", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SchedulerV2Server).KubernetesPermissionCheck(ctx, req.(*SchedulerV2KubernetesPermissionCheckRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SchedulerV2_ListCharts_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SchedulerV2ListChartsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(SchedulerV2Server).ListCharts(m, &schedulerV2ListChartsServer{stream}) +} + +type SchedulerV2_ListChartsServer interface { + Send(*SchedulerV2ListChartsResponse) error + grpc.ServerStream +} + +type schedulerV2ListChartsServer struct { + grpc.ServerStream +} + +func (x *schedulerV2ListChartsServer) Send(m *SchedulerV2ListChartsResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _SchedulerV2_GetChart_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SchedulerV2GetChartRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SchedulerV2Server).GetChart(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/scheduler.SchedulerV2/GetChart", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SchedulerV2Server).GetChart(ctx, req.(*SchedulerV2GetChartRequest)) + } + return interceptor(ctx, in, info, handler) +} + // SchedulerV2_ServiceDesc is the grpc.ServiceDesc for SchedulerV2 service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -520,7 +648,21 @@ var SchedulerV2_ServiceDesc = grpc.ServiceDesc{ MethodName: "KubernetesGet", Handler: _SchedulerV2_KubernetesGet_Handler, }, + { + MethodName: "KubernetesPermissionCheck", + Handler: _SchedulerV2_KubernetesPermissionCheck_Handler, + }, + { + MethodName: "GetChart", + Handler: _SchedulerV2_GetChart_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "ListCharts", + Handler: _SchedulerV2_ListCharts_Handler, + ServerStreams: true, + }, }, - Streams: []grpc.StreamDesc{}, Metadata: "integrations/scheduler/v2/definition/definition.proto", } diff --git a/integrations/scheduler/v2/definition/kubernetes.pb.go b/integrations/scheduler/v2/definition/kubernetes.pb.go index c1bee3050..f305b89f2 100644 --- a/integrations/scheduler/v2/definition/kubernetes.pb.go +++ b/integrations/scheduler/v2/definition/kubernetes.pb.go @@ -491,6 +491,195 @@ func (x *SchedulerV2KubernetesGetResponse) GetObjects() []*SchedulerV2ReleaseInf return nil } +// SchedulerV2 KubernetesPermissionCheck Request +type SchedulerV2KubernetesPermissionCheckRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. "*" means all. + Verb string `protobuf:"bytes,1,opt,name=verb,proto3" json:"verb,omitempty"` + // Group is the API Group of the Resource. "*" means all. + Group string `protobuf:"bytes,2,opt,name=group,proto3" json:"group,omitempty"` + // Version is the API Version of the Resource. "*" means all. + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + // Resource is one of the existing resource types. "*" means all. + Resource string `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` + // Subresource is one of the existing resource types. "" means none. + SubResource string `protobuf:"bytes,5,opt,name=sub_resource,json=subResource,proto3" json:"sub_resource,omitempty"` + // Name is the name of the resource being requested for a "get" or deleted for a "delete". "" (empty) means all. + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + // Namespace is the namespace of the action being requested. + // "" (empty) is defaulted for LocalSubjectAccessReviews + // "" (empty) is empty for cluster-scoped resources + // "" (empty) means "all" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview + // Defaults to the current namespace + Namespace *string `protobuf:"bytes,7,opt,name=namespace,proto3,oneof" json:"namespace,omitempty"` +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) Reset() { + *x = SchedulerV2KubernetesPermissionCheckRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2KubernetesPermissionCheckRequest) ProtoMessage() {} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_kubernetes_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 SchedulerV2KubernetesPermissionCheckRequest.ProtoReflect.Descriptor instead. +func (*SchedulerV2KubernetesPermissionCheckRequest) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_kubernetes_proto_rawDescGZIP(), []int{7} +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetVerb() string { + if x != nil { + return x.Verb + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetGroup() string { + if x != nil { + return x.Group + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetResource() string { + if x != nil { + return x.Resource + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetSubResource() string { + if x != nil { + return x.SubResource + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckRequest) GetNamespace() string { + if x != nil && x.Namespace != nil { + return *x.Namespace + } + return "" +} + +// SchedulerV2 KubernetesPermissionCheck Response +type SchedulerV2KubernetesPermissionCheckResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Allowed is required. True if the action would be allowed, false otherwise. + Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` + // Denied is optional. True if the action would be denied, otherwise + // false. If both allowed is false and denied is false, then the + // authorizer has no opinion on whether to authorize the action. Denied + // may not be true if Allowed is true. + // +optional + Denied *bool `protobuf:"varint,2,opt,name=denied,proto3,oneof" json:"denied,omitempty"` + // Reason is optional. It indicates why a request was allowed or denied. + Reason *string `protobuf:"bytes,3,opt,name=reason,proto3,oneof" json:"reason,omitempty"` + // EvaluationError is an indication that some error occurred during the authorization check. + // It is entirely possible to get an error and be able to continue determine authorization status in spite of it. + // For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request. + EvaluationError *string `protobuf:"bytes,4,opt,name=evaluation_error,json=evaluationError,proto3,oneof" json:"evaluation_error,omitempty"` +} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) Reset() { + *x = SchedulerV2KubernetesPermissionCheckResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2KubernetesPermissionCheckResponse) ProtoMessage() {} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) ProtoReflect() protoreflect.Message { + mi := &file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[8] + 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 SchedulerV2KubernetesPermissionCheckResponse.ProtoReflect.Descriptor instead. +func (*SchedulerV2KubernetesPermissionCheckResponse) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_kubernetes_proto_rawDescGZIP(), []int{8} +} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) GetAllowed() bool { + if x != nil { + return x.Allowed + } + return false +} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) GetDenied() bool { + if x != nil && x.Denied != nil { + return *x.Denied + } + return false +} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) GetReason() string { + if x != nil && x.Reason != nil { + return *x.Reason + } + return "" +} + +func (x *SchedulerV2KubernetesPermissionCheckResponse) GetEvaluationError() string { + if x != nil && x.EvaluationError != nil { + return *x.EvaluationError + } + return "" +} + var File_integrations_scheduler_v2_definition_kubernetes_proto protoreflect.FileDescriptor var file_integrations_scheduler_v2_definition_kubernetes_proto_rawDesc = []byte{ @@ -563,12 +752,42 @@ var file_integrations_scheduler_v2_definition_kubernetes_proto_rawDesc = []byte{ 0x2f, 0x2e, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x48, 0x5a, 0x46, 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, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, - 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0xf5, 0x01, 0x0a, 0x2b, 0x53, 0x63, + 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x65, 0x72, + 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x65, 0x72, 0x62, 0x12, 0x14, 0x0a, + 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, + 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x75, 0x62, + 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x73, 0x75, 0x62, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x21, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x22, 0xdd, 0x01, 0x0a, 0x2c, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, + 0x32, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x06, + 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, + 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x02, 0x52, 0x0f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x64, 0x65, 0x6e, 0x69, 0x65, + 0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x13, 0x0a, 0x11, + 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x42, 0x48, 0x5a, 0x46, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x2f, 0x76, 0x32, + 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -583,28 +802,30 @@ func file_integrations_scheduler_v2_definition_kubernetes_proto_rawDescGZIP() [] return file_integrations_scheduler_v2_definition_kubernetes_proto_rawDescData } -var file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_integrations_scheduler_v2_definition_kubernetes_proto_goTypes = []interface{}{ - (*SchedulerV2DiscoverAPIResourcesRequest)(nil), // 0: scheduler.SchedulerV2DiscoverAPIResourcesRequest - (*SchedulerV2DiscoverAPIResourcesResponse)(nil), // 1: scheduler.SchedulerV2DiscoverAPIResourcesResponse - (*SchedulerV2DiscoverAPIResourceRequest)(nil), // 2: scheduler.SchedulerV2DiscoverAPIResourceRequest - (*SchedulerV2DiscoverAPIResourceResponse)(nil), // 3: scheduler.SchedulerV2DiscoverAPIResourceResponse - (*SchedulerV2DiscoverAPIResource)(nil), // 4: scheduler.SchedulerV2DiscoverAPIResource - (*SchedulerV2KubernetesGetRequest)(nil), // 5: scheduler.SchedulerV2KubernetesGetRequest - (*SchedulerV2KubernetesGetResponse)(nil), // 6: scheduler.SchedulerV2KubernetesGetResponse - (*SchedulerV2ReleaseInfoResource)(nil), // 7: scheduler.SchedulerV2ReleaseInfoResource - (*SchedulerV2ReleaseInfoResourceObject)(nil), // 8: scheduler.SchedulerV2ReleaseInfoResourceObject + (*SchedulerV2DiscoverAPIResourcesRequest)(nil), // 0: scheduler.SchedulerV2DiscoverAPIResourcesRequest + (*SchedulerV2DiscoverAPIResourcesResponse)(nil), // 1: scheduler.SchedulerV2DiscoverAPIResourcesResponse + (*SchedulerV2DiscoverAPIResourceRequest)(nil), // 2: scheduler.SchedulerV2DiscoverAPIResourceRequest + (*SchedulerV2DiscoverAPIResourceResponse)(nil), // 3: scheduler.SchedulerV2DiscoverAPIResourceResponse + (*SchedulerV2DiscoverAPIResource)(nil), // 4: scheduler.SchedulerV2DiscoverAPIResource + (*SchedulerV2KubernetesGetRequest)(nil), // 5: scheduler.SchedulerV2KubernetesGetRequest + (*SchedulerV2KubernetesGetResponse)(nil), // 6: scheduler.SchedulerV2KubernetesGetResponse + (*SchedulerV2KubernetesPermissionCheckRequest)(nil), // 7: scheduler.SchedulerV2KubernetesPermissionCheckRequest + (*SchedulerV2KubernetesPermissionCheckResponse)(nil), // 8: scheduler.SchedulerV2KubernetesPermissionCheckResponse + (*SchedulerV2ReleaseInfoResource)(nil), // 9: scheduler.SchedulerV2ReleaseInfoResource + (*SchedulerV2ReleaseInfoResourceObject)(nil), // 10: scheduler.SchedulerV2ReleaseInfoResourceObject } var file_integrations_scheduler_v2_definition_kubernetes_proto_depIdxs = []int32{ - 4, // 0: scheduler.SchedulerV2DiscoverAPIResourcesResponse.resources:type_name -> scheduler.SchedulerV2DiscoverAPIResource - 4, // 1: scheduler.SchedulerV2DiscoverAPIResourceResponse.resource:type_name -> scheduler.SchedulerV2DiscoverAPIResource - 7, // 2: scheduler.SchedulerV2KubernetesGetRequest.resources:type_name -> scheduler.SchedulerV2ReleaseInfoResource - 8, // 3: scheduler.SchedulerV2KubernetesGetResponse.objects:type_name -> scheduler.SchedulerV2ReleaseInfoResourceObject - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 4, // 0: scheduler.SchedulerV2DiscoverAPIResourcesResponse.resources:type_name -> scheduler.SchedulerV2DiscoverAPIResource + 4, // 1: scheduler.SchedulerV2DiscoverAPIResourceResponse.resource:type_name -> scheduler.SchedulerV2DiscoverAPIResource + 9, // 2: scheduler.SchedulerV2KubernetesGetRequest.resources:type_name -> scheduler.SchedulerV2ReleaseInfoResource + 10, // 3: scheduler.SchedulerV2KubernetesGetResponse.objects:type_name -> scheduler.SchedulerV2ReleaseInfoResourceObject + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_integrations_scheduler_v2_definition_kubernetes_proto_init() } @@ -698,15 +919,41 @@ func file_integrations_scheduler_v2_definition_kubernetes_proto_init() { return nil } } + file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2KubernetesPermissionCheckRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchedulerV2KubernetesPermissionCheckResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[3].OneofWrappers = []interface{}{} + file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[7].OneofWrappers = []interface{}{} + file_integrations_scheduler_v2_definition_kubernetes_proto_msgTypes[8].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_integrations_scheduler_v2_definition_kubernetes_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/integrations/scheduler/v2/definition/kubernetes.proto b/integrations/scheduler/v2/definition/kubernetes.proto index 34248f77e..7f13d5718 100644 --- a/integrations/scheduler/v2/definition/kubernetes.proto +++ b/integrations/scheduler/v2/definition/kubernetes.proto @@ -90,4 +90,44 @@ message SchedulerV2KubernetesGetRequest { message SchedulerV2KubernetesGetResponse { // Kubernetes API Objects repeated SchedulerV2ReleaseInfoResourceObject objects = 1; +} + +// SchedulerV2 KubernetesPermissionCheck Request +message SchedulerV2KubernetesPermissionCheckRequest { + // Verb is a kubernetes resource API verb, like: get, list, watch, create, update, delete, proxy. "*" means all. + string verb =1; + // Group is the API Group of the Resource. "*" means all. + string group=2; + // Version is the API Version of the Resource. "*" means all. + string version=3; + // Resource is one of the existing resource types. "*" means all. + string resource=4; + // Subresource is one of the existing resource types. "" means none. + string sub_resource=5; + // Name is the name of the resource being requested for a "get" or deleted for a "delete". "" (empty) means all. + string name=6; + // Namespace is the namespace of the action being requested. + // "" (empty) is defaulted for LocalSubjectAccessReviews + // "" (empty) is empty for cluster-scoped resources + // "" (empty) means "all" for namespace scoped resources from a SubjectAccessReview or SelfSubjectAccessReview + // Defaults to the current namespace + optional string namespace=7; +} + +// SchedulerV2 KubernetesPermissionCheck Response +message SchedulerV2KubernetesPermissionCheckResponse { + // Allowed is required. True if the action would be allowed, false otherwise. + bool allowed =1; + // Denied is optional. True if the action would be denied, otherwise + // false. If both allowed is false and denied is false, then the + // authorizer has no opinion on whether to authorize the action. Denied + // may not be true if Allowed is true. + // +optional + optional bool denied =2; + // Reason is optional. It indicates why a request was allowed or denied. + optional string reason =3; + // EvaluationError is an indication that some error occurred during the authorization check. + // It is entirely possible to get an error and be able to continue determine authorization status in spite of it. + // For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request. + optional string evaluation_error=4; } \ No newline at end of file diff --git a/integrations/scheduler/v2/errors.go b/integrations/scheduler/v2/errors.go new file mode 100644 index 000000000..65bc50aa6 --- /dev/null +++ b/integrations/scheduler/v2/errors.go @@ -0,0 +1,44 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 v2 + +import ( + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/kerrors" +) + +func asGRPCError(err error) error { + if err == nil { + return nil + } + + if kerrors.IsForbiddenC(err) { + return status.Errorf(codes.PermissionDenied, "Permission Denied: %s", err.Error()) + } + + if kerrors.IsNotFound(err) { + return status.Errorf(codes.NotFound, "NotFound: %s", err.Error()) + } + + return status.Errorf(codes.Internal, "Unable to run action: %s", err.Error()) +} diff --git a/integrations/scheduler/v2/implementation_test.go b/integrations/scheduler/v2/implementation_test.go index db4f83679..86bf1cadf 100644 --- a/integrations/scheduler/v2/implementation_test.go +++ b/integrations/scheduler/v2/implementation_test.go @@ -27,7 +27,7 @@ import ( "github.com/stretchr/testify/require" "helm.sh/helm/v3/pkg/action" - "github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition" + pbSchedulerV2 "github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition" pbSharedV1 "github.com/arangodb/kube-arangodb/integrations/shared/v1/definition" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/helm" "github.com/arangodb/kube-arangodb/pkg/util/tests" @@ -71,7 +71,7 @@ func Test_Implementation(t *testing.T) { ctx, c := context.WithCancel(context.Background()) defer c() - scheduler, h := Client(t, ctx, func(c Configuration) Configuration { + scheduler, h := ExternalClient(t, ctx, func(c Configuration) Configuration { c.Namespace = tests.FakeNamespace c.Deployment = tests.FakeNamespace return c @@ -90,7 +90,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Check API Resources", func(t *testing.T) { - o, err := scheduler.DiscoverAPIResources(context.Background(), &definition.SchedulerV2DiscoverAPIResourcesRequest{ + o, err := scheduler.DiscoverAPIResources(context.Background(), &pbSchedulerV2.SchedulerV2DiscoverAPIResourcesRequest{ Version: "v1", }) require.NoError(t, err) @@ -101,7 +101,7 @@ func Test_Implementation(t *testing.T) { t.Run("Check API Resource", func(t *testing.T) { - oz, err := scheduler.DiscoverAPIResource(context.Background(), &definition.SchedulerV2DiscoverAPIResourceRequest{ + oz, err := scheduler.DiscoverAPIResource(context.Background(), &pbSchedulerV2.SchedulerV2DiscoverAPIResourceRequest{ Version: "v1", Kind: "ConfigMap", }) @@ -111,7 +111,7 @@ func Test_Implementation(t *testing.T) { t.Run("Check API Resource - Missing", func(t *testing.T) { - oz, err := scheduler.DiscoverAPIResource(context.Background(), &definition.SchedulerV2DiscoverAPIResourceRequest{ + oz, err := scheduler.DiscoverAPIResource(context.Background(), &pbSchedulerV2.SchedulerV2DiscoverAPIResourceRequest{ Version: "v1", Kind: "ConfigMap2", }) @@ -120,7 +120,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Status on Missing", func(t *testing.T) { - status, err := scheduler.Status(context.Background(), &definition.SchedulerV2StatusRequest{ + status, err := scheduler.Status(context.Background(), &pbSchedulerV2.SchedulerV2StatusRequest{ Name: "test", }) require.NoError(t, err) @@ -129,14 +129,14 @@ func Test_Implementation(t *testing.T) { }) t.Run("List Empty", func(t *testing.T) { - status, err := scheduler.List(context.Background(), &definition.SchedulerV2ListRequest{}) + status, err := scheduler.List(context.Background(), &pbSchedulerV2.SchedulerV2ListRequest{}) require.NoError(t, err) require.Len(t, status.GetReleases(), 0) }) t.Run("Install", func(t *testing.T) { - status, err := scheduler.Install(context.Background(), &definition.SchedulerV2InstallRequest{ + status, err := scheduler.Install(context.Background(), &pbSchedulerV2.SchedulerV2InstallRequest{ Name: "test", Values: nil, Chart: example_1_0_0, @@ -147,7 +147,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("List After", func(t *testing.T) { - status, err := scheduler.List(context.Background(), &definition.SchedulerV2ListRequest{}) + status, err := scheduler.List(context.Background(), &pbSchedulerV2.SchedulerV2ListRequest{}) require.NoError(t, err) require.Len(t, status.GetReleases(), 1) @@ -163,18 +163,18 @@ func Test_Implementation(t *testing.T) { }) t.Run("List After - Still should not see first one", func(t *testing.T) { - status, err := scheduler.List(context.Background(), &definition.SchedulerV2ListRequest{}) + status, err := scheduler.List(context.Background(), &pbSchedulerV2.SchedulerV2ListRequest{}) require.NoError(t, err) require.Len(t, status.GetReleases(), 1) }) t.Run("Install Second", func(t *testing.T) { - status, err := scheduler.Install(context.Background(), &definition.SchedulerV2InstallRequest{ + status, err := scheduler.Install(context.Background(), &pbSchedulerV2.SchedulerV2InstallRequest{ Name: "test-x", Values: nil, Chart: example_1_0_0, - Options: &definition.SchedulerV2InstallRequestOptions{ + Options: &pbSchedulerV2.SchedulerV2InstallRequestOptions{ Labels: map[string]string{ "X": "X", }, @@ -198,15 +198,15 @@ func Test_Implementation(t *testing.T) { }) t.Run("List After - Should see 2 services", func(t *testing.T) { - status, err := scheduler.List(context.Background(), &definition.SchedulerV2ListRequest{}) + status, err := scheduler.List(context.Background(), &pbSchedulerV2.SchedulerV2ListRequest{}) require.NoError(t, err) require.Len(t, status.GetReleases(), 2) }) t.Run("List After - Filter one", func(t *testing.T) { - status, err := scheduler.List(context.Background(), &definition.SchedulerV2ListRequest{ - Options: &definition.SchedulerV2ListRequestOptions{ + status, err := scheduler.List(context.Background(), &pbSchedulerV2.SchedulerV2ListRequest{ + Options: &pbSchedulerV2.SchedulerV2ListRequestOptions{ Selectors: map[string]string{ "X": "X", }, @@ -218,7 +218,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Check - Version 1", func(t *testing.T) { - status, err := scheduler.Status(context.Background(), &definition.SchedulerV2StatusRequest{ + status, err := scheduler.Status(context.Background(), &pbSchedulerV2.SchedulerV2StatusRequest{ Name: "test", }) require.NoError(t, err) @@ -231,7 +231,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Upgrade", func(t *testing.T) { - status, err := scheduler.Upgrade(context.Background(), &definition.SchedulerV2UpgradeRequest{ + status, err := scheduler.Upgrade(context.Background(), &pbSchedulerV2.SchedulerV2UpgradeRequest{ Name: "test", Values: values, Chart: example_1_0_0, @@ -244,7 +244,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Check - Version 2", func(t *testing.T) { - status, err := scheduler.Status(context.Background(), &definition.SchedulerV2StatusRequest{ + status, err := scheduler.Status(context.Background(), &pbSchedulerV2.SchedulerV2StatusRequest{ Name: "test", }) require.NoError(t, err) @@ -257,7 +257,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Test", func(t *testing.T) { - status, err := scheduler.Test(context.Background(), &definition.SchedulerV2TestRequest{ + status, err := scheduler.Test(context.Background(), &pbSchedulerV2.SchedulerV2TestRequest{ Name: "test", }) require.NoError(t, err) @@ -266,7 +266,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Uninstall", func(t *testing.T) { - status, err := scheduler.Uninstall(context.Background(), &definition.SchedulerV2UninstallRequest{ + status, err := scheduler.Uninstall(context.Background(), &pbSchedulerV2.SchedulerV2UninstallRequest{ Name: "test", }) require.NoError(t, err) diff --git a/integrations/scheduler/v2/kubernetes.go b/integrations/scheduler/v2/kubernetes.go index cb49ed026..92b531509 100644 --- a/integrations/scheduler/v2/kubernetes.go +++ b/integrations/scheduler/v2/kubernetes.go @@ -28,7 +28,9 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" pbSchedulerV2 "github.com/arangodb/kube-arangodb/integrations/scheduler/v2/definition" + "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/helm" + kresources "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/resources" ) func (i *implementation) DiscoverAPIResources(ctx context.Context, in *pbSchedulerV2.SchedulerV2DiscoverAPIResourcesRequest) (*pbSchedulerV2.SchedulerV2DiscoverAPIResourcesResponse, error) { @@ -93,10 +95,37 @@ func (i *implementation) KubernetesGet(ctx context.Context, in *pbSchedulerV2.Sc resp, err := i.client.NativeGet(ctx, reqs...) if err != nil { logger.Err(err).Warn("Unable to run action: KubernetesGet") - return nil, status.Errorf(codes.Internal, "Unable to run action: KubernetesGet: %s", err.Error()) + return nil, asGRPCError(err) } return &pbSchedulerV2.SchedulerV2KubernetesGetResponse{ Objects: newReleaseInfoResourceObjectsFromResourceObjects(resp), }, nil } + +func (i *implementation) KubernetesPermissionCheck(ctx context.Context, in *pbSchedulerV2.SchedulerV2KubernetesPermissionCheckRequest) (*pbSchedulerV2.SchedulerV2KubernetesPermissionCheckResponse, error) { + resp := kresources.AccessRequest{ + Verb: in.GetVerb(), + Group: in.GetGroup(), + Version: in.GetVersion(), + Resource: in.GetResource(), + SubResource: in.GetSubResource(), + Name: in.GetName(), + Namespace: util.OptionalType(in.Namespace, i.client.Namespace()), + }.Verify(ctx, i.client.Client().Kubernetes()) + + var res pbSchedulerV2.SchedulerV2KubernetesPermissionCheckResponse + + res.Allowed = resp.Allowed + if resp.Denied { + res.Denied = util.NewType(resp.Denied) + } + if resp.Reason != "" { + res.Reason = util.NewType(resp.Reason) + } + if resp.EvaluationError != "" { + res.EvaluationError = util.NewType(resp.EvaluationError) + } + + return &res, nil +} diff --git a/integrations/scheduler/v2/suite_test.go b/integrations/scheduler/v2/suite_test.go index 12578fa66..621048aa1 100644 --- a/integrations/scheduler/v2/suite_test.go +++ b/integrations/scheduler/v2/suite_test.go @@ -54,7 +54,25 @@ func Handler(t *testing.T, ctx context.Context, client helm.Client, mods ...Mod) return handler } -func Client(t *testing.T, ctx context.Context, mods ...Mod) (pbSchedulerV2.SchedulerV2Client, helm.Client) { +func InternalClient(t *testing.T, ctx context.Context, mods ...Mod) (pbSchedulerV2.SchedulerV2Client, helm.Client) { + client := kclient.NewFakeClient() + + h, err := helm.NewClient(helm.Configuration{ + Namespace: tests.FakeNamespace, + Client: client, + }) + require.NoError(t, err) + + local := svc.NewService(svc.Configuration{ + Address: "127.0.0.1:0", + }, Handler(t, ctx, h, mods...)) + + start := local.Start(ctx) + + return tgrpc.NewGRPCClient(t, ctx, pbSchedulerV2.NewSchedulerV2Client, start.Address()), h +} + +func ExternalClient(t *testing.T, ctx context.Context, mods ...Mod) (pbSchedulerV2.SchedulerV2Client, helm.Client) { z, ok := os.LookupEnv("TEST_KUBECONFIG") if !ok { t.Skipf("TEST_KUBECONFIG is not set") diff --git a/integrations/storage/v2/definition/helpers.go b/integrations/storage/v2/definition/helpers.go index c964d3759..17759f599 100644 --- a/integrations/storage/v2/definition/helpers.go +++ b/integrations/storage/v2/definition/helpers.go @@ -26,6 +26,7 @@ import ( "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/errors" + ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc" ) const BufferSize = 4094 @@ -38,35 +39,19 @@ func Send(ctx context.Context, client StorageV2Client, key string, in io.Reader) return nil, err } - for { + return ugrpc.Send[*StorageV2WriteObjectRequest, *StorageV2WriteObjectResponse](wr, func() (*StorageV2WriteObjectRequest, error) { n, err := in.Read(cache) if err != nil { - if errors.Is(err, io.EOF) { - break - } - - if cerr := wr.CloseSend(); cerr != nil { - return nil, errors.Errors(err, cerr) - } - return nil, err } - if err := wr.Send(&StorageV2WriteObjectRequest{ + return &StorageV2WriteObjectRequest{ Path: &StorageV2Path{ Path: key, }, Chunk: cache[:n], - }); err != nil { - if cerr := wr.CloseSend(); cerr != nil { - return nil, errors.Errors(err, cerr) - } - - return nil, err - } - } - - return wr.CloseAndRecv() + }, nil + }) } func Receive(ctx context.Context, client StorageV2Client, key string, out io.Writer) (int, error) { @@ -79,30 +64,21 @@ func Receive(ctx context.Context, client StorageV2Client, key string, out io.Wri var bytes int - for { - resp, err := wr.Recv() - if err != nil { - if errors.Is(err, io.EOF) { - break - } - - if cerr := wr.CloseSend(); cerr != nil { - return 0, errors.Errors(err, cerr) - } - - return 0, err - } - - n, err := util.WriteAll(out, resp.GetChunk()) + if err := ugrpc.Recv[*StorageV2ReadObjectResponse](wr, func(response *StorageV2ReadObjectResponse) error { + n, err := util.WriteAll(out, response.GetChunk()) if err != nil { if cerr := wr.CloseSend(); cerr != nil { - return 0, errors.Errors(err, cerr) + return errors.Errors(err, cerr) } - return 0, err + return err } bytes += n + + return nil + }); err != nil { + return 0, err } return bytes, nil diff --git a/integrations/storage/v2/storage_test.go b/integrations/storage/v2/storage_test.go index 5f00b57a7..d9d745544 100644 --- a/integrations/storage/v2/storage_test.go +++ b/integrations/storage/v2/storage_test.go @@ -25,7 +25,6 @@ import ( "context" "crypto/rand" "fmt" - "io" "sort" "strings" "testing" @@ -37,6 +36,7 @@ import ( pbStorageV2 "github.com/arangodb/kube-arangodb/integrations/storage/v2/definition" "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/errors" + ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc" ) func listAllFilesHelper(t *testing.T, ctx context.Context, h pbStorageV2.StorageV2Client, prefix string) []*pbStorageV2.StorageV2Object { @@ -49,15 +49,10 @@ func listAllFilesHelper(t *testing.T, ctx context.Context, h pbStorageV2.Storage }) require.NoError(t, err) - for { - files, err := res.Recv() - if errors.Is(err, io.EOF) { - break - } - require.NoError(t, err) - - r = append(r, files.GetFiles()...) - } + require.NoError(t, ugrpc.Recv[*pbStorageV2.StorageV2ListObjectsResponse](res, func(response *pbStorageV2.StorageV2ListObjectsResponse) error { + r = append(r, response.GetFiles()...) + return nil + })) return r } diff --git a/pkg/apis/shared/v1/data.go b/pkg/apis/shared/v1/data.go index b25c623f3..11d9c83b7 100644 --- a/pkg/apis/shared/v1/data.go +++ b/pkg/apis/shared/v1/data.go @@ -48,7 +48,13 @@ func (d *Data) UnmarshalJSON(bytes []byte) error { return errors.Errorf("nil object provided") } - ret, err := base64.StdEncoding.DecodeString(string(bytes)) + var s string + + if err := json.Unmarshal(bytes, &s); err != nil { + return err + } + + ret, err := base64.StdEncoding.DecodeString(s) if err != nil { return err } diff --git a/pkg/apis/shared/v1/data_test.go b/pkg/apis/shared/v1/data_test.go new file mode 100644 index 000000000..39af26a66 --- /dev/null +++ b/pkg/apis/shared/v1/data_test.go @@ -0,0 +1,37 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/arangodb/kube-arangodb/pkg/util" +) + +func Test_Data(t *testing.T) { + var d Data = make([]byte, 1024) + + z, err := util.JSONRemarshal[Data, Data](d) + require.NoError(t, err) + require.EqualValues(t, d, z) +} diff --git a/pkg/debug_package/generators/kubernetes/arango_platform.go b/pkg/debug_package/generators/kubernetes/arango_platform.go index 39292bdca..fd78e3fde 100644 --- a/pkg/debug_package/generators/kubernetes/arango_platform.go +++ b/pkg/debug_package/generators/kubernetes/arango_platform.go @@ -43,5 +43,10 @@ func platform(logger zerolog.Logger, files chan<- shared.File) error { return err } + if err := platformArangoPlatformCharts(logger, files, k); err != nil { + logger.Err(err).Msgf("Error while collecting platform arango charts") + return err + } + return nil } diff --git a/pkg/debug_package/generators/kubernetes/arango_platform_c.go b/pkg/debug_package/generators/kubernetes/arango_platform_c.go new file mode 100644 index 000000000..7611a1602 --- /dev/null +++ b/pkg/debug_package/generators/kubernetes/arango_platform_c.go @@ -0,0 +1,73 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 kubernetes + +import ( + "context" + "fmt" + + "github.com/rs/zerolog" + + platformApi "github.com/arangodb/kube-arangodb/pkg/apis/platform/v1alpha1" + "github.com/arangodb/kube-arangodb/pkg/debug_package/cli" + "github.com/arangodb/kube-arangodb/pkg/debug_package/shared" + "github.com/arangodb/kube-arangodb/pkg/util/errors" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/kerrors" + "github.com/arangodb/kube-arangodb/pkg/util/kclient" +) + +func platformArangoPlatformCharts(logger zerolog.Logger, files chan<- shared.File, client kclient.Client) error { + arangoPlatformStorages, err := listNetowkingArangoPlatformCharts(client) + if err != nil { + if kerrors.IsForbiddenOrNotFound(err) { + return nil + } + + return err + } + + if err := errors.ExecuteWithErrorArrayP2(platformArangoPlatformChart, client, files, arangoPlatformStorages...); err != nil { + logger.Err(err).Msgf("Error while collecting platform arango charts") + return err + } + + return nil +} + +func platformArangoPlatformChart(client kclient.Client, files chan<- shared.File, ext *platformApi.ArangoPlatformChart) error { + files <- shared.NewYAMLFile(fmt.Sprintf("kubernetes/arango/platform/arangoplatformcharts/%s.yaml", ext.GetName()), func() ([]interface{}, error) { + return []interface{}{ext}, nil + }) + + return nil +} + +func listNetowkingArangoPlatformCharts(client kclient.Client) ([]*platformApi.ArangoPlatformChart, error) { + return ListObjects[*platformApi.ArangoPlatformChartList, *platformApi.ArangoPlatformChart](context.Background(), client.Arango().PlatformV1alpha1().ArangoPlatformCharts(cli.GetInput().Namespace), func(result *platformApi.ArangoPlatformChartList) []*platformApi.ArangoPlatformChart { + q := make([]*platformApi.ArangoPlatformChart, len(result.Items)) + + for id, e := range result.Items { + q[id] = e.DeepCopy() + } + + return q + }) +} diff --git a/pkg/deployment/deployment_suite_test.go b/pkg/deployment/deployment_suite_test.go index 940280b27..bb506e2a3 100644 --- a/pkg/deployment/deployment_suite_test.go +++ b/pkg/deployment/deployment_suite_test.go @@ -592,7 +592,7 @@ func createTestDeployment(t *testing.T, config Config, arangoDeployment *api.Ara deps := Dependencies{ EventRecorder: eventRecorder, - Client: kclient.NewStaticClient(kubernetesClientSet, kubernetesExtClientSet, arangoClientSet, monitoringClientSet), + Client: kclient.NewStaticClient(nil, kubernetesClientSet, kubernetesExtClientSet, arangoClientSet, monitoringClientSet), } i := inspector.NewInspector(throttle.NewAlwaysThrottleComponents(), deps.Client, arangoDeployment.GetNamespace(), arangoDeployment.GetName()) diff --git a/pkg/deployment/resources/arango_profiles.go b/pkg/deployment/resources/arango_profiles.go index fc83682c0..016428570 100644 --- a/pkg/deployment/resources/arango_profiles.go +++ b/pkg/deployment/resources/arango_profiles.go @@ -149,7 +149,10 @@ func (r *Resources) EnsureArangoProfiles(ctx context.Context, cachedStatus inspe gen(constants.ProfilesIntegrationAuthz, constants.ProfilesIntegrationV0, always(sidecar.IntegrationAuthorizationV0{})), gen(constants.ProfilesIntegrationAuthn, constants.ProfilesIntegrationV1, always(sidecar.IntegrationAuthenticationV1{Spec: spec, DeploymentName: apiObject.GetName()})), gen(constants.ProfilesIntegrationSched, constants.ProfilesIntegrationV1, always(sidecar.IntegrationSchedulerV1{})), - gen(constants.ProfilesIntegrationSched, constants.ProfilesIntegrationV2, always(sidecar.IntegrationSchedulerV2{})), + gen(constants.ProfilesIntegrationSched, constants.ProfilesIntegrationV2, always(sidecar.IntegrationSchedulerV2{ + Spec: spec, + DeploymentName: apiObject.GetName(), + })), gen(constants.ProfilesIntegrationEnvoy, constants.ProfilesIntegrationV3, always(sidecar.IntegrationEnvoyV3{Spec: spec})), gen(constants.ProfilesIntegrationStorage, constants.ProfilesIntegrationV2, func() (sidecar.Integration, bool) { if v, err := cachedStatus.ArangoPlatformStorage().V1Alpha1(); err == nil { diff --git a/pkg/util/grpc/stream.go b/pkg/util/grpc/stream.go new file mode 100644 index 000000000..4441546f9 --- /dev/null +++ b/pkg/util/grpc/stream.go @@ -0,0 +1,87 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 grpc + +import ( + "io" + + "google.golang.org/grpc" + + "github.com/arangodb/kube-arangodb/pkg/util" + "github.com/arangodb/kube-arangodb/pkg/util/errors" +) + +type RecvInterface[T any] interface { + Recv() (T, error) + grpc.ClientStream +} + +func Recv[T any](recv RecvInterface[T], parser func(T) error) error { + for { + resp, err := recv.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + return nil + } + + if cerr := recv.CloseSend(); cerr != nil { + return errors.Errors(err, cerr) + } + + return err + } + + if err := parser(resp); err != nil { + return err + } + } +} + +type SendInterface[T, O any] interface { + Send(T) error + CloseAndRecv() (O, error) + grpc.ClientStream +} + +func Send[T, O any](send SendInterface[T, O], batch func() (T, error)) (O, error) { + for { + v, err := batch() + if err != nil { + if errors.Is(err, io.EOF) { + return send.CloseAndRecv() + } + + if cerr := send.CloseSend(); cerr != nil { + return util.Default[O](), errors.Errors(err, cerr) + } + + return util.Default[O](), err + } + + if err := send.Send(v); err != nil { + if cerr := send.CloseSend(); cerr != nil { + return util.Default[O](), errors.Errors(err, cerr) + } + + return util.Default[O](), err + } + } +} diff --git a/pkg/util/json.go b/pkg/util/json.go new file mode 100644 index 000000000..ae2e462d9 --- /dev/null +++ b/pkg/util/json.go @@ -0,0 +1,60 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 util + +import ( + "encoding/json" + + "sigs.k8s.io/yaml" +) + +func JSONRemarshal[A, B any](in A) (B, error) { + d, err := json.Marshal(in) + if err != nil { + return Default[B](), err + } + + var o B + + if err := json.Unmarshal(d, &o); err != nil { + return Default[B](), err + } + + return o, nil +} + +func JsonOrYamlUnmarshal[T any](b []byte) (T, error) { + var z T + + if json.Valid(b) { + if err := json.Unmarshal(b, &z); err != nil { + return Default[T](), err + } + + return z, nil + } + + if err := yaml.UnmarshalStrict(b, &z); err != nil { + return Default[T](), err + } + + return z, nil +} diff --git a/pkg/util/k8sutil/helm/chart_manager.go b/pkg/util/k8sutil/helm/chart_manager.go new file mode 100644 index 000000000..b146a764a --- /dev/null +++ b/pkg/util/k8sutil/helm/chart_manager.go @@ -0,0 +1,252 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 helm + +import ( + "context" + "fmt" + "io" + "net/http" + "sort" + "sync" + + "helm.sh/helm/v3/pkg/repo" + + "github.com/arangodb/kube-arangodb/pkg/util" + "github.com/arangodb/kube-arangodb/pkg/util/errors" +) + +func NewChartManager(ctx context.Context, client *http.Client, url string) (ChartManager, error) { + if client == nil { + client = http.DefaultClient + } + + m := manager{ + client: client, + url: url, + } + + if err := m.Reload(ctx); err != nil { + return nil, err + } + + return &m, nil +} + +type ChartManager interface { + Reload(ctx context.Context) error + + Repositories() []string + Versions(repo string) []string + Latest(repo string) (string, bool) + Chart(ctx context.Context, repo, version string) (Chart, error) +} + +type manager struct { + lock sync.Mutex + + client *http.Client + + url string + + index *repo.IndexFile +} + +func (m *manager) Latest(repoName string) (string, bool) { + m.lock.Lock() + defer m.lock.Unlock() + + if v := m.latest(repoName); v == nil { + return "", false + } else { + return v.Version, true + } +} + +func (m *manager) latest(repoName string) *repo.ChartVersion { + r, ok := m.index.Entries[repoName] + if !ok { + return nil + } + + if len(r) == 0 { + return nil + } + + if len(r) == 1 { + return r[0] + } + + var p = 0 + + for id := range r { + if id == p { + continue + } + + if r[id].Created.After(r[p].Created) { + p = id + } + } + + if p == -1 { + return nil + } + + return r[p] +} + +func (m *manager) Chart(ctx context.Context, repoName, version string) (Chart, error) { + m.lock.Lock() + defer m.lock.Unlock() + + r, ok := m.index.Entries[repoName] + if !ok { + return nil, errors.Errorf("Repo `%s` not found", repoName) + } + + var ver *repo.ChartVersion + + if version == "latest" { + ver = m.latest(repoName) + } else { + vs, ok := util.PickFromList(r, func(v *repo.ChartVersion) bool { + if v == nil { + return false + } + + return v.Version == version + }) + if !ok { + return nil, errors.Errorf("Repo `%s` does not contains version `%s`", repoName, version) + } + ver = vs + } + + if len(ver.URLs) == 0 { + return nil, errors.Errorf("Chart `%s-%s` does not have any urls defined", repoName, version) + } + + var errs = make([]error, len(ver.URLs)) + + for id, url := range ver.URLs { + data, err := m.download(ctx, url) + if err != nil { + errs[id] = err + continue + } + + return data, nil + } + + return nil, errors.Errors(errs...) +} + +func (m *manager) download(ctx context.Context, url string) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + resp, err := m.client.Do(req) + if err != nil { + return nil, err + } + + data, err := io.ReadAll(resp.Body) + if err != nil { + if err := resp.Body.Close(); err != nil { + return nil, err + } + + return nil, err + } + + if err := resp.Body.Close(); err != nil { + return nil, err + } + + if resp.StatusCode != 200 { + return nil, errors.Errorf("Unexpected code: %d", resp.StatusCode) + } + + return data, nil +} + +func (m *manager) Repositories() []string { + m.lock.Lock() + defer m.lock.Unlock() + + var s = make([]string, 0, len(m.index.Entries)) + + for v := range m.index.Entries { + s = append(s, v) + } + + sort.Strings(s) + + return s +} + +func (m *manager) Versions(repo string) []string { + m.lock.Lock() + defer m.lock.Unlock() + + r, ok := m.index.Entries[repo] + if !ok { + return nil + } + + if len(r) == 0 { + return []string{} + } + + s := make([]string, 0, len(r)) + + for _, v := range r { + s = append(s, v.Version) + } + + sort.Strings(s) + + return s +} + +func (m *manager) Reload(ctx context.Context) error { + m.lock.Lock() + defer m.lock.Unlock() + + data, err := m.download(ctx, fmt.Sprintf("%s/index.yaml", m.url)) + if err != nil { + return err + } + + idx, err := util.JsonOrYamlUnmarshal[repo.IndexFile](data) + if err != nil { + return err + } + + idx.SortEntries() + + m.index = &idx + + return nil +} diff --git a/pkg/util/k8sutil/helm/chart_manager_test.go b/pkg/util/k8sutil/helm/chart_manager_test.go new file mode 100644 index 000000000..b1cd665a0 --- /dev/null +++ b/pkg/util/k8sutil/helm/chart_manager_test.go @@ -0,0 +1,83 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 helm + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" +) + +func limitArray[T any](in []T, max int) []T { + if len(in) <= max { + return in + } + + return in[:max] +} + +func Test_Manager(t *testing.T) { + mgr, err := NewChartManager(context.Background(), nil, "https://arangodb-platform-dev-chart-registry.s3.amazonaws.com") + require.NoError(t, err) + + for _, repo := range limitArray(mgr.Repositories(), 5) { + t.Run(repo, func(t *testing.T) { + t.Run("Latest", func(t *testing.T) { + v, ok := mgr.Latest(repo) + require.True(t, ok) + + vdata, err := mgr.Chart(context.Background(), repo, v) + require.NoError(t, err) + + vchart, err := vdata.Get() + require.NoError(t, err) + require.NotNil(t, vchart.Metadata) + + data, err := mgr.Chart(context.Background(), repo, "latest") + require.NoError(t, err) + + chart, err := data.Get() + require.NoError(t, err) + require.NotNil(t, chart.Metadata) + + require.EqualValues(t, v, vchart.Metadata.Version) + require.EqualValues(t, v, chart.Metadata.Version) + }) + t.Run("ByVersion", func(t *testing.T) { + for _, version := range limitArray(mgr.Versions(repo), 5) { + t.Run(version, func(t *testing.T) { + data, err := mgr.Chart(context.Background(), repo, version) + require.NoError(t, err) + + c, err := data.Get() + require.NoError(t, err) + + require.NotNil(t, c.Metadata) + require.EqualValues(t, version, c.Metadata.Version) + }) + } + }) + }) + } + + require.NoError(t, mgr.Reload(context.Background())) +} diff --git a/pkg/util/kclient/client_factory.go b/pkg/util/kclient/client_factory.go index f4d22e9ad..7a362a6e2 100644 --- a/pkg/util/kclient/client_factory.go +++ b/pkg/util/kclient/client_factory.go @@ -191,13 +191,14 @@ type Client interface { Config() *rest.Config } -func NewStaticClient(kubernetes kubernetes.Interface, kubernetesExtensions apiextensionsclient.Interface, arango versioned.Interface, monitoring monitoring.Interface) Client { +func NewStaticClient(config *rest.Config, kubernetes kubernetes.Interface, kubernetesExtensions apiextensionsclient.Interface, arango versioned.Interface, monitoring monitoring.Interface) Client { return &client{ name: "static", kubernetes: kubernetes, kubernetesExtensions: kubernetesExtensions, arango: arango, monitoring: monitoring, + config: config, } } diff --git a/pkg/util/kclient/fake.go b/pkg/util/kclient/fake.go index 82e89c39d..36d084ebc 100644 --- a/pkg/util/kclient/fake.go +++ b/pkg/util/kclient/fake.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2024 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. @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/discovery/fake" kubernetesFake "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" versionedFake "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/fake" @@ -109,6 +110,9 @@ func (f *fakeClientBuilder) Client() Client { panic("Unable to get client") } return NewStaticClient( + &rest.Config{ + Host: "x.y.z.d:12345", + }, q, apiextensionsclientFake.NewSimpleClientset(f.filter(apiextensionsclientFake.AddToScheme)...), versionedFake.NewSimpleClientset(f.filter(versionedFake.AddToScheme)...), diff --git a/pkg/util/mod.go b/pkg/util/mod.go new file mode 100644 index 000000000..439189cc0 --- /dev/null +++ b/pkg/util/mod.go @@ -0,0 +1,49 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 util + +func emptyMod[T any](_ *T) {} + +func WithMods[T any](mods ...Mod[T]) Mod[T] { + return func(in *T) { + for _, m := range mods { + if m != nil { + m(in) + } + } + } +} + +type Mod[T any] func(in *T) + +func (m Mod[T]) Optional() Mod[T] { + if m == nil { + return emptyMod[T] + } + + return m +} + +func ApplyMods[T any](in *T, mods ...Mod[T]) { + for _, mod := range mods { + mod(in) + } +} diff --git a/pkg/util/next.go b/pkg/util/next.go new file mode 100644 index 000000000..9e2130a08 --- /dev/null +++ b/pkg/util/next.go @@ -0,0 +1,27 @@ +// +// DISCLAIMER +// +// Copyright 2024 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 util + +import "context" + +type NextIterator[T any] interface { + Next(ctx context.Context) (T, error) +} diff --git a/pkg/util/refs.go b/pkg/util/refs.go index 1f73f4ecb..9121c1b8e 100644 --- a/pkg/util/refs.go +++ b/pkg/util/refs.go @@ -21,8 +21,6 @@ package util import ( - "context" - "encoding/json" "reflect" ) @@ -176,29 +174,6 @@ func And(in ...bool) bool { return len(in) > 0 } -type Mod[T any] func(in *T) - -func ApplyMods[T any](in *T, mods ...Mod[T]) { - for _, mod := range mods { - mod(in) - } -} - -func JSONRemarshal[A, B any](in A) (B, error) { - d, err := json.Marshal(in) - if err != nil { - return Default[B](), err - } - - var o B - - if err := json.Unmarshal(d, &o); err != nil { - return Default[B](), err - } - - return o, nil -} - func InitOptional[T any](in *T, ok bool) *T { if ok { return in @@ -207,7 +182,3 @@ func InitOptional[T any](in *T, ok bool) *T { var z T return &z } - -type NextIterator[T any] interface { - Next(ctx context.Context) (T, error) -}