From e85370817aa5f329644bf4ec821764fa845aa101 Mon Sep 17 00:00:00 2001 From: Adam Janikowski <12255597+ajanikow@users.noreply.github.com> Date: Fri, 29 Nov 2024 14:47:16 +0100 Subject: [PATCH] [Feature] [Platform] Platform Requirements support (#1772) --- CHANGELOG.md | 1 + go.mod | 2 +- .../scheduler/v2/definition/chart.pb.go | 202 +++++++++++++----- .../scheduler/v2/definition/chart.proto | 8 + .../scheduler/v2/implementation_test.go | 73 ++++++- .../scheduler/v2/suite/example-1.0.0.tgz | Bin 588 -> 0 bytes integrations/scheduler/v2/suite_test.go | 3 - pkg/apis/platform/v1alpha1/chart_details.go | 13 +- .../v1alpha1/chart_details_platform.go | 33 +++ .../chart_details_platform_version.go | 37 ++++ .../v1alpha1/zz_generated.deepcopy.go | 52 ++++- pkg/apis/shared/validate.go | 13 ++ pkg/handlers/platform/chart/chart_test.go | 39 +++- pkg/handlers/platform/chart/handler.go | 36 +++- .../platform/chart/suite/example-1.0.0.tgz | Bin 588 -> 0 bytes pkg/handlers/platform/chart/suite_test.go | 6 - pkg/util/k8sutil/helm/chart.go | 8 +- pkg/util/k8sutil/helm/chart_data.go | 58 +++++ pkg/util/k8sutil/helm/chart_manager_test.go | 12 +- pkg/util/k8sutil/helm/client.go | 6 +- pkg/util/k8sutil/helm/client_test.go | 21 +- pkg/util/k8sutil/helm/platform.go | 54 +++++ pkg/util/k8sutil/helm/platform_object.go | 29 +++ pkg/util/k8sutil/helm/platform_test.go | 46 ++++ pkg/util/k8sutil/helm/suite/example-1.0.0.tgz | Bin 588 -> 0 bytes pkg/util/k8sutil/helm/suite_test.go | 3 - pkg/util/tests/suite/chart.go | 55 +++++ pkg/util/tests/suite/chart/example-1.0.0.tgz | Bin 0 -> 440 bytes pkg/util/tests/suite/chart/example-1.0.1.tgz | Bin 0 -> 496 bytes .../tests/suite/chart}/example-1.1.0.tgz | Bin pkg/util/version.go | 57 +++++ pkg/util/version_test.go | 127 +++++++++++ 32 files changed, 887 insertions(+), 107 deletions(-) delete mode 100644 integrations/scheduler/v2/suite/example-1.0.0.tgz create mode 100644 pkg/apis/platform/v1alpha1/chart_details_platform.go create mode 100644 pkg/apis/platform/v1alpha1/chart_details_platform_version.go delete mode 100644 pkg/handlers/platform/chart/suite/example-1.0.0.tgz create mode 100644 pkg/util/k8sutil/helm/chart_data.go create mode 100644 pkg/util/k8sutil/helm/platform.go create mode 100644 pkg/util/k8sutil/helm/platform_object.go create mode 100644 pkg/util/k8sutil/helm/platform_test.go delete mode 100644 pkg/util/k8sutil/helm/suite/example-1.0.0.tgz create mode 100644 pkg/util/tests/suite/chart.go create mode 100644 pkg/util/tests/suite/chart/example-1.0.0.tgz create mode 100644 pkg/util/tests/suite/chart/example-1.0.1.tgz rename pkg/{handlers/platform/chart/suite => util/tests/suite/chart}/example-1.1.0.tgz (100%) create mode 100644 pkg/util/version.go create mode 100644 pkg/util/version_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 26cd02704..b2b9ff12c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - (Maintenance) Switch to google.golang.org/protobuf - (Feature) Add DebugPackage to the OPS Binary - (Feature) (Networking) ArangoRoute Protocol +- (Feature) (Platform) Platform Requirements support ## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14) - (Feature) ArangoRoute CRD diff --git a/go.mod b/go.mod index 886044454..b02eb624d 100644 --- a/go.mod +++ b/go.mod @@ -73,6 +73,7 @@ require ( ) require ( + github.com/Masterminds/semver/v3 v3.3.0 github.com/aws/aws-sdk-go v1.55.5 helm.sh/helm/v3 v3.16.2 ) @@ -85,7 +86,6 @@ require ( github.com/BurntSushi/toml v1.3.2 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect diff --git a/integrations/scheduler/v2/definition/chart.pb.go b/integrations/scheduler/v2/definition/chart.pb.go index 77d22e830..6bbcc5eaa 100644 --- a/integrations/scheduler/v2/definition/chart.pb.go +++ b/integrations/scheduler/v2/definition/chart.pb.go @@ -50,6 +50,8 @@ type SchedulerV2ChartInfo struct { 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"` + // Keeps the Platform details from the output + Platform *SchedulerV2ChartPlatform `protobuf:"bytes,3,opt,name=platform,proto3,oneof" json:"platform,omitempty"` } func (x *SchedulerV2ChartInfo) Reset() { @@ -98,6 +100,62 @@ func (x *SchedulerV2ChartInfo) GetVersion() string { return "" } +func (x *SchedulerV2ChartInfo) GetPlatform() *SchedulerV2ChartPlatform { + if x != nil { + return x.Platform + } + return nil +} + +// Chart Platform Details +type SchedulerV2ChartPlatform struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of the requirements + Requirements map[string]string `protobuf:"bytes,1,rep,name=requirements,proto3" json:"requirements,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *SchedulerV2ChartPlatform) Reset() { + *x = SchedulerV2ChartPlatform{} + 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 *SchedulerV2ChartPlatform) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchedulerV2ChartPlatform) ProtoMessage() {} + +func (x *SchedulerV2ChartPlatform) 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 SchedulerV2ChartPlatform.ProtoReflect.Descriptor instead. +func (*SchedulerV2ChartPlatform) Descriptor() ([]byte, []int) { + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{1} +} + +func (x *SchedulerV2ChartPlatform) GetRequirements() map[string]string { + if x != nil { + return x.Requirements + } + return nil +} + // SchedulerV2 ListCharts Request type SchedulerV2ListChartsRequest struct { state protoimpl.MessageState @@ -111,7 +169,7 @@ type SchedulerV2ListChartsRequest struct { func (x *SchedulerV2ListChartsRequest) Reset() { *x = SchedulerV2ListChartsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1] + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -124,7 +182,7 @@ func (x *SchedulerV2ListChartsRequest) String() string { func (*SchedulerV2ListChartsRequest) ProtoMessage() {} func (x *SchedulerV2ListChartsRequest) ProtoReflect() protoreflect.Message { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1] + 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 { @@ -137,7 +195,7 @@ func (x *SchedulerV2ListChartsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SchedulerV2ListChartsRequest.ProtoReflect.Descriptor instead. func (*SchedulerV2ListChartsRequest) Descriptor() ([]byte, []int) { - return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{1} + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{2} } func (x *SchedulerV2ListChartsRequest) GetItems() int64 { @@ -160,7 +218,7 @@ type SchedulerV2ListChartsResponse struct { func (x *SchedulerV2ListChartsResponse) Reset() { *x = SchedulerV2ListChartsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2] + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -173,7 +231,7 @@ func (x *SchedulerV2ListChartsResponse) String() string { func (*SchedulerV2ListChartsResponse) ProtoMessage() {} func (x *SchedulerV2ListChartsResponse) ProtoReflect() protoreflect.Message { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2] + 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 { @@ -186,7 +244,7 @@ func (x *SchedulerV2ListChartsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SchedulerV2ListChartsResponse.ProtoReflect.Descriptor instead. func (*SchedulerV2ListChartsResponse) Descriptor() ([]byte, []int) { - return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{2} + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{3} } func (x *SchedulerV2ListChartsResponse) GetCharts() []string { @@ -209,7 +267,7 @@ type SchedulerV2GetChartRequest struct { func (x *SchedulerV2GetChartRequest) Reset() { *x = SchedulerV2GetChartRequest{} if protoimpl.UnsafeEnabled { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[3] + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -222,7 +280,7 @@ func (x *SchedulerV2GetChartRequest) String() string { func (*SchedulerV2GetChartRequest) ProtoMessage() {} func (x *SchedulerV2GetChartRequest) ProtoReflect() protoreflect.Message { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[3] + 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 { @@ -235,7 +293,7 @@ func (x *SchedulerV2GetChartRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SchedulerV2GetChartRequest.ProtoReflect.Descriptor instead. func (*SchedulerV2GetChartRequest) Descriptor() ([]byte, []int) { - return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{3} + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{4} } func (x *SchedulerV2GetChartRequest) GetName() string { @@ -260,7 +318,7 @@ type SchedulerV2GetChartResponse struct { func (x *SchedulerV2GetChartResponse) Reset() { *x = SchedulerV2GetChartResponse{} if protoimpl.UnsafeEnabled { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[4] + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -273,7 +331,7 @@ func (x *SchedulerV2GetChartResponse) String() string { func (*SchedulerV2GetChartResponse) ProtoMessage() {} func (x *SchedulerV2GetChartResponse) ProtoReflect() protoreflect.Message { - mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[4] + mi := &file_integrations_scheduler_v2_definition_chart_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -286,7 +344,7 @@ func (x *SchedulerV2GetChartResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SchedulerV2GetChartResponse.ProtoReflect.Descriptor instead. func (*SchedulerV2GetChartResponse) Descriptor() ([]byte, []int) { - return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{4} + return file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP(), []int{5} } func (x *SchedulerV2GetChartResponse) GetChart() []byte { @@ -309,34 +367,51 @@ 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, + 0x74, 0x6f, 0x12, 0x09, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x22, 0x97, 0x01, + 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, 0x12, 0x44, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, + 0x61, 0x72, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x48, 0x00, 0x52, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xb6, 0x01, 0x0a, 0x18, 0x53, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x72, 0x56, 0x32, 0x43, 0x68, 0x61, 0x72, 0x74, 0x50, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x59, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 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, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, + 0x3f, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 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 ( @@ -351,21 +426,25 @@ func file_integrations_scheduler_v2_definition_chart_proto_rawDescGZIP() []byte 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_msgTypes = make([]protoimpl.MessageInfo, 7) 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 + (*SchedulerV2ChartPlatform)(nil), // 1: scheduler.SchedulerV2ChartPlatform + (*SchedulerV2ListChartsRequest)(nil), // 2: scheduler.SchedulerV2ListChartsRequest + (*SchedulerV2ListChartsResponse)(nil), // 3: scheduler.SchedulerV2ListChartsResponse + (*SchedulerV2GetChartRequest)(nil), // 4: scheduler.SchedulerV2GetChartRequest + (*SchedulerV2GetChartResponse)(nil), // 5: scheduler.SchedulerV2GetChartResponse + nil, // 6: scheduler.SchedulerV2ChartPlatform.RequirementsEntry } 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 + 1, // 0: scheduler.SchedulerV2ChartInfo.platform:type_name -> scheduler.SchedulerV2ChartPlatform + 6, // 1: scheduler.SchedulerV2ChartPlatform.requirements:type_name -> scheduler.SchedulerV2ChartPlatform.RequirementsEntry + 0, // 2: scheduler.SchedulerV2GetChartResponse.info:type_name -> scheduler.SchedulerV2ChartInfo + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_integrations_scheduler_v2_definition_chart_proto_init() } @@ -387,7 +466,7 @@ func file_integrations_scheduler_v2_definition_chart_proto_init() { } } file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SchedulerV2ListChartsRequest); i { + switch v := v.(*SchedulerV2ChartPlatform); i { case 0: return &v.state case 1: @@ -399,7 +478,7 @@ func file_integrations_scheduler_v2_definition_chart_proto_init() { } } file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SchedulerV2ListChartsResponse); i { + switch v := v.(*SchedulerV2ListChartsRequest); i { case 0: return &v.state case 1: @@ -411,7 +490,7 @@ func file_integrations_scheduler_v2_definition_chart_proto_init() { } } file_integrations_scheduler_v2_definition_chart_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SchedulerV2GetChartRequest); i { + switch v := v.(*SchedulerV2ListChartsResponse); i { case 0: return &v.state case 1: @@ -423,6 +502,18 @@ func file_integrations_scheduler_v2_definition_chart_proto_init() { } } file_integrations_scheduler_v2_definition_chart_proto_msgTypes[4].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[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SchedulerV2GetChartResponse); i { case 0: return &v.state @@ -435,14 +526,15 @@ func file_integrations_scheduler_v2_definition_chart_proto_init() { } } } - file_integrations_scheduler_v2_definition_chart_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[0].OneofWrappers = []interface{}{} + file_integrations_scheduler_v2_definition_chart_proto_msgTypes[2].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, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, diff --git a/integrations/scheduler/v2/definition/chart.proto b/integrations/scheduler/v2/definition/chart.proto index 7dad5cffb..920ad09ae 100644 --- a/integrations/scheduler/v2/definition/chart.proto +++ b/integrations/scheduler/v2/definition/chart.proto @@ -30,6 +30,14 @@ message SchedulerV2ChartInfo { string name = 1; // Chart Version string version = 2; + // Keeps the Platform details from the output + optional SchedulerV2ChartPlatform platform = 3; +} + +// Chart Platform Details +message SchedulerV2ChartPlatform { + // List of the requirements + map requirements = 1; } // SchedulerV2 ListCharts Request diff --git a/integrations/scheduler/v2/implementation_test.go b/integrations/scheduler/v2/implementation_test.go index 86bf1cadf..bb51d5194 100644 --- a/integrations/scheduler/v2/implementation_test.go +++ b/integrations/scheduler/v2/implementation_test.go @@ -23,14 +23,19 @@ package v2 import ( "context" "testing" + "time" "github.com/stretchr/testify/require" "helm.sh/helm/v3/pkg/action" + core "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" 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/k8sutil/kerrors" "github.com/arangodb/kube-arangodb/pkg/util/tests" + "github.com/arangodb/kube-arangodb/pkg/util/tests/suite" ) func cleanup(t *testing.T, c helm.Client) func() { @@ -47,6 +52,32 @@ func cleanup(t *testing.T, c helm.Client) func() { require.NoError(t, err) }) } + + t.Run("Remove NS", func(t *testing.T) { + if err := c.Client().Kubernetes().CoreV1().Namespaces().Delete(context.Background(), tests.FakeNamespace, meta.DeleteOptions{}); !kerrors.IsNotFound(err) { + require.NoError(t, err) + } + + for { + time.Sleep(time.Second) + + if _, err := c.Client().Kubernetes().CoreV1().Namespaces().Get(context.Background(), tests.FakeNamespace, meta.GetOptions{}); !kerrors.IsNotFound(err) { + require.NoError(t, err) + continue + } + + break + } + }) + + t.Run("Create NS", func(t *testing.T) { + _, err = c.Client().Kubernetes().CoreV1().Namespaces().Create(context.Background(), &core.Namespace{ + ObjectMeta: meta.ObjectMeta{ + Name: tests.FakeNamespace, + }, + }, meta.CreateOptions{}) + require.NoError(t, err) + }) }) return func() { @@ -63,6 +94,23 @@ func cleanup(t *testing.T, c helm.Client) func() { require.NoError(t, err) }) } + + t.Run("Remove NS", func(t *testing.T) { + if err := c.Client().Kubernetes().CoreV1().Namespaces().Delete(context.Background(), tests.FakeNamespace, meta.DeleteOptions{}); !kerrors.IsNotFound(err) { + require.NoError(t, err) + } + + for { + time.Sleep(time.Second) + + if _, err := c.Client().Kubernetes().CoreV1().Namespaces().Get(context.Background(), tests.FakeNamespace, meta.GetOptions{}); !kerrors.IsNotFound(err) { + require.NoError(t, err) + continue + } + + break + } + }) }) } } @@ -139,7 +187,7 @@ func Test_Implementation(t *testing.T) { status, err := scheduler.Install(context.Background(), &pbSchedulerV2.SchedulerV2InstallRequest{ Name: "test", Values: nil, - Chart: example_1_0_0, + Chart: suite.GetChart(t, "example", "1.0.0"), }) require.NoError(t, err) @@ -154,7 +202,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Install Outside", func(t *testing.T) { - resp, err := h.Install(context.Background(), example_1_0_0, nil, func(in *action.Install) { + resp, err := h.Install(context.Background(), suite.GetChart(t, "example", "1.0.0"), nil, func(in *action.Install) { in.ReleaseName = "test-outside" }) require.NoError(t, err) @@ -173,7 +221,7 @@ func Test_Implementation(t *testing.T) { status, err := scheduler.Install(context.Background(), &pbSchedulerV2.SchedulerV2InstallRequest{ Name: "test-x", Values: nil, - Chart: example_1_0_0, + Chart: suite.GetChart(t, "example", "1.0.0"), Options: &pbSchedulerV2.SchedulerV2InstallRequestOptions{ Labels: map[string]string{ "X": "X", @@ -186,7 +234,7 @@ func Test_Implementation(t *testing.T) { }) t.Run("Install Second Outside", func(t *testing.T) { - resp, err := h.Install(context.Background(), example_1_0_0, nil, func(in *action.Install) { + resp, err := h.Install(context.Background(), suite.GetChart(t, "example", "1.0.0"), nil, func(in *action.Install) { in.ReleaseName = "test-outside-x" in.Labels = map[string]string{ "X": "X", @@ -234,7 +282,20 @@ func Test_Implementation(t *testing.T) { status, err := scheduler.Upgrade(context.Background(), &pbSchedulerV2.SchedulerV2UpgradeRequest{ Name: "test", Values: values, - Chart: example_1_0_0, + Chart: suite.GetChart(t, "example", "1.0.0"), + }) + require.NoError(t, err) + + require.NotNil(t, status.GetAfter()) + t.Logf("Data: %s", string(status.GetAfter().GetValues())) + require.Len(t, status.GetAfter().GetValues(), len(values)) + }) + + t.Run("Upgrade to 1", func(t *testing.T) { + status, err := scheduler.Upgrade(context.Background(), &pbSchedulerV2.SchedulerV2UpgradeRequest{ + Name: "test", + Values: values, + Chart: suite.GetChart(t, "example", "1.0.1"), }) require.NoError(t, err) @@ -251,7 +312,7 @@ func Test_Implementation(t *testing.T) { require.NotNil(t, status.GetRelease()) - require.EqualValues(t, 2, status.GetRelease().GetVersion()) + require.EqualValues(t, 3, status.GetRelease().GetVersion()) t.Logf("Data: %s", string(status.GetRelease().GetValues())) require.Len(t, status.GetRelease().GetValues(), len(values)) }) diff --git a/integrations/scheduler/v2/suite/example-1.0.0.tgz b/integrations/scheduler/v2/suite/example-1.0.0.tgz deleted file mode 100644 index c12100f2b635d307804e91629b3ea140cca5d81f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmV-S0<--eiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PI##kDD+I?lZr_s_t>n(59_~w5NOC>9k4r?t<4wg@h#mt>XCa z6A(0wcI&3Gb|>+@AjO{(+wx~jUop#5T09<5+u(#*IvX8~F}C5n{W8XeU&hva7V<4y zalTwH`HY3j&5F%{jUUQ63S&{v*k8XjOzw>UbMZpj2qhyZLr-Ex5xA!C%H9$NEMVTf zW1TQQdi|G}7G(a-0Jy6Ea6QofifvYt{%--__dPE`ixE`yy@Q!>bM*SRl;tT}GK)AH zdkS3B|8_alKM%Lzr2kuB@c%ywnMClYr)5F@@+o z1TWn`xM4Nys%i=F3SSCk30^_SgrtQ{UAOnQj=i;Y@PTAf|H&Lb*S{rW7r9Etn*vw$ zzupe?zh3ca|Gxi=0Kzo&e^X_iUYEy130iog{FrBoKJP|{Up-lus`>Ns~ilT+N7 zV 0 { + c.Requirements = make(platformApi.ChartDetailsPlatformRequirements, len(platform.Requirements)) + + for k, v := range platform.Requirements { + c.Requirements[k] = platformApi.ChartDetailsPlatformVersionConstrain(v) + } + } + + r.Platform = &c + } + + return r } diff --git a/pkg/handlers/platform/chart/suite/example-1.0.0.tgz b/pkg/handlers/platform/chart/suite/example-1.0.0.tgz deleted file mode 100644 index c12100f2b635d307804e91629b3ea140cca5d81f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmV-S0<--eiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PI##kDD+I?lZr_s_t>n(59_~w5NOC>9k4r?t<4wg@h#mt>XCa z6A(0wcI&3Gb|>+@AjO{(+wx~jUop#5T09<5+u(#*IvX8~F}C5n{W8XeU&hva7V<4y zalTwH`HY3j&5F%{jUUQ63S&{v*k8XjOzw>UbMZpj2qhyZLr-Ex5xA!C%H9$NEMVTf zW1TQQdi|G}7G(a-0Jy6Ea6QofifvYt{%--__dPE`ixE`yy@Q!>bM*SRl;tT}GK)AH zdkS3B|8_alKM%Lzr2kuB@c%ywnMClYr)5F@@+o z1TWn`xM4Nys%i=F3SSCk30^_SgrtQ{UAOnQj=i;Y@PTAf|H&Lb*S{rW7r9Etn*vw$ zzupe?zh3ca|Gxi=0Kzo&e^X_iUYEy130iog{FrBoKJP|{Up-lus`>Ns~ilT+N7 zVDc zVQyr3R8em|NM&qo0PI##kDD+I?lZr_s_t>n(59_~w5NOC>9k4r?t<4wg@h#mt>XCa z6A(0wcI&3Gb|>+@AjO{(+wx~jUop#5T09<5+u(#*IvX8~F}C5n{W8XeU&hva7V<4y zalTwH`HY3j&5F%{jUUQ63S&{v*k8XjOzw>UbMZpj2qhyZLr-Ex5xA!C%H9$NEMVTf zW1TQQdi|G}7G(a-0Jy6Ea6QofifvYt{%--__dPE`ixE`yy@Q!>bM*SRl;tT}GK)AH zdkS3B|8_alKM%Lzr2kuB@c%ywnMClYr)5F@@+o z1TWn`xM4Nys%i=F3SSCk30^_SgrtQ{UAOnQj=i;Y@PTAf|H&Lb*S{rW7r9Etn*vw$ zzupe?zh3ca|Gxi=0Kzo&e^X_iUYEy130iog{FrBoKJP|{Up-lus`>Ns~ilT+N7 zVDc zVQyr3R8em|NM&qo0PK~`irX*{$9?uwh}U zrCHJ*YML(icM)j*qZth|5`9PGH5H$G3@oo`bhbDE0QYKr_aTS^HM@<->ovOM$r zGa0XuDHcqT3-7w+9)my4|6zByng89VYMuXo!p;1jmF*hw?7G|#V~31QF2wXIyu1kc zg*0I#`GkhV>+5!GmRtypN78YW3W46s^KhhKi786uio5P_`ku6ru`k;32byHlXEew7 zxsx)TJ>N$%Xz@hd_IUj@-d742)zW=OWh0|)f0JgI_U;S#>ZuW_AZV>)WaVtC%4WW1 z@7#HlbkS2gnpDc zVQyr3R8em|NM&qo0PL1gi<~eJ$9?uw1mBH`>)t}3ed+sgw9xliovvX`Vw1R3j{EK< zYoyd=dk>X64*WeBNM@W#oPS3A1*-3`_|k&)bOhBUtHT&$4^?#?8DqQHjd zc==E!;mHpPVe6-I%iuiNg#CA{<>o#J(97>=oitjI3r{sD6eJc!dYM-^Wt6Ayo$JQ> z%=-7J`VKt0!lUy=Z<_TkgV*$b*dG@9-|xyz|8K%V|7WQiL7q&LD)i8R2ayso-3rgo zgnq>i!6AJFh2-TW55=bovQHKsRnN7`T zj`3$EW;%P`MpB^RgiU@N|Bm+!?M2pj-%)DkLD&CC(@t~u4gA=nAn`yzYvaL7qvNS$ z^EO*!&RMi`J=S5lHrj*KXrpl+PdvUXAQhZYkZd>(+7F_vD66u#2KE#kCugi%lZK2# zY5OPB$$Avz5ie+OzW=QMApRf5Dmt$J2k>hDul5W5@5+jA`hN@ZJWo@LKL=@1q4w88 m3Uwz)_W2Xxw4}T2y_4M7*x1-uo!= 1.2.3 < 1.3.0", + constrain{ + version: "1.2.3", + valid: true, + }, + constrain{ + version: "1.2.5", + valid: true, + }, + constrain{ + version: "1.3.0", + }, + constrain{ + version: "v1.2.3-abcdefg", + valid: true, + }, + ) + + validate(">= 1.2.3 < 1.3.0 || >= 1.3.1 < 1.4.0", + constrain{ + version: "1.2.3", + valid: true, + }, + constrain{ + version: "1.2.5", + valid: true, + }, + constrain{ + version: "1.3.0", + }, + constrain{ + version: "v1.2.3-abcdefg", + valid: true, + }, + constrain{ + version: "1.3.5", + valid: true, + }, + constrain{ + version: "1.4.0", + }, + ) + + validate("~ 1", + constrain{ + version: "1.2.3", + valid: true, + }, + constrain{ + version: "1.2.5", + valid: true, + }, + constrain{ + version: "1.3.0", + valid: true, + }, + constrain{ + version: "v1.2.3-abcdefg", + valid: true, + }, + constrain{ + version: "1.3.5", + valid: true, + }, + constrain{ + version: "1.4.0", + valid: true, + }, + constrain{ + version: "2.0.0", + }, + ) +}