1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

[Feature] [Networking] Gateway options sync (#1780)

This commit is contained in:
Adam Janikowski 2024-12-10 23:40:39 +01:00 committed by GitHub
parent c7cce48584
commit 3993a0c40f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 385 additions and 13 deletions

View file

@ -32,6 +32,7 @@
- (Feature) (Platform) Shutdown migration to CE
- (Feature) (Scheduler) Shutdown Integration
- (Feature) CertManager Integration
- (Feature) (Networking) Gateway Options sync
## [1.2.43](https://github.com/arangodb/kube-arangodb/tree/1.2.43) (2024-10-14)
- (Feature) ArangoRoute CRD

View file

@ -163,7 +163,7 @@ Insecure allows Insecure traffic
### .spec.options.upgrade\[int\].enabled
Type: `boolean` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go#L37)</sup>
Type: `boolean` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go#L50)</sup>
Enabled defines if upgrade option is enabled
@ -171,7 +171,7 @@ Enabled defines if upgrade option is enabled
### .spec.options.upgrade\[int\].type
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go#L34)</sup>
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_options_upgrade.go#L47)</sup>
Type defines type of the Upgrade
@ -252,9 +252,28 @@ Type: `integer` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.
***
### .status.target.options.upgrade\[int\].enabled
Type: `boolean` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target_options_upgrade.go#L43)</sup>
Enabled defines if upgrade option is enabled
***
### .status.target.options.upgrade\[int\].type
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target_options_upgrade.go#L40)</sup>
Type defines type of the Upgrade
Possible Values:
* `"websocket"` (default) - HTTP WebSocket Upgrade type
***
### .status.target.path
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L46)</sup>
Type: `string` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L49)</sup>
Path specifies request path override
@ -268,7 +287,7 @@ Protocol defines http protocol used for the route
***
### .status.target.TLS.insecure
### .status.target.tls.insecure
Type: `boolean` <sup>[\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target_tls.go#L27)</sup>

View file

@ -17,8 +17,8 @@ Example:
```yaml
metadata:
annotations:
core.shutdown.arangodb.com/app: "true"
core.shutdown.arangodb.com/app2: "true"
core.shutdown.arangodb.com/app: "wait"
core.shutdown.arangodb.com/app2: "wait"
container.shutdown.arangodb.com/app3: port1
spec:
containers:

View file

@ -27,6 +27,16 @@ type ArangoRouteSpecOptions struct {
Upgrade ArangoRouteSpecOptionsUpgrade `json:"upgrade,omitempty"`
}
func (a *ArangoRouteSpecOptions) AsStatus() *ArangoRouteStatusTargetOptions {
if a == nil {
return nil
}
return &ArangoRouteStatusTargetOptions{
Upgrade: a.Upgrade.asStatus(),
}
}
func (a *ArangoRouteSpecOptions) Validate() error {
if a == nil {
a = &ArangoRouteSpecOptions{}

View file

@ -20,7 +20,10 @@
package v1alpha1
import shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
import (
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
"github.com/arangodb/kube-arangodb/pkg/util"
)
type ArangoRouteSpecOptionsUpgrade []ArangoRouteSpecOptionUpgrade
@ -28,6 +31,16 @@ func (a ArangoRouteSpecOptionsUpgrade) Validate() error {
return shared.ValidateInterfaceList(a)
}
func (a ArangoRouteSpecOptionsUpgrade) asStatus() ArangoRouteStatusTargetOptionsUpgrade {
if len(a) == 0 {
return nil
}
return util.FormatList(a, func(a ArangoRouteSpecOptionUpgrade) ArangoRouteStatusTargetOptionUpgrade {
return a.asStatus()
})
}
type ArangoRouteSpecOptionUpgrade struct {
// Type defines type of the Upgrade
// +doc/enum: websocket|HTTP WebSocket Upgrade type
@ -37,6 +50,13 @@ type ArangoRouteSpecOptionUpgrade struct {
Enabled *bool `json:"enabled,omitempty"`
}
func (a ArangoRouteSpecOptionUpgrade) asStatus() ArangoRouteStatusTargetOptionUpgrade {
return ArangoRouteStatusTargetOptionUpgrade{
Type: a.Type,
Enabled: util.NewType(util.WithDefault(a.Enabled)),
}
}
func (a ArangoRouteSpecOptionUpgrade) Validate() error {
if err := shared.WithErrors(
shared.ValidateRequiredInterfacePath("type", a.Type),

View file

@ -34,7 +34,7 @@ type ArangoRouteStatusTarget struct {
Type ArangoRouteStatusTargetType `json:"type,omitempty"`
// TLS Keeps target TLS Settings (if not nil, TLS is enabled)
TLS *ArangoRouteStatusTargetTLS `json:"TLS,omitempty"`
TLS *ArangoRouteStatusTargetTLS `json:"tls,omitempty"`
// Protocol defines http protocol used for the route
Protocol ArangoRouteDestinationProtocol `json:"protocol,omitempty"`
@ -42,6 +42,9 @@ type ArangoRouteStatusTarget struct {
// Authentication specifies the authentication details
Authentication ArangoRouteStatusTargetAuthentication `json:"authentication,omitempty"`
// Options defines connection upgrade options
Options *ArangoRouteStatusTargetOptions `json:"options,omitempty"`
// Path specifies request path override
Path string `json:"path,omitempty"`
}
@ -70,5 +73,5 @@ func (a *ArangoRouteStatusTarget) Hash() string {
if a == nil {
return ""
}
return util.SHA256FromStringArray(a.Destinations.Hash(), a.Type.Hash(), a.TLS.Hash(), a.Path, a.Authentication.Hash())
return util.SHA256FromStringArray(a.Destinations.Hash(), a.Type.Hash(), a.TLS.Hash(), a.Protocol.String(), a.Path, a.Authentication.Hash(), a.Options.Hash())
}

View file

@ -0,0 +1,36 @@
//
// 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 Statusific 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"
type ArangoRouteStatusTargetOptions struct {
// Upgrade keeps the connection upgrade options
Upgrade ArangoRouteStatusTargetOptionsUpgrade `json:"upgrade,omitempty"`
}
func (a *ArangoRouteStatusTargetOptions) Hash() string {
if a == nil {
return ""
}
return util.SHA256FromStringArray(a.Upgrade.Hash())
}

View file

@ -0,0 +1,52 @@
//
// 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 Statusific 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"
type ArangoRouteStatusTargetOptionsUpgrade []ArangoRouteStatusTargetOptionUpgrade
func (a ArangoRouteStatusTargetOptionsUpgrade) Hash() string {
if len(a) == 0 {
return ""
}
return util.SHA256FromStringArray(util.FormatList(a, func(a ArangoRouteStatusTargetOptionUpgrade) string {
return a.Hash()
})...)
}
type ArangoRouteStatusTargetOptionUpgrade 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 *ArangoRouteStatusTargetOptionUpgrade) Hash() string {
if a == nil {
return ""
}
return util.SHA256FromStringArray(string(a.Type), util.BoolSwitch(util.WithDefault(a.Enabled), "true", "false"))
}

View file

@ -413,6 +413,11 @@ func (in *ArangoRouteStatusTarget) DeepCopyInto(out *ArangoRouteStatusTarget) {
(*in).DeepCopyInto(*out)
}
out.Authentication = in.Authentication
if in.Options != nil {
in, out := &in.Options, &out.Options
*out = new(ArangoRouteStatusTargetOptions)
(*in).DeepCopyInto(*out)
}
return
}
@ -478,6 +483,72 @@ func (in ArangoRouteStatusTargetDestinations) DeepCopy() ArangoRouteStatusTarget
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoRouteStatusTargetOptionUpgrade) DeepCopyInto(out *ArangoRouteStatusTargetOptionUpgrade) {
*out = *in
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteStatusTargetOptionUpgrade.
func (in *ArangoRouteStatusTargetOptionUpgrade) DeepCopy() *ArangoRouteStatusTargetOptionUpgrade {
if in == nil {
return nil
}
out := new(ArangoRouteStatusTargetOptionUpgrade)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoRouteStatusTargetOptions) DeepCopyInto(out *ArangoRouteStatusTargetOptions) {
*out = *in
if in.Upgrade != nil {
in, out := &in.Upgrade, &out.Upgrade
*out = make(ArangoRouteStatusTargetOptionsUpgrade, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteStatusTargetOptions.
func (in *ArangoRouteStatusTargetOptions) DeepCopy() *ArangoRouteStatusTargetOptions {
if in == nil {
return nil
}
out := new(ArangoRouteStatusTargetOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in ArangoRouteStatusTargetOptionsUpgrade) DeepCopyInto(out *ArangoRouteStatusTargetOptionsUpgrade) {
{
in := &in
*out = make(ArangoRouteStatusTargetOptionsUpgrade, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
return
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArangoRouteStatusTargetOptionsUpgrade.
func (in ArangoRouteStatusTargetOptionsUpgrade) DeepCopy() ArangoRouteStatusTargetOptionsUpgrade {
if in == nil {
return nil
}
out := new(ArangoRouteStatusTargetOptionsUpgrade)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ArangoRouteStatusTargetTLS) DeepCopyInto(out *ArangoRouteStatusTargetTLS) {
*out = *in

View file

@ -206,6 +206,21 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto
}
if tls := target.TLS; tls != nil {
dest.Type = util.NewType(gateway.ConfigDestinationTypeHTTPS)
dest.TLS.Insecure = util.NewType(tls.IsInsecure())
}
switch target.Protocol {
case networkingApi.ArangoRouteDestinationProtocolHTTP1:
dest.Protocol = util.NewType(gateway.ConfigDestinationProtocolHTTP1)
case networkingApi.ArangoRouteDestinationProtocolHTTP2:
dest.Protocol = util.NewType(gateway.ConfigDestinationProtocolHTTP2)
}
if opts := target.Options; opts != nil {
for _, upgrade := range opts.Upgrade {
dest.UpgradeConfigs = append(dest.UpgradeConfigs, gateway.ConfigDestinationUpgrade{
Type: string(upgrade.Type),
Enabled: util.NewType(util.WithDefault(upgrade.Enabled)),
})
}
}
dest.Path = util.NewType(target.Path)
dest.AuthExtension = &gateway.ConfigAuthZExtension{

View file

@ -0,0 +1,44 @@
//
// DISCLAIMER
//
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
package gateway
import "strings"
type ALPNProtocol int
const (
ALPNProtocolHTTP1 ALPNProtocol = 1 << iota
ALPNProtocolHTTP2 ALPNProtocol = 1 << iota
)
func (a ALPNProtocol) String() string {
elements := make([]string, 0, 2)
if a&ALPNProtocolHTTP2 == ALPNProtocolHTTP2 {
elements = append(elements, "h2")
}
if a&ALPNProtocolHTTP1 == ALPNProtocolHTTP1 {
elements = append(elements, "http/1.1")
}
return strings.Join(elements, ",")
}

View file

@ -0,0 +1,35 @@
//
// 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 (
"testing"
"github.com/stretchr/testify/require"
)
func Test_ALPN(t *testing.T) {
require.Equal(t, "", ALPNProtocol(0).String())
require.Equal(t, "http/1.1", ALPNProtocolHTTP1.String())
require.Equal(t, "h2", ALPNProtocolHTTP2.String())
require.Equal(t, "h2,http/1.1", (ALPNProtocolHTTP1 | ALPNProtocolHTTP2).String())
require.Equal(t, "h2,http/1.1", (ALPNProtocolHTTP2 | ALPNProtocolHTTP1).String())
}

View file

@ -68,6 +68,8 @@ type ConfigDestination struct {
AuthExtension *ConfigAuthZExtension `json:"authExtension,omitempty"`
UpgradeConfigs ConfigDestinationsUpgrade `json:"upgradeConfigs,omitempty"`
TLS ConfigDestinationTLS `json:"tls,omitempty"`
}
func (c *ConfigDestination) Validate() error {
@ -78,6 +80,7 @@ func (c *ConfigDestination) Validate() error {
shared.PrefixResourceError("targets", c.Targets.Validate()),
shared.PrefixResourceError("type", c.Type.Validate()),
shared.PrefixResourceError("protocol", c.Protocol.Validate()),
shared.PrefixResourceError("tls", c.TLS.Validate()),
shared.PrefixResourceError("path", shared.ValidateAPIPath(c.GetPath())),
shared.PrefixResourceError("authExtension", c.AuthExtension.Validate()),
shared.PrefixResourceError("upgradeConfigs", c.UpgradeConfigs.Validate()),
@ -153,7 +156,7 @@ func (c *ConfigDestination) RenderCluster(name string) (*clusterAPI.Cluster, err
},
}
if t, err := c.Type.RenderUpstreamTransportSocket(); err != nil {
if t, err := c.Type.RenderUpstreamTransportSocket(c.Protocol, c.TLS); err != nil {
return nil, err
} else {
cluster.TransportSocket = t

View file

@ -50,6 +50,17 @@ func (c *ConfigDestinationProtocol) Get() ConfigDestinationProtocol {
}
}
func (c *ConfigDestinationProtocol) ALPN() ALPNProtocol {
switch c.Get() {
case ConfigDestinationProtocolHTTP1:
return ALPNProtocolHTTP1
case ConfigDestinationProtocolHTTP2:
return ALPNProtocolHTTP2
default:
return ALPNProtocolHTTP1
}
}
func (c *ConfigDestinationProtocol) Options() *upstreamHttpApi.HttpProtocolOptions {
switch c.Get() {
case ConfigDestinationProtocolHTTP1:

View file

@ -0,0 +1,37 @@
//
// DISCLAIMER
//
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
package gateway
type ConfigDestinationTLS struct {
Insecure *bool `json:"insecure,omitempty"`
}
func (c *ConfigDestinationTLS) Validate() error {
return nil
}
func (c *ConfigDestinationTLS) IsInsecure() bool {
if c == nil || c.Insecure == nil {
return false
}
return *c.Insecure
}

View file

@ -25,6 +25,7 @@ import (
tlsApi "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
"google.golang.org/protobuf/types/known/anypb"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
)
@ -48,11 +49,16 @@ func (c *ConfigDestinationType) Get() ConfigDestinationType {
}
}
func (c *ConfigDestinationType) RenderUpstreamTransportSocket() (*coreAPI.TransportSocket, error) {
func (c *ConfigDestinationType) RenderUpstreamTransportSocket(protocol *ConfigDestinationProtocol, config ConfigDestinationTLS) (*coreAPI.TransportSocket, error) {
if c.Get() == ConfigDestinationTypeHTTPS {
tlsConfig, err := anypb.New(&tlsApi.UpstreamTlsContext{
CommonTlsContext: &tlsApi.CommonTlsContext{
ValidationContextType: &tlsApi.CommonTlsContext_ValidationContext{},
AlpnProtocols: []string{protocol.ALPN().String()},
ValidationContextType: &tlsApi.CommonTlsContext_ValidationContext{
ValidationContext: &tlsApi.CertificateValidationContext{
TrustChainVerification: util.BoolSwitch(!config.IsInsecure(), tlsApi.CertificateValidationContext_VERIFY_TRUST_CHAIN, tlsApi.CertificateValidationContext_ACCEPT_UNTRUSTED),
},
},
},
})
if err != nil {

View file

@ -54,7 +54,7 @@ func (c *ConfigTLS) RenderListenerTransportSocket() (*coreAPI.TransportSocket, e
},
},
},
AlpnProtocols: []string{"h2,http/1.1"},
AlpnProtocols: []string{(ALPNProtocolHTTP2 | ALPNProtocolHTTP1).String()},
},
})
if err != nil {

View file

@ -122,6 +122,8 @@ func (h *handler) HandleArangoDestinationEndpoints(ctx context.Context, item ope
target.Type = networkingApi.ArangoRouteStatusTargetEndpointsType
target.Protocol = dest.GetProtocol().Get()
target.Options = extension.Spec.Options.AsStatus()
// Render Auth Settings
target.Authentication.Type = dest.GetAuthentication().GetType()

View file

@ -121,6 +121,8 @@ func (h *handler) HandleArangoDestinationService(ctx context.Context, item opera
target.Type = networkingApi.ArangoRouteStatusTargetServiceType
target.Protocol = dest.GetProtocol().Get()
target.Options = extension.Spec.Options.AsStatus()
// Render Auth Settings
target.Authentication.Type = dest.GetAuthentication().GetType()

View file

@ -83,6 +83,11 @@ func (h *handler) Handle(ctx context.Context, item operation.Item) error {
// Container is not yet stopped, skip shutdown
return nil
}
default:
if container.State.Terminated == nil {
// Container is not yet stopped, skip shutdown
return nil
}
}
}