mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] ConfigV1 Integration Service (#1704)
This commit is contained in:
parent
e97e425485
commit
25d636e2b5
37 changed files with 2389 additions and 61 deletions
|
@ -99,6 +99,10 @@ linters-settings:
|
|||
alias: pbAuthorizationV0
|
||||
- pkg: github.com/arangodb/kube-arangodb/integrations/authorization/v0
|
||||
alias: pbImplAuthorizationV0
|
||||
- pkg: github.com/arangodb/kube-arangodb/integrations/config/v1/definition
|
||||
alias: pbConfigV1
|
||||
- pkg: github.com/arangodb/kube-arangodb/integrations/config/v1
|
||||
alias: pbImplConfigV1
|
||||
- pkg: github.com/arangodb/kube-arangodb/integrations/shared/v1/definition
|
||||
alias: pbSharedV1
|
||||
- pkg: github.com/arangodb/kube-arangodb/integrations/shared/v1
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
- (Maintenance) Switch to ubuntu:24.04 base image
|
||||
- (Feature) Gateway Group for ArangoDeployment
|
||||
- (Feature) Gateway config loader
|
||||
- (Feature) ConfigV1 Integration Service
|
||||
|
||||
## [1.2.42](https://github.com/arangodb/kube-arangodb/tree/1.2.42) (2024-07-23)
|
||||
- (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries
|
||||
|
|
14
Makefile
14
Makefile
|
@ -726,19 +726,9 @@ manifest-verify-helm-ee: manifests-verify-env-reset
|
|||
.PHONY: run-unit-tests
|
||||
run-unit-tests: $(SOURCES)
|
||||
go test --count=1 --tags "$(GOBUILDTAGS)" $(TESTVERBOSEOPTIONS) \
|
||||
$(REPOPATH)/pkg/apis/shared/... \
|
||||
$(REPOPATH)/pkg/apis/backup/... \
|
||||
$(REPOPATH)/pkg/apis/deployment/... \
|
||||
$(REPOPATH)/pkg/apis/replication/... \
|
||||
$(REPOPATH)/pkg/apis/storage/... \
|
||||
$(REPOPATH)/pkg/apis/ml/... \
|
||||
$(REPOPATH)/pkg/deployment/... \
|
||||
$(REPOPATH)/pkg/storage/... \
|
||||
$(REPOPATH)/pkg/crd/... \
|
||||
$(REPOPATH)/pkg/util/... \
|
||||
$(REPOPATH)/pkg/generated/metric_descriptions/... \
|
||||
$(REPOPATH)/pkg/... \
|
||||
$(REPOPATH)/cmd/... \
|
||||
$(REPOPATH)/pkg/handlers/...
|
||||
$(REPOPATH)/integrations/...
|
||||
|
||||
# Release building
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ Flags:
|
|||
--kubernetes.max-batch-size int Size of batch during objects read (default 256)
|
||||
--kubernetes.qps float32 Number of queries per second for k8s API (default 15)
|
||||
--log.format string Set log format. Allowed values: 'pretty', 'JSON'. If empty, default format is used (default "pretty")
|
||||
--log.level stringArray Set log levels in format <level> or <logger>=<level>. Possible loggers: action, agency, api-server, assertion, backup-operator, chaos-monkey, crd, deployment, deployment-ci, deployment-reconcile, deployment-replication, deployment-resilience, deployment-resources, deployment-storage, deployment-storage-pc, deployment-storage-service, http, inspector, integrations, k8s-client, monitor, networking-route-operator, operator, operator-arangojob-handler, operator-v2, operator-v2-event, operator-v2-worker, panics, pod_compare, root, root-event-recorder, server, server-authentication (default [info])
|
||||
--log.level stringArray Set log levels in format <level> or <logger>=<level>. Possible loggers: action, agency, api-server, assertion, backup-operator, chaos-monkey, crd, deployment, deployment-ci, deployment-reconcile, deployment-replication, deployment-resilience, deployment-resources, deployment-storage, deployment-storage-pc, deployment-storage-service, http, inspector, integration-config-v1, integrations, k8s-client, monitor, networking-route-operator, operator, operator-arangojob-handler, operator-v2, operator-v2-event, operator-v2-worker, panics, pod_compare, root, root-event-recorder, server, server-authentication (default [info])
|
||||
--log.sampling If true, operator will try to minimize duplication of logging events (default true)
|
||||
--memory-limit uint Define memory limit for hard shutdown and the dump of goroutines. Used for testing
|
||||
--metrics.excluded-prefixes stringArray List of the excluded metrics prefixes
|
||||
|
|
|
@ -40,10 +40,11 @@ func Test_Basic(t *testing.T) {
|
|||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
s, err := newInternal(ctx, Configuration{
|
||||
Path: directory,
|
||||
TTL: time.Duration(0),
|
||||
})
|
||||
s, err := newInternal(ctx, NewConfiguration().With(func(c Configuration) Configuration {
|
||||
c.Path = directory
|
||||
c.TTL = 0
|
||||
return c
|
||||
}))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create token
|
||||
|
|
40
integrations/config/v1/config.go
Normal file
40
integrations/config/v1/config.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
type Config struct {
|
||||
Modules ModuleDefinitions `json:"modules,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Config) Init() {
|
||||
for k := range c.Modules {
|
||||
m := c.Modules[k]
|
||||
m.Name = k
|
||||
c.Modules[k] = m
|
||||
}
|
||||
}
|
||||
|
||||
type ModuleDefinitions map[string]ModuleDefinition
|
||||
|
||||
type ModuleDefinition struct {
|
||||
Name string `json:"-"`
|
||||
Path string `json:"path"`
|
||||
}
|
80
integrations/config/v1/config_test.go
Normal file
80
integrations/config/v1/config_test.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_ConfigCreation(t *testing.T) {
|
||||
create := func(config Config) error {
|
||||
_, err := New(config)
|
||||
return err
|
||||
}
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
require.NoError(t, os.WriteFile(fmt.Sprintf("%s/file", dir), []byte{}, 0644))
|
||||
|
||||
require.EqualError(t, create(Config{}), "Requires at least 1 module")
|
||||
|
||||
require.EqualError(t, create(Config{
|
||||
Modules: map[string]ModuleDefinition{
|
||||
"test": {},
|
||||
},
|
||||
}), "Path for module `test` cannot be empty")
|
||||
|
||||
require.EqualError(t, create(Config{
|
||||
Modules: map[string]ModuleDefinition{
|
||||
"test": {
|
||||
Path: "some/relative/path",
|
||||
},
|
||||
},
|
||||
}), "Path `some/relative/path` for module `test` needs to be absolute")
|
||||
|
||||
require.EqualError(t, create(Config{
|
||||
Modules: map[string]ModuleDefinition{
|
||||
"test": {
|
||||
Path: fmt.Sprintf("%s/non-existent", dir),
|
||||
},
|
||||
},
|
||||
}), fmt.Sprintf("Path `%s/non-existent` for module `test` does not exists", dir))
|
||||
|
||||
require.EqualError(t, create(Config{
|
||||
Modules: map[string]ModuleDefinition{
|
||||
"test": {
|
||||
Path: fmt.Sprintf("%s/file", dir),
|
||||
},
|
||||
},
|
||||
}), fmt.Sprintf("Path `%s/file` for module `test` is not a directory", dir))
|
||||
|
||||
require.NoError(t, create(Config{
|
||||
Modules: map[string]ModuleDefinition{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
}))
|
||||
}
|
25
integrations/config/v1/consts.go
Normal file
25
integrations/config/v1/consts.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
const (
|
||||
Name = "config.v1"
|
||||
)
|
652
integrations/config/v1/definition/config.pb.go
Normal file
652
integrations/config/v1/definition/config.pb.go
Normal file
|
@ -0,0 +1,652 @@
|
|||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.1
|
||||
// source: integrations/config/v1/definition/config.proto
|
||||
|
||||
package definition
|
||||
|
||||
import (
|
||||
definition "github.com/arangodb/kube-arangodb/integrations/shared/v1/definition"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// ConfigV1 Modules Call Response
|
||||
type ConfigV1ModulesResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// List of registered modules
|
||||
Modules []string `protobuf:"bytes,1,rep,name=modules,proto3" json:"modules,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModulesResponse) Reset() {
|
||||
*x = ConfigV1ModulesResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModulesResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigV1ModulesResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigV1ModulesResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_integrations_config_v1_definition_config_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 ConfigV1ModulesResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigV1ModulesResponse) Descriptor() ([]byte, []int) {
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModulesResponse) GetModules() []string {
|
||||
if x != nil {
|
||||
return x.Modules
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Request
|
||||
type ConfigV1ModuleDetailsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Name of the module
|
||||
Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"`
|
||||
// Define if checksum of module should be returned
|
||||
Checksum *bool `protobuf:"varint,2,opt,name=checksum,proto3,oneof" json:"checksum,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsRequest) Reset() {
|
||||
*x = ConfigV1ModuleDetailsRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigV1ModuleDetailsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_integrations_config_v1_definition_config_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 ConfigV1ModuleDetailsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigV1ModuleDetailsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsRequest) GetModule() string {
|
||||
if x != nil {
|
||||
return x.Module
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsRequest) GetChecksum() bool {
|
||||
if x != nil && x.Checksum != nil {
|
||||
return *x.Checksum
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Response
|
||||
type ConfigV1ModuleDetailsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Name of the module
|
||||
Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"`
|
||||
// List of the files
|
||||
Files []*ConfigV1File `protobuf:"bytes,2,rep,name=files,proto3" json:"files,omitempty"`
|
||||
// Sha256Sum of the module (if requested)
|
||||
Checksum *string `protobuf:"bytes,3,opt,name=checksum,proto3,oneof" json:"checksum,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsResponse) Reset() {
|
||||
*x = ConfigV1ModuleDetailsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigV1ModuleDetailsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_integrations_config_v1_definition_config_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 ConfigV1ModuleDetailsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigV1ModuleDetailsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsResponse) GetModule() string {
|
||||
if x != nil {
|
||||
return x.Module
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsResponse) GetFiles() []*ConfigV1File {
|
||||
if x != nil {
|
||||
return x.Files
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConfigV1ModuleDetailsResponse) GetChecksum() string {
|
||||
if x != nil && x.Checksum != nil {
|
||||
return *x.Checksum
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Request
|
||||
type ConfigV1FileDetailsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Name of the module
|
||||
Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"`
|
||||
// Name of the file
|
||||
File string `protobuf:"bytes,2,opt,name=file,proto3" json:"file,omitempty"`
|
||||
// Define if checksum of module should be returned
|
||||
Checksum *bool `protobuf:"varint,3,opt,name=checksum,proto3,oneof" json:"checksum,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsRequest) Reset() {
|
||||
*x = ConfigV1FileDetailsRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigV1FileDetailsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigV1FileDetailsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_integrations_config_v1_definition_config_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 ConfigV1FileDetailsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigV1FileDetailsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsRequest) GetModule() string {
|
||||
if x != nil {
|
||||
return x.Module
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsRequest) GetFile() string {
|
||||
if x != nil {
|
||||
return x.File
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsRequest) GetChecksum() bool {
|
||||
if x != nil && x.Checksum != nil {
|
||||
return *x.Checksum
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Response
|
||||
type ConfigV1FileDetailsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Name of the module
|
||||
Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"`
|
||||
// Spec of the file
|
||||
File *ConfigV1File `protobuf:"bytes,3,opt,name=file,proto3" json:"file,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsResponse) Reset() {
|
||||
*x = ConfigV1FileDetailsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigV1FileDetailsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigV1FileDetailsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_integrations_config_v1_definition_config_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 ConfigV1FileDetailsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigV1FileDetailsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsResponse) GetModule() string {
|
||||
if x != nil {
|
||||
return x.Module
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1FileDetailsResponse) GetFile() *ConfigV1File {
|
||||
if x != nil {
|
||||
return x.File
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Information about configuration file
|
||||
type ConfigV1File struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Relative path of the config file
|
||||
Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
|
||||
// Size of the config file in bytes
|
||||
Size int64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
|
||||
// Sha256Sum of the file (if requested)
|
||||
Checksum *string `protobuf:"bytes,3,opt,name=checksum,proto3,oneof" json:"checksum,omitempty"`
|
||||
// Timestamp of the file creation
|
||||
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||
// Timestamp of the file update
|
||||
UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) Reset() {
|
||||
*x = ConfigV1File{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigV1File) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigV1File) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_integrations_config_v1_definition_config_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ConfigV1File.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigV1File) Descriptor() ([]byte, []int) {
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) GetPath() string {
|
||||
if x != nil {
|
||||
return x.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) GetSize() int64 {
|
||||
if x != nil {
|
||||
return x.Size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) GetChecksum() string {
|
||||
if x != nil && x.Checksum != nil {
|
||||
return *x.Checksum
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) GetCreatedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConfigV1File) GetUpdatedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.UpdatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_integrations_config_v1_definition_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_integrations_config_v1_definition_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x12, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x22, 0x33, 0x0a, 0x17, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x56, 0x31, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x64, 0x0a,
|
||||
0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x44,
|
||||
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75,
|
||||
0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b,
|
||||
0x73, 0x75, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b,
|
||||
0x73, 0x75, 0x6d, 0x22, 0x91, 0x01, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31,
|
||||
0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x2a, 0x0a,
|
||||
0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x46, 0x69,
|
||||
0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x63, 0x68, 0x65,
|
||||
0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x22, 0x76, 0x0a, 0x1a, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x56, 0x31, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c,
|
||||
0x65, 0x12, 0x1f, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x88,
|
||||
0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x22,
|
||||
0x5f, 0x0a, 0x1b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x46, 0x69, 0x6c, 0x65, 0x44,
|
||||
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65,
|
||||
0x22, 0xda, 0x01, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x46, 0x69, 0x6c,
|
||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1f, 0x0a, 0x08, 0x63, 0x68, 0x65,
|
||||
0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
|
||||
0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
|
||||
0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x32, 0xfb, 0x01,
|
||||
0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x12, 0x39, 0x0a, 0x07, 0x4d, 0x6f,
|
||||
0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x0d, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x44,
|
||||
0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x44, 0x65,
|
||||
0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x4d, 0x6f,
|
||||
0x64, 0x75, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69,
|
||||
0x6c, 0x73, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x56, 0x31, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x74, 0x61,
|
||||
0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x45, 0x5a, 0x43, 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, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_integrations_config_v1_definition_config_proto_rawDescOnce sync.Once
|
||||
file_integrations_config_v1_definition_config_proto_rawDescData = file_integrations_config_v1_definition_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_integrations_config_v1_definition_config_proto_rawDescGZIP() []byte {
|
||||
file_integrations_config_v1_definition_config_proto_rawDescOnce.Do(func() {
|
||||
file_integrations_config_v1_definition_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_integrations_config_v1_definition_config_proto_rawDescData)
|
||||
})
|
||||
return file_integrations_config_v1_definition_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_integrations_config_v1_definition_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_integrations_config_v1_definition_config_proto_goTypes = []interface{}{
|
||||
(*ConfigV1ModulesResponse)(nil), // 0: config.ConfigV1ModulesResponse
|
||||
(*ConfigV1ModuleDetailsRequest)(nil), // 1: config.ConfigV1ModuleDetailsRequest
|
||||
(*ConfigV1ModuleDetailsResponse)(nil), // 2: config.ConfigV1ModuleDetailsResponse
|
||||
(*ConfigV1FileDetailsRequest)(nil), // 3: config.ConfigV1FileDetailsRequest
|
||||
(*ConfigV1FileDetailsResponse)(nil), // 4: config.ConfigV1FileDetailsResponse
|
||||
(*ConfigV1File)(nil), // 5: config.ConfigV1File
|
||||
(*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp
|
||||
(*definition.Empty)(nil), // 7: shared.Empty
|
||||
}
|
||||
var file_integrations_config_v1_definition_config_proto_depIdxs = []int32{
|
||||
5, // 0: config.ConfigV1ModuleDetailsResponse.files:type_name -> config.ConfigV1File
|
||||
5, // 1: config.ConfigV1FileDetailsResponse.file:type_name -> config.ConfigV1File
|
||||
6, // 2: config.ConfigV1File.created_at:type_name -> google.protobuf.Timestamp
|
||||
6, // 3: config.ConfigV1File.updated_at:type_name -> google.protobuf.Timestamp
|
||||
7, // 4: config.ConfigV1.Modules:input_type -> shared.Empty
|
||||
1, // 5: config.ConfigV1.ModuleDetails:input_type -> config.ConfigV1ModuleDetailsRequest
|
||||
3, // 6: config.ConfigV1.FileDetails:input_type -> config.ConfigV1FileDetailsRequest
|
||||
0, // 7: config.ConfigV1.Modules:output_type -> config.ConfigV1ModulesResponse
|
||||
2, // 8: config.ConfigV1.ModuleDetails:output_type -> config.ConfigV1ModuleDetailsResponse
|
||||
4, // 9: config.ConfigV1.FileDetails:output_type -> config.ConfigV1FileDetailsResponse
|
||||
7, // [7:10] is the sub-list for method output_type
|
||||
4, // [4:7] 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_config_v1_definition_config_proto_init() }
|
||||
func file_integrations_config_v1_definition_config_proto_init() {
|
||||
if File_integrations_config_v1_definition_config_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigV1ModulesResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigV1ModuleDetailsRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigV1ModuleDetailsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigV1FileDetailsRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigV1FileDetailsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigV1File); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[1].OneofWrappers = []interface{}{}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[2].OneofWrappers = []interface{}{}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[3].OneofWrappers = []interface{}{}
|
||||
file_integrations_config_v1_definition_config_proto_msgTypes[5].OneofWrappers = []interface{}{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_integrations_config_v1_definition_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_integrations_config_v1_definition_config_proto_goTypes,
|
||||
DependencyIndexes: file_integrations_config_v1_definition_config_proto_depIdxs,
|
||||
MessageInfos: file_integrations_config_v1_definition_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_integrations_config_v1_definition_config_proto = out.File
|
||||
file_integrations_config_v1_definition_config_proto_rawDesc = nil
|
||||
file_integrations_config_v1_definition_config_proto_goTypes = nil
|
||||
file_integrations_config_v1_definition_config_proto_depIdxs = nil
|
||||
}
|
106
integrations/config/v1/definition/config.proto
Normal file
106
integrations/config/v1/definition/config.proto
Normal file
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package config;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
import "integrations/shared/v1/definition/empty.proto";
|
||||
|
||||
option go_package = "github.com/arangodb/kube-arangodb/integrations/config/v1/definition";
|
||||
|
||||
// ConfigV1 Service implementation
|
||||
service ConfigV1 {
|
||||
rpc Modules(shared.Empty) returns (ConfigV1ModulesResponse);
|
||||
rpc ModuleDetails(ConfigV1ModuleDetailsRequest) returns (ConfigV1ModuleDetailsResponse);
|
||||
rpc FileDetails(ConfigV1FileDetailsRequest) returns (ConfigV1FileDetailsResponse);
|
||||
}
|
||||
|
||||
// Calls
|
||||
|
||||
// ConfigV1 Modules Call Response
|
||||
message ConfigV1ModulesResponse {
|
||||
// List of registered modules
|
||||
repeated string modules = 1;
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Request
|
||||
message ConfigV1ModuleDetailsRequest {
|
||||
// Name of the module
|
||||
string module = 1;
|
||||
|
||||
// Define if checksum of module should be returned
|
||||
optional bool checksum = 2;
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Response
|
||||
message ConfigV1ModuleDetailsResponse {
|
||||
// Name of the module
|
||||
string module = 1;
|
||||
|
||||
// List of the files
|
||||
repeated ConfigV1File files = 2;
|
||||
|
||||
// Sha256Sum of the module (if requested)
|
||||
optional string checksum = 3;
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Request
|
||||
message ConfigV1FileDetailsRequest {
|
||||
// Name of the module
|
||||
string module = 1;
|
||||
|
||||
// Name of the file
|
||||
string file = 2;
|
||||
|
||||
// Define if checksum of module should be returned
|
||||
optional bool checksum = 3;
|
||||
}
|
||||
|
||||
// ConfigV1 ModuleDetails Call Response
|
||||
message ConfigV1FileDetailsResponse {
|
||||
// Name of the module
|
||||
string module = 1;
|
||||
|
||||
// Spec of the file
|
||||
ConfigV1File file = 3;
|
||||
}
|
||||
|
||||
// Types
|
||||
|
||||
// Information about configuration file
|
||||
message ConfigV1File {
|
||||
// Relative path of the config file
|
||||
string path = 1;
|
||||
|
||||
// Size of the config file in bytes
|
||||
int64 size = 2;
|
||||
|
||||
// Sha256Sum of the file (if requested)
|
||||
optional string checksum = 3;
|
||||
|
||||
// Timestamp of the file creation
|
||||
google.protobuf.Timestamp created_at = 4;
|
||||
|
||||
// Timestamp of the file update
|
||||
google.protobuf.Timestamp updated_at = 5;
|
||||
}
|
178
integrations/config/v1/definition/config_grpc.pb.go
Normal file
178
integrations/config/v1/definition/config_grpc.pb.go
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.21.1
|
||||
// source: integrations/config/v1/definition/config.proto
|
||||
|
||||
package definition
|
||||
|
||||
import (
|
||||
context "context"
|
||||
definition "github.com/arangodb/kube-arangodb/integrations/shared/v1/definition"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// ConfigV1Client is the client API for ConfigV1 service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ConfigV1Client interface {
|
||||
Modules(ctx context.Context, in *definition.Empty, opts ...grpc.CallOption) (*ConfigV1ModulesResponse, error)
|
||||
ModuleDetails(ctx context.Context, in *ConfigV1ModuleDetailsRequest, opts ...grpc.CallOption) (*ConfigV1ModuleDetailsResponse, error)
|
||||
FileDetails(ctx context.Context, in *ConfigV1FileDetailsRequest, opts ...grpc.CallOption) (*ConfigV1FileDetailsResponse, error)
|
||||
}
|
||||
|
||||
type configV1Client struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewConfigV1Client(cc grpc.ClientConnInterface) ConfigV1Client {
|
||||
return &configV1Client{cc}
|
||||
}
|
||||
|
||||
func (c *configV1Client) Modules(ctx context.Context, in *definition.Empty, opts ...grpc.CallOption) (*ConfigV1ModulesResponse, error) {
|
||||
out := new(ConfigV1ModulesResponse)
|
||||
err := c.cc.Invoke(ctx, "/config.ConfigV1/Modules", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configV1Client) ModuleDetails(ctx context.Context, in *ConfigV1ModuleDetailsRequest, opts ...grpc.CallOption) (*ConfigV1ModuleDetailsResponse, error) {
|
||||
out := new(ConfigV1ModuleDetailsResponse)
|
||||
err := c.cc.Invoke(ctx, "/config.ConfigV1/ModuleDetails", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configV1Client) FileDetails(ctx context.Context, in *ConfigV1FileDetailsRequest, opts ...grpc.CallOption) (*ConfigV1FileDetailsResponse, error) {
|
||||
out := new(ConfigV1FileDetailsResponse)
|
||||
err := c.cc.Invoke(ctx, "/config.ConfigV1/FileDetails", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ConfigV1Server is the server API for ConfigV1 service.
|
||||
// All implementations must embed UnimplementedConfigV1Server
|
||||
// for forward compatibility
|
||||
type ConfigV1Server interface {
|
||||
Modules(context.Context, *definition.Empty) (*ConfigV1ModulesResponse, error)
|
||||
ModuleDetails(context.Context, *ConfigV1ModuleDetailsRequest) (*ConfigV1ModuleDetailsResponse, error)
|
||||
FileDetails(context.Context, *ConfigV1FileDetailsRequest) (*ConfigV1FileDetailsResponse, error)
|
||||
mustEmbedUnimplementedConfigV1Server()
|
||||
}
|
||||
|
||||
// UnimplementedConfigV1Server must be embedded to have forward compatible implementations.
|
||||
type UnimplementedConfigV1Server struct {
|
||||
}
|
||||
|
||||
func (UnimplementedConfigV1Server) Modules(context.Context, *definition.Empty) (*ConfigV1ModulesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Modules not implemented")
|
||||
}
|
||||
func (UnimplementedConfigV1Server) ModuleDetails(context.Context, *ConfigV1ModuleDetailsRequest) (*ConfigV1ModuleDetailsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ModuleDetails not implemented")
|
||||
}
|
||||
func (UnimplementedConfigV1Server) FileDetails(context.Context, *ConfigV1FileDetailsRequest) (*ConfigV1FileDetailsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method FileDetails not implemented")
|
||||
}
|
||||
func (UnimplementedConfigV1Server) mustEmbedUnimplementedConfigV1Server() {}
|
||||
|
||||
// UnsafeConfigV1Server may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ConfigV1Server will
|
||||
// result in compilation errors.
|
||||
type UnsafeConfigV1Server interface {
|
||||
mustEmbedUnimplementedConfigV1Server()
|
||||
}
|
||||
|
||||
func RegisterConfigV1Server(s grpc.ServiceRegistrar, srv ConfigV1Server) {
|
||||
s.RegisterService(&ConfigV1_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ConfigV1_Modules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(definition.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigV1Server).Modules(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/config.ConfigV1/Modules",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigV1Server).Modules(ctx, req.(*definition.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ConfigV1_ModuleDetails_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ConfigV1ModuleDetailsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigV1Server).ModuleDetails(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/config.ConfigV1/ModuleDetails",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigV1Server).ModuleDetails(ctx, req.(*ConfigV1ModuleDetailsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ConfigV1_FileDetails_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ConfigV1FileDetailsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigV1Server).FileDetails(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/config.ConfigV1/FileDetails",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigV1Server).FileDetails(ctx, req.(*ConfigV1FileDetailsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ConfigV1_ServiceDesc is the grpc.ServiceDesc for ConfigV1 service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ConfigV1_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "config.ConfigV1",
|
||||
HandlerType: (*ConfigV1Server)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Modules",
|
||||
Handler: _ConfigV1_Modules_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ModuleDetails",
|
||||
Handler: _ConfigV1_ModuleDetails_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "FileDetails",
|
||||
Handler: _ConfigV1_FileDetails_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "integrations/config/v1/definition/config.proto",
|
||||
}
|
179
integrations/config/v1/file_details_test.go
Normal file
179
integrations/config/v1/file_details_test.go
Normal file
|
@ -0,0 +1,179 @@
|
|||
//
|
||||
// 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 (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
pbConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/tests"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/tests/tgrpc"
|
||||
)
|
||||
|
||||
func Test_Files_Details_Missing(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
_, err := client.FileDetails(ctx, &pbConfigV1.ConfigV1FileDetailsRequest{
|
||||
Module: "test",
|
||||
File: "non-existent",
|
||||
})
|
||||
tgrpc.AsGRPCError(t, err).Code(t, codes.NotFound).Errorf(t, "File `non-existent` not found within module `test`")
|
||||
}
|
||||
|
||||
func Test_Files_Details_Empty(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
tests.NewFileGenerator(t, dir).FileR(t, "file", 0)
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
resp, err := client.FileDetails(ctx, &pbConfigV1.ConfigV1FileDetailsRequest{
|
||||
Module: "test",
|
||||
File: "file",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", resp.GetModule())
|
||||
require.NotNil(t, resp.GetFile())
|
||||
require.Equal(t, "file", resp.GetFile().GetPath())
|
||||
require.EqualValues(t, 0, resp.GetFile().GetSize())
|
||||
require.Empty(t, resp.GetFile().GetChecksum())
|
||||
}
|
||||
|
||||
func Test_Files_Details_Empty_WC(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
tests.NewFileGenerator(t, dir).FileR(t, "file", 0)
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
resp, err := client.FileDetails(ctx, &pbConfigV1.ConfigV1FileDetailsRequest{
|
||||
Module: "test",
|
||||
File: "file",
|
||||
Checksum: util.NewType(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", resp.GetModule())
|
||||
require.NotNil(t, resp.GetFile())
|
||||
require.Equal(t, "file", resp.GetFile().GetPath())
|
||||
require.EqualValues(t, 0, resp.GetFile().GetSize())
|
||||
require.Equal(t, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", resp.GetFile().GetChecksum())
|
||||
}
|
||||
|
||||
func Test_Files_Details_Data(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
tests.NewFileGenerator(t, dir).File(t, "file", []byte("DATA"))
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
resp, err := client.FileDetails(ctx, &pbConfigV1.ConfigV1FileDetailsRequest{
|
||||
Module: "test",
|
||||
File: "file",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", resp.GetModule())
|
||||
require.NotNil(t, resp.GetFile())
|
||||
require.Equal(t, "file", resp.GetFile().GetPath())
|
||||
require.EqualValues(t, 4, resp.GetFile().GetSize())
|
||||
require.Empty(t, resp.GetFile().GetChecksum())
|
||||
}
|
||||
|
||||
func Test_Files_Details_Data_WC(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
tests.NewFileGenerator(t, dir).File(t, "file", []byte("DATA"))
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
resp, err := client.FileDetails(ctx, &pbConfigV1.ConfigV1FileDetailsRequest{
|
||||
Module: "test",
|
||||
File: "file",
|
||||
Checksum: util.NewType(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", resp.GetModule())
|
||||
require.NotNil(t, resp.GetFile())
|
||||
require.Equal(t, "file", resp.GetFile().GetPath())
|
||||
require.EqualValues(t, 4, resp.GetFile().GetSize())
|
||||
require.Equal(t, "c97c29c7a71b392b437ee03fd17f09bb10b75e879466fc0eb757b2c4a78ac938", resp.GetFile().GetChecksum())
|
||||
}
|
197
integrations/config/v1/impl.go
Normal file
197
integrations/config/v1/impl.go
Normal file
|
@ -0,0 +1,197 @@
|
|||
//
|
||||
// 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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
pbConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1/definition"
|
||||
pbSharedV1 "github.com/arangodb/kube-arangodb/integrations/shared/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
func New(config Config) (svc.Handler, error) {
|
||||
config.Init()
|
||||
|
||||
if len(config.Modules) == 0 {
|
||||
return nil, errors.Errorf("Requires at least 1 module")
|
||||
}
|
||||
|
||||
for module, moduleConfig := range config.Modules {
|
||||
if moduleConfig.Path == "" {
|
||||
return nil, errors.Errorf("Path for module `%s` cannot be empty", module)
|
||||
}
|
||||
|
||||
if !path.IsAbs(moduleConfig.Path) {
|
||||
return nil, errors.Errorf("Path `%s` for module `%s` needs to be absolute", moduleConfig.Path, module)
|
||||
}
|
||||
|
||||
info, err := os.Stat(moduleConfig.Path)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, errors.Errorf("Path `%s` for module `%s` does not exists", moduleConfig.Path, module)
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(err, "Path `%s` for module `%s` received unknown error", moduleConfig.Path, module)
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
return nil, errors.Errorf("Path `%s` for module `%s` is not a directory", moduleConfig.Path, module)
|
||||
}
|
||||
}
|
||||
|
||||
return &impl{
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ pbConfigV1.ConfigV1Server = &impl{}
|
||||
var _ svc.Handler = &impl{}
|
||||
|
||||
type impl struct {
|
||||
pbConfigV1.UnsafeConfigV1Server
|
||||
|
||||
config Config
|
||||
}
|
||||
|
||||
func (i *impl) Name() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
func (i *impl) Health() svc.HealthState {
|
||||
return svc.Healthy
|
||||
}
|
||||
|
||||
func (i *impl) Register(registrar *grpc.Server) {
|
||||
pbConfigV1.RegisterConfigV1Server(registrar, i)
|
||||
}
|
||||
|
||||
func (i *impl) Modules(ctx context.Context, empty *pbSharedV1.Empty) (*pbConfigV1.ConfigV1ModulesResponse, error) {
|
||||
res := &pbConfigV1.ConfigV1ModulesResponse{}
|
||||
|
||||
res.Modules = util.SortKeys(i.config.Modules)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (i *impl) ModuleDetails(ctx context.Context, request *pbConfigV1.ConfigV1ModuleDetailsRequest) (*pbConfigV1.ConfigV1ModuleDetailsResponse, error) {
|
||||
if request.GetModule() == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Module name cannot be empty")
|
||||
}
|
||||
|
||||
module, ok := i.config.Modules[request.GetModule()]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "Module `%s` not found", request.GetModule())
|
||||
}
|
||||
|
||||
var resp pbConfigV1.ConfigV1ModuleDetailsResponse
|
||||
|
||||
resp.Module = request.GetModule()
|
||||
|
||||
var files []*pbConfigV1.ConfigV1File
|
||||
|
||||
if err := filepath.Walk(module.Path, func(p string, info fs.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.Mode().IsRegular() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(p, fmt.Sprintf("%s/", module.Path)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := i.fileDetails(module, strings.TrimPrefix(p, fmt.Sprintf("%s/", module.Path)), request.GetChecksum())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files = append(files, f)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
if gErr, ok := svc.AsGRPCErrorStatus(err); ok {
|
||||
return nil, gErr
|
||||
}
|
||||
return nil, status.Errorf(codes.Internal, "Unable to list directory for module `%s`", request.GetModule())
|
||||
}
|
||||
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].GetPath() < files[j].GetPath()
|
||||
})
|
||||
|
||||
resp.Files = files
|
||||
|
||||
if request.GetChecksum() {
|
||||
checksums := make([]string, len(files))
|
||||
for id := range files {
|
||||
checksums[id] = fmt.Sprintf("%s:%s", files[id].GetPath(), files[id].GetChecksum())
|
||||
}
|
||||
|
||||
resp.Checksum = util.NewType(util.SHA256FromStringArray(checksums...))
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (i *impl) FileDetails(ctx context.Context, request *pbConfigV1.ConfigV1FileDetailsRequest) (*pbConfigV1.ConfigV1FileDetailsResponse, error) {
|
||||
if request.GetModule() == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Module name cannot be empty")
|
||||
}
|
||||
|
||||
module, ok := i.config.Modules[request.GetModule()]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "Module `%s` not found", request.GetModule())
|
||||
}
|
||||
|
||||
if request.GetFile() == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "File name cannot be empty")
|
||||
}
|
||||
|
||||
if request.GetFile() == "" {
|
||||
return nil, status.Errorf(codes.NotFound, "File name cannot be empty")
|
||||
}
|
||||
|
||||
f, err := i.fileDetails(module, request.GetFile(), request.GetChecksum())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pbConfigV1.ConfigV1FileDetailsResponse{
|
||||
Module: request.GetModule(),
|
||||
File: f,
|
||||
}, nil
|
||||
}
|
80
integrations/config/v1/impl_darwin.go
Normal file
80
integrations/config/v1/impl_darwin.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
pbConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
)
|
||||
|
||||
func (i *impl) fileDetails(module ModuleDefinition, file string, checksum bool) (*pbConfigV1.ConfigV1File, error) {
|
||||
expectedPath := path.Clean(path.Join(module.Path, file))
|
||||
|
||||
if !strings.HasPrefix(expectedPath, fmt.Sprintf("%s/", module.Path)) {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "File name cannot be empty")
|
||||
}
|
||||
|
||||
stat, err := os.Stat(expectedPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, status.Errorf(codes.NotFound, "File `%s` not found within module `%s`", file, module.Name)
|
||||
}
|
||||
|
||||
logger.Err(err).Str("module", module.Name).Str("file", file).Str("real-path", expectedPath).Warn("Unable to get file")
|
||||
return nil, status.Errorf(codes.Internal, "Unable to list directory for module `%s`", module.Name)
|
||||
}
|
||||
|
||||
finfo, ok := stat.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
logger.Str("module", module.Name).Str("file", file).Str("real-path", expectedPath).Warn("Invalid Stat Pointer for file")
|
||||
return nil, status.Errorf(codes.Internal, "Fetch of file `%s` within module `%s` failed", file, module.Name)
|
||||
}
|
||||
|
||||
var f pbConfigV1.ConfigV1File
|
||||
|
||||
f.Path = strings.TrimPrefix(expectedPath, fmt.Sprintf("%s/", module.Path))
|
||||
f.Size = finfo.Size
|
||||
f.CreatedAt = timestamppb.New(time.Unix(finfo.Ctimespec.Sec, finfo.Ctimespec.Nsec))
|
||||
f.UpdatedAt = timestamppb.New(time.Unix(finfo.Mtimespec.Sec, finfo.Mtimespec.Nsec))
|
||||
|
||||
if checksum {
|
||||
c, err := util.SHA256FromFile(expectedPath)
|
||||
if err != nil {
|
||||
logger.Str("module", module.Name).Str("file", file).Str("real-path", expectedPath).Warn("Unable to get file checksum")
|
||||
return nil, status.Errorf(codes.Internal, "Unable to calculate checksum of file `%s` within module `%s` failed", file, module.Name)
|
||||
}
|
||||
f.Checksum = util.NewType(c)
|
||||
}
|
||||
|
||||
return &f, nil
|
||||
}
|
80
integrations/config/v1/impl_linux.go
Normal file
80
integrations/config/v1/impl_linux.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// 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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
pbConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
)
|
||||
|
||||
func (i *impl) fileDetails(module ModuleDefinition, file string, checksum bool) (*pbConfigV1.ConfigV1File, error) {
|
||||
expectedPath := path.Clean(path.Join(module.Path, file))
|
||||
|
||||
if !strings.HasPrefix(expectedPath, fmt.Sprintf("%s/", module.Path)) {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "File name cannot be empty")
|
||||
}
|
||||
|
||||
stat, err := os.Stat(expectedPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, status.Errorf(codes.NotFound, "File `%s` not found within module `%s`", file, module.Name)
|
||||
}
|
||||
|
||||
logger.Err(err).Str("module", module.Name).Str("file", file).Str("real-path", expectedPath).Warn("Unable to get file")
|
||||
return nil, status.Errorf(codes.Internal, "Unable to list directory for module `%s`", module.Name)
|
||||
}
|
||||
|
||||
finfo, ok := stat.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
logger.Str("module", module.Name).Str("file", file).Str("real-path", expectedPath).Warn("Invalid Stat Pointer for file")
|
||||
return nil, status.Errorf(codes.Internal, "Fetch of file `%s` within module `%s` failed", file, module.Name)
|
||||
}
|
||||
|
||||
var f pbConfigV1.ConfigV1File
|
||||
|
||||
f.Path = strings.TrimPrefix(expectedPath, fmt.Sprintf("%s/", module.Path))
|
||||
f.Size = finfo.Size
|
||||
f.CreatedAt = timestamppb.New(time.Unix(finfo.Ctim.Sec, finfo.Ctim.Nsec))
|
||||
f.UpdatedAt = timestamppb.New(time.Unix(finfo.Mtim.Sec, finfo.Mtim.Nsec))
|
||||
|
||||
if checksum {
|
||||
c, err := util.SHA256FromFile(expectedPath)
|
||||
if err != nil {
|
||||
logger.Str("module", module.Name).Str("file", file).Str("real-path", expectedPath).Warn("Unable to get file checksum")
|
||||
return nil, status.Errorf(codes.Internal, "Unable to calculate checksum of file `%s` within module `%s` failed", file, module.Name)
|
||||
}
|
||||
f.Checksum = util.NewType(c)
|
||||
}
|
||||
|
||||
return &f, nil
|
||||
}
|
25
integrations/config/v1/logger.go
Normal file
25
integrations/config/v1/logger.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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 "github.com/arangodb/kube-arangodb/pkg/logging"
|
||||
|
||||
var logger = logging.Global().RegisterAndGetLogger("integration-config-v1", logging.Info)
|
192
integrations/config/v1/module_details_test.go
Normal file
192
integrations/config/v1/module_details_test.go
Normal file
|
@ -0,0 +1,192 @@
|
|||
//
|
||||
// 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 (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
||||
pbConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/tests"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/tests/tgrpc"
|
||||
)
|
||||
|
||||
func Test_Modules_Details_Empty(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
_, err := client.ModuleDetails(ctx, &pbConfigV1.ConfigV1ModuleDetailsRequest{})
|
||||
tgrpc.AsGRPCError(t, err).Code(t, codes.InvalidArgument).Errorf(t, "Module name cannot be empty")
|
||||
}
|
||||
|
||||
func Test_Modules_Details_NotFound(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
_, err := client.ModuleDetails(ctx, &pbConfigV1.ConfigV1ModuleDetailsRequest{
|
||||
Module: "some",
|
||||
})
|
||||
tgrpc.AsGRPCError(t, err).Code(t, codes.NotFound).Errorf(t, "Module `some` not found")
|
||||
}
|
||||
|
||||
func Test_Modules_Details_Exists_EmptyFiles(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
module, err := client.ModuleDetails(ctx, &pbConfigV1.ConfigV1ModuleDetailsRequest{
|
||||
Module: "test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", module.GetModule())
|
||||
require.Len(t, module.GetFiles(), 0)
|
||||
require.Equal(t, "", module.GetChecksum())
|
||||
}
|
||||
|
||||
func Test_Modules_Details_Exists_EmptyFiles_WithChecksum(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
module, err := client.ModuleDetails(ctx, &pbConfigV1.ConfigV1ModuleDetailsRequest{
|
||||
Module: "test",
|
||||
Checksum: util.NewType(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", module.GetModule())
|
||||
require.Len(t, module.GetFiles(), 0)
|
||||
require.Equal(t, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", module.GetChecksum())
|
||||
}
|
||||
|
||||
func Test_Modules_Details_Exists_SomeFiles(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
tests.NewFileGenerator(t, dir).
|
||||
FileR(t, "test", 128).
|
||||
Directory(t, "sub").FileR(t, "test", 128)
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
module, err := client.ModuleDetails(ctx, &pbConfigV1.ConfigV1ModuleDetailsRequest{
|
||||
Module: "test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", module.GetModule())
|
||||
require.Len(t, module.GetFiles(), 2)
|
||||
files := module.GetFiles()
|
||||
require.Equal(t, "sub/test", files[0].GetPath())
|
||||
require.Equal(t, "test", files[1].GetPath())
|
||||
require.Equal(t, "", module.GetChecksum())
|
||||
}
|
||||
|
||||
func Test_Modules_Details_Exists_SomeFiles_WithChecksum(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
tests.NewFileGenerator(t, dir).
|
||||
File(t, "test", []byte("DATA")).
|
||||
Directory(t, "sub").File(t, "test", []byte("DATA2"))
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
module, err := client.ModuleDetails(ctx, &pbConfigV1.ConfigV1ModuleDetailsRequest{
|
||||
Module: "test",
|
||||
Checksum: util.NewType(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", module.GetModule())
|
||||
require.Len(t, module.GetFiles(), 2)
|
||||
files := module.GetFiles()
|
||||
require.Equal(t, "sub/test", files[0].GetPath())
|
||||
require.Equal(t, "test", files[1].GetPath())
|
||||
require.Equal(t, "e357414aec56cf8e5e3988b53b766049521a1f4920ad72462d48ebbe16942915", module.GetChecksum())
|
||||
}
|
75
integrations/config/v1/module_test.go
Normal file
75
integrations/config/v1/module_test.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// 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 (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
pbSharedV1 "github.com/arangodb/kube-arangodb/integrations/shared/v1/definition"
|
||||
)
|
||||
|
||||
func Test_Modules_Single(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
modules, err := client.Modules(ctx, &pbSharedV1.Empty{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, modules.GetModules(), 1)
|
||||
}
|
||||
|
||||
func Test_Modules_Multi(t *testing.T) {
|
||||
ctx, c := context.WithCancel(context.Background())
|
||||
defer c()
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
client := Client(t, ctx, Config{
|
||||
Modules: ModuleDefinitions{
|
||||
"test": {
|
||||
Path: dir,
|
||||
},
|
||||
"test2": {
|
||||
Path: dir,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.NotNil(t, client)
|
||||
|
||||
modules, err := client.Modules(ctx, &pbSharedV1.Empty{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, modules.GetModules(), 2)
|
||||
}
|
46
integrations/config/v1/service_test.go
Normal file
46
integrations/config/v1/service_test.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// 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 (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
pbConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1/definition"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/tests/tgrpc"
|
||||
)
|
||||
|
||||
func Client(t *testing.T, ctx context.Context, config Config) pbConfigV1.ConfigV1Client {
|
||||
h, err := New(config)
|
||||
require.NoError(t, err)
|
||||
local := svc.NewService(svc.Configuration{
|
||||
Address: "127.0.0.1:0",
|
||||
}, h)
|
||||
|
||||
start := local.Start(ctx)
|
||||
|
||||
client := tgrpc.NewGRPCClient(t, ctx, pbConfigV1.NewConfigV1Client, start.Address())
|
||||
|
||||
return client
|
||||
}
|
25
integrations/scheduler/v1/consts.go
Normal file
25
integrations/scheduler/v1/consts.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
const (
|
||||
Name = "scheduler.v1"
|
||||
)
|
|
@ -31,7 +31,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
register(func() Integration {
|
||||
registerer.Register(pbAuthenticationV1.Name, func() Integration {
|
||||
return &authenticationV1{}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
register(func() Integration {
|
||||
registerer.Register(pbAuthorizationV0.Name, func() Integration {
|
||||
return &authorizationV0{}
|
||||
})
|
||||
}
|
||||
|
|
77
pkg/integrations/config_v1.go
Normal file
77
pkg/integrations/config_v1.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// 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 integrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
pbImplConfigV1 "github.com/arangodb/kube-arangodb/integrations/config/v1"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/strings"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerer.Register(pbImplConfigV1.Name, func() Integration {
|
||||
return &configV1{}
|
||||
})
|
||||
}
|
||||
|
||||
type configV1 struct {
|
||||
modules []string
|
||||
}
|
||||
|
||||
func (a *configV1) Register(cmd *cobra.Command, arg ArgGen) error {
|
||||
f := cmd.Flags()
|
||||
|
||||
f.StringSliceVar(&a.modules, arg("module"), nil, "Module in the reference <name>=<abs path>")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *configV1) Handler(ctx context.Context) (svc.Handler, error) {
|
||||
var cfg pbImplConfigV1.Config
|
||||
|
||||
cfg.Modules = map[string]pbImplConfigV1.ModuleDefinition{}
|
||||
|
||||
for _, module := range a.modules {
|
||||
l := strings.SplitN(module, "=", 2)
|
||||
if len(l) != 2 {
|
||||
return nil, errors.Errorf("Invalid module definition: %s", module)
|
||||
}
|
||||
|
||||
cfg.Modules[l[0]] = pbImplConfigV1.ModuleDefinition{
|
||||
Path: l[1],
|
||||
}
|
||||
}
|
||||
|
||||
return pbImplConfigV1.New(cfg)
|
||||
}
|
||||
|
||||
func (a *configV1) Name() string {
|
||||
return pbImplConfigV1.Name
|
||||
}
|
||||
|
||||
func (a *configV1) Description() string {
|
||||
return "Enable ConfigV1 Integration Service"
|
||||
}
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
register(func() Integration {
|
||||
registerer.Register(pbImplEnvoyAuthV3.Name, func() Integration {
|
||||
return &envoyAuthV3{}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -23,26 +23,16 @@ package integrations
|
|||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/shutdown"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
var (
|
||||
lock sync.Mutex
|
||||
registered []Factory
|
||||
)
|
||||
|
||||
func register(i Factory) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
registered = append(registered, i)
|
||||
}
|
||||
var registerer = util.NewRegisterer[string, Factory]()
|
||||
|
||||
func Register(cmd *cobra.Command) error {
|
||||
var c configuration
|
||||
|
@ -65,13 +55,9 @@ type configuration struct {
|
|||
}
|
||||
|
||||
func (c *configuration) Register(cmd *cobra.Command) error {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
c.registered = make([]Integration, len(registered))
|
||||
for id := range registered {
|
||||
c.registered[id] = registered[id]()
|
||||
}
|
||||
c.registered = util.FormatList(registerer.Items(), func(a util.KV[string, Factory]) Integration {
|
||||
return a.V()
|
||||
})
|
||||
|
||||
sort.Slice(c.registered, func(i, j int) bool {
|
||||
return c.registered[i].Name() < c.registered[j].Name()
|
||||
|
|
|
@ -33,7 +33,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
register(func() Integration {
|
||||
registerer.Register(pbImplSchedulerV1.Name, func() Integration {
|
||||
return &schedulerV1{}
|
||||
})
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ type schedulerV1 struct {
|
|||
}
|
||||
|
||||
func (b *schedulerV1) Name() string {
|
||||
return "scheduler.v1"
|
||||
return pbImplSchedulerV1.Name
|
||||
}
|
||||
|
||||
func (b *schedulerV1) Description() string {
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
register(func() Integration {
|
||||
registerer.Register(pbImplShutdownV1.Name, func() Integration {
|
||||
return &shutdownV1{}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
register(func() Integration {
|
||||
registerer.Register(storage.Name, func() Integration {
|
||||
return &storageV1{}
|
||||
})
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ type storageV1 struct {
|
|||
}
|
||||
|
||||
func (b *storageV1) Name() string {
|
||||
return "storage.v1"
|
||||
return storage.Name
|
||||
}
|
||||
|
||||
func (b *storageV1) Description() string {
|
||||
|
|
23
pkg/ml/storage/consts.go
Normal file
23
pkg/ml/storage/consts.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// 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 storage
|
||||
|
||||
const Name = "storage.v1"
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2022 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.
|
||||
|
@ -79,7 +79,7 @@ func Test_Verify_WrongOrder(t *testing.T) {
|
|||
)
|
||||
|
||||
_, err := u.Execute(api.ArangoDeployment{}, nil, nil)
|
||||
require.EqualError(t, err, "Invalid version in 1.1.1 - got 3, expected 2")
|
||||
require.EqualError(t, err, "Invalid version in 1.1.1 - got 3, expected 1")
|
||||
})
|
||||
t.Run("Valid multi version", func(t *testing.T) {
|
||||
var u Upgrades
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
|
||||
|
@ -56,6 +58,27 @@ func SHA256(data []byte) string {
|
|||
return fmt.Sprintf("%0x", sha256.Sum256(data))
|
||||
}
|
||||
|
||||
func SHA256FromFile(file string) (string, error) {
|
||||
in, err := os.OpenFile(file, os.O_RDONLY, 0644)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer in.Close()
|
||||
|
||||
return SHA256FromIO(in)
|
||||
}
|
||||
|
||||
func SHA256FromIO(in io.Reader) (string, error) {
|
||||
c := sha256.New()
|
||||
|
||||
if _, err := io.CopyBuffer(c, in, make([]byte, 4096)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%0x", c.Sum(nil)), nil
|
||||
}
|
||||
|
||||
func MD5FromString(data string) string {
|
||||
return MD5([]byte(data))
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ package util
|
|||
|
||||
import (
|
||||
"maps"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
|
@ -53,24 +52,34 @@ func Sort[IN any](in []IN, cmp func(i, j IN) bool) []IN {
|
|||
return r
|
||||
}
|
||||
|
||||
func SortKeys(m interface{}) []string {
|
||||
if m == nil {
|
||||
return []string{}
|
||||
func MapValues[K comparable, V any](m map[K]V) []V {
|
||||
r := make([]V, 0, len(m))
|
||||
|
||||
for k := range m {
|
||||
r = append(r, m[k])
|
||||
}
|
||||
|
||||
q := reflect.ValueOf(m).MapKeys()
|
||||
|
||||
r := make([]string, len(q))
|
||||
|
||||
for id, v := range q {
|
||||
r[id] = v.String()
|
||||
}
|
||||
|
||||
sort.Strings(r)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func MapKeys[K comparable, V any](m map[K]V) []K {
|
||||
r := make([]K, 0, len(m))
|
||||
|
||||
for k := range m {
|
||||
r = append(r, k)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func SortKeys[V any](m map[string]V) []string {
|
||||
keys := MapKeys(m)
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
func CopyFullMap[K comparable, V any](src map[K]V) map[K]V {
|
||||
if src == nil {
|
||||
return nil
|
||||
|
|
71
pkg/util/registerer.go
Normal file
71
pkg/util/registerer.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// 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 "sync"
|
||||
|
||||
func NewRegisterer[K comparable, V any]() Registerer[K, V] {
|
||||
return ®isterer[K, V]{
|
||||
items: make(map[K]V),
|
||||
}
|
||||
}
|
||||
|
||||
type Registerer[K comparable, V any] interface {
|
||||
Register(key K, value V) bool
|
||||
MustRegister(key K, value V)
|
||||
|
||||
Items() []KV[K, V]
|
||||
}
|
||||
|
||||
type registerer[K comparable, V any] struct {
|
||||
lock sync.Mutex
|
||||
|
||||
items map[K]V
|
||||
}
|
||||
|
||||
func (r *registerer[K, V]) Register(key K, value V) bool {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
if _, ok := r.items[key]; ok {
|
||||
return false
|
||||
}
|
||||
|
||||
r.items[key] = value
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *registerer[K, V]) MustRegister(key K, value V) {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
if !r.Register(key, value) {
|
||||
panic("Unable to register item")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *registerer[K, V]) Items() []KV[K, V] {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
return Extract(r.items)
|
||||
}
|
|
@ -130,6 +130,23 @@ func Split(s, sep string) []string {
|
|||
return strings.Split(s, sep)
|
||||
}
|
||||
|
||||
// SplitN slices s into substrings separated by sep and returns a slice of
|
||||
// the substrings between those separators.
|
||||
//
|
||||
// The count determines the number of substrings to return:
|
||||
//
|
||||
// n > 0: at most n substrings; the last substring will be the unsplit remainder.
|
||||
// n == 0: the result is nil (zero substrings)
|
||||
// n < 0: all substrings
|
||||
//
|
||||
// Edge cases for s and sep (for example, empty strings) are handled
|
||||
// as described in the documentation for [Split].
|
||||
//
|
||||
// To split around the first instance of a separator, see Cut.
|
||||
func SplitN(s, sep string, n int) []string {
|
||||
return strings.SplitN(s, sep, n)
|
||||
}
|
||||
|
||||
// ToLower returns s with all Unicode letters mapped to their lower case.
|
||||
func ToLower(s string) string {
|
||||
return strings.ToLower(s)
|
||||
|
|
|
@ -20,7 +20,12 @@
|
|||
|
||||
package svc
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type serviceError struct {
|
||||
error
|
||||
|
@ -45,3 +50,17 @@ func (p serviceError) Update(key string, state HealthState) {
|
|||
func (p serviceError) Start(ctx context.Context) ServiceStarter {
|
||||
return p
|
||||
}
|
||||
|
||||
type GRPCErrorStatus interface {
|
||||
error
|
||||
|
||||
GRPCStatus() *status.Status
|
||||
}
|
||||
|
||||
func AsGRPCErrorStatus(err error) (GRPCErrorStatus, bool) {
|
||||
var v GRPCErrorStatus
|
||||
if errors.As(err, &v) {
|
||||
return v, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
|
95
pkg/util/tests/path.go
Normal file
95
pkg/util/tests/path.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// 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 tests
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||
)
|
||||
|
||||
type FileGenerator interface {
|
||||
Parent(t *testing.T) FileGenerator
|
||||
|
||||
Directory(t *testing.T, name string) FileGenerator
|
||||
|
||||
File(t *testing.T, name string, data []byte) FileGenerator
|
||||
|
||||
FileR(t *testing.T, name string, size int) FileGenerator
|
||||
}
|
||||
|
||||
type fileGenerator struct {
|
||||
root string
|
||||
path string
|
||||
}
|
||||
|
||||
func (f fileGenerator) FileR(t *testing.T, name string, size int) FileGenerator {
|
||||
var data = make([]byte, size)
|
||||
|
||||
_, err := util.Rand().Read(data)
|
||||
require.NoError(t, err)
|
||||
|
||||
return f.File(t, name, data)
|
||||
}
|
||||
|
||||
func (f fileGenerator) Parent(t *testing.T) FileGenerator {
|
||||
require.NotEqual(t, f.root, f.path, "Unable to jump above root")
|
||||
|
||||
return fileGenerator{
|
||||
root: f.root,
|
||||
path: path.Dir(f.path),
|
||||
}
|
||||
}
|
||||
|
||||
func (f fileGenerator) Directory(t *testing.T, name string) FileGenerator {
|
||||
np := path.Join(f.path, name)
|
||||
|
||||
if err := os.Mkdir(np, 0755); err != nil {
|
||||
if !errors.Is(err, os.ErrExist) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
return fileGenerator{
|
||||
root: f.root,
|
||||
path: np,
|
||||
}
|
||||
}
|
||||
|
||||
func (f fileGenerator) File(t *testing.T, name string, data []byte) FileGenerator {
|
||||
require.NoError(t, os.WriteFile(path.Join(f.path, name), data, 0644))
|
||||
return f
|
||||
}
|
||||
|
||||
func NewFileGenerator(t *testing.T, root string) FileGenerator {
|
||||
if err := os.Mkdir(root, 0755); err != nil {
|
||||
if !errors.Is(err, os.ErrExist) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
return fileGenerator{root: root, path: root}
|
||||
}
|
|
@ -22,11 +22,16 @@ package tgrpc
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
func NewGRPCClient[T any](t *testing.T, ctx context.Context, in func(cc grpc.ClientConnInterface) T, addr string, opts ...grpc.DialOption) T {
|
||||
|
@ -51,3 +56,30 @@ func NewGRPCConn(t *testing.T, ctx context.Context, addr string, opts ...grpc.Di
|
|||
|
||||
return conn
|
||||
}
|
||||
|
||||
type ErrorStatusValidator interface {
|
||||
Code(t *testing.T, code codes.Code) ErrorStatusValidator
|
||||
Errorf(t *testing.T, msg string, args ...interface{}) ErrorStatusValidator
|
||||
}
|
||||
|
||||
type errorStatusValidator struct {
|
||||
st *status.Status
|
||||
}
|
||||
|
||||
func (e errorStatusValidator) Errorf(t *testing.T, msg string, args ...interface{}) ErrorStatusValidator {
|
||||
require.Equal(t, e.st.Message(), fmt.Sprintf(msg, args...))
|
||||
return e
|
||||
}
|
||||
|
||||
func (e errorStatusValidator) Code(t *testing.T, code codes.Code) ErrorStatusValidator {
|
||||
require.Equal(t, code, e.st.Code())
|
||||
return e
|
||||
}
|
||||
|
||||
func AsGRPCError(t *testing.T, err error) ErrorStatusValidator {
|
||||
v, ok := svc.AsGRPCErrorStatus(err)
|
||||
require.True(t, ok)
|
||||
st := v.GRPCStatus()
|
||||
require.NotNil(t, st)
|
||||
return errorStatusValidator{st: st}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue