diff --git a/CHANGELOG.md b/CHANGELOG.md
index f9d590a18..aa3ef40f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
- (Feature) (Platform) Storage V1Alpha1
- (Feature) StorageV2 Integration Service Implementation
- (Feature) (Platform) Storage V1Alpha1 RC
+- (Feature) (Networking) ArangoRotue WebSocket Support
## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14)
- (Feature) ArangoRoute CRD
diff --git a/docs/api/ArangoRoute.V1Alpha1.md b/docs/api/ArangoRoute.V1Alpha1.md
index a2398a1e7..2c358b396 100644
--- a/docs/api/ArangoRoute.V1Alpha1.md
+++ b/docs/api/ArangoRoute.V1Alpha1.md
@@ -145,6 +145,25 @@ Insecure allows Insecure traffic
***
+### .spec.options.upgrade\[int\].enabled
+
+Type: `boolean` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go#L37)
+
+Enabled defines if upgrade option is enabled
+
+***
+
+### .spec.options.upgrade\[int\].type
+
+Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go#L34)
+
+Type defines type of the Upgrade
+
+Possible Values:
+* `"websocket"` (default) - HTTP WebSocket Upgrade type
+
+***
+
### .spec.route.path
Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_route.go#L29)
diff --git a/pkg/apis/networking/v1alpha1/route_spec.go b/pkg/apis/networking/v1alpha1/route_spec.go
index 85bb6348f..dfc945c7a 100644
--- a/pkg/apis/networking/v1alpha1/route_spec.go
+++ b/pkg/apis/networking/v1alpha1/route_spec.go
@@ -31,6 +31,9 @@ type ArangoRouteSpec struct {
// Route defines the route spec
Route *ArangoRouteSpecRoute `json:"route,omitempty"`
+
+ // Options defines connection upgrade options
+ Options *ArangoRouteSpecOptions `json:"options,omitempty"`
}
func (s *ArangoRouteSpec) GetDeployment() string {
@@ -65,6 +68,7 @@ func (s *ArangoRouteSpec) Validate() error {
shared.PrefixResourceErrors("deployment", shared.ValidateResourceNamePointer(s.Deployment)),
shared.ValidateRequiredInterfacePath("destination", s.Destination),
shared.ValidateOptionalInterfacePath("route", s.Route),
+ shared.ValidateOptionalInterfacePath("options", s.Options),
)); err != nil {
return err
}
diff --git a/pkg/apis/networking/v1alpha1/route_spec_options.go b/pkg/apis/networking/v1alpha1/route_spec_options.go
new file mode 100644
index 000000000..9b7505c90
--- /dev/null
+++ b/pkg/apis/networking/v1alpha1/route_spec_options.go
@@ -0,0 +1,42 @@
+//
+// 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 v1alpha1
+
+import shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
+
+type ArangoRouteSpecOptions struct {
+ // Upgrade keeps the connection upgrade options
+ Upgrade ArangoRouteSpecOptionsUpgrade `json:"upgrade,omitempty"`
+}
+
+func (a *ArangoRouteSpecOptions) Validate() error {
+ if a == nil {
+ a = &ArangoRouteSpecOptions{}
+ }
+
+ if err := shared.WithErrors(
+ shared.ValidateOptionalInterfacePath("upgrade", a.Upgrade),
+ ); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go b/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go
new file mode 100644
index 000000000..bb0d2fb2a
--- /dev/null
+++ b/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go
@@ -0,0 +1,48 @@
+//
+// 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 v1alpha1
+
+import shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
+
+type ArangoRouteSpecOptionsUpgrade []ArangoRouteSpecOptionUpgrade
+
+func (a ArangoRouteSpecOptionsUpgrade) Validate() error {
+ return shared.ValidateInterfaceList(a)
+}
+
+type ArangoRouteSpecOptionUpgrade struct {
+ // Type defines type of the Upgrade
+ // +doc/enum: websocket|HTTP WebSocket Upgrade type
+ Type ArangoRouteUpgradeOptionType `json:"type"`
+
+ // Enabled defines if upgrade option is enabled
+ Enabled *bool `json:"enabled,omitempty"`
+}
+
+func (a ArangoRouteSpecOptionUpgrade) Validate() error {
+ if err := shared.WithErrors(
+ shared.ValidateRequiredInterfacePath("type", a.Type),
+ ); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/apis/networking/v1alpha1/route_upgrade_type.go b/pkg/apis/networking/v1alpha1/route_upgrade_type.go
new file mode 100644
index 000000000..8c0691246
--- /dev/null
+++ b/pkg/apis/networking/v1alpha1/route_upgrade_type.go
@@ -0,0 +1,38 @@
+//
+// 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 v1alpha1
+
+import "github.com/arangodb/kube-arangodb/pkg/util/errors"
+
+type ArangoRouteUpgradeOptionType string
+
+const (
+ ArangoRouteUpgradeOptionWebsocket ArangoRouteUpgradeOptionType = "websocket"
+)
+
+func (a ArangoRouteUpgradeOptionType) Validate() error {
+ switch a {
+ case ArangoRouteUpgradeOptionWebsocket:
+ return nil
+ default:
+ return errors.Errorf("Invalid UpgradeOptionType: %s", a)
+ }
+}
diff --git a/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go
index fa67283f8..39ad7add0 100644
--- a/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go
@@ -111,6 +111,11 @@ func (in *ArangoRouteSpec) DeepCopyInto(out *ArangoRouteSpec) {
*out = new(ArangoRouteSpecRoute)
(*in).DeepCopyInto(*out)
}
+ if in.Options != nil {
+ in, out := &in.Options, &out.Options
+ *out = new(ArangoRouteSpecOptions)
+ (*in).DeepCopyInto(*out)
+ }
return
}
@@ -269,6 +274,63 @@ func (in *ArangoRouteSpecDestinationTLS) DeepCopy() *ArangoRouteSpecDestinationT
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ArangoRouteSpecOptionUpgrade) DeepCopyInto(out *ArangoRouteSpecOptionUpgrade) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteSpecOptionUpgrade.
+func (in *ArangoRouteSpecOptionUpgrade) DeepCopy() *ArangoRouteSpecOptionUpgrade {
+ if in == nil {
+ return nil
+ }
+ out := new(ArangoRouteSpecOptionUpgrade)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ArangoRouteSpecOptions) DeepCopyInto(out *ArangoRouteSpecOptions) {
+ *out = *in
+ if in.Upgrade != nil {
+ in, out := &in.Upgrade, &out.Upgrade
+ *out = make(ArangoRouteSpecOptionsUpgrade, len(*in))
+ copy(*out, *in)
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteSpecOptions.
+func (in *ArangoRouteSpecOptions) DeepCopy() *ArangoRouteSpecOptions {
+ if in == nil {
+ return nil
+ }
+ out := new(ArangoRouteSpecOptions)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in ArangoRouteSpecOptionsUpgrade) DeepCopyInto(out *ArangoRouteSpecOptionsUpgrade) {
+ {
+ in := &in
+ *out = make(ArangoRouteSpecOptionsUpgrade, len(*in))
+ copy(*out, *in)
+ return
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteSpecOptionsUpgrade.
+func (in ArangoRouteSpecOptionsUpgrade) DeepCopy() ArangoRouteSpecOptionsUpgrade {
+ if in == nil {
+ return nil
+ }
+ out := new(ArangoRouteSpecOptionsUpgrade)
+ in.DeepCopyInto(out)
+ return *out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoRouteSpecRoute) DeepCopyInto(out *ArangoRouteSpecRoute) {
*out = *in
diff --git a/pkg/apis/shared/validate.go b/pkg/apis/shared/validate.go
index b9da30205..59e5c139b 100644
--- a/pkg/apis/shared/validate.go
+++ b/pkg/apis/shared/validate.go
@@ -181,6 +181,17 @@ func ValidateRequiredInterfacePath[T ValidateInterface](path string, in T) error
return PrefixResourceErrors(path, ValidateRequiredInterface(in))
}
+// ValidateInterfaceList Validates object if is not nil with path
+func ValidateInterfaceList[T ValidateInterface](in []T) error {
+ errors := make([]error, len(in))
+
+ for id := range in {
+ errors[id] = PrefixResourceError(fmt.Sprintf("[%d]", id), in[id].Validate())
+ }
+
+ return WithErrors(errors...)
+}
+
// ValidateList validates all elements on the list
func ValidateList[T any](in []T, validator func(T) error, checks ...func(in []T) error) error {
errors := make([]error, len(in)+len(checks))
diff --git a/pkg/crd/crds/networking-route.schema.generated.yaml b/pkg/crd/crds/networking-route.schema.generated.yaml
index 9d82639de..2544f6324 100644
--- a/pkg/crd/crds/networking-route.schema.generated.yaml
+++ b/pkg/crd/crds/networking-route.schema.generated.yaml
@@ -80,6 +80,24 @@ v1alpha1:
type: boolean
type: object
type: object
+ options:
+ description: Options defines connection upgrade options
+ properties:
+ upgrade:
+ description: Upgrade keeps the connection upgrade options
+ items:
+ properties:
+ enabled:
+ description: Enabled defines if upgrade option is enabled
+ type: boolean
+ type:
+ description: Type defines type of the Upgrade
+ enum:
+ - websocket
+ type: string
+ type: object
+ type: array
+ type: object
route:
description: Route defines the route spec
properties:
diff --git a/pkg/deployment/resources/gateway/gateway_config_destination.go b/pkg/deployment/resources/gateway/gateway_config_destination.go
index 83c8b709e..d17e80089 100644
--- a/pkg/deployment/resources/gateway/gateway_config_destination.go
+++ b/pkg/deployment/resources/gateway/gateway_config_destination.go
@@ -67,6 +67,8 @@ type ConfigDestination struct {
Path *string `json:"path,omitempty"`
AuthExtension *ConfigAuthZExtension `json:"authExtension,omitempty"`
+
+ UpgradeConfigs ConfigDestinationsUpgrade `json:"upgradeConfigs,omitempty"`
}
func (c *ConfigDestination) Validate() error {
@@ -78,6 +80,7 @@ func (c *ConfigDestination) Validate() error {
shared.PrefixResourceError("type", c.Type.Validate()),
shared.PrefixResourceError("path", shared.ValidateAPIPath(c.GetPath())),
shared.PrefixResourceError("authExtension", c.AuthExtension.Validate()),
+ shared.PrefixResourceError("upgradeConfigs", c.UpgradeConfigs.Validate()),
)
}
@@ -111,13 +114,22 @@ func (c *ConfigDestination) RenderRoute(name, prefix string) (*routeAPI.Route, e
ClusterSpecifier: &routeAPI.RouteAction_Cluster{
Cluster: name,
},
- PrefixRewrite: c.GetPath(),
+ UpgradeConfigs: c.getUpgradeConfigs().render(),
+ PrefixRewrite: c.GetPath(),
},
},
TypedPerFilterConfig: tc,
}, nil
}
+func (c *ConfigDestination) getUpgradeConfigs() ConfigDestinationsUpgrade {
+ if c == nil {
+ return nil
+ }
+
+ return c.UpgradeConfigs
+}
+
func (c *ConfigDestination) RenderCluster(name string) (*clusterAPI.Cluster, error) {
hpo, err := anypb.New(&upstreamHttpApi.HttpProtocolOptions{
UpstreamProtocolOptions: &upstreamHttpApi.HttpProtocolOptions_ExplicitHttpConfig_{
diff --git a/pkg/deployment/resources/gateway/gateway_config_destination_upgrade.go b/pkg/deployment/resources/gateway/gateway_config_destination_upgrade.go
new file mode 100644
index 000000000..f4b90823b
--- /dev/null
+++ b/pkg/deployment/resources/gateway/gateway_config_destination_upgrade.go
@@ -0,0 +1,72 @@
+//
+// 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 gateway
+
+import (
+ routeAPI "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
+ "google.golang.org/protobuf/types/known/wrapperspb"
+
+ shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
+ "github.com/arangodb/kube-arangodb/pkg/util"
+ "github.com/arangodb/kube-arangodb/pkg/util/errors"
+)
+
+type ConfigDestinationsUpgrade []ConfigDestinationUpgrade
+
+func (c ConfigDestinationsUpgrade) render() []*routeAPI.RouteAction_UpgradeConfig {
+ if len(c) == 0 {
+ return nil
+ }
+
+ var r = make([]*routeAPI.RouteAction_UpgradeConfig, len(c))
+
+ for id := range c {
+ r[id] = c[id].render()
+ }
+
+ return r
+}
+
+func (c ConfigDestinationsUpgrade) Validate() error {
+ return shared.ValidateInterfaceList(c)
+}
+
+type ConfigDestinationUpgrade struct {
+ Type string `json:"type"`
+
+ Enabled *bool `json:"enabled,omitempty"`
+}
+
+func (c ConfigDestinationUpgrade) render() *routeAPI.RouteAction_UpgradeConfig {
+ return &routeAPI.RouteAction_UpgradeConfig{
+ UpgradeType: c.Type,
+ Enabled: wrapperspb.Bool(util.OptionalType(c.Enabled, true)),
+ }
+}
+
+func (c ConfigDestinationUpgrade) Validate() error {
+ switch c.Type {
+ case "websocket":
+ return nil
+ default:
+ return shared.PrefixResourceError("type", errors.Errorf("Unknown type: %s", c.Type))
+ }
+}
diff --git a/pkg/deployment/resources/gateway/gateway_config_test.go b/pkg/deployment/resources/gateway/gateway_config_test.go
index 99ba60384..05fcfd119 100644
--- a/pkg/deployment/resources/gateway/gateway_config_test.go
+++ b/pkg/deployment/resources/gateway/gateway_config_test.go
@@ -25,12 +25,16 @@ import (
"testing"
bootstrapAPI "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v3"
+ httpConnectionManagerAPI "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
"github.com/stretchr/testify/require"
"github.com/arangodb/kube-arangodb/pkg/util"
+ "github.com/arangodb/kube-arangodb/pkg/util/tests/tgrpc"
)
func renderAndPrintGatewayConfig(t *testing.T, cfg Config, validates ...func(t *testing.T, b *bootstrapAPI.Bootstrap)) {
+ require.NoError(t, cfg.Validate())
+
data, checksum, obj, err := cfg.RenderYAML()
require.NoError(t, err)
@@ -75,6 +79,136 @@ func Test_GatewayConfig(t *testing.T) {
require.EqualValues(t, 12345, b.StaticResources.Clusters[0].LoadAssignment.Endpoints[0].LbEndpoints[0].GetEndpoint().Address.GetSocketAddress().GetPortValue())
})
})
+ t.Run("Without WebSocket", func(t *testing.T) {
+ renderAndPrintGatewayConfig(t, Config{
+ DefaultDestination: ConfigDestination{
+ Targets: []ConfigDestinationTarget{
+ {
+ Host: "127.0.0.1",
+ Port: 12345,
+ },
+ },
+ },
+ }, func(t *testing.T, b *bootstrapAPI.Bootstrap) {
+ require.NotNil(t, b)
+ require.NotNil(t, b.StaticResources)
+ require.NotNil(t, b.StaticResources.Listeners)
+ require.Len(t, b.StaticResources.Listeners, 1)
+ require.NotNil(t, b.StaticResources.Listeners[0])
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain)
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters)
+ require.Len(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters, 1)
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters[0])
+ var o httpConnectionManagerAPI.HttpConnectionManager
+ tgrpc.GRPCAnyCastAs(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters[0].GetTypedConfig(), &o)
+ rc := o.GetRouteConfig()
+ require.NotNil(t, rc)
+ require.NotNil(t, rc.VirtualHosts)
+ require.Len(t, rc.VirtualHosts, 1)
+ require.NotNil(t, rc.VirtualHosts[0])
+ require.Len(t, rc.VirtualHosts[0].Routes, 1)
+ require.NotNil(t, rc.VirtualHosts[0].Routes[0])
+ r := rc.VirtualHosts[0].Routes[0].GetRoute()
+ require.NotNil(t, r)
+ require.Len(t, r.UpgradeConfigs, 0)
+ })
+ })
+
+ t.Run("With WebSocket", func(t *testing.T) {
+ renderAndPrintGatewayConfig(t, Config{
+ DefaultDestination: ConfigDestination{
+ Targets: []ConfigDestinationTarget{
+ {
+ Host: "127.0.0.1",
+ Port: 12345,
+ },
+ },
+ UpgradeConfigs: ConfigDestinationsUpgrade{
+ {
+ Type: "websocket",
+ },
+ },
+ },
+ }, func(t *testing.T, b *bootstrapAPI.Bootstrap) {
+ require.NotNil(t, b)
+ require.NotNil(t, b.StaticResources)
+ require.NotNil(t, b.StaticResources.Listeners)
+ require.Len(t, b.StaticResources.Listeners, 1)
+ require.NotNil(t, b.StaticResources.Listeners[0])
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain)
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters)
+ require.Len(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters, 1)
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters[0])
+ var o httpConnectionManagerAPI.HttpConnectionManager
+ tgrpc.GRPCAnyCastAs(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters[0].GetTypedConfig(), &o)
+ rc := o.GetRouteConfig()
+ require.NotNil(t, rc)
+ require.NotNil(t, rc.VirtualHosts)
+ require.Len(t, rc.VirtualHosts, 1)
+ require.NotNil(t, rc.VirtualHosts[0])
+ require.Len(t, rc.VirtualHosts[0].Routes, 1)
+ require.NotNil(t, rc.VirtualHosts[0].Routes[0])
+ r := rc.VirtualHosts[0].Routes[0].GetRoute()
+ require.NotNil(t, r)
+ require.Len(t, r.UpgradeConfigs, 1)
+ require.NotNil(t, r.UpgradeConfigs[0])
+ require.EqualValues(t, "websocket", r.UpgradeConfigs[0].UpgradeType)
+ require.NotNil(t, r.UpgradeConfigs[0].Enabled)
+ require.True(t, r.UpgradeConfigs[0].Enabled.GetValue())
+ })
+ })
+
+ t.Run("With Multi WebSocket", func(t *testing.T) {
+ renderAndPrintGatewayConfig(t, Config{
+ DefaultDestination: ConfigDestination{
+ Targets: []ConfigDestinationTarget{
+ {
+ Host: "127.0.0.1",
+ Port: 12345,
+ },
+ },
+ UpgradeConfigs: ConfigDestinationsUpgrade{
+ {
+ Type: "websocket",
+ },
+ {
+ Type: "websocket",
+ Enabled: util.NewType(false),
+ },
+ },
+ },
+ }, func(t *testing.T, b *bootstrapAPI.Bootstrap) {
+ require.NotNil(t, b)
+ require.NotNil(t, b.StaticResources)
+ require.NotNil(t, b.StaticResources.Listeners)
+ require.Len(t, b.StaticResources.Listeners, 1)
+ require.NotNil(t, b.StaticResources.Listeners[0])
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain)
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters)
+ require.Len(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters, 1)
+ require.NotNil(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters[0])
+ var o httpConnectionManagerAPI.HttpConnectionManager
+ tgrpc.GRPCAnyCastAs(t, b.StaticResources.Listeners[0].DefaultFilterChain.Filters[0].GetTypedConfig(), &o)
+ rc := o.GetRouteConfig()
+ require.NotNil(t, rc)
+ require.NotNil(t, rc.VirtualHosts)
+ require.Len(t, rc.VirtualHosts, 1)
+ require.NotNil(t, rc.VirtualHosts[0])
+ require.Len(t, rc.VirtualHosts[0].Routes, 1)
+ require.NotNil(t, rc.VirtualHosts[0].Routes[0])
+ r := rc.VirtualHosts[0].Routes[0].GetRoute()
+ require.NotNil(t, r)
+ require.Len(t, r.UpgradeConfigs, 2)
+ require.NotNil(t, r.UpgradeConfigs[0])
+ require.NotNil(t, r.UpgradeConfigs[1])
+ require.EqualValues(t, "websocket", r.UpgradeConfigs[0].UpgradeType)
+ require.NotNil(t, r.UpgradeConfigs[0].Enabled)
+ require.True(t, r.UpgradeConfigs[0].Enabled.GetValue())
+ require.EqualValues(t, "websocket", r.UpgradeConfigs[1].UpgradeType)
+ require.NotNil(t, r.UpgradeConfigs[1].Enabled)
+ require.False(t, r.UpgradeConfigs[1].Enabled.GetValue())
+ })
+ })
t.Run("Default", func(t *testing.T) {
renderAndPrintGatewayConfig(t, Config{
diff --git a/pkg/util/grpc.go b/pkg/util/grpc.go
index 254887b16..b5c1f9685 100644
--- a/pkg/util/grpc.go
+++ b/pkg/util/grpc.go
@@ -25,11 +25,13 @@ import (
"crypto/tls"
"io"
+ any1 "github.com/golang/protobuf/ptypes/any"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
+ proto "google.golang.org/protobuf/proto"
pbPongV1 "github.com/arangodb/kube-arangodb/integrations/pong/v1/definition"
pbSharedV1 "github.com/arangodb/kube-arangodb/integrations/shared/v1/definition"
@@ -133,3 +135,11 @@ func TokenAuthInterceptors(token string) []grpc.DialOption {
func attachTokenAuthToInterceptors(ctx context.Context, token string) context.Context {
return metadata.AppendToOutgoingContext(ctx, AuthorizationGRPCHeader, token)
}
+
+func GRPCAnyCastAs[T proto.Message](in *any1.Any, v T) error {
+ if err := in.UnmarshalTo(v); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/util/tests/tgrpc/grpc.go b/pkg/util/tests/tgrpc/grpc.go
index 7145aa842..a977c22c0 100644
--- a/pkg/util/tests/tgrpc/grpc.go
+++ b/pkg/util/tests/tgrpc/grpc.go
@@ -25,10 +25,12 @@ import (
"fmt"
"testing"
+ any1 "github.com/golang/protobuf/ptypes/any"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
+ proto "google.golang.org/protobuf/proto"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/svc"
@@ -72,3 +74,7 @@ func AsGRPCError(t *testing.T, err error) ErrorStatusValidator {
require.NotNil(t, st)
return errorStatusValidator{st: st}
}
+
+func GRPCAnyCastAs[T proto.Message](t *testing.T, in *any1.Any, v T) {
+ require.NoError(t, util.GRPCAnyCastAs[T](in, v))
+}