mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-04-09 12:17:31 +00:00
Compare commits
1 Commits
copilot/fe
...
copilot/cr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1ec9de6f5 |
2
.github/workflows/releaser.yml
vendored
2
.github/workflows/releaser.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
|||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- uses: creekorful/goreportcard-action@1f35ced8cdac2cba28c9a2f2288a16aacfd507f9 # v1.0
|
- uses: creekorful/goreportcard-action@1f35ced8cdac2cba28c9a2f2288a16aacfd507f9 # v1.0
|
||||||
- uses: anchore/sbom-action/download-syft@a0a65128ee20bfc2cba8a1e7fc6ca46a88149706
|
- uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610
|
||||||
- name: Install Cosign
|
- name: Install Cosign
|
||||||
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
|
|||||||
@@ -30,9 +30,4 @@ type NamespaceRuleEnforceBody struct {
|
|||||||
// Define registries which are allowed to be used within this tenant
|
// Define registries which are allowed to be used within this tenant
|
||||||
// The rules are aggregated, since you can use Regular Expressions the match registry endpoints
|
// The rules are aggregated, since you can use Regular Expressions the match registry endpoints
|
||||||
Registries []api.OCIRegistry `json:"registries,omitempty"`
|
Registries []api.OCIRegistry `json:"registries,omitempty"`
|
||||||
|
|
||||||
// Define gateway rules for this namespace, restricting which Gateway resources
|
|
||||||
// Routes may reference and optionally injecting a default Gateway parentRef.
|
|
||||||
// +optional
|
|
||||||
Gateways *api.GatewayRuleSpec `json:"gateways,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,11 +464,6 @@ func (in *NamespaceRuleEnforceBody) DeepCopyInto(out *NamespaceRuleEnforceBody)
|
|||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.Gateways != nil {
|
|
||||||
in, out := &in.Gateways, &out.Gateways
|
|
||||||
*out = new(api.GatewayRuleSpec)
|
|
||||||
(*in).DeepCopyInto(*out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceRuleEnforceBody.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceRuleEnforceBody.
|
||||||
|
|||||||
@@ -51,86 +51,6 @@ spec:
|
|||||||
enforce:
|
enforce:
|
||||||
description: Enforcement Rules applied
|
description: Enforcement Rules applied
|
||||||
properties:
|
properties:
|
||||||
gateways:
|
|
||||||
description: Define gateway rules for this namespace, restricting
|
|
||||||
which Gateway resources Routes may reference and optionally
|
|
||||||
injecting a default Gateway parentRef.
|
|
||||||
properties:
|
|
||||||
gateway:
|
|
||||||
description: Gateway restricts which Gateways Routes may
|
|
||||||
reference and optionally specifies a default Gateway injected
|
|
||||||
when no parentRef is provided.
|
|
||||||
properties:
|
|
||||||
allowed:
|
|
||||||
description: Allowed is an explicit list of Gateways
|
|
||||||
(by name and optional namespace) that Routes in this
|
|
||||||
namespace may reference.
|
|
||||||
items:
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name of the Gateway.
|
|
||||||
type: string
|
|
||||||
namespace:
|
|
||||||
description: Namespace of the Gateway. When empty,
|
|
||||||
the Route's namespace is assumed.
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
default:
|
|
||||||
description: Default is the Gateway injected as parentRef
|
|
||||||
when no parentRef is specified in a Route resource.
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name of the Gateway.
|
|
||||||
type: string
|
|
||||||
namespace:
|
|
||||||
description: Namespace of the Gateway. When empty,
|
|
||||||
the Route's namespace is assumed.
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
matchExpressions:
|
|
||||||
description: matchExpressions is a list of label selector
|
|
||||||
requirements. The requirements are ANDed.
|
|
||||||
items:
|
|
||||||
description: |-
|
|
||||||
A label selector requirement is a selector that contains values, a key, and an operator that
|
|
||||||
relates the key and values.
|
|
||||||
properties:
|
|
||||||
key:
|
|
||||||
description: key is the label key that the selector
|
|
||||||
applies to.
|
|
||||||
type: string
|
|
||||||
operator:
|
|
||||||
description: |-
|
|
||||||
operator represents a key's relationship to a set of values.
|
|
||||||
Valid operators are In, NotIn, Exists and DoesNotExist.
|
|
||||||
type: string
|
|
||||||
values:
|
|
||||||
description: |-
|
|
||||||
values is an array of string values. If the operator is In or NotIn,
|
|
||||||
the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
|
||||||
the values array must be empty.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-type: atomic
|
|
||||||
required:
|
|
||||||
- key
|
|
||||||
- operator
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-type: atomic
|
|
||||||
matchLabels:
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
description: matchLabels is a map of {key,value} pairs.
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
registries:
|
registries:
|
||||||
description: |-
|
description: |-
|
||||||
Define registries which are allowed to be used within this tenant
|
Define registries which are allowed to be used within this tenant
|
||||||
|
|||||||
@@ -2492,86 +2492,6 @@ spec:
|
|||||||
enforce:
|
enforce:
|
||||||
description: Enforcement Rules applied
|
description: Enforcement Rules applied
|
||||||
properties:
|
properties:
|
||||||
gateways:
|
|
||||||
description: Define gateway rules for this namespace, restricting
|
|
||||||
which Gateway resources Routes may reference and optionally
|
|
||||||
injecting a default Gateway parentRef.
|
|
||||||
properties:
|
|
||||||
gateway:
|
|
||||||
description: Gateway restricts which Gateways Routes may
|
|
||||||
reference and optionally specifies a default Gateway
|
|
||||||
injected when no parentRef is provided.
|
|
||||||
properties:
|
|
||||||
allowed:
|
|
||||||
description: Allowed is an explicit list of Gateways
|
|
||||||
(by name and optional namespace) that Routes in this
|
|
||||||
namespace may reference.
|
|
||||||
items:
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name of the Gateway.
|
|
||||||
type: string
|
|
||||||
namespace:
|
|
||||||
description: Namespace of the Gateway. When empty,
|
|
||||||
the Route's namespace is assumed.
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
default:
|
|
||||||
description: Default is the Gateway injected as parentRef
|
|
||||||
when no parentRef is specified in a Route resource.
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
description: Name of the Gateway.
|
|
||||||
type: string
|
|
||||||
namespace:
|
|
||||||
description: Namespace of the Gateway. When empty,
|
|
||||||
the Route's namespace is assumed.
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
type: object
|
|
||||||
matchExpressions:
|
|
||||||
description: matchExpressions is a list of label selector
|
|
||||||
requirements. The requirements are ANDed.
|
|
||||||
items:
|
|
||||||
description: |-
|
|
||||||
A label selector requirement is a selector that contains values, a key, and an operator that
|
|
||||||
relates the key and values.
|
|
||||||
properties:
|
|
||||||
key:
|
|
||||||
description: key is the label key that the selector
|
|
||||||
applies to.
|
|
||||||
type: string
|
|
||||||
operator:
|
|
||||||
description: |-
|
|
||||||
operator represents a key's relationship to a set of values.
|
|
||||||
Valid operators are In, NotIn, Exists and DoesNotExist.
|
|
||||||
type: string
|
|
||||||
values:
|
|
||||||
description: |-
|
|
||||||
values is an array of string values. If the operator is In or NotIn,
|
|
||||||
the values array must be non-empty. If the operator is Exists or DoesNotExist,
|
|
||||||
the values array must be empty.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-type: atomic
|
|
||||||
required:
|
|
||||||
- key
|
|
||||||
- operator
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
x-kubernetes-list-type: atomic
|
|
||||||
matchLabels:
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
description: matchLabels is a map of {key,value} pairs.
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
registries:
|
registries:
|
||||||
description: |-
|
description: |-
|
||||||
Define registries which are allowed to be used within this tenant
|
Define registries which are allowed to be used within this tenant
|
||||||
|
|||||||
@@ -157,43 +157,6 @@ webhooks:
|
|||||||
timeoutSeconds: {{ $.Values.webhooks.mutatingWebhooksTimeoutSeconds }}
|
timeoutSeconds: {{ $.Values.webhooks.mutatingWebhooksTimeoutSeconds }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.webhooks.hooks.httproutes }}
|
|
||||||
{{- if .enabled }}
|
|
||||||
- name: httproute.defaults.projectcapsule.dev
|
|
||||||
admissionReviewVersions:
|
|
||||||
- v1
|
|
||||||
clientConfig:
|
|
||||||
{{- include "capsule.webhooks.service" (dict "path" "/defaults" "ctx" $) | nindent 4 }}
|
|
||||||
failurePolicy: {{ .failurePolicy }}
|
|
||||||
matchPolicy: {{ .matchPolicy }}
|
|
||||||
reinvocationPolicy: {{ .reinvocationPolicy }}
|
|
||||||
{{- with .namespaceSelector }}
|
|
||||||
namespaceSelector:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .objectSelector }}
|
|
||||||
objectSelector:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .matchConditions }}
|
|
||||||
matchConditions:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- gateway.networking.k8s.io
|
|
||||||
apiVersions:
|
|
||||||
- v1
|
|
||||||
operations:
|
|
||||||
- CREATE
|
|
||||||
- UPDATE
|
|
||||||
resources:
|
|
||||||
- httproutes
|
|
||||||
scope: "Namespaced"
|
|
||||||
sideEffects: None
|
|
||||||
timeoutSeconds: {{ $.Values.webhooks.mutatingWebhooksTimeoutSeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with (mergeOverwrite .Values.webhooks.hooks.namespaces .Values.webhooks.hooks.namespaceOwnerReference) }}
|
{{- with (mergeOverwrite .Values.webhooks.hooks.namespaces .Values.webhooks.hooks.namespaceOwnerReference) }}
|
||||||
{{- if .enabled }}
|
{{- if .enabled }}
|
||||||
- name: namespaces.tenants.projectcapsule.dev
|
- name: namespaces.tenants.projectcapsule.dev
|
||||||
|
|||||||
@@ -153,43 +153,6 @@ webhooks:
|
|||||||
timeoutSeconds: {{ $.Values.webhooks.validatingWebhooksTimeoutSeconds }}
|
timeoutSeconds: {{ $.Values.webhooks.validatingWebhooksTimeoutSeconds }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.webhooks.hooks.httproutes }}
|
|
||||||
{{- if .enabled }}
|
|
||||||
- name: httproute.projectcapsule.dev
|
|
||||||
admissionReviewVersions:
|
|
||||||
- v1
|
|
||||||
- v1beta1
|
|
||||||
clientConfig:
|
|
||||||
{{- include "capsule.webhooks.service" (dict "path" "/httproutes/validating" "ctx" $) | nindent 4 }}
|
|
||||||
failurePolicy: {{ .failurePolicy }}
|
|
||||||
matchPolicy: {{ .matchPolicy }}
|
|
||||||
{{- with .namespaceSelector }}
|
|
||||||
namespaceSelector:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .objectSelector }}
|
|
||||||
objectSelector:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .matchConditions }}
|
|
||||||
matchConditions:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- gateway.networking.k8s.io
|
|
||||||
apiVersions:
|
|
||||||
- v1
|
|
||||||
operations:
|
|
||||||
- CREATE
|
|
||||||
- UPDATE
|
|
||||||
resources:
|
|
||||||
- httproutes
|
|
||||||
scope: Namespaced
|
|
||||||
sideEffects: None
|
|
||||||
timeoutSeconds: {{ $.Values.webhooks.validatingWebhooksTimeoutSeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.webhooks.hooks.ingresses }}
|
{{- with .Values.webhooks.hooks.ingresses }}
|
||||||
{{- if .enabled }}
|
{{- if .enabled }}
|
||||||
- name: ingress.projectcapsule.dev
|
- name: ingress.projectcapsule.dev
|
||||||
|
|||||||
@@ -623,27 +623,6 @@ webhooks:
|
|||||||
operator: Exists
|
operator: Exists
|
||||||
# -- [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy)
|
# -- [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy)
|
||||||
matchConditions: []
|
matchConditions: []
|
||||||
# -- [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy)
|
|
||||||
reinvocationPolicy: Never
|
|
||||||
|
|
||||||
httproutes:
|
|
||||||
# -- Enable the Hook
|
|
||||||
enabled: true
|
|
||||||
# -- [FailurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy)
|
|
||||||
failurePolicy: Fail
|
|
||||||
# -- [MatchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy)
|
|
||||||
matchPolicy: Equivalent
|
|
||||||
# -- [ObjectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector)
|
|
||||||
objectSelector: {}
|
|
||||||
# -- [NamespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector)
|
|
||||||
namespaceSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: capsule.clastix.io/tenant
|
|
||||||
operator: Exists
|
|
||||||
# -- [MatchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy)
|
|
||||||
matchConditions: []
|
|
||||||
# -- [ReinvocationPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#reinvocation-policy)
|
|
||||||
reinvocationPolicy: Never
|
|
||||||
|
|
||||||
ingresses:
|
ingresses:
|
||||||
# -- Enable the Hook
|
# -- Enable the Hook
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import (
|
|||||||
"github.com/projectcapsule/capsule/internal/webhook/defaults"
|
"github.com/projectcapsule/capsule/internal/webhook/defaults"
|
||||||
"github.com/projectcapsule/capsule/internal/webhook/dra"
|
"github.com/projectcapsule/capsule/internal/webhook/dra"
|
||||||
"github.com/projectcapsule/capsule/internal/webhook/gateway"
|
"github.com/projectcapsule/capsule/internal/webhook/gateway"
|
||||||
"github.com/projectcapsule/capsule/internal/webhook/httproute"
|
|
||||||
"github.com/projectcapsule/capsule/internal/webhook/ingress"
|
"github.com/projectcapsule/capsule/internal/webhook/ingress"
|
||||||
"github.com/projectcapsule/capsule/internal/webhook/misc"
|
"github.com/projectcapsule/capsule/internal/webhook/misc"
|
||||||
namespacemutation "github.com/projectcapsule/capsule/internal/webhook/namespace/mutation"
|
namespacemutation "github.com/projectcapsule/capsule/internal/webhook/namespace/mutation"
|
||||||
@@ -281,11 +280,6 @@ func main() {
|
|||||||
),
|
),
|
||||||
route.MiscCustomResources(misc.ResourceCounterHandler(manager.GetClient())),
|
route.MiscCustomResources(misc.ResourceCounterHandler(manager.GetClient())),
|
||||||
route.Gateway(gateway.Class(cfg)),
|
route.Gateway(gateway.Class(cfg)),
|
||||||
route.HTTPRoute(
|
|
||||||
httproute.Handler(
|
|
||||||
httproute.GatewayValidator(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
route.DeviceClass(dra.DeviceClass()),
|
route.DeviceClass(dra.DeviceClass()),
|
||||||
route.Defaults(defaults.Handler(cfg, kubeVersion)),
|
route.Defaults(defaults.Handler(cfg, kubeVersion)),
|
||||||
route.TenantMutation(
|
route.TenantMutation(
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ func (h *handler) mutate(ctx context.Context, req admission.Request, c client.Cl
|
|||||||
response = mutateIngressDefaults(ctx, req, h.version, c, decoder, req.Namespace)
|
response = mutateIngressDefaults(ctx, req, h.version, c, decoder, req.Namespace)
|
||||||
case metav1.GroupVersionResource{Group: "gateway.networking.k8s.io", Version: "v1", Resource: "gateways"}:
|
case metav1.GroupVersionResource{Group: "gateway.networking.k8s.io", Version: "v1", Resource: "gateways"}:
|
||||||
response = mutateGatewayDefaults(ctx, req, c, decoder, req.Namespace)
|
response = mutateGatewayDefaults(ctx, req, c, decoder, req.Namespace)
|
||||||
case metav1.GroupVersionResource{Group: "gateway.networking.k8s.io", Version: "v1", Resource: "httproutes"}:
|
|
||||||
response = mutateHTTPRouteDefaults(ctx, req, c, decoder, req.Namespace)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if response == nil {
|
if response == nil {
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
// Copyright 2020-2026 Project Capsule Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package defaults
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
|
||||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
|
|
||||||
capsulehttproute "github.com/projectcapsule/capsule/internal/webhook/httproute"
|
|
||||||
"github.com/projectcapsule/capsule/internal/webhook/utils"
|
|
||||||
"github.com/projectcapsule/capsule/pkg/tenant"
|
|
||||||
)
|
|
||||||
|
|
||||||
func mutateHTTPRouteDefaults(ctx context.Context, req admission.Request, c client.Client, decoder admission.Decoder, namespace string) *admission.Response {
|
|
||||||
routeObj := &gatewayv1.HTTPRoute{}
|
|
||||||
if err := decoder.Decode(req, routeObj); err != nil {
|
|
||||||
return utils.ErroredResponse(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
routeObj.SetNamespace(namespace)
|
|
||||||
|
|
||||||
tnt, err := capsulehttproute.TenantFromHTTPRoute(ctx, c, routeObj)
|
|
||||||
if err != nil {
|
|
||||||
return utils.ErroredResponse(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if tnt == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve namespace-level rules to find the gateway default.
|
|
||||||
ns := &corev1.Namespace{}
|
|
||||||
if err = c.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil {
|
|
||||||
return utils.ErroredResponse(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ruleBody, err := tenant.BuildNamespaceRuleBodyForNamespace(ns, tnt)
|
|
||||||
if err != nil {
|
|
||||||
return utils.ErroredResponse(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ruleBody == nil || ruleBody.Enforce.Gateways == nil || ruleBody.Enforce.Gateways.Gateway == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
gwDefault := ruleBody.Enforce.Gateways.Gateway.Default
|
|
||||||
if gwDefault == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only inject the default when the HTTPRoute has no parentRefs.
|
|
||||||
if len(routeObj.Spec.ParentRefs) > 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultNamespace := gwDefault.Namespace
|
|
||||||
if defaultNamespace == "" {
|
|
||||||
defaultNamespace = namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
ns16 := gatewayv1.Namespace(defaultNamespace)
|
|
||||||
|
|
||||||
routeObj.Spec.ParentRefs = []gatewayv1.ParentReference{
|
|
||||||
{
|
|
||||||
Group: groupPtr(gatewayv1.GroupName),
|
|
||||||
Kind: kindPtr("Gateway"),
|
|
||||||
Name: gatewayv1.ObjectName(gwDefault.Name),
|
|
||||||
Namespace: &ns16,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
marshaled, err := json.Marshal(routeObj)
|
|
||||||
if err != nil {
|
|
||||||
response := admission.Errored(http.StatusInternalServerError, err)
|
|
||||||
|
|
||||||
return &response
|
|
||||||
}
|
|
||||||
|
|
||||||
response := admission.PatchResponseFromRaw(req.Object.Raw, marshaled)
|
|
||||||
|
|
||||||
return &response
|
|
||||||
}
|
|
||||||
|
|
||||||
func groupPtr(g string) *gatewayv1.Group {
|
|
||||||
v := gatewayv1.Group(g)
|
|
||||||
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
func kindPtr(k string) *gatewayv1.Kind {
|
|
||||||
v := gatewayv1.Kind(k)
|
|
||||||
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright 2020-2026 Project Capsule Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package httproute
|
|
||||||
|
|
||||||
import (
|
|
||||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
|
|
||||||
"github.com/projectcapsule/capsule/pkg/runtime/handlers"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handler builds a handlers.Handler that wraps all provided
|
|
||||||
// TypedHandlerWithTenantWithRuleset[*gatewayv1.HTTPRoute] implementations.
|
|
||||||
func Handler(handler ...handlers.TypedHandlerWithTenantWithRuleset[*gatewayv1.HTTPRoute]) handlers.Handler {
|
|
||||||
return &handlers.TypedTenantWithRulesetHandler[*gatewayv1.HTTPRoute]{
|
|
||||||
Factory: func() *gatewayv1.HTTPRoute {
|
|
||||||
return &gatewayv1.HTTPRoute{}
|
|
||||||
},
|
|
||||||
Handlers: handler,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright 2020-2026 Project Capsule Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package httproute
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
|
|
||||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TenantFromHTTPRoute returns the Tenant owning the namespace of the given HTTPRoute,
|
|
||||||
// or nil if the namespace does not belong to any Tenant.
|
|
||||||
func TenantFromHTTPRoute(ctx context.Context, c client.Client, route *gatewayv1.HTTPRoute) (*capsulev1beta2.Tenant, error) {
|
|
||||||
tenantList := &capsulev1beta2.TenantList{}
|
|
||||||
if err := c.List(ctx, tenantList, client.MatchingFields{".status.namespaces": route.Namespace}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(tenantList.Items) == 0 {
|
|
||||||
return nil, nil //nolint:nilnil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tenantList.Items[0], nil
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
// Copyright 2020-2026 Project Capsule Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package httproute
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/client-go/tools/events"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
|
||||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
|
|
||||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
|
||||||
caperrors "github.com/projectcapsule/capsule/pkg/api/errors"
|
|
||||||
evt "github.com/projectcapsule/capsule/pkg/runtime/events"
|
|
||||||
"github.com/projectcapsule/capsule/pkg/runtime/handlers"
|
|
||||||
)
|
|
||||||
|
|
||||||
type gatewayValidator struct{}
|
|
||||||
|
|
||||||
// GatewayValidator returns a TypedHandlerWithTenantWithRuleset that validates
|
|
||||||
// HTTPRoute parentRefs against the gateway rules configured in namespace rules.
|
|
||||||
func GatewayValidator() handlers.TypedHandlerWithTenantWithRuleset[*gatewayv1.HTTPRoute] {
|
|
||||||
return &gatewayValidator{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *gatewayValidator) OnCreate(
|
|
||||||
c client.Client,
|
|
||||||
obj *gatewayv1.HTTPRoute,
|
|
||||||
_ admission.Decoder,
|
|
||||||
recorder events.EventRecorder,
|
|
||||||
tnt *capsulev1beta2.Tenant,
|
|
||||||
rule *capsulev1beta2.NamespaceRuleBody,
|
|
||||||
) handlers.Func {
|
|
||||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
|
||||||
return h.validate(ctx, c, req, obj, tnt, recorder, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *gatewayValidator) OnUpdate(
|
|
||||||
c client.Client,
|
|
||||||
_ *gatewayv1.HTTPRoute,
|
|
||||||
obj *gatewayv1.HTTPRoute,
|
|
||||||
_ admission.Decoder,
|
|
||||||
recorder events.EventRecorder,
|
|
||||||
tnt *capsulev1beta2.Tenant,
|
|
||||||
rule *capsulev1beta2.NamespaceRuleBody,
|
|
||||||
) handlers.Func {
|
|
||||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
|
||||||
return h.validate(ctx, c, req, obj, tnt, recorder, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *gatewayValidator) OnDelete(
|
|
||||||
_ client.Client,
|
|
||||||
_ *gatewayv1.HTTPRoute,
|
|
||||||
_ admission.Decoder,
|
|
||||||
_ events.EventRecorder,
|
|
||||||
_ *capsulev1beta2.Tenant,
|
|
||||||
_ *capsulev1beta2.NamespaceRuleBody,
|
|
||||||
) handlers.Func {
|
|
||||||
return func(context.Context, admission.Request) *admission.Response {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *gatewayValidator) validate(
|
|
||||||
ctx context.Context,
|
|
||||||
c client.Client,
|
|
||||||
req admission.Request,
|
|
||||||
route *gatewayv1.HTTPRoute,
|
|
||||||
tnt *capsulev1beta2.Tenant,
|
|
||||||
recorder events.EventRecorder,
|
|
||||||
rule *capsulev1beta2.NamespaceRuleBody,
|
|
||||||
) *admission.Response {
|
|
||||||
if rule == nil || rule.Enforce.Gateways == nil || rule.Enforce.Gateways.Gateway == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
allowed := rule.Enforce.Gateways.Gateway
|
|
||||||
|
|
||||||
for _, parentRef := range route.Spec.ParentRefs {
|
|
||||||
// Only validate parentRefs that point to a Gateway resource.
|
|
||||||
if parentRef.Kind != nil && *parentRef.Kind != gatewayv1.Kind("Gateway") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if parentRef.Group != nil && string(*parentRef.Group) != gatewayv1.GroupName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
gwName := string(parentRef.Name)
|
|
||||||
gwNamespace := route.Namespace
|
|
||||||
|
|
||||||
if parentRef.Namespace != nil {
|
|
||||||
gwNamespace = string(*parentRef.Namespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to fetch the Gateway object for label-selector matching.
|
|
||||||
gw := &gatewayv1.Gateway{}
|
|
||||||
|
|
||||||
var gwObj client.Object
|
|
||||||
|
|
||||||
if err := c.Get(ctx, types.NamespacedName{Namespace: gwNamespace, Name: gwName}, gw); err != nil {
|
|
||||||
if !k8serrors.IsNotFound(err) {
|
|
||||||
return errResponse(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gwObj = gw
|
|
||||||
}
|
|
||||||
|
|
||||||
if !allowed.MatchGateway(gwNamespace, gwName, gwObj) {
|
|
||||||
recorder.Eventf(
|
|
||||||
tnt,
|
|
||||||
nil,
|
|
||||||
corev1.EventTypeWarning,
|
|
||||||
evt.ReasonForbiddenGateway,
|
|
||||||
evt.ActionValidationDenied,
|
|
||||||
"HTTPRoute %s/%s references forbidden Gateway %s/%s",
|
|
||||||
req.Namespace, req.Name, gwNamespace, gwName,
|
|
||||||
)
|
|
||||||
|
|
||||||
response := admission.Denied(
|
|
||||||
caperrors.NewGatewayForbidden(gwName, gwNamespace, *allowed).Error(),
|
|
||||||
)
|
|
||||||
|
|
||||||
return &response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func errResponse(err error) *admission.Response {
|
|
||||||
resp := admission.Errored(500, err)
|
|
||||||
|
|
||||||
return &resp
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Copyright 2020-2026 Project Capsule Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package route
|
|
||||||
|
|
||||||
import "github.com/projectcapsule/capsule/pkg/runtime/handlers"
|
|
||||||
|
|
||||||
type httproute struct {
|
|
||||||
handlers []handlers.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPRoute returns a Webhook that handles admission requests for
|
|
||||||
// gateway.networking.k8s.io/v1 HTTPRoute resources.
|
|
||||||
func HTTPRoute(handler ...handlers.Handler) handlers.Webhook {
|
|
||||||
return &httproute{handlers: handler}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *httproute) GetHandlers() []handlers.Handler {
|
|
||||||
return w.handlers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *httproute) GetPath() string {
|
|
||||||
return "/httproutes/validating"
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@ package errors
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
|
|
||||||
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
||||||
|
|
||||||
@@ -77,41 +76,3 @@ func NewGatewayClassUndefined(spec api.DefaultAllowedListSpec) error {
|
|||||||
func (i GatewayClassUndefinedError) Error() string {
|
func (i GatewayClassUndefinedError) Error() string {
|
||||||
return utils.DefaultAllowedValuesErrorMessage(i.spec, "No gateway Class is forbidden for the current Tenant. Specify a gateway Class which is allowed within the Tenant: ")
|
return utils.DefaultAllowedValuesErrorMessage(i.spec, "No gateway Class is forbidden for the current Tenant. Specify a gateway Class which is allowed within the Tenant: ")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GatewayForbiddenError is returned when an HTTPRoute references a Gateway that
|
|
||||||
// is not in the allowed list for the Tenant's namespace rules.
|
|
||||||
type GatewayForbiddenError struct {
|
|
||||||
gatewayNamespace string
|
|
||||||
gatewayName string
|
|
||||||
spec api.AllowedGatewaySpec
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewGatewayForbidden(name, namespace string, spec api.AllowedGatewaySpec) error {
|
|
||||||
return &GatewayForbiddenError{
|
|
||||||
gatewayNamespace: namespace,
|
|
||||||
gatewayName: name,
|
|
||||||
spec: spec,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e GatewayForbiddenError) Error() string {
|
|
||||||
msg := fmt.Sprintf("Gateway %s/%s is forbidden for the current Tenant: ", e.gatewayNamespace, e.gatewayName)
|
|
||||||
|
|
||||||
parts := []string{msg}
|
|
||||||
|
|
||||||
if e.spec.Default != nil {
|
|
||||||
parts = append(parts, fmt.Sprintf("default: %s/%s", e.spec.Default.Namespace, e.spec.Default.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(e.spec.Allowed) > 0 {
|
|
||||||
names := make([]string, 0, len(e.spec.Allowed))
|
|
||||||
|
|
||||||
for _, a := range e.spec.Allowed {
|
|
||||||
names = append(names, fmt.Sprintf("%s/%s", a.Namespace, a.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
parts = append(parts, fmt.Sprintf("allowed: [%s]", strings.Join(names, ", ")))
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(parts, " ")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
// Copyright 2020-2026 Project Capsule Authors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GatewayNamespacedName is a namespaced reference to a Gateway resource.
|
|
||||||
// +kubebuilder:object:generate=true
|
|
||||||
type GatewayNamespacedName struct {
|
|
||||||
// Name of the Gateway.
|
|
||||||
Name string `json:"name"`
|
|
||||||
// Namespace of the Gateway. When empty, the Route's namespace is assumed.
|
|
||||||
// +optional
|
|
||||||
Namespace string `json:"namespace,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllowedGatewaySpec defines which Gateway resources are allowed to be
|
|
||||||
// referenced by Routes in a namespace, and an optional default Gateway.
|
|
||||||
// +kubebuilder:object:generate=true
|
|
||||||
type AllowedGatewaySpec struct {
|
|
||||||
// Default is the Gateway injected as parentRef when no parentRef is specified
|
|
||||||
// in a Route resource. The Gateway must also be allowed via Allowed or the
|
|
||||||
// LabelSelector.
|
|
||||||
// +optional
|
|
||||||
Default *GatewayNamespacedName `json:"default,omitempty"`
|
|
||||||
|
|
||||||
// LabelSelector matches Gateway resources by labels.
|
|
||||||
// +optional
|
|
||||||
metav1.LabelSelector `json:",inline"`
|
|
||||||
|
|
||||||
// Allowed is an explicit list of Gateways (by name and optional namespace)
|
|
||||||
// that Routes in this namespace may reference.
|
|
||||||
// +optional
|
|
||||||
Allowed []GatewayNamespacedName `json:"allowed,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchDefault returns true when the given namespace/name matches the configured
|
|
||||||
// default Gateway.
|
|
||||||
func (in *AllowedGatewaySpec) MatchDefault(gwNamespace, gwName string) bool {
|
|
||||||
if in.Default == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return in.Default.Name == gwName && (in.Default.Namespace == "" || in.Default.Namespace == gwNamespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchGateway returns true when the given Gateway is allowed by this spec.
|
|
||||||
// A Gateway is allowed if it is the default, appears in the Allowed list, or
|
|
||||||
// its labels match the LabelSelector.
|
|
||||||
func (in *AllowedGatewaySpec) MatchGateway(gwNamespace, gwName string, obj client.Object) bool {
|
|
||||||
if in.MatchDefault(gwNamespace, gwName) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, a := range in.Allowed {
|
|
||||||
if a.Name == gwName && (a.Namespace == "" || a.Namespace == gwNamespace) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj != nil && (len(in.MatchLabels) > 0 || len(in.MatchExpressions) > 0) {
|
|
||||||
selector, err := metav1.LabelSelectorAsSelector(&in.LabelSelector)
|
|
||||||
if err == nil && selector.Matches(labels.Set(obj.GetLabels())) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// GatewayRuleSpec defines gateway-related enforcement rules for a namespace.
|
|
||||||
// +kubebuilder:object:generate=true
|
|
||||||
type GatewayRuleSpec struct {
|
|
||||||
// Gateway restricts which Gateways Routes may reference and optionally
|
|
||||||
// specifies a default Gateway injected when no parentRef is provided.
|
|
||||||
// +optional
|
|
||||||
Gateway *AllowedGatewaySpec `json:"gateway,omitempty"`
|
|
||||||
}
|
|
||||||
@@ -111,32 +111,6 @@ func (in *AdditionalRoleBindingsSpec) DeepCopy() *AdditionalRoleBindingsSpec {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *AllowedGatewaySpec) DeepCopyInto(out *AllowedGatewaySpec) {
|
|
||||||
*out = *in
|
|
||||||
if in.Default != nil {
|
|
||||||
in, out := &in.Default, &out.Default
|
|
||||||
*out = new(GatewayNamespacedName)
|
|
||||||
**out = **in
|
|
||||||
}
|
|
||||||
in.LabelSelector.DeepCopyInto(&out.LabelSelector)
|
|
||||||
if in.Allowed != nil {
|
|
||||||
in, out := &in.Allowed, &out.Allowed
|
|
||||||
*out = make([]GatewayNamespacedName, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedGatewaySpec.
|
|
||||||
func (in *AllowedGatewaySpec) DeepCopy() *AllowedGatewaySpec {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(AllowedGatewaySpec)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *AllowedListSpec) DeepCopyInto(out *AllowedListSpec) {
|
func (in *AllowedListSpec) DeepCopyInto(out *AllowedListSpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@@ -264,41 +238,6 @@ func (in *ForbiddenListSpec) DeepCopy() *ForbiddenListSpec {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *GatewayNamespacedName) DeepCopyInto(out *GatewayNamespacedName) {
|
|
||||||
*out = *in
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayNamespacedName.
|
|
||||||
func (in *GatewayNamespacedName) DeepCopy() *GatewayNamespacedName {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(GatewayNamespacedName)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *GatewayRuleSpec) DeepCopyInto(out *GatewayRuleSpec) {
|
|
||||||
*out = *in
|
|
||||||
if in.Gateway != nil {
|
|
||||||
in, out := &in.Gateway, &out.Gateway
|
|
||||||
*out = new(AllowedGatewaySpec)
|
|
||||||
(*in).DeepCopyInto(*out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayRuleSpec.
|
|
||||||
func (in *GatewayRuleSpec) DeepCopy() *GatewayRuleSpec {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(GatewayRuleSpec)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *LimitRangesSpec) DeepCopyInto(out *LimitRangesSpec) {
|
func (in *LimitRangesSpec) DeepCopyInto(out *LimitRangesSpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ const (
|
|||||||
ReasonMissingGatewayClass string = "MissingGatewayClass"
|
ReasonMissingGatewayClass string = "MissingGatewayClass"
|
||||||
ReasonMissingDeviceClass string = "MissingDeviceClass"
|
ReasonMissingDeviceClass string = "MissingDeviceClass"
|
||||||
ReasonForbiddenDeviceClass string = "ForbiddenDeviceClass"
|
ReasonForbiddenDeviceClass string = "ForbiddenDeviceClass"
|
||||||
ReasonForbiddenGateway string = "ForbiddenGateway"
|
|
||||||
|
|
||||||
// Pods.
|
// Pods.
|
||||||
ReasonMissingFQCI string = "MissingFQCI"
|
ReasonMissingFQCI string = "MissingFQCI"
|
||||||
|
|||||||
@@ -58,11 +58,6 @@ func BuildNamespaceRuleBodyForNamespace(
|
|||||||
if len(rule.Enforce.Registries) > 0 {
|
if len(rule.Enforce.Registries) > 0 {
|
||||||
out.Enforce.Registries = append(out.Enforce.Registries, rule.Enforce.Registries...)
|
out.Enforce.Registries = append(out.Enforce.Registries, rule.Enforce.Registries...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge gateway rules: last non-nil gateway rule wins.
|
|
||||||
if rule.Enforce.Gateways != nil {
|
|
||||||
out.Enforce.Gateways = rule.Enforce.Gateways.DeepCopy()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user