diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d0adde5f..ac20f3c68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ - (Bugfix) (Platform) Proper Path handler in StorageV2 - (Feature) Helm Chart Values merge methods - (Feature) (Platform) Expose Route Name via Header +- (Feature) (Platform) Route Upstream Timeout ## [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 676ae906c..26bec1a7f 100644 --- a/docs/api/ArangoRoute.V1Alpha1.md +++ b/docs/api/ArangoRoute.V1Alpha1.md @@ -83,7 +83,7 @@ UID keeps the information about object UID ### .spec.destination.path -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L46) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L51) Path defines service path used for overrides @@ -91,7 +91,7 @@ Path defines service path used for overrides ### .spec.destination.protocol -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L40) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L45) Protocol defines http protocol used for the route @@ -103,7 +103,7 @@ Possible Values: ### .spec.destination.schema -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L35) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L40) Schema defines HTTP/S schema used for connection @@ -153,6 +153,14 @@ UID keeps the information about object UID *** +### .spec.destination.timeout + +Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination.go#L57) + +Timeout specify the upstream request timeout + +*** + ### .spec.destination.tls.insecure Type: `boolean` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_spec_destination_tls.go#L25) @@ -273,7 +281,7 @@ Possible Values: ### .status.target.path -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L49) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L51) Path specifies request path override @@ -281,12 +289,20 @@ Path specifies request path override ### .status.target.protocol -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L40) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L42) Protocol defines http protocol used for the route *** +### .status.target.timeout + +Type: `integer` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L54) + +Timeout specify the upstream request timeout + +*** + ### .status.target.tls.insecure Type: `boolean` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target_tls.go#L27) @@ -297,7 +313,7 @@ Insecure allows Insecure traffic ### .status.target.type -Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L34) +Type: `string` [\[ref\]](https://github.com/arangodb/kube-arangodb/blob/1.2.43/pkg/apis/networking/v1alpha1/route_status_target.go#L36) Type define destination type diff --git a/pkg/apis/networking/v1alpha1/route_spec_destination.go b/pkg/apis/networking/v1alpha1/route_spec_destination.go index c4d32f683..2366415d3 100644 --- a/pkg/apis/networking/v1alpha1/route_spec_destination.go +++ b/pkg/apis/networking/v1alpha1/route_spec_destination.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -20,7 +20,12 @@ package v1alpha1 -import shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" +import ( + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + + shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" + "github.com/arangodb/kube-arangodb/pkg/util/constants" +) type ArangoRouteSpecDestination struct { // Service defines service upstream reference @@ -47,6 +52,9 @@ type ArangoRouteSpecDestination struct { // Authentication defines auth methods Authentication *ArangoRouteSpecDestinationAuthentication `json:"authentication,omitempty"` + + // Timeout specify the upstream request timeout + Timeout *meta.Duration `json:"timeout,omitempty"` } func (a *ArangoRouteSpecDestination) GetService() *ArangoRouteSpecDestinationService { @@ -89,6 +97,16 @@ func (a *ArangoRouteSpecDestination) GetPath() string { return *a.Path } +func (a *ArangoRouteSpecDestination) GetTimeout() meta.Duration { + if a == nil || a.Timeout == nil { + return meta.Duration{ + Duration: constants.DefaultEnvoyUpstreamTimeout, + } + } + + return *a.Timeout +} + func (a *ArangoRouteSpecDestination) GetTLS() *ArangoRouteSpecDestinationTLS { if a == nil || a.TLS == nil { return nil diff --git a/pkg/apis/networking/v1alpha1/route_status_target.go b/pkg/apis/networking/v1alpha1/route_status_target.go index 2b8cb5bd7..c166a0525 100644 --- a/pkg/apis/networking/v1alpha1/route_status_target.go +++ b/pkg/apis/networking/v1alpha1/route_status_target.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -23,6 +23,8 @@ package v1alpha1 import ( "fmt" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/arangodb/kube-arangodb/pkg/util" ) @@ -47,6 +49,9 @@ type ArangoRouteStatusTarget struct { // Path specifies request path override Path string `json:"path,omitempty"` + + // Timeout specify the upstream request timeout + Timeout meta.Duration `json:"timeout,omitempty"` } func (a *ArangoRouteStatusTarget) RenderURLs() []string { @@ -73,5 +78,5 @@ func (a *ArangoRouteStatusTarget) Hash() string { if a == nil { return "" } - return util.SHA256FromStringArray(a.Destinations.Hash(), a.Type.Hash(), a.TLS.Hash(), a.Protocol.String(), a.Path, a.Authentication.Hash(), a.Options.Hash()) + return util.SHA256FromStringArray(a.Destinations.Hash(), a.Type.Hash(), a.TLS.Hash(), a.Protocol.String(), a.Path, a.Authentication.Hash(), a.Options.Hash(), a.Timeout.String()) } diff --git a/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go index 7058314e5..c6698d399 100644 --- a/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go @@ -27,7 +27,8 @@ package v1alpha1 import ( deploymentv1 "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" - v1 "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1" + sharedv1 "github.com/arangodb/kube-arangodb/pkg/apis/shared/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" intstr "k8s.io/apimachinery/pkg/util/intstr" ) @@ -167,6 +168,11 @@ func (in *ArangoRouteSpecDestination) DeepCopyInto(out *ArangoRouteSpecDestinati *out = new(ArangoRouteSpecDestinationAuthentication) (*in).DeepCopyInto(*out) } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(v1.Duration) + **out = **in + } return } @@ -211,7 +217,7 @@ func (in *ArangoRouteSpecDestinationEndpoints) DeepCopyInto(out *ArangoRouteSpec *out = *in if in.Object != nil { in, out := &in.Object, &out.Object - *out = new(v1.Object) + *out = new(sharedv1.Object) (*in).DeepCopyInto(*out) } if in.Port != nil { @@ -237,7 +243,7 @@ func (in *ArangoRouteSpecDestinationService) DeepCopyInto(out *ArangoRouteSpecDe *out = *in if in.Object != nil { in, out := &in.Object, &out.Object - *out = new(v1.Object) + *out = new(sharedv1.Object) (*in).DeepCopyInto(*out) } if in.Port != nil { @@ -378,7 +384,7 @@ func (in *ArangoRouteStatus) DeepCopyInto(out *ArangoRouteStatus) { } if in.Deployment != nil { in, out := &in.Deployment, &out.Deployment - *out = new(v1.Object) + *out = new(sharedv1.Object) (*in).DeepCopyInto(*out) } if in.Target != nil { @@ -418,6 +424,7 @@ func (in *ArangoRouteStatusTarget) DeepCopyInto(out *ArangoRouteStatusTarget) { *out = new(ArangoRouteStatusTargetOptions) (*in).DeepCopyInto(*out) } + out.Timeout = in.Timeout return } diff --git a/pkg/apis/shared/errors.go b/pkg/apis/shared/errors.go index 9e15af9da..6887b53c4 100644 --- a/pkg/apis/shared/errors.go +++ b/pkg/apis/shared/errors.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2016-2022 ArangoDB GmbH, Cologne, Germany +// Copyright 2016-2025 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. @@ -53,6 +53,11 @@ func (p *ResourceError) Format(s fmt.State, verb rune) { } } +// PrefixResourceErrorFunc creates new prefixed error from func output. If error is already prefixed then current key is appended +func PrefixResourceErrorFunc(prefix string, f func() error) error { + return PrefixResourceError(prefix, f()) +} + // PrefixResourceError creates new prefixed error. If error is already prefixed then current key is appended func PrefixResourceError(prefix string, err error) error { if err == nil { diff --git a/pkg/crd/crds/networking-route.schema.generated.yaml b/pkg/crd/crds/networking-route.schema.generated.yaml index d8ba4e7d7..cfa8761cb 100644 --- a/pkg/crd/crds/networking-route.schema.generated.yaml +++ b/pkg/crd/crds/networking-route.schema.generated.yaml @@ -81,6 +81,9 @@ v1alpha1: description: UID keeps the information about object UID type: string type: object + timeout: + description: Timeout specify the upstream request timeout + type: string tls: description: TLS defines TLS Configuration properties: diff --git a/pkg/deployment/resources/config_map_gateway.go b/pkg/deployment/resources/config_map_gateway.go index 0e840a453..6c8d23d35 100644 --- a/pkg/deployment/resources/config_map_gateway.go +++ b/pkg/deployment/resources/config_map_gateway.go @@ -34,6 +34,7 @@ import ( networkingApi "github.com/arangodb/kube-arangodb/pkg/apis/networking/v1alpha1" shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" "github.com/arangodb/kube-arangodb/pkg/deployment/resources/gateway" + "github.com/arangodb/kube-arangodb/pkg/platform" "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/errors" @@ -44,21 +45,35 @@ import ( "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/patcher" ) -const ( - EnvoyRouteHeader = "arangodb-platform-route" -) - func (r *Resources) ensureGatewayConfig(ctx context.Context, cachedStatus inspectorInterface.Inspector, configMaps generic.ModClient[*core.ConfigMap]) error { - deploymentName := r.context.GetAPIObject().GetName() - configMapName := GetGatewayConfigMapName(deploymentName) - - log := r.log.Str("section", "gateway-config").Str("name", configMapName) - cfg, err := r.renderGatewayConfig(cachedStatus) if err != nil { return errors.WithStack(errors.Wrapf(err, "Failed to generate gateway config")) } + _, baseGatewayCfgYamlChecksum, _, err := cfg.RenderYAML() + if err != nil { + return errors.WithStack(errors.Wrapf(err, "Failed to render gateway config")) + } + + cfg.Destinations[constants.EnvoyInventoryConfigDestination] = gateway.ConfigDestination{ + Type: util.NewType(gateway.ConfigDestinationTypeStatic), + AuthExtension: &gateway.ConfigAuthZExtension{ + AuthZExtension: map[string]string{ + pbImplEnvoyAuthV3.AuthConfigAuthRequiredKey: pbImplEnvoyAuthV3.AuthConfigKeywordTrue, + pbImplEnvoyAuthV3.AuthConfigAuthPassModeKey: string(networkingApi.ArangoRouteSpecAuthenticationPassModeRemove), + }, + }, + Static: &gateway.ConfigDestinationStatic{ + Code: util.NewType[uint32](200), + Response: &platform.State{ + Configuration: platform.StateConfiguration{ + Hash: baseGatewayCfgYamlChecksum, + }, + }, + }, + } + gatewayCfgYaml, _, _, err := cfg.RenderYAML() if err != nil { return errors.WithStack(errors.Wrapf(err, "Failed to render gateway config")) @@ -74,20 +89,40 @@ func (r *Resources) ensureGatewayConfig(ctx context.Context, cachedStatus inspec return errors.WithStack(errors.Wrapf(err, "Failed to render gateway lds config")) } - elements, err := r.renderConfigMap(map[string]string{ - GatewayConfigFileName: string(gatewayCfgYaml), - GatewayCDSConfigFileName: string(gatewayCfgCDSYaml), - GatewayLDSConfigFileName: string(gatewayCfgLDSYaml), - }) + if err := r.ensureGatewayConfigMap(ctx, cachedStatus, configMaps, GetGatewayConfigMapName(r.context.GetAPIObject().GetName()), map[string]string{ + constants.GatewayConfigFileName: string(gatewayCfgYaml), + }); err != nil { + return err + } + + if err := r.ensureGatewayConfigMap(ctx, cachedStatus, configMaps, GetGatewayConfigMapName(r.context.GetAPIObject().GetName(), "cds"), map[string]string{ + constants.GatewayConfigFileName: string(gatewayCfgCDSYaml), + }); err != nil { + return err + } + + if err := r.ensureGatewayConfigMap(ctx, cachedStatus, configMaps, GetGatewayConfigMapName(r.context.GetAPIObject().GetName(), "lds"), map[string]string{ + constants.GatewayConfigFileName: string(gatewayCfgLDSYaml), + }); err != nil { + return err + } + + return nil +} + +func (r *Resources) ensureGatewayConfigMap(ctx context.Context, cachedStatus inspectorInterface.Inspector, configMaps generic.ModClient[*core.ConfigMap], name string, data map[string]string) error { + log := r.log.Str("section", "gateway-config").Str("name", name) + + elements, err := r.renderConfigMap(data) if err != nil { return errors.WithStack(errors.Wrapf(err, "Failed to render gateway config")) } - if cm, exists := cachedStatus.ConfigMap().V1().GetSimple(configMapName); !exists { + if cm, exists := cachedStatus.ConfigMap().V1().GetSimple(name); !exists { // Create cm = &core.ConfigMap{ ObjectMeta: meta.ObjectMeta{ - Name: configMapName, + Name: name, }, Data: elements, } @@ -108,7 +143,7 @@ func (r *Resources) ensureGatewayConfig(ctx context.Context, cachedStatus inspec return errors.Reconcile() } else { // CM Exists, checks checksum - if key is not in the map we return empty string - if currentSha, expectedSha := util.Optional(cm.Data, ConfigMapChecksumKey, ""), util.Optional(elements, ConfigMapChecksumKey, ""); currentSha != expectedSha || currentSha == "" { + if currentSha, expectedSha := util.Optional(cm.Data, constants.ConfigMapChecksumKey, ""), util.Optional(elements, constants.ConfigMapChecksumKey, ""); currentSha != expectedSha || currentSha == "" { // We need to do the update if _, changed, err := patcher.Patcher[*core.ConfigMap](ctx, cachedStatus.ConfigMapsModInterface().V1(), cm, meta.PatchOptions{}, patcher.PatchConfigMapData(elements)); err != nil { @@ -137,6 +172,10 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto var cfg gateway.Config + cfg.Options = &gateway.ConfigOptions{ + MergeSlashes: util.NewType(true), + } + cfg.IntegrationSidecar = &gateway.ConfigDestinationTarget{ Host: "127.0.0.1", Port: int32(r.context.GetSpec().Integration.GetSidecar().GetListenPort()), @@ -150,6 +189,9 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto }, }, AuthExtension: &gateway.ConfigAuthZExtension{}, + Timeout: &meta.Duration{ + Duration: constants.MaxGatewayTimeout, + }, } if spec.TLS.IsSecure() { @@ -227,6 +269,7 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto } } dest.Path = util.NewType(target.Path) + dest.Timeout = target.Timeout.DeepCopy() dest.AuthExtension = &gateway.ConfigAuthZExtension{ AuthZExtension: map[string]string{ pbImplEnvoyAuthV3.AuthConfigAuthRequiredKey: util.BoolSwitch[string](target.Authentication.Type.Get() == networkingApi.ArangoRouteSpecAuthenticationTypeRequired, pbImplEnvoyAuthV3.AuthConfigKeywordTrue, pbImplEnvoyAuthV3.AuthConfigKeywordFalse), @@ -234,7 +277,7 @@ func (r *Resources) renderGatewayConfig(cachedStatus inspectorInterface.Inspecto }, } dest.ResponseHeaders = map[string]string{ - EnvoyRouteHeader: at.GetName(), + constants.EnvoyRouteHeader: at.GetName(), } cfg.Destinations[at.Spec.GetRoute().GetPath()] = dest } diff --git a/pkg/deployment/resources/config_map_gateway_member.go b/pkg/deployment/resources/config_map_gateway_member.go index 2ca0c509e..fddfa3196 100644 --- a/pkg/deployment/resources/config_map_gateway_member.go +++ b/pkg/deployment/resources/config_map_gateway_member.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -25,6 +25,7 @@ import ( api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" "github.com/arangodb/kube-arangodb/pkg/deployment/resources/gateway" + "github.com/arangodb/kube-arangodb/pkg/util/constants" inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector" ) @@ -34,17 +35,17 @@ func (r *Resources) ensureMemberConfigGatewayConfig(ctx context.Context, cachedS } data, _, _, err := gateway.NodeDynamicConfig("arangodb", member.Member.ID, &gateway.DynamicConfig{ - Path: GatewayVolumeMountDir, - File: GatewayCDSConfigFileName, + Path: constants.GatewayCDSVolumeMountDir, + File: constants.GatewayConfigFileName, }, &gateway.DynamicConfig{ - Path: GatewayVolumeMountDir, - File: GatewayLDSConfigFileName, + Path: constants.GatewayLDSVolumeMountDir, + File: constants.GatewayConfigFileName, }) if err != nil { return nil, err } return map[string]string{ - GatewayDynamicConfigFileName: string(data), + constants.GatewayConfigFileName: string(data), }, nil } diff --git a/pkg/deployment/resources/config_maps_member.go b/pkg/deployment/resources/config_maps_member.go index 90bd1117d..88712a6b1 100644 --- a/pkg/deployment/resources/config_maps_member.go +++ b/pkg/deployment/resources/config_maps_member.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -29,6 +29,7 @@ import ( api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/assertion" + "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/errors" "github.com/arangodb/kube-arangodb/pkg/util/globals" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" @@ -38,15 +39,6 @@ import ( "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/patcher" ) -const ( - ConfigMapChecksumKey = "CHECKSUM" - - MemberConfigVolumeMountDir = "/etc/member/" - MemberConfigVolumeName = "member-config" - - MemberConfigChecksumENV = "MEMBER_CONFIG_CHECKSUM" -) - type memberConfigMapRenderer func(ctx context.Context, cachedStatus inspectorInterface.Inspector, member api.DeploymentStatusMemberElement) (map[string]string, error) func (r *Resources) ensureMemberConfig(ctx context.Context, cachedStatus inspectorInterface.Inspector, configMaps generic.ModClient[*core.ConfigMap]) error { @@ -111,7 +103,7 @@ func (r *Resources) ensureMemberConfig(ctx context.Context, cachedStatus inspect return errors.Reconcile() } else { // CM Exists, checks checksum - if key is not in the map we return empty string - if currentSha, expectedSha := util.Optional(obj.Data, ConfigMapChecksumKey, ""), util.Optional(elements, ConfigMapChecksumKey, ""); currentSha != expectedSha || currentSha == "" { + if currentSha, expectedSha := util.Optional(obj.Data, constants.ConfigMapChecksumKey, ""), util.Optional(elements, constants.ConfigMapChecksumKey, ""); currentSha != expectedSha || currentSha == "" { // We need to do the update if _, changed, err := patcher.Patcher[*core.ConfigMap](ctx, cachedStatus.ConfigMapsModInterface().V1(), obj, meta.PatchOptions{}, patcher.PatchConfigMapData(elements)); err != nil { @@ -152,7 +144,7 @@ func (r *Resources) renderConfigMap(elements ...map[string]string) (map[string]s return nil, nil } - result[ConfigMapChecksumKey] = util.SHA256FromStringMap(result) + result[constants.ConfigMapChecksumKey] = util.SHA256FromStringMap(result) return result, nil } diff --git a/pkg/deployment/resources/gateway/gateway_authz_extension.go b/pkg/deployment/resources/gateway/gateway_authz_extension.go index b7e6edf0c..931482128 100644 --- a/pkg/deployment/resources/gateway/gateway_authz_extension.go +++ b/pkg/deployment/resources/gateway/gateway_authz_extension.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -26,6 +26,7 @@ import ( pbImplEnvoyAuthV3 "github.com/arangodb/kube-arangodb/integrations/envoy/auth/v3" "github.com/arangodb/kube-arangodb/pkg/util" + "github.com/arangodb/kube-arangodb/pkg/util/constants" ) type ConfigAuthZExtension struct { @@ -57,7 +58,7 @@ func (c *ConfigAuthZExtension) RenderTypedFilterConfig() (util.KV[string, *anypb } return util.KV[string, *anypb.Any]{ - K: IntegrationSidecarFilterName, + K: constants.EnvoyIntegrationSidecarFilterName, V: q, }, nil } diff --git a/pkg/deployment/resources/gateway/gateway_config.go b/pkg/deployment/resources/gateway/gateway_config.go index f55d8a20a..b18bf335b 100644 --- a/pkg/deployment/resources/gateway/gateway_config.go +++ b/pkg/deployment/resources/gateway/gateway_config.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -43,6 +43,7 @@ import ( shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" "github.com/arangodb/kube-arangodb/pkg/util" + "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/errors" ) @@ -56,6 +57,8 @@ type Config struct { IntegrationSidecar *ConfigDestinationTarget `json:"integrationSidecar,omitempty"` SNI ConfigSNIList `json:"sni,omitempty"` + + Options *ConfigOptions `json:"options,omitempty"` } func (c Config) Validate() error { @@ -212,6 +215,9 @@ func (c Config) RenderClusters() ([]*clusterAPI.Cluster, error) { return nil, err } + if c == nil { + continue + } clusters = append(clusters, c) } @@ -267,7 +273,7 @@ func (c Config) RenderIntegrationSidecarFilter() (*httpConnectionManagerAPI.Http } return &httpConnectionManagerAPI.HttpFilter{ - Name: IntegrationSidecarFilterName, + Name: constants.EnvoyIntegrationSidecarFilterName, ConfigType: &httpConnectionManagerAPI.HttpFilter_TypedConfig{ TypedConfig: e, }, @@ -300,6 +306,7 @@ func (c Config) RenderFilters() ([]*listenerAPI.Filter, error) { StatPrefix: "ingress_http", CodecType: httpConnectionManagerAPI.HttpConnectionManager_AUTO, ServerHeaderTransformation: httpConnectionManagerAPI.HttpConnectionManager_PASS_THROUGH, + MergeSlashes: c.Options.GetMergeSlashes(), RouteSpecifier: &httpConnectionManagerAPI.HttpConnectionManager_RouteConfig{ RouteConfig: &routeAPI.RouteConfiguration{ Name: "default", diff --git a/pkg/deployment/resources/gateway/gateway_config_destination.go b/pkg/deployment/resources/gateway/gateway_config_destination.go index fb2ddda7e..feed655e6 100644 --- a/pkg/deployment/resources/gateway/gateway_config_destination.go +++ b/pkg/deployment/resources/gateway/gateway_config_destination.go @@ -21,6 +21,7 @@ package gateway import ( + "encoding/json" "time" clusterAPI "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" @@ -29,8 +30,10 @@ import ( routeAPI "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" + "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/errors" ) @@ -72,22 +75,53 @@ type ConfigDestination struct { TLS ConfigDestinationTLS `json:"tls,omitempty"` + Timeout *meta.Duration `json:"timeout,omitempty"` + ResponseHeaders map[string]string `json:"responseHeaders,omitempty"` + + Static *ConfigDestinationStatic `json:"static,omitempty"` } func (c *ConfigDestination) Validate() error { if c == nil { c = &ConfigDestination{} } - return shared.WithErrors( - 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()), - ) + + switch c.Type.Get() { + case ConfigDestinationTypeStatic: + return shared.WithErrors( + shared.PrefixResourceError("type", c.Type.Validate()), + shared.PrefixResourceError("path", shared.ValidateAPIPath(c.GetPath())), + shared.PrefixResourceError("authExtension", c.AuthExtension.Validate()), + shared.PrefixResourceError("static", shared.ValidateRequiredInterface(c.Static)), + ) + default: + return shared.WithErrors( + 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()), + shared.PrefixResourceErrorFunc("timeout", func() error { + if t := c.GetTimeout(); t < constants.MinGatewayTimeout { + return errors.Errorf("Timeout lower than %s not allowed", constants.MinGatewayTimeout.String()) + } else if t > constants.MaxGatewayTimeout { + return errors.Errorf("Timeout greater than %s not allowed", constants.MaxGatewayTimeout.String()) + } + return nil + }), + ) + } +} + +func (c *ConfigDestination) GetTimeout() time.Duration { + if c == nil || c.Timeout == nil { + return constants.DefaultEnvoyUpstreamTimeout + } + + return c.Timeout.Duration } func (c *ConfigDestination) GetPath() string { @@ -99,16 +133,9 @@ func (c *ConfigDestination) GetPath() string { } func (c *ConfigDestination) RenderRoute(name, prefix string) (*routeAPI.Route, error) { - var tcg []TypedFilterConfigGen - - if c != nil && c.AuthExtension != nil { - tcg = append(tcg, c.AuthExtension) - } - tc, err := NewTypedFilterConfig(tcg...) - if err != nil { - return nil, err + if c == nil { + return nil, errors.Errorf("Route cannot be nil") } - var headers []*coreAPI.HeaderValueOption for k, v := range c.ResponseHeaders { @@ -122,24 +149,72 @@ func (c *ConfigDestination) RenderRoute(name, prefix string) (*routeAPI.Route, e }) } - return &routeAPI.Route{ + var tcg []TypedFilterConfigGen + + if c.AuthExtension != nil { + tcg = append(tcg, c.AuthExtension) + } + tc, err := NewTypedFilterConfig(tcg...) + if err != nil { + return nil, err + } + + r := &routeAPI.Route{ Match: &routeAPI.RouteMatch{ PathSpecifier: &routeAPI.RouteMatch_Prefix{ Prefix: prefix, }, }, ResponseHeadersToAdd: headers, - Action: &routeAPI.Route_Route{ - Route: &routeAPI.RouteAction{ - ClusterSpecifier: &routeAPI.RouteAction_Cluster{ - Cluster: name, + + TypedPerFilterConfig: tc, + } + + if err := c.appendRouteAction(r, name); err != nil { + return nil, err + } + + return r, nil +} + +func (c *ConfigDestination) appendRouteAction(route *routeAPI.Route, name string) error { + if c.Type.Get() == ConfigDestinationTypeStatic { + obj := c.Static.GetResponse() + + if obj == nil { + obj = struct{}{} + } + + data, err := json.Marshal(obj) + if err != nil { + return err + } + + // Return static response + route.Action = &routeAPI.Route_DirectResponse{ + DirectResponse: &routeAPI.DirectResponseAction{ + Status: c.Static.GetCode(), + Body: &coreAPI.DataSource{ + Specifier: &coreAPI.DataSource_InlineBytes{ + InlineBytes: data, + }, }, - UpgradeConfigs: c.getUpgradeConfigs().render(), - PrefixRewrite: c.GetPath(), }, + } + return nil + } + + route.Action = &routeAPI.Route_Route{ + Route: &routeAPI.RouteAction{ + ClusterSpecifier: &routeAPI.RouteAction_Cluster{ + Cluster: name, + }, + UpgradeConfigs: c.getUpgradeConfigs().render(), + PrefixRewrite: c.GetPath(), + Timeout: durationpb.New(c.GetTimeout()), }, - TypedPerFilterConfig: tc, - }, nil + } + return nil } func (c *ConfigDestination) getUpgradeConfigs() ConfigDestinationsUpgrade { @@ -151,6 +226,10 @@ func (c *ConfigDestination) getUpgradeConfigs() ConfigDestinationsUpgrade { } func (c *ConfigDestination) RenderCluster(name string) (*clusterAPI.Cluster, error) { + if c.Type.Get() == ConfigDestinationTypeStatic { + return nil, nil + } + hpo, err := anypb.New(c.Protocol.Options()) if err != nil { return nil, err diff --git a/pkg/deployment/resources/gateway/gateway_config_destination_static.go b/pkg/deployment/resources/gateway/gateway_config_destination_static.go new file mode 100644 index 000000000..7979127ec --- /dev/null +++ b/pkg/deployment/resources/gateway/gateway_config_destination_static.go @@ -0,0 +1,51 @@ +// +// DISCLAIMER +// +// Copyright 2024-2025 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 ( + "net/http" +) + +type ConfigDestinationStatic struct { + Code *uint32 `json:"insecure,omitempty"` + + Response any `json:"response,omitempty"` +} + +func (c *ConfigDestinationStatic) Validate() error { + return nil +} + +func (c *ConfigDestinationStatic) GetResponse() any { + if c == nil || c.Response == nil { + return []byte("{}") + } + + return c.Response +} + +func (c *ConfigDestinationStatic) GetCode() uint32 { + if c == nil || c.Code == nil { + return http.StatusOK + } + + return *c.Code +} diff --git a/pkg/deployment/resources/gateway/gateway_config_destination_type.go b/pkg/deployment/resources/gateway/gateway_config_destination_type.go index 4e281900a..ef4638a81 100644 --- a/pkg/deployment/resources/gateway/gateway_config_destination_type.go +++ b/pkg/deployment/resources/gateway/gateway_config_destination_type.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -34,6 +34,7 @@ type ConfigDestinationType int const ( ConfigDestinationTypeHTTP ConfigDestinationType = iota ConfigDestinationTypeHTTPS + ConfigDestinationTypeStatic ) func (c *ConfigDestinationType) Get() ConfigDestinationType { @@ -42,7 +43,7 @@ func (c *ConfigDestinationType) Get() ConfigDestinationType { } switch v := *c; v { - case ConfigDestinationTypeHTTP, ConfigDestinationTypeHTTPS: + case ConfigDestinationTypeHTTP, ConfigDestinationTypeHTTPS, ConfigDestinationTypeStatic: return v default: return ConfigDestinationTypeHTTP @@ -78,7 +79,7 @@ func (c *ConfigDestinationType) RenderUpstreamTransportSocket(protocol *ConfigDe func (c *ConfigDestinationType) Validate() error { switch c.Get() { - case ConfigDestinationTypeHTTP, ConfigDestinationTypeHTTPS: + case ConfigDestinationTypeHTTP, ConfigDestinationTypeHTTPS, ConfigDestinationTypeStatic: return nil default: return errors.Errorf("Invalid destination type") diff --git a/pkg/deployment/resources/gateway/gateway_config_options.go b/pkg/deployment/resources/gateway/gateway_config_options.go new file mode 100644 index 000000000..2bade44d0 --- /dev/null +++ b/pkg/deployment/resources/gateway/gateway_config_options.go @@ -0,0 +1,37 @@ +// +// DISCLAIMER +// +// Copyright 2024-2025 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 ConfigOptions struct { + MergeSlashes *bool `json:"mergeSlashes,omitempty"` +} + +func (c *ConfigOptions) Validate() error { + return nil +} + +func (c *ConfigOptions) GetMergeSlashes() bool { + if c == nil || c.MergeSlashes == nil { + return true + } + + return *c.MergeSlashes +} diff --git a/pkg/deployment/resources/gateway/gateway_config_test.go b/pkg/deployment/resources/gateway/gateway_config_test.go index 05fcfd119..b5a280b8c 100644 --- a/pkg/deployment/resources/gateway/gateway_config_test.go +++ b/pkg/deployment/resources/gateway/gateway_config_test.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -401,4 +401,66 @@ func Test_GatewayConfig(t *testing.T) { }, }) }) + + t.Run("Default", func(t *testing.T) { + renderAndPrintGatewayConfig(t, Config{ + DefaultDestination: ConfigDestination{ + Targets: []ConfigDestinationTarget{ + { + Host: "127.0.0.1", + Port: 12345, + }, + }, + Path: util.NewType("/test/path/"), + Type: util.NewType(ConfigDestinationTypeHTTPS), + }, + DefaultTLS: &ConfigTLS{ + CertificatePath: "/test", + PrivateKeyPath: "/test12", + }, + SNI: []ConfigSNI{ + { + ConfigTLS: ConfigTLS{ + CertificatePath: "/cp", + PrivateKeyPath: "/pp", + }, + ServerNames: []string{ + "example.com", + }, + }, + { + ConfigTLS: ConfigTLS{ + CertificatePath: "/c2", + PrivateKeyPath: "/p2", + }, + ServerNames: []string{ + "2.example.com", + }, + }, + }, + Destinations: ConfigDestinations{ + "/_test/": { + Targets: []ConfigDestinationTarget{ + { + Host: "127.0.0.1", + Port: 12346, + }, + }, + Path: util.NewType("/test/path/"), + Type: util.NewType(ConfigDestinationTypeHTTP), + }, + "/_test2": { + Type: util.NewType(ConfigDestinationTypeStatic), + Static: &ConfigDestinationStatic{ + Code: util.NewType[uint32](302), + Response: struct { + Data string `json:"data"` + }{ + Data: "TEST", + }, + }, + }, + }, + }) + }) } diff --git a/pkg/deployment/resources/pod_creator.go b/pkg/deployment/resources/pod_creator.go index a80fd48c3..efaef3ef5 100644 --- a/pkg/deployment/resources/pod_creator.go +++ b/pkg/deployment/resources/pod_creator.go @@ -290,9 +290,9 @@ func createArangoSyncArgs(apiObject meta.Object, spec api.DeploymentSpec, group func createArangoGatewayArgs(input pod.Input, additionalOptions ...k8sutil.OptionPair) []string { options := k8sutil.CreateOptionPairs(64) if input.Deployment.Gateway.IsDynamic() { - options.Add("--config-path", path.Join(MemberConfigVolumeMountDir, GatewayDynamicConfigFileName)) + options.Add("--config-path", path.Join(constants.MemberConfigVolumeMountDir, constants.GatewayConfigFileName)) } else { - options.Add("--config-path", path.Join(GatewayVolumeMountDir, GatewayConfigFileName)) + options.Add("--config-path", path.Join(constants.GatewayVolumeMountDir, constants.GatewayConfigFileName)) } options.Append(additionalOptions...) diff --git a/pkg/deployment/resources/pod_creator_gateway.go b/pkg/deployment/resources/pod_creator_gateway.go index 0450b007e..8bcd41b29 100644 --- a/pkg/deployment/resources/pod_creator_gateway.go +++ b/pkg/deployment/resources/pod_creator_gateway.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -22,41 +22,48 @@ package resources import ( "fmt" + "strings" core "k8s.io/api/core/v1" "github.com/arangodb/kube-arangodb/pkg/deployment/pod" + "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" ) -const ( - ArangoGatewayExecutor = "/usr/local/bin/envoy" - GatewayVolumeMountDir = "/etc/gateway/" - GatewayVolumeName = "gateway" - GatewayConfigFileName = "gateway.yaml" - GatewayDynamicConfigFileName = "gateway.dynamic.yaml" - GatewayCDSConfigFileName = "gateway.dynamic.cds.yaml" - GatewayLDSConfigFileName = "gateway.dynamic.lds.yaml" - GatewayConfigChecksumENV = "GATEWAY_CONFIG_CHECKSUM" -) +func GetGatewayConfigMapName(name string, parts ...string) string { + if len(parts) == 0 { + return fmt.Sprintf("%s-gateway", name) + } -func GetGatewayConfigMapName(name string) string { - return fmt.Sprintf("%s-gateway", name) + return fmt.Sprintf("%s-gateway-%s", name, strings.Join(parts, "-")) } func createGatewayVolumes(input pod.Input) pod.Volumes { volumes := pod.NewVolumes() - volumes.AddVolume(k8sutil.CreateVolumeWithConfigMap(GatewayVolumeName, GetGatewayConfigMapName(input.ApiObject.GetName()))) - volumes.AddVolume(k8sutil.CreateVolumeWithConfigMap(MemberConfigVolumeName, input.ArangoMember.GetName())) + volumes.AddVolume(k8sutil.CreateVolumeWithConfigMap(constants.GatewayVolumeName, GetGatewayConfigMapName(input.ApiObject.GetName()))) + volumes.AddVolume(k8sutil.CreateVolumeWithConfigMap(constants.GatewayCDSVolumeName, GetGatewayConfigMapName(input.ApiObject.GetName(), "cds"))) + volumes.AddVolume(k8sutil.CreateVolumeWithConfigMap(constants.GatewayLDSVolumeName, GetGatewayConfigMapName(input.ApiObject.GetName(), "lds"))) + volumes.AddVolume(k8sutil.CreateVolumeWithConfigMap(constants.MemberConfigVolumeName, input.ArangoMember.GetName())) + volumes.AddVolumeMount(core.VolumeMount{ + Name: constants.GatewayVolumeName, + MountPath: constants.GatewayVolumeMountDir, + ReadOnly: true, + }) + volumes.AddVolumeMount(core.VolumeMount{ + Name: constants.GatewayCDSVolumeName, + MountPath: constants.GatewayCDSVolumeMountDir, + ReadOnly: true, + }) volumes.AddVolumeMount(core.VolumeMount{ - Name: GatewayVolumeName, - MountPath: GatewayVolumeMountDir, + Name: constants.GatewayLDSVolumeName, + MountPath: constants.GatewayLDSVolumeMountDir, ReadOnly: true, }) volumes.AddVolumeMount(core.VolumeMount{ - Name: MemberConfigVolumeName, - MountPath: MemberConfigVolumeMountDir, + Name: constants.MemberConfigVolumeName, + MountPath: constants.MemberConfigVolumeMountDir, ReadOnly: true, }) diff --git a/pkg/deployment/resources/pod_creator_gateway_container.go b/pkg/deployment/resources/pod_creator_gateway_container.go index cfbd6bc6c..4d893e4ee 100644 --- a/pkg/deployment/resources/pod_creator_gateway_container.go +++ b/pkg/deployment/resources/pod_creator_gateway_container.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -26,6 +26,7 @@ import ( api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" shared "github.com/arangodb/kube-arangodb/pkg/apis/shared" "github.com/arangodb/kube-arangodb/pkg/deployment/pod" + "github.com/arangodb/kube-arangodb/pkg/util/constants" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/interfaces" kresources "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/resources" @@ -70,7 +71,7 @@ func (a *ArangoGatewayContainer) GetPorts() []core.ContainerPort { } func (a *ArangoGatewayContainer) GetExecutor() string { - return a.groupSpec.GetEntrypoint(ArangoGatewayExecutor) + return a.groupSpec.GetEntrypoint(constants.ArangoGatewayExecutor) } func (a *ArangoGatewayContainer) GetSecurityContext() *core.SecurityContext { @@ -133,9 +134,9 @@ func (a *ArangoGatewayContainer) GetEnvs() ([]core.EnvVar, []core.EnvFromSource) if !a.spec.Gateway.IsDynamic() { if cm, ok := a.cachedStatus.ConfigMap().V1().GetSimple(GetGatewayConfigMapName(a.input.ApiObject.GetName())); ok { - if v, ok := cm.Data[ConfigMapChecksumKey]; ok { + if v, ok := cm.Data[constants.ConfigMapChecksumKey]; ok { envs.Add(true, core.EnvVar{ - Name: GatewayConfigChecksumENV, + Name: constants.GatewayConfigChecksumENV, Value: v, }) } diff --git a/pkg/handlers/networking/route/handler_destination_endpoints.go b/pkg/handlers/networking/route/handler_destination_endpoints.go index 9d7f469e1..c4a94fffb 100644 --- a/pkg/handlers/networking/route/handler_destination_endpoints.go +++ b/pkg/handlers/networking/route/handler_destination_endpoints.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -119,6 +119,7 @@ func (h *handler) HandleArangoDestinationEndpoints(ctx context.Context, item ope var target networkingApi.ArangoRouteStatusTarget target.Path = dest.GetPath() + target.Timeout = dest.GetTimeout() target.Type = networkingApi.ArangoRouteStatusTargetEndpointsType target.Protocol = dest.GetProtocol().Get() diff --git a/pkg/handlers/networking/route/handler_destination_service.go b/pkg/handlers/networking/route/handler_destination_service.go index 175917e3b..5ccb1a3b3 100644 --- a/pkg/handlers/networking/route/handler_destination_service.go +++ b/pkg/handlers/networking/route/handler_destination_service.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2024-2025 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. @@ -118,6 +118,7 @@ func (h *handler) HandleArangoDestinationService(ctx context.Context, item opera var target networkingApi.ArangoRouteStatusTarget target.Path = dest.GetPath() + target.Timeout = dest.GetTimeout() target.Type = networkingApi.ArangoRouteStatusTargetServiceType target.Protocol = dest.GetProtocol().Get() diff --git a/pkg/deployment/resources/gateway/consts.go b/pkg/platform/state.go similarity index 73% rename from pkg/deployment/resources/gateway/consts.go rename to pkg/platform/state.go index a624495df..57417f28c 100644 --- a/pkg/deployment/resources/gateway/consts.go +++ b/pkg/platform/state.go @@ -1,7 +1,7 @@ // // DISCLAIMER // -// Copyright 2024 ArangoDB GmbH, Cologne, Germany +// Copyright 2025 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. @@ -18,8 +18,12 @@ // Copyright holder is ArangoDB GmbH, Cologne, Germany // -package gateway +package platform -const ( - IntegrationSidecarFilterName = "envoy.filters.http.ext_authz" -) +type State struct { + Configuration StateConfiguration `json:"configuration,omitempty"` +} + +type StateConfiguration struct { + Hash string `json:"hash,omitempty"` +} diff --git a/pkg/util/constants/envoy.go b/pkg/util/constants/envoy.go new file mode 100644 index 000000000..b25e9b0c0 --- /dev/null +++ b/pkg/util/constants/envoy.go @@ -0,0 +1,33 @@ +// +// DISCLAIMER +// +// Copyright 2025 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 constants + +import "time" + +const ( + EnvoyRouteHeader = "arangodb-platform-route" + + EnvoyInventoryConfigDestination = "/_inventory" + + EnvoyIntegrationSidecarFilterName = "envoy.filters.http.ext_authz" + + DefaultEnvoyUpstreamTimeout = time.Minute +) diff --git a/pkg/util/constants/gateway.go b/pkg/util/constants/gateway.go new file mode 100644 index 000000000..2b4408030 --- /dev/null +++ b/pkg/util/constants/gateway.go @@ -0,0 +1,47 @@ +// +// DISCLAIMER +// +// Copyright 2025 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 constants + +import "time" + +const ( + MaxGatewayTimeout = 15 * time.Minute + MinGatewayTimeout = 15 * time.Second + + ConfigMapChecksumKey = "CHECKSUM" + + ArangoGatewayExecutor = "/usr/local/bin/envoy" + + GatewayConfigFileName = "gateway.yaml" + GatewayConfigChecksumENV = "GATEWAY_CONFIG_CHECKSUM" + + GatewayVolumeMountDir = "/etc/gateway/core/" + GatewayVolumeName = "gateway" + + GatewayLDSVolumeMountDir = "/etc/gateway/lds/" + GatewayLDSVolumeName = "gateway-lds" + + GatewayCDSVolumeMountDir = "/etc/gateway/cds/" + GatewayCDSVolumeName = "gateway-cds" + + MemberConfigVolumeMountDir = "/etc/gateway/member/" + MemberConfigVolumeName = "member-config" +)