mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Maintenance] Extract GRPC Package for compatibility (#1763)
This commit is contained in:
parent
4462669547
commit
cce50b32d0
14 changed files with 267 additions and 30 deletions
|
@ -133,6 +133,8 @@ linters-settings:
|
|||
pkg: k8s.io/apimachinery/pkg/apis/meta/v1
|
||||
- alias: typedCore
|
||||
pkg: k8s.io/client-go/kubernetes/typed/core/v1
|
||||
- alias: ugrpc
|
||||
pkg: github.com/arangodb/kube-arangodb/pkg/util/grpc
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
- (Feature) (Scheduler) Helm Driver Param
|
||||
- (Feature) (Integration) Services Endpoint
|
||||
- (Feature) (Platform) Storage
|
||||
- (Maintenance) Extract GRPC Client Package
|
||||
|
||||
## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14)
|
||||
- (Feature) ArangoRoute CRD
|
||||
|
|
30
pkg/apis/deployment/v1/compatibility_test.go
Normal file
30
pkg/apis/deployment/v1/compatibility_test.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_ServerGroupSpecVolumeMount(t *testing.T) {
|
||||
// TODO: Uncomment after upgrade to 1.31.1+
|
||||
// require.NoError(t, types.EnsureTypeForwardCompatibility(reflect.TypeOf(core.VolumeMount{}), reflect.TypeOf(ServerGroupSpecVolumeMount{})))
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -55,10 +55,71 @@ func (s ServerGroupSpecVolumeMounts) Validate() error {
|
|||
return shared.WithErrors(validateErrors...)
|
||||
}
|
||||
|
||||
type ServerGroupSpecVolumeMount core.VolumeMount
|
||||
type ServerGroupSpecVolumeMount struct {
|
||||
// This must match the Name of a Volume.
|
||||
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||
// Mounted read-only if true, read-write otherwise (false or unspecified).
|
||||
// Defaults to false.
|
||||
// +optional
|
||||
|
||||
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"`
|
||||
// RecursiveReadOnly specifies whether read-only mounts should be handled
|
||||
// recursively.
|
||||
//
|
||||
// If ReadOnly is false, this field has no meaning and must be unspecified.
|
||||
//
|
||||
// If ReadOnly is true, and this field is set to Disabled, the mount is not made
|
||||
// recursively read-only. If this field is set to IfPossible, the mount is made
|
||||
// recursively read-only, if it is supported by the container runtime. If this
|
||||
// field is set to Enabled, the mount is made recursively read-only if it is
|
||||
// supported by the container runtime, otherwise the pod will not be started and
|
||||
// an error will be generated to indicate the reason.
|
||||
//
|
||||
// If this field is set to IfPossible or Enabled, MountPropagation must be set to
|
||||
// None (or be unspecified, which defaults to None).
|
||||
//
|
||||
// If this field is not specified, it is treated as an equivalent of Disabled.
|
||||
//
|
||||
// +featureGate=RecursiveReadOnlyMounts
|
||||
// +optional
|
||||
// TODO: Uncomment after upgrade to 1.31.1+
|
||||
// RecursiveReadOnly *RecursiveReadOnlyMode `json:"recursiveReadOnly,omitempty" protobuf:"bytes,7,opt,name=recursiveReadOnly,casttype=RecursiveReadOnlyMode"`
|
||||
|
||||
// Path within the container at which the volume should be mounted. Must
|
||||
// not contain ':'.
|
||||
MountPath string `json:"mountPath" protobuf:"bytes,3,opt,name=mountPath"`
|
||||
// Path within the volume from which the container's volume should be mounted.
|
||||
// Defaults to "" (volume's root).
|
||||
// +optional
|
||||
|
||||
SubPath string `json:"subPath,omitempty" protobuf:"bytes,4,opt,name=subPath"`
|
||||
// mountPropagation determines how mounts are propagated from the host
|
||||
// to container and the other way around.
|
||||
// When not set, MountPropagationNone is used.
|
||||
// This field is beta in 1.10.
|
||||
// When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified
|
||||
// (which defaults to None).
|
||||
// +optional
|
||||
|
||||
MountPropagation *core.MountPropagationMode `json:"mountPropagation,omitempty" protobuf:"bytes,5,opt,name=mountPropagation,casttype=MountPropagationMode"`
|
||||
// Expanded path within the volume from which the container's volume should be mounted.
|
||||
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
||||
// Defaults to "" (volume's root).
|
||||
// SubPathExpr and SubPath are mutually exclusive.
|
||||
// +optional
|
||||
SubPathExpr string `json:"subPathExpr,omitempty" protobuf:"bytes,6,opt,name=subPathExpr"`
|
||||
}
|
||||
|
||||
func (s ServerGroupSpecVolumeMount) VolumeMount() core.VolumeMount {
|
||||
return core.VolumeMount(s)
|
||||
return core.VolumeMount{
|
||||
Name: s.Name,
|
||||
ReadOnly: s.ReadOnly,
|
||||
//RecursiveReadOnly: s.RecursiveReadOnly, TODO: Uncomment after upgrade to 1.31.1+
|
||||
MountPath: s.MountPath,
|
||||
SubPath: s.SubPath,
|
||||
MountPropagation: s.MountPropagation,
|
||||
SubPathExpr: s.SubPathExpr,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServerGroupSpecVolumeMount) Validate() error {
|
||||
|
|
5
pkg/apis/deployment/v1/zz_generated.deepcopy.go
generated
5
pkg/apis/deployment/v1/zz_generated.deepcopy.go
generated
|
@ -2907,11 +2907,6 @@ func (in *ServerGroupSpecVolumeHostPath) DeepCopy() *ServerGroupSpecVolumeHostPa
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServerGroupSpecVolumeMount) DeepCopyInto(out *ServerGroupSpecVolumeMount) {
|
||||
*out = *in
|
||||
if in.RecursiveReadOnly != nil {
|
||||
in, out := &in.RecursiveReadOnly, &out.RecursiveReadOnly
|
||||
*out = new(corev1.RecursiveReadOnlyMode)
|
||||
**out = **in
|
||||
}
|
||||
if in.MountPropagation != nil {
|
||||
in, out := &in.MountPropagation, &out.MountPropagation
|
||||
*out = new(corev1.MountPropagationMode)
|
||||
|
|
30
pkg/apis/deployment/v2alpha1/compatibility_test.go
Normal file
30
pkg/apis/deployment/v2alpha1/compatibility_test.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// 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 v2alpha1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_ServerGroupSpecVolumeMount(t *testing.T) {
|
||||
// TODO: Uncomment after upgrade to 1.31.1+
|
||||
// require.NoError(t, types.EnsureTypeForwardCompatibility(reflect.TypeOf(core.VolumeMount{}), reflect.TypeOf(ServerGroupSpecVolumeMount{})))
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
|
||||
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -55,10 +55,71 @@ func (s ServerGroupSpecVolumeMounts) Validate() error {
|
|||
return shared.WithErrors(validateErrors...)
|
||||
}
|
||||
|
||||
type ServerGroupSpecVolumeMount core.VolumeMount
|
||||
type ServerGroupSpecVolumeMount struct {
|
||||
// This must match the Name of a Volume.
|
||||
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||
// Mounted read-only if true, read-write otherwise (false or unspecified).
|
||||
// Defaults to false.
|
||||
// +optional
|
||||
|
||||
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,2,opt,name=readOnly"`
|
||||
// RecursiveReadOnly specifies whether read-only mounts should be handled
|
||||
// recursively.
|
||||
//
|
||||
// If ReadOnly is false, this field has no meaning and must be unspecified.
|
||||
//
|
||||
// If ReadOnly is true, and this field is set to Disabled, the mount is not made
|
||||
// recursively read-only. If this field is set to IfPossible, the mount is made
|
||||
// recursively read-only, if it is supported by the container runtime. If this
|
||||
// field is set to Enabled, the mount is made recursively read-only if it is
|
||||
// supported by the container runtime, otherwise the pod will not be started and
|
||||
// an error will be generated to indicate the reason.
|
||||
//
|
||||
// If this field is set to IfPossible or Enabled, MountPropagation must be set to
|
||||
// None (or be unspecified, which defaults to None).
|
||||
//
|
||||
// If this field is not specified, it is treated as an equivalent of Disabled.
|
||||
//
|
||||
// +featureGate=RecursiveReadOnlyMounts
|
||||
// +optional
|
||||
// TODO: Uncomment after upgrade to 1.31.1+
|
||||
// RecursiveReadOnly *RecursiveReadOnlyMode `json:"recursiveReadOnly,omitempty" protobuf:"bytes,7,opt,name=recursiveReadOnly,casttype=RecursiveReadOnlyMode"`
|
||||
|
||||
// Path within the container at which the volume should be mounted. Must
|
||||
// not contain ':'.
|
||||
MountPath string `json:"mountPath" protobuf:"bytes,3,opt,name=mountPath"`
|
||||
// Path within the volume from which the container's volume should be mounted.
|
||||
// Defaults to "" (volume's root).
|
||||
// +optional
|
||||
|
||||
SubPath string `json:"subPath,omitempty" protobuf:"bytes,4,opt,name=subPath"`
|
||||
// mountPropagation determines how mounts are propagated from the host
|
||||
// to container and the other way around.
|
||||
// When not set, MountPropagationNone is used.
|
||||
// This field is beta in 1.10.
|
||||
// When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified
|
||||
// (which defaults to None).
|
||||
// +optional
|
||||
|
||||
MountPropagation *core.MountPropagationMode `json:"mountPropagation,omitempty" protobuf:"bytes,5,opt,name=mountPropagation,casttype=MountPropagationMode"`
|
||||
// Expanded path within the volume from which the container's volume should be mounted.
|
||||
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
||||
// Defaults to "" (volume's root).
|
||||
// SubPathExpr and SubPath are mutually exclusive.
|
||||
// +optional
|
||||
SubPathExpr string `json:"subPathExpr,omitempty" protobuf:"bytes,6,opt,name=subPathExpr"`
|
||||
}
|
||||
|
||||
func (s ServerGroupSpecVolumeMount) VolumeMount() core.VolumeMount {
|
||||
return core.VolumeMount(s)
|
||||
return core.VolumeMount{
|
||||
Name: s.Name,
|
||||
ReadOnly: s.ReadOnly,
|
||||
//RecursiveReadOnly: s.RecursiveReadOnly, TODO: Uncomment after upgrade to 1.31.1+
|
||||
MountPath: s.MountPath,
|
||||
SubPath: s.SubPath,
|
||||
MountPropagation: s.MountPropagation,
|
||||
SubPathExpr: s.SubPathExpr,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServerGroupSpecVolumeMount) Validate() error {
|
||||
|
|
|
@ -2907,11 +2907,6 @@ func (in *ServerGroupSpecVolumeHostPath) DeepCopy() *ServerGroupSpecVolumeHostPa
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServerGroupSpecVolumeMount) DeepCopyInto(out *ServerGroupSpecVolumeMount) {
|
||||
*out = *in
|
||||
if in.RecursiveReadOnly != nil {
|
||||
in, out := &in.RecursiveReadOnly, &out.RecursiveReadOnly
|
||||
*out = new(v1.RecursiveReadOnlyMode)
|
||||
**out = **in
|
||||
}
|
||||
if in.MountPropagation != nil {
|
||||
in, out := &in.MountPropagation, &out.MountPropagation
|
||||
*out = new(v1.MountPropagationMode)
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc"
|
||||
)
|
||||
|
||||
func basicTokenAuthAuthorize(ctx context.Context, token string) error {
|
||||
|
@ -37,7 +37,7 @@ func basicTokenAuthAuthorize(ctx context.Context, token string) error {
|
|||
return status.Errorf(codes.Unauthenticated, "metadata is not provided")
|
||||
}
|
||||
|
||||
values := md[util.AuthorizationGRPCHeader]
|
||||
values := md[ugrpc.AuthorizationGRPCHeader]
|
||||
if len(values) == 0 {
|
||||
return status.Errorf(codes.Unauthenticated, "authorization token is not provided")
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/shutdown"
|
||||
)
|
||||
|
||||
|
@ -74,7 +75,7 @@ func client[T any](ctx context.Context, cfg *Config, in func(cc grpc.ClientConnI
|
|||
var opts []grpc.DialOption
|
||||
|
||||
if token := cfg.Token; token != "" {
|
||||
opts = append(opts, util.TokenAuthInterceptors(token)...)
|
||||
opts = append(opts, ugrpc.TokenAuthInterceptors(token)...)
|
||||
}
|
||||
|
||||
if cfg.TLS.Enabled {
|
||||
|
@ -99,18 +100,18 @@ func client[T any](ctx context.Context, cfg *Config, in func(cc grpc.ClientConnI
|
|||
}
|
||||
|
||||
if cfg.TLS.Fallback {
|
||||
client, closer, err := util.NewOptionalTLSGRPCClient(ctx, in, cfg.Address, config, opts...)
|
||||
client, closer, err := ugrpc.NewOptionalTLSGRPCClient(ctx, in, cfg.Address, config, opts...)
|
||||
if err != nil {
|
||||
return util.Default[T](), nil, err
|
||||
}
|
||||
|
||||
return client, closer, nil
|
||||
} else {
|
||||
opts = append(opts, util.ClientTLS(config)...)
|
||||
opts = append(opts, ugrpc.ClientTLS(config)...)
|
||||
}
|
||||
}
|
||||
|
||||
client, closer, err := util.NewGRPCClient(ctx, in, cfg.Address, opts...)
|
||||
client, closer, err := ugrpc.NewGRPCClient(ctx, in, cfg.Address, opts...)
|
||||
if err != nil {
|
||||
return util.Default[T](), nil, err
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
|
||||
pbAuthenticationV1 "github.com/arangodb/kube-arangodb/integrations/authentication/v1/definition"
|
||||
pbImplEnvoyAuthV3 "github.com/arangodb/kube-arangodb/integrations/envoy/auth/v3"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc"
|
||||
"github.com/arangodb/kube-arangodb/pkg/util/svc"
|
||||
)
|
||||
|
||||
|
@ -60,7 +60,7 @@ func (a *envoyAuthV3) Handler(ctx context.Context, cmd *cobra.Command) (svc.Hand
|
|||
return nil, err
|
||||
}
|
||||
|
||||
c, _, err := util.NewGRPCClient(ctx, pbAuthenticationV1.NewAuthenticationV1Client, v)
|
||||
c, _, err := ugrpc.NewGRPCClient(ctx, pbAuthenticationV1.NewAuthenticationV1Client, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package util
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -35,6 +35,7 @@ import (
|
|||
|
||||
pbPongV1 "github.com/arangodb/kube-arangodb/integrations/pong/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/svc"
|
||||
)
|
||||
|
||||
|
@ -43,7 +44,7 @@ const AuthorizationGRPCHeader = "adb-authorization"
|
|||
func NewGRPCClient[T any](ctx context.Context, in func(cc grpc.ClientConnInterface) T, addr string, opts ...grpc.DialOption) (T, io.Closer, error) {
|
||||
con, err := NewGRPCConn(addr, opts...)
|
||||
if err != nil {
|
||||
return Default[T](), nil, err
|
||||
return util.Default[T](), nil, err
|
||||
}
|
||||
|
||||
return in(con), con, nil
|
||||
|
@ -52,7 +53,7 @@ func NewGRPCClient[T any](ctx context.Context, in func(cc grpc.ClientConnInterfa
|
|||
func NewOptionalTLSGRPCClient[T any](ctx context.Context, in func(cc grpc.ClientConnInterface) T, addr string, tls *tls.Config, opts ...grpc.DialOption) (T, io.Closer, error) {
|
||||
con, err := NewOptionalTLSGRPCConn(ctx, addr, tls, opts...)
|
||||
if err != nil {
|
||||
return Default[T](), nil, err
|
||||
return util.Default[T](), nil, err
|
||||
}
|
||||
|
||||
return in(con), con, nil
|
|
@ -32,12 +32,12 @@ import (
|
|||
"google.golang.org/grpc/status"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||
ugrpc "github.com/arangodb/kube-arangodb/pkg/util/grpc"
|
||||
"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 {
|
||||
client, closer, err := util.NewGRPCClient(ctx, in, addr, opts...)
|
||||
client, closer, err := ugrpc.NewGRPCClient(ctx, in, addr, opts...)
|
||||
require.NoError(t, err)
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
|
@ -76,5 +76,5 @@ func AsGRPCError(t *testing.T, err error) ErrorStatusValidator {
|
|||
}
|
||||
|
||||
func GRPCAnyCastAs[T proto.Message](t *testing.T, in *any1.Any, v T) {
|
||||
require.NoError(t, util.GRPCAnyCastAs[T](in, v))
|
||||
require.NoError(t, ugrpc.GRPCAnyCastAs[T](in, v))
|
||||
}
|
||||
|
|
60
pkg/util/tests/types/compatibility.go
Normal file
60
pkg/util/tests/types/compatibility.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// DISCLAIMER
|
||||
//
|
||||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
//
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||
)
|
||||
|
||||
func EnsureTypeForwardCompatibility(a, b reflect.Type) error {
|
||||
if a.Kind() != b.Kind() {
|
||||
return errors.Errorf("Invalid kind, got %s, expected %s", a.Kind().String(), b.Kind().String())
|
||||
}
|
||||
|
||||
if a == b {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch a.Kind() {
|
||||
case reflect.Struct:
|
||||
var err = make([]error, 0, a.NumField())
|
||||
|
||||
for id := 0; id < a.NumField(); id++ {
|
||||
f := a.Field(id)
|
||||
|
||||
bf, ok := b.FieldByName(f.Name)
|
||||
if !ok {
|
||||
err = append(err, shared.PrefixResourceError(f.Name, errors.Errorf("Field not defined in target")))
|
||||
continue
|
||||
}
|
||||
|
||||
err = append(err, shared.PrefixResourceError(f.Name, EnsureTypeForwardCompatibility(f.Type, bf.Type)))
|
||||
}
|
||||
|
||||
return shared.WithErrors(err...)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue