From 2b809a82facdcc972bb70aa75ab24fc5e409adc8 Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Tue, 21 Jul 2026 19:12:37 -0300 Subject: [PATCH 1/9] Add Network, NetworkLink, InterNetworkIngress, NetworkAccess CRD types and manifests Introduces four new Skupper v2alpha1 API types to enable inter-network connectivity: - Network: identifies a Skupper network by its NetworkId - NetworkLink: establishes a link to another network via TLS hostname/port - InterNetworkIngress: routes traffic from a NetworkLink or NetworkAccess to a local routing key - NetworkAccess: exposes a local endpoint to another network with optional dynamic port allocation and TLS Also adds: - CRD YAML manifests for all four new types under config/crd/bases/ - Generated client, informer, and lister code for all four new types - Updates config/crd/kustomization.yaml to reference the new manifests - Updates pkg/apis/skupper/v2alpha1/register.go to register the new types - Updates zz_generated.deepcopy.go with DeepCopy methods for new types --- .../skupper_inter_network_ingress_crd.yaml | 134 ++++++ .../crd/bases/skupper_network_access_crd.yaml | 186 ++++++++ config/crd/bases/skupper_network_crd.yaml | 126 ++++++ .../crd/bases/skupper_network_link_crd.yaml | 138 ++++++ .../crd/bases/skupper_router_access_crd.yaml | 12 + config/crd/kustomization.yaml | 6 +- pkg/apis/skupper/v2alpha1/register.go | 2 +- pkg/apis/skupper/v2alpha1/types.go | 361 ++++++++++++++- .../skupper/v2alpha1/zz_generated.deepcopy.go | 419 ++++++++++++++++++ .../v2alpha1/fake/fake_internetworkingress.go | 52 +++ .../skupper/v2alpha1/fake/fake_network.go | 50 +++ .../v2alpha1/fake/fake_networkaccess.go | 52 +++ .../skupper/v2alpha1/fake/fake_networklink.go | 52 +++ .../v2alpha1/fake/fake_skupper_client.go | 16 + .../skupper/v2alpha1/generated_expansion.go | 8 + .../skupper/v2alpha1/internetworkingress.go | 70 +++ .../typed/skupper/v2alpha1/network.go | 70 +++ .../typed/skupper/v2alpha1/networkaccess.go | 70 +++ .../typed/skupper/v2alpha1/networklink.go | 70 +++ .../typed/skupper/v2alpha1/skupper_client.go | 20 + .../informers/externalversions/generic.go | 8 + .../skupper/v2alpha1/interface.go | 28 ++ .../skupper/v2alpha1/internetworkingress.go | 102 +++++ .../skupper/v2alpha1/network.go | 102 +++++ .../skupper/v2alpha1/networkaccess.go | 102 +++++ .../skupper/v2alpha1/networklink.go | 102 +++++ .../skupper/v2alpha1/expansion_generated.go | 32 ++ .../skupper/v2alpha1/internetworkingress.go | 70 +++ .../listers/skupper/v2alpha1/network.go | 70 +++ .../listers/skupper/v2alpha1/networkaccess.go | 70 +++ .../listers/skupper/v2alpha1/networklink.go | 70 +++ 31 files changed, 2667 insertions(+), 3 deletions(-) create mode 100644 config/crd/bases/skupper_inter_network_ingress_crd.yaml create mode 100644 config/crd/bases/skupper_network_access_crd.yaml create mode 100644 config/crd/bases/skupper_network_crd.yaml create mode 100644 config/crd/bases/skupper_network_link_crd.yaml create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_internetworkingress.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_network.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networkaccess.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networklink.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/internetworkingress.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/network.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networkaccess.go create mode 100644 pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networklink.go create mode 100644 pkg/generated/client/informers/externalversions/skupper/v2alpha1/internetworkingress.go create mode 100644 pkg/generated/client/informers/externalversions/skupper/v2alpha1/network.go create mode 100644 pkg/generated/client/informers/externalversions/skupper/v2alpha1/networkaccess.go create mode 100644 pkg/generated/client/informers/externalversions/skupper/v2alpha1/networklink.go create mode 100644 pkg/generated/client/listers/skupper/v2alpha1/internetworkingress.go create mode 100644 pkg/generated/client/listers/skupper/v2alpha1/network.go create mode 100644 pkg/generated/client/listers/skupper/v2alpha1/networkaccess.go create mode 100644 pkg/generated/client/listers/skupper/v2alpha1/networklink.go diff --git a/config/crd/bases/skupper_inter_network_ingress_crd.yaml b/config/crd/bases/skupper_inter_network_ingress_crd.yaml new file mode 100644 index 000000000..8c34c2ad2 --- /dev/null +++ b/config/crd/bases/skupper_inter_network_ingress_crd.yaml @@ -0,0 +1,134 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: internetworkingresses.skupper.io +spec: + group: skupper.io + versions: + - name: v2alpha1 + served: true + storage: true + schema: + openAPIV3Schema: + description: |- + An InterNetworkIngress can be defined alongside a NetworkLink or a NetworkAccess, exposing + a local ingress routing key to be used by the remote router through an inter-network + mTLS connection. + The remote router can only send messages to the provided routing key. + type: object + properties: + spec: + type: object + properties: + routingKey: + type: string + description: The local ingress key to be exposed through the inter-network connection. + networkLink: + type: string + description: Name of the NetworkLink to expose the routing key through. + networkAccess: + type: string + description: Name of the NetworkAccess to expose the routing key through. + settings: + description: |- + Advanced. A map containing additional settings. Each map + entry has a string name and a string value. + + **Note:** In general, we recommend not changing `settings` + from their default values. + type: object + additionalProperties: + type: string + x-kubernetes-validations: + - message: At least one of networkLink or networkAccess must be set + rule: has(self.networkLink) || has(self.networkAccess) + required: + - routingKey + status: + type: object + properties: + status: + description: |- + The current state of the resource. + - `Pending`: The resource is being processed. + - `Error`: There was an error processing the resource. See `message` for more information. + - `Ready`: The resource is ready to use. + type: string + message: + description: |- + A human-readable status message. Error messages are reported here. + type: string + conditions: + type: array + description: |- + A set of named conditions describing the current state of the resource. + + - `Configured`: The output resources for this resource have been created. + - `Running`: There is at least one router pod running. + - `Resolved`: The hostname or IP address for link access is available. + - `Ready`: The site is ready for use. All other conditions are true. + items: + type: object + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + subresources: + status: {} + additionalPrinterColumns: + - name: Routing Key + type: string + description: The local ingress key + jsonPath: .spec.routingKey + - name: Network Link + type: string + description: The network link name to use + jsonPath: .spec.networkLink + - name: Network Access + type: string + description: The network access name to use + jsonPath: .spec.networkAccess + - name: Status + type: string + description: The status of the VAN site + jsonPath: .status.status + - name: Message + type: string + description: Any human readable message relevant to the site + jsonPath: .status.message + scope: Namespaced + names: + plural: internetworkingresses + singular: internetworkingress + kind: InterNetworkIngress + listKind: InterNetworkIngressList + shortNames: + - ini diff --git a/config/crd/bases/skupper_network_access_crd.yaml b/config/crd/bases/skupper_network_access_crd.yaml new file mode 100644 index 000000000..b3c20f60d --- /dev/null +++ b/config/crd/bases/skupper_network_access_crd.yaml @@ -0,0 +1,186 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networkaccesses.skupper.io +spec: + group: skupper.io + versions: + - name: v2alpha1 + served: true + storage: true + schema: + openAPIV3Schema: + description: |- + Configuration for secure access to the site router for inter-network communication. + The configuration includes TLS credentials and router ports. + The NetworkAccess resource is used to implement inter-network access for sites. + type: object + properties: + spec: + type: object + properties: + port: + description: The port for the router to bind. + type: integer + generateTlsCredentials: + description: |- + When set, Skupper generates the TLS credentials to be + stored in the Secret specified by `tlsCredentials`. See + also `issuer`. + type: boolean + issuer: + type: string + description: |- + The name of the Kubernetes Secret containing the signing CA + used to generate TLS certificates for the NetworkAccess when + `generateTlsCredentials` is set. + remoteIssuer: + description: |- + Advanced. Enable it if you want the Skupper Controller to + generate CertificateRequests (CRs) instead of the default + self-signed certificates. + The CRs must be reconciled by an external application. + type: boolean + accessType: + description: |- + Configures the access type for the router endpoints. + Available access types and the default selection is + configured on the Skupper controller for Kubernetes. + + The options available by default are: + - `local`: No external ingress. Implies a Kubernetes Service with type ClusterIP. + - `route`: Exposed via an OpenShift Route. + - `loadbalancer`: Exposed via a Kubernetes Service with type LoadBalancer. + type: string + tlsCredentials: + description: |- + The name of a bundle of TLS certificates used for mutual TLS + router-to-router communication. The bundle contains the + server certificate and key and the trusted client certificate + (usually a CA). + + On Kubernetes, the value is the name of a Secret in the + current namespace. + + On Docker, Podman, and Linux, the value is the name of a + directory under `input/certs/` in the current namespace. + type: string + bindHost: + description: |- + The hostname or IP address of the network interface to bind + to. By default, Skupper binds all the interfaces on the host. + type: string + subjectAlternativeNames: + type: array + description: |- + The hostnames and IPs secured by the router TLS certificate. + items: + type: string + settings: + description: |- + Advanced. A map containing additional settings. Each map + entry has a string name and a string value. + + **Note:** In general, we recommend not changing `settings` + from their default values. + type: object + additionalProperties: + type: string + required: + - tlsCredentials + status: + type: object + properties: + status: + description: |- + The current state of the resource. + - `Pending`: The resource is being processed. + - `Error`: There was an error processing the resource. See `message` for more information. + - `Ready`: The resource is ready to use. + type: string + message: + description: |- + A human-readable status message. Error messages are reported here. + type: string + networkId: + description: |- + The network id currently associated with the Network Access. + type: string + port: + description: |- + If a port is not specified, the controller assigns a dynamic port and reports it here. + type: integer + conditions: + type: array + description: |- + A set of named conditions describing the current state of the resource. + + - `Configured`: The output resources for this resource have been created. + - `Resolved`: The connection endpoints are available. + - `Ready`: The router access is ready for use. All other conditions are true. + items: + type: object + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + endpoints: + type: array + description: |- + An array of connection endpoints. Each item has a name, host, + port, and group. + items: + type: object + properties: + name: + type: string + host: + type: string + port: + type: string + group: + type: string + subresources: + status: {} + additionalPrinterColumns: + - name: Status + type: string + description: The status of the router access + jsonPath: .status.status + - name: Message + type: string + description: Any relevant human readable message + jsonPath: .status.message + scope: Namespaced + names: + plural: networkaccesses + singular: networkaccess + kind: NetworkAccess diff --git a/config/crd/bases/skupper_network_crd.yaml b/config/crd/bases/skupper_network_crd.yaml new file mode 100644 index 000000000..3af570fc6 --- /dev/null +++ b/config/crd/bases/skupper_network_crd.yaml @@ -0,0 +1,126 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networks.skupper.io +spec: + group: skupper.io + versions: + - name: v2alpha1 + served: true + storage: true + schema: + openAPIV3Schema: + description: |- + A Network can be placed along with a Site resource and it is used to + indicate that the given Site is a member of the indicated Network ID. + + A single Network can be associated with a Site and it must be named "network". + + Once a Network is defined, all Sites that compose your network must + be part of the same Network ID for your VAN to operate. + type: object + properties: + spec: + type: object + properties: + networkId: + type: string + description: The ID of the Virtual Application Network to participate. + image: + type: string + description: |- + The Site Controller image to use. If not provided, + the default one defined by the controller will be used. + settings: + description: |- + Advanced. A map containing additional settings. Each map + entry has a string name and a string value. + + **Note:** In general, we recommend not changing `settings` + from their default values. + type: object + additionalProperties: + type: string + required: + - networkId + status: + type: object + properties: + status: + description: |- + The current state of the resource. + - `Pending`: The resource is being processed. + - `Error`: There was an error processing the resource. See `message` for more information. + - `Ready`: The resource is ready to use. + type: string + message: + description: |- + A human-readable status message. Error messages are reported here. + type: string + conditions: + type: array + description: |- + A set of named conditions describing the current state of the resource. + + - `Configured`: The output resources for this resource have been created. + - `Running`: There is at least one router pod running. + - `Resolved`: The hostname or IP address for link access is available. + - `Ready`: The site is ready for use. All other conditions are true. + items: + type: object + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + subresources: + status: {} + additionalPrinterColumns: + - name: Network ID + type: string + description: The Network ID to join + jsonPath: .spec.networkId + - name: Status + type: string + description: The status of the VAN site + jsonPath: .status.status + - name: Message + type: string + description: Any human readable message relevant to the site + jsonPath: .status.message + scope: Namespaced + names: + plural: networks + singular: network + kind: Network + listKind: NetworkList + shortNames: + - nw diff --git a/config/crd/bases/skupper_network_link_crd.yaml b/config/crd/bases/skupper_network_link_crd.yaml new file mode 100644 index 000000000..1a4357a8b --- /dev/null +++ b/config/crd/bases/skupper_network_link_crd.yaml @@ -0,0 +1,138 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networklinks.skupper.io +spec: + group: skupper.io + versions: + - name: v2alpha1 + served: true + storage: true + schema: + openAPIV3Schema: + description: |- + A NetworkLink can be defined when you have a Network that defines a network id. + + The NetworkLink is used to establish an inter-network communication link with another + Site that accepts such kind of incoming link, usually a central management backbone. + + The Network resource must be in ready state before a NetworkLink resource can be configured. + type: object + properties: + spec: + type: object + properties: + hostname: + type: string + description: >- + The hostname used to establish an inter-network connection. + port: + type: integer + description: The port number to establish a connection using an inter-network link. + tlsCredentials: + type: string + description: >- + The name of the Secret that contains the TLS Credentials used to + establish an mTLS connection. + settings: + description: |- + Advanced. A map containing additional settings. Each map + entry has a string name and a string value. + + **Note:** In general, we recommend not changing `settings` + from their default values. + type: object + additionalProperties: + type: string + required: + - hostname + - port + - tlsCredentials + status: + type: object + properties: + status: + description: |- + The current state of the resource. + - `Pending`: The resource is being processed. + - `Error`: There was an error processing the resource. See `message` for more information. + - `Ready`: The resource is ready to use. + type: string + message: + description: |- + A human-readable status message. Error messages are reported here. + type: string + conditions: + type: array + description: |- + A set of named conditions describing the current state of the resource. + + - `Configured`: The output resources for this resource have been created. + - `Running`: There is at least one router pod running. + - `Resolved`: The hostname or IP address for link access is available. + - `Ready`: The site is ready for use. All other conditions are true. + items: + type: object + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + subresources: + status: {} + additionalPrinterColumns: + - name: Hostname + type: string + description: The hostname used to establish an inter-network connection + jsonPath: .spec.hostname + - name: Port + type: integer + description: The port number to establish a connection using an inter-network link + jsonPath: .spec.port + - name: Credentials + type: string + description: The Secret name that contains the TLS Credentials used to establish an mTLS connection + jsonPath: .spec.tlsCredentials + - name: Status + type: string + description: The status of the NetworkLink + jsonPath: .status.status + - name: Message + type: string + description: Any human readable message relevant to the site + jsonPath: .status.message + scope: Namespaced + names: + plural: networklinks + singular: networklink + kind: NetworkLink + listKind: NetworkLinkList + shortNames: + - nwln diff --git a/config/crd/bases/skupper_router_access_crd.yaml b/config/crd/bases/skupper_router_access_crd.yaml index 2966e4454..198c4e946 100644 --- a/config/crd/bases/skupper_router_access_crd.yaml +++ b/config/crd/bases/skupper_router_access_crd.yaml @@ -162,6 +162,18 @@ spec: - reason - status - type + roles: + type: array + description: |- + List of roles and their allocated ports. + If a role does not specify a port, the controller assigns a dynamic port and reports it here. + items: + type: object + properties: + name: + type: string + port: + type: integer endpoints: type: array description: |- diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 64f07e5e0..e4a17af1d 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -7,9 +7,13 @@ resources: - bases/skupper_attached_connector_crd.yaml - bases/skupper_certificate_crd.yaml - bases/skupper_connector_crd.yaml +- bases/skupper_inter_network_ingress_crd.yaml - bases/skupper_link_crd.yaml - bases/skupper_listener_crd.yaml - bases/skupper_multikeylistener_crd.yaml +- bases/skupper_network_crd.yaml +- bases/skupper_network_link_crd.yaml +- bases/skupper_network_access_crd.yaml - bases/skupper_router_access_crd.yaml - bases/skupper_secured_access_crd.yaml -- bases/skupper_site_crd.yaml \ No newline at end of file +- bases/skupper_site_crd.yaml diff --git a/pkg/apis/skupper/v2alpha1/register.go b/pkg/apis/skupper/v2alpha1/register.go index 8dedf474f..8d3bc0cc4 100644 --- a/pkg/apis/skupper/v2alpha1/register.go +++ b/pkg/apis/skupper/v2alpha1/register.go @@ -26,7 +26,7 @@ var ( ) func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(SchemeGroupVersion, &Site{}, &SiteList{}, &Listener{}, &ListenerList{}, &Connector{}, &ConnectorList{}, &Link{}, &LinkList{}, &AccessToken{}, &AccessTokenList{}, &AccessGrant{}, &AccessGrantList{}, &SecuredAccess{}, &SecuredAccessList{}, &Certificate{}, &CertificateList{}, &RouterAccess{}, &RouterAccessList{}, &AttachedConnector{}, &AttachedConnectorList{}, &AttachedConnectorBinding{}, &AttachedConnectorBindingList{}, &MultiKeyListener{}, &MultiKeyListenerList{}) + scheme.AddKnownTypes(SchemeGroupVersion, &Site{}, &SiteList{}, &Listener{}, &ListenerList{}, &Connector{}, &ConnectorList{}, &Link{}, &LinkList{}, &AccessToken{}, &AccessTokenList{}, &AccessGrant{}, &AccessGrantList{}, &SecuredAccess{}, &SecuredAccessList{}, &Certificate{}, &CertificateList{}, &RouterAccess{}, &RouterAccessList{}, &AttachedConnector{}, &AttachedConnectorList{}, &AttachedConnectorBinding{}, &AttachedConnectorBindingList{}, &MultiKeyListener{}, &MultiKeyListenerList{}, &Network{}, &NetworkList{}, &NetworkLink{}, &NetworkLinkList{}, &InterNetworkIngress{}, &InterNetworkIngressList{}, &NetworkAccess{}, &NetworkAccessList{}) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil } diff --git a/pkg/apis/skupper/v2alpha1/types.go b/pkg/apis/skupper/v2alpha1/types.go index e51819398..b014d45b3 100644 --- a/pkg/apis/skupper/v2alpha1/types.go +++ b/pkg/apis/skupper/v2alpha1/types.go @@ -982,6 +982,85 @@ func (role RouterAccessRole) GetPort() int32 { } } +func (r *RouterAccess) GetPortForRole(name string) int32 { + for _, role := range r.Spec.Roles { + if role.Name == name { + if role.Port > 0 { + return int32(role.Port) + } + return r.GetAllocatedPortForRole(name) + } + } + return 0 +} + +func (r *RouterAccess) GetAllocatedPortForRole(name string) int32 { + for _, role := range r.Status.Roles { + if role.Name == name { + return int32(role.Port) + } + } + return 0 +} + +func (r *RouterAccess) GetAllocatedPorts() []int32 { + var ports []int32 + for _, role := range r.Spec.Roles { + if role.Port != 0 { + continue + } + if allocatedPort := r.GetAllocatedPortForRole(role.Name); allocatedPort != 0 { + ports = append(ports, allocatedPort) + } + } + return ports +} + +func (r *RouterAccess) GetUnusedPorts() []int32 { + var ports []int32 + for _, role := range r.Status.Roles { + if r.FindRole(role.Name) == nil { + ports = append(ports, int32(role.Port)) + } + } + return ports +} + +func (r *RouterAccess) AllocatePort(role string, port int) bool { + if port == 0 { + return false + } + var ports []RouterAccessRole + for _, portStatus := range r.Status.Roles { + if portStatus.Name == role { + if portStatus.Port == port { + return false + } + continue + } + ports = append(ports, portStatus) + } + ports = append(ports, RouterAccessRole{ + Name: role, + Port: port, + }) + r.Status.Roles = ports + return true +} + +func (r *RouterAccess) ReleaseUnusedPorts(unusedPorts []int32) { + var ports []RouterAccessRole + for _, port := range unusedPorts { + for _, portStatus := range r.Status.Roles { + if portStatus.Port == int(port) { + continue + } + ports = append(ports, portStatus) + } + } + r.Status.Roles = ports +} + type RouterAccessSpec struct { AccessType string `json:"accessType,omitempty"` Roles []RouterAccessRole `json:"roles"` @@ -995,7 +1074,8 @@ type RouterAccessSpec struct { type RouterAccessStatus struct { Status `json:",inline"` - Endpoints []Endpoint `json:"endpoints,omitempty"` + Roles []RouterAccessRole `json:"roles,omitempty"` + Endpoints []Endpoint `json:"endpoints,omitempty"` } // +genclient @@ -1104,3 +1184,282 @@ type AttachedConnectorBindingSpec struct { ExposePodsByName bool `json:"exposePodsByName,omitempty"` Settings map[string]string `json:"settings,omitempty"` } + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type Network struct { + v1.TypeMeta `json:",inline"` + v1.ObjectMeta `json:"metadata,omitempty"` + Spec NetworkSpec `json:"spec,omitempty"` + Status NetworkStatus `json:"status,omitempty"` +} + +type NetworkStatus struct { + Status `json:",inline"` +} + +func (m *Network) SetConfigured(ready bool) bool { + if m.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ReadyOrPendingCondition(ready), m.ObjectMeta.Generation) { + m.Status.setReady([]string{CONDITION_TYPE_CONFIGURED}, m.ObjectMeta.Generation) + return true + } + return false +} + +func (m *Network) SetError(expectedName string) bool { + if m.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ErrorCondition(fmt.Errorf("name must be '%s'", expectedName)), m.ObjectMeta.Generation) { + m.Status.setReady([]string{CONDITION_TYPE_CONFIGURED}, m.ObjectMeta.Generation) + return true + } + return false +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NetworkList contains a List of Network instances +type NetworkList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata,omitempty"` + Items []Network `json:"items"` +} + +type NetworkSpec struct { + NetworkId string `json:"networkId"` + Image string `json:"image,omitempty"` + Settings map[string]string `json:"settings,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type NetworkLink struct { + v1.TypeMeta `json:",inline"` + v1.ObjectMeta `json:"metadata,omitempty"` + Spec NetworkLinkSpec `json:"spec,omitempty"` + Status NetworkLinkStatus `json:"status,omitempty"` +} + +type NetworkLinkStatus struct { + Status `json:",inline"` +} + +func (m *NetworkLink) SetConfigured(ready bool) bool { + if m.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ReadyOrPendingCondition(ready), m.ObjectMeta.Generation) { + m.Status.setReady([]string{CONDITION_TYPE_CONFIGURED}, m.ObjectMeta.Generation) + return true + } + return false +} + +func (m *NetworkLink) SetError(err error) bool { + if m.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ErrorOrReadyCondition(err), m.ObjectMeta.Generation) { + m.Status.setReady([]string{CONDITION_TYPE_CONFIGURED}, m.ObjectMeta.Generation) + return true + } + return false +} + +func (m *NetworkLink) IsReady() bool { + return meta.IsStatusConditionTrue(m.Status.Conditions, CONDITION_TYPE_CONFIGURED) && + meta.IsStatusConditionTrue(m.Status.Conditions, CONDITION_TYPE_READY) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NetworkLinkList contains a List of NetworkLink instances +type NetworkLinkList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata,omitempty"` + Items []NetworkLink `json:"items"` +} + +type NetworkLinkSpec struct { + Hostname string `json:"hostname"` + Port int `json:"port"` + TlsCredentials string `json:"tlsCredentials"` + Settings map[string]string `json:"settings,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type InterNetworkIngress struct { + v1.TypeMeta `json:",inline"` + v1.ObjectMeta `json:"metadata,omitempty"` + Spec InterNetworkIngressSpec `json:"spec,omitempty"` + Status InterNetworkIngressStatus `json:"status,omitempty"` +} + +type InterNetworkIngressStatus struct { + Status `json:",inline"` +} + +func (i *InterNetworkIngress) SetConfigured(ready bool) bool { + if i.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ReadyOrPendingCondition(ready), i.ObjectMeta.Generation) { + i.Status.setReady([]string{CONDITION_TYPE_CONFIGURED}, i.ObjectMeta.Generation) + return true + } + return false +} + +func (i *InterNetworkIngress) SetError(err error) bool { + if i.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ErrorOrReadyCondition(err), i.ObjectMeta.Generation) { + i.Status.setReady([]string{CONDITION_TYPE_CONFIGURED}, i.ObjectMeta.Generation) + return true + } + return false +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// InterNetworkIngressList contains a List of InterNetworkIngress instances +type InterNetworkIngressList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata,omitempty"` + Items []InterNetworkIngress `json:"items"` +} + +// InterNetworkIngressSpec +// +kubebuilder:validation:XValidation:rule="has(self.networkLink) || has(self.networkAccess)",message="At least one of networkLink or networkAccess must be set" +type InterNetworkIngressSpec struct { + RoutingKey string `json:"routingKey"` + // +optional + NetworkLink string `json:"networkLink"` + // +optional + NetworkAccess string `json:"networkAccess"` + Settings map[string]string `json:"settings,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type NetworkAccess struct { + v1.TypeMeta `json:",inline"` + v1.ObjectMeta `json:"metadata,omitempty"` + Spec NetworkAccessSpec `json:"spec,omitempty"` + Status NetworkAccessStatus `json:"status,omitempty"` +} + +func (r *NetworkAccess) ListenerName() string { + return r.Name + "-inter-network" +} + +func (r *NetworkAccess) Key() string { + return fmt.Sprintf("%s/%s", r.Namespace, r.Name) +} + +func (r *NetworkAccess) SetConfigured(networkId string, err error) bool { + updated := false + if r.Status.SetCondition(CONDITION_TYPE_CONFIGURED, ErrorOrReadyCondition(err), r.ObjectMeta.Generation) { + r.Status.setReady([]string{CONDITION_TYPE_CONFIGURED, CONDITION_TYPE_RESOLVED}, r.ObjectMeta.Generation) + updated = true + } + if r.Status.NetworkId != networkId { + r.Status.NetworkId = networkId + updated = true + } + return updated +} + +func (r *NetworkAccess) Resolve(endpoints []Endpoint, group string) bool { + changed := false + if r.Status.UpdateEndpointsForGroup(endpoints, group) { + changed = true + } + if r.Status.SetCondition(CONDITION_TYPE_RESOLVED, ReadyOrPendingCondition(len(r.Status.Endpoints) > 0), r.ObjectMeta.Generation) { + r.Status.setReady([]string{CONDITION_TYPE_CONFIGURED, CONDITION_TYPE_RESOLVED}, r.ObjectMeta.Generation) + changed = true + } + return changed +} + +func (r *NetworkAccess) IsConfigured(networkId string) bool { + return r.Status.NetworkId == networkId && meta.IsStatusConditionTrue(r.Status.Conditions, CONDITION_TYPE_CONFIGURED) +} + +// endpoints are assumed all to be from one group +func (s *NetworkAccessStatus) UpdateEndpointsForGroup(endpoints []Endpoint, group string) bool { + all := []Endpoint{} + updated := false + byName := map[string]Endpoint{} + for _, endpoint := range endpoints { + endpoint.Group = group + byName[endpoint.Name] = endpoint + } + for _, endpoint := range s.Endpoints { + if endpoint.Group != group { + all = append(all, endpoint) + } else if desired, ok := byName[endpoint.Name]; ok { + if desired.MatchHostPort(&endpoint) { + all = append(all, endpoint) + } else { + all = append(all, desired) + updated = true + } + delete(byName, endpoint.Name) + } else { + // endpoint is in group, but not in desired list so don't add it + updated = true + } + } + for _, endpoint := range byName { + all = append(all, endpoint) + updated = true + } + if updated { + s.Endpoints = all + return true + } + return false +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NetworkAccessList contains a List of NetworkAccess instances +type NetworkAccessList struct { + v1.TypeMeta `json:",inline"` + v1.ListMeta `json:"metadata,omitempty"` + Items []NetworkAccess `json:"items"` +} + +type NetworkAccessSpec struct { + AccessType string `json:"accessType,omitempty"` + Port int `json:"port,omitempty"` + TlsCredentials string `json:"tlsCredentials"` + GenerateTlsCredentials bool `json:"generateTlsCredentials,omitempty"` + RemoteIssuer bool `json:"remoteIssuer,omitempty"` + Issuer string `json:"issuer,omitempty"` + BindHost string `json:"bindHost,omitempty"` + SubjectAlternativeNames []string `json:"subjectAlternativeNames,omitempty"` + Settings map[string]string `json:"settings,omitempty"` +} + +type NetworkAccessStatus struct { + Status `json:",inline"` + Port int `json:"port,omitempty"` + NetworkId string `json:"networkId"` + Endpoints []Endpoint `json:"endpoints,omitempty"` +} + +func (n *NetworkAccess) GetPort() int { + if n.Spec.Port > 0 { + return n.Spec.Port + } + return n.Status.Port +} + +func (n *NetworkAccess) HasAllocatedPort() bool { + return n.Spec.Port == 0 && n.Status.Port > 0 +} + +func (n *NetworkAccess) AllocatePort(port int) bool { + if port == 0 { + return false + } + if n.Status.Port != port { + n.Status.Port = port + return true + } + return false +} diff --git a/pkg/apis/skupper/v2alpha1/zz_generated.deepcopy.go b/pkg/apis/skupper/v2alpha1/zz_generated.deepcopy.go index 4deb897ce..daba9a28b 100644 --- a/pkg/apis/skupper/v2alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/skupper/v2alpha1/zz_generated.deepcopy.go @@ -695,6 +695,107 @@ func (in *Endpoint) DeepCopy() *Endpoint { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterNetworkIngress) DeepCopyInto(out *InterNetworkIngress) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterNetworkIngress. +func (in *InterNetworkIngress) DeepCopy() *InterNetworkIngress { + if in == nil { + return nil + } + out := new(InterNetworkIngress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InterNetworkIngress) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterNetworkIngressList) DeepCopyInto(out *InterNetworkIngressList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]InterNetworkIngress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterNetworkIngressList. +func (in *InterNetworkIngressList) DeepCopy() *InterNetworkIngressList { + if in == nil { + return nil + } + out := new(InterNetworkIngressList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InterNetworkIngressList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterNetworkIngressSpec) DeepCopyInto(out *InterNetworkIngressSpec) { + *out = *in + if in.Settings != nil { + in, out := &in.Settings, &out.Settings + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterNetworkIngressSpec. +func (in *InterNetworkIngressSpec) DeepCopy() *InterNetworkIngressSpec { + if in == nil { + return nil + } + out := new(InterNetworkIngressSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InterNetworkIngressStatus) DeepCopyInto(out *InterNetworkIngressStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterNetworkIngressStatus. +func (in *InterNetworkIngressStatus) DeepCopy() *InterNetworkIngressStatus { + if in == nil { + return nil + } + out := new(InterNetworkIngressStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Link) DeepCopyInto(out *Link) { *out = *in @@ -918,6 +1019,319 @@ func (in *ListenerStatus) DeepCopy() *ListenerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Network) DeepCopyInto(out *Network) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network. +func (in *Network) DeepCopy() *Network { + if in == nil { + return nil + } + out := new(Network) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Network) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkAccess) DeepCopyInto(out *NetworkAccess) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkAccess. +func (in *NetworkAccess) DeepCopy() *NetworkAccess { + if in == nil { + return nil + } + out := new(NetworkAccess) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkAccess) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkAccessList) DeepCopyInto(out *NetworkAccessList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NetworkAccess, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkAccessList. +func (in *NetworkAccessList) DeepCopy() *NetworkAccessList { + if in == nil { + return nil + } + out := new(NetworkAccessList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkAccessList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkAccessSpec) DeepCopyInto(out *NetworkAccessSpec) { + *out = *in + if in.SubjectAlternativeNames != nil { + in, out := &in.SubjectAlternativeNames, &out.SubjectAlternativeNames + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Settings != nil { + in, out := &in.Settings, &out.Settings + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkAccessSpec. +func (in *NetworkAccessSpec) DeepCopy() *NetworkAccessSpec { + if in == nil { + return nil + } + out := new(NetworkAccessSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkAccessStatus) DeepCopyInto(out *NetworkAccessStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]Endpoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkAccessStatus. +func (in *NetworkAccessStatus) DeepCopy() *NetworkAccessStatus { + if in == nil { + return nil + } + out := new(NetworkAccessStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkLink) DeepCopyInto(out *NetworkLink) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkLink. +func (in *NetworkLink) DeepCopy() *NetworkLink { + if in == nil { + return nil + } + out := new(NetworkLink) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkLink) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkLinkList) DeepCopyInto(out *NetworkLinkList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NetworkLink, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkLinkList. +func (in *NetworkLinkList) DeepCopy() *NetworkLinkList { + if in == nil { + return nil + } + out := new(NetworkLinkList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkLinkList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkLinkSpec) DeepCopyInto(out *NetworkLinkSpec) { + *out = *in + if in.Settings != nil { + in, out := &in.Settings, &out.Settings + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkLinkSpec. +func (in *NetworkLinkSpec) DeepCopy() *NetworkLinkSpec { + if in == nil { + return nil + } + out := new(NetworkLinkSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkLinkStatus) DeepCopyInto(out *NetworkLinkStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkLinkStatus. +func (in *NetworkLinkStatus) DeepCopy() *NetworkLinkStatus { + if in == nil { + return nil + } + out := new(NetworkLinkStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkList) DeepCopyInto(out *NetworkList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Network, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkList. +func (in *NetworkList) DeepCopy() *NetworkList { + if in == nil { + return nil + } + out := new(NetworkList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NetworkList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) { + *out = *in + if in.Settings != nil { + in, out := &in.Settings, &out.Settings + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSpec. +func (in *NetworkSpec) DeepCopy() *NetworkSpec { + if in == nil { + return nil + } + out := new(NetworkSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkStatus) DeepCopyInto(out *NetworkStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkStatus. +func (in *NetworkStatus) DeepCopy() *NetworkStatus { + if in == nil { + return nil + } + out := new(NetworkStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MultiKeyListener) DeepCopyInto(out *MultiKeyListener) { *out = *in @@ -1229,6 +1643,11 @@ func (in *RouterAccessSpec) DeepCopy() *RouterAccessSpec { func (in *RouterAccessStatus) DeepCopyInto(out *RouterAccessStatus) { *out = *in in.Status.DeepCopyInto(&out.Status) + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]RouterAccessRole, len(*in)) + copy(*out, *in) + } if in.Endpoints != nil { in, out := &in.Endpoints, &out.Endpoints *out = make([]Endpoint, len(*in)) diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_internetworkingress.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_internetworkingress.go new file mode 100644 index 000000000..fbf00015c --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_internetworkingress.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1" + gentype "k8s.io/client-go/gentype" +) + +// fakeInterNetworkIngresses implements InterNetworkIngressInterface +type fakeInterNetworkIngresses struct { + *gentype.FakeClientWithList[*v2alpha1.InterNetworkIngress, *v2alpha1.InterNetworkIngressList] + Fake *FakeSkupperV2alpha1 +} + +func newFakeInterNetworkIngresses(fake *FakeSkupperV2alpha1, namespace string) skupperv2alpha1.InterNetworkIngressInterface { + return &fakeInterNetworkIngresses{ + gentype.NewFakeClientWithList[*v2alpha1.InterNetworkIngress, *v2alpha1.InterNetworkIngressList]( + fake.Fake, + namespace, + v2alpha1.SchemeGroupVersion.WithResource("internetworkingresses"), + v2alpha1.SchemeGroupVersion.WithKind("InterNetworkIngress"), + func() *v2alpha1.InterNetworkIngress { return &v2alpha1.InterNetworkIngress{} }, + func() *v2alpha1.InterNetworkIngressList { return &v2alpha1.InterNetworkIngressList{} }, + func(dst, src *v2alpha1.InterNetworkIngressList) { dst.ListMeta = src.ListMeta }, + func(list *v2alpha1.InterNetworkIngressList) []*v2alpha1.InterNetworkIngress { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v2alpha1.InterNetworkIngressList, items []*v2alpha1.InterNetworkIngress) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_network.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_network.go new file mode 100644 index 000000000..4a42497ee --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_network.go @@ -0,0 +1,50 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1" + gentype "k8s.io/client-go/gentype" +) + +// fakeNetworks implements NetworkInterface +type fakeNetworks struct { + *gentype.FakeClientWithList[*v2alpha1.Network, *v2alpha1.NetworkList] + Fake *FakeSkupperV2alpha1 +} + +func newFakeNetworks(fake *FakeSkupperV2alpha1, namespace string) skupperv2alpha1.NetworkInterface { + return &fakeNetworks{ + gentype.NewFakeClientWithList[*v2alpha1.Network, *v2alpha1.NetworkList]( + fake.Fake, + namespace, + v2alpha1.SchemeGroupVersion.WithResource("networks"), + v2alpha1.SchemeGroupVersion.WithKind("Network"), + func() *v2alpha1.Network { return &v2alpha1.Network{} }, + func() *v2alpha1.NetworkList { return &v2alpha1.NetworkList{} }, + func(dst, src *v2alpha1.NetworkList) { dst.ListMeta = src.ListMeta }, + func(list *v2alpha1.NetworkList) []*v2alpha1.Network { return gentype.ToPointerSlice(list.Items) }, + func(list *v2alpha1.NetworkList, items []*v2alpha1.Network) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networkaccess.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networkaccess.go new file mode 100644 index 000000000..35337163e --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networkaccess.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1" + gentype "k8s.io/client-go/gentype" +) + +// fakeNetworkAccesses implements NetworkAccessInterface +type fakeNetworkAccesses struct { + *gentype.FakeClientWithList[*v2alpha1.NetworkAccess, *v2alpha1.NetworkAccessList] + Fake *FakeSkupperV2alpha1 +} + +func newFakeNetworkAccesses(fake *FakeSkupperV2alpha1, namespace string) skupperv2alpha1.NetworkAccessInterface { + return &fakeNetworkAccesses{ + gentype.NewFakeClientWithList[*v2alpha1.NetworkAccess, *v2alpha1.NetworkAccessList]( + fake.Fake, + namespace, + v2alpha1.SchemeGroupVersion.WithResource("networkaccesses"), + v2alpha1.SchemeGroupVersion.WithKind("NetworkAccess"), + func() *v2alpha1.NetworkAccess { return &v2alpha1.NetworkAccess{} }, + func() *v2alpha1.NetworkAccessList { return &v2alpha1.NetworkAccessList{} }, + func(dst, src *v2alpha1.NetworkAccessList) { dst.ListMeta = src.ListMeta }, + func(list *v2alpha1.NetworkAccessList) []*v2alpha1.NetworkAccess { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v2alpha1.NetworkAccessList, items []*v2alpha1.NetworkAccess) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networklink.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networklink.go new file mode 100644 index 000000000..36615ac10 --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_networklink.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1" + gentype "k8s.io/client-go/gentype" +) + +// fakeNetworkLinks implements NetworkLinkInterface +type fakeNetworkLinks struct { + *gentype.FakeClientWithList[*v2alpha1.NetworkLink, *v2alpha1.NetworkLinkList] + Fake *FakeSkupperV2alpha1 +} + +func newFakeNetworkLinks(fake *FakeSkupperV2alpha1, namespace string) skupperv2alpha1.NetworkLinkInterface { + return &fakeNetworkLinks{ + gentype.NewFakeClientWithList[*v2alpha1.NetworkLink, *v2alpha1.NetworkLinkList]( + fake.Fake, + namespace, + v2alpha1.SchemeGroupVersion.WithResource("networklinks"), + v2alpha1.SchemeGroupVersion.WithKind("NetworkLink"), + func() *v2alpha1.NetworkLink { return &v2alpha1.NetworkLink{} }, + func() *v2alpha1.NetworkLinkList { return &v2alpha1.NetworkLinkList{} }, + func(dst, src *v2alpha1.NetworkLinkList) { dst.ListMeta = src.ListMeta }, + func(list *v2alpha1.NetworkLinkList) []*v2alpha1.NetworkLink { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v2alpha1.NetworkLinkList, items []*v2alpha1.NetworkLink) { + list.Items = gentype.FromPointerSlice(items) + }, + ), + fake, + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_skupper_client.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_skupper_client.go index 04a797f85..895e0e3a3 100644 --- a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_skupper_client.go +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/fake/fake_skupper_client.go @@ -52,6 +52,10 @@ func (c *FakeSkupperV2alpha1) Connectors(namespace string) v2alpha1.ConnectorInt return newFakeConnectors(c, namespace) } +func (c *FakeSkupperV2alpha1) InterNetworkIngresses(namespace string) v2alpha1.InterNetworkIngressInterface { + return newFakeInterNetworkIngresses(c, namespace) +} + func (c *FakeSkupperV2alpha1) Links(namespace string) v2alpha1.LinkInterface { return newFakeLinks(c, namespace) } @@ -64,6 +68,18 @@ func (c *FakeSkupperV2alpha1) MultiKeyListeners(namespace string) v2alpha1.Multi return newFakeMultiKeyListeners(c, namespace) } +func (c *FakeSkupperV2alpha1) Networks(namespace string) v2alpha1.NetworkInterface { + return newFakeNetworks(c, namespace) +} + +func (c *FakeSkupperV2alpha1) NetworkAccesses(namespace string) v2alpha1.NetworkAccessInterface { + return newFakeNetworkAccesses(c, namespace) +} + +func (c *FakeSkupperV2alpha1) NetworkLinks(namespace string) v2alpha1.NetworkLinkInterface { + return newFakeNetworkLinks(c, namespace) +} + func (c *FakeSkupperV2alpha1) RouterAccesses(namespace string) v2alpha1.RouterAccessInterface { return newFakeRouterAccesses(c, namespace) } diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/generated_expansion.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/generated_expansion.go index 4c8eb86b2..41931a884 100644 --- a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/generated_expansion.go +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/generated_expansion.go @@ -30,12 +30,20 @@ type CertificateExpansion interface{} type ConnectorExpansion interface{} +type InterNetworkIngressExpansion interface{} + type LinkExpansion interface{} type ListenerExpansion interface{} type MultiKeyListenerExpansion interface{} +type NetworkExpansion interface{} + +type NetworkAccessExpansion interface{} + +type NetworkLinkExpansion interface{} + type RouterAccessExpansion interface{} type SecuredAccessExpansion interface{} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/internetworkingress.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/internetworkingress.go new file mode 100644 index 000000000..c0263069c --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/internetworkingress.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + scheme "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// InterNetworkIngressesGetter has a method to return a InterNetworkIngressInterface. +// A group's client should implement this interface. +type InterNetworkIngressesGetter interface { + InterNetworkIngresses(namespace string) InterNetworkIngressInterface +} + +// InterNetworkIngressInterface has methods to work with InterNetworkIngress resources. +type InterNetworkIngressInterface interface { + Create(ctx context.Context, interNetworkIngress *skupperv2alpha1.InterNetworkIngress, opts v1.CreateOptions) (*skupperv2alpha1.InterNetworkIngress, error) + Update(ctx context.Context, interNetworkIngress *skupperv2alpha1.InterNetworkIngress, opts v1.UpdateOptions) (*skupperv2alpha1.InterNetworkIngress, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, interNetworkIngress *skupperv2alpha1.InterNetworkIngress, opts v1.UpdateOptions) (*skupperv2alpha1.InterNetworkIngress, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*skupperv2alpha1.InterNetworkIngress, error) + List(ctx context.Context, opts v1.ListOptions) (*skupperv2alpha1.InterNetworkIngressList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *skupperv2alpha1.InterNetworkIngress, err error) + InterNetworkIngressExpansion +} + +// interNetworkIngresses implements InterNetworkIngressInterface +type interNetworkIngresses struct { + *gentype.ClientWithList[*skupperv2alpha1.InterNetworkIngress, *skupperv2alpha1.InterNetworkIngressList] +} + +// newInterNetworkIngresses returns a InterNetworkIngresses +func newInterNetworkIngresses(c *SkupperV2alpha1Client, namespace string) *interNetworkIngresses { + return &interNetworkIngresses{ + gentype.NewClientWithList[*skupperv2alpha1.InterNetworkIngress, *skupperv2alpha1.InterNetworkIngressList]( + "internetworkingresses", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *skupperv2alpha1.InterNetworkIngress { return &skupperv2alpha1.InterNetworkIngress{} }, + func() *skupperv2alpha1.InterNetworkIngressList { return &skupperv2alpha1.InterNetworkIngressList{} }, + ), + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/network.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/network.go new file mode 100644 index 000000000..41e1a42d6 --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/network.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + scheme "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// NetworksGetter has a method to return a NetworkInterface. +// A group's client should implement this interface. +type NetworksGetter interface { + Networks(namespace string) NetworkInterface +} + +// NetworkInterface has methods to work with Network resources. +type NetworkInterface interface { + Create(ctx context.Context, network *skupperv2alpha1.Network, opts v1.CreateOptions) (*skupperv2alpha1.Network, error) + Update(ctx context.Context, network *skupperv2alpha1.Network, opts v1.UpdateOptions) (*skupperv2alpha1.Network, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, network *skupperv2alpha1.Network, opts v1.UpdateOptions) (*skupperv2alpha1.Network, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*skupperv2alpha1.Network, error) + List(ctx context.Context, opts v1.ListOptions) (*skupperv2alpha1.NetworkList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *skupperv2alpha1.Network, err error) + NetworkExpansion +} + +// networks implements NetworkInterface +type networks struct { + *gentype.ClientWithList[*skupperv2alpha1.Network, *skupperv2alpha1.NetworkList] +} + +// newNetworks returns a Networks +func newNetworks(c *SkupperV2alpha1Client, namespace string) *networks { + return &networks{ + gentype.NewClientWithList[*skupperv2alpha1.Network, *skupperv2alpha1.NetworkList]( + "networks", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *skupperv2alpha1.Network { return &skupperv2alpha1.Network{} }, + func() *skupperv2alpha1.NetworkList { return &skupperv2alpha1.NetworkList{} }, + ), + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networkaccess.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networkaccess.go new file mode 100644 index 000000000..09a44925b --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networkaccess.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + scheme "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// NetworkAccessesGetter has a method to return a NetworkAccessInterface. +// A group's client should implement this interface. +type NetworkAccessesGetter interface { + NetworkAccesses(namespace string) NetworkAccessInterface +} + +// NetworkAccessInterface has methods to work with NetworkAccess resources. +type NetworkAccessInterface interface { + Create(ctx context.Context, networkAccess *skupperv2alpha1.NetworkAccess, opts v1.CreateOptions) (*skupperv2alpha1.NetworkAccess, error) + Update(ctx context.Context, networkAccess *skupperv2alpha1.NetworkAccess, opts v1.UpdateOptions) (*skupperv2alpha1.NetworkAccess, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, networkAccess *skupperv2alpha1.NetworkAccess, opts v1.UpdateOptions) (*skupperv2alpha1.NetworkAccess, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*skupperv2alpha1.NetworkAccess, error) + List(ctx context.Context, opts v1.ListOptions) (*skupperv2alpha1.NetworkAccessList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *skupperv2alpha1.NetworkAccess, err error) + NetworkAccessExpansion +} + +// networkAccesses implements NetworkAccessInterface +type networkAccesses struct { + *gentype.ClientWithList[*skupperv2alpha1.NetworkAccess, *skupperv2alpha1.NetworkAccessList] +} + +// newNetworkAccesses returns a NetworkAccesses +func newNetworkAccesses(c *SkupperV2alpha1Client, namespace string) *networkAccesses { + return &networkAccesses{ + gentype.NewClientWithList[*skupperv2alpha1.NetworkAccess, *skupperv2alpha1.NetworkAccessList]( + "networkaccesses", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *skupperv2alpha1.NetworkAccess { return &skupperv2alpha1.NetworkAccess{} }, + func() *skupperv2alpha1.NetworkAccessList { return &skupperv2alpha1.NetworkAccessList{} }, + ), + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networklink.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networklink.go new file mode 100644 index 000000000..a003335d5 --- /dev/null +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/networklink.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + scheme "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// NetworkLinksGetter has a method to return a NetworkLinkInterface. +// A group's client should implement this interface. +type NetworkLinksGetter interface { + NetworkLinks(namespace string) NetworkLinkInterface +} + +// NetworkLinkInterface has methods to work with NetworkLink resources. +type NetworkLinkInterface interface { + Create(ctx context.Context, networkLink *skupperv2alpha1.NetworkLink, opts v1.CreateOptions) (*skupperv2alpha1.NetworkLink, error) + Update(ctx context.Context, networkLink *skupperv2alpha1.NetworkLink, opts v1.UpdateOptions) (*skupperv2alpha1.NetworkLink, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, networkLink *skupperv2alpha1.NetworkLink, opts v1.UpdateOptions) (*skupperv2alpha1.NetworkLink, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*skupperv2alpha1.NetworkLink, error) + List(ctx context.Context, opts v1.ListOptions) (*skupperv2alpha1.NetworkLinkList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *skupperv2alpha1.NetworkLink, err error) + NetworkLinkExpansion +} + +// networkLinks implements NetworkLinkInterface +type networkLinks struct { + *gentype.ClientWithList[*skupperv2alpha1.NetworkLink, *skupperv2alpha1.NetworkLinkList] +} + +// newNetworkLinks returns a NetworkLinks +func newNetworkLinks(c *SkupperV2alpha1Client, namespace string) *networkLinks { + return &networkLinks{ + gentype.NewClientWithList[*skupperv2alpha1.NetworkLink, *skupperv2alpha1.NetworkLinkList]( + "networklinks", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *skupperv2alpha1.NetworkLink { return &skupperv2alpha1.NetworkLink{} }, + func() *skupperv2alpha1.NetworkLinkList { return &skupperv2alpha1.NetworkLinkList{} }, + ), + } +} diff --git a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/skupper_client.go b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/skupper_client.go index d22308175..c73bd0dc1 100644 --- a/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/skupper_client.go +++ b/pkg/generated/client/clientset/versioned/typed/skupper/v2alpha1/skupper_client.go @@ -34,9 +34,13 @@ type SkupperV2alpha1Interface interface { AttachedConnectorBindingsGetter CertificatesGetter ConnectorsGetter + InterNetworkIngressesGetter LinksGetter ListenersGetter MultiKeyListenersGetter + NetworksGetter + NetworkAccessesGetter + NetworkLinksGetter RouterAccessesGetter SecuredAccessesGetter SitesGetter @@ -71,6 +75,10 @@ func (c *SkupperV2alpha1Client) Connectors(namespace string) ConnectorInterface return newConnectors(c, namespace) } +func (c *SkupperV2alpha1Client) InterNetworkIngresses(namespace string) InterNetworkIngressInterface { + return newInterNetworkIngresses(c, namespace) +} + func (c *SkupperV2alpha1Client) Links(namespace string) LinkInterface { return newLinks(c, namespace) } @@ -83,6 +91,18 @@ func (c *SkupperV2alpha1Client) MultiKeyListeners(namespace string) MultiKeyList return newMultiKeyListeners(c, namespace) } +func (c *SkupperV2alpha1Client) Networks(namespace string) NetworkInterface { + return newNetworks(c, namespace) +} + +func (c *SkupperV2alpha1Client) NetworkAccesses(namespace string) NetworkAccessInterface { + return newNetworkAccesses(c, namespace) +} + +func (c *SkupperV2alpha1Client) NetworkLinks(namespace string) NetworkLinkInterface { + return newNetworkLinks(c, namespace) +} + func (c *SkupperV2alpha1Client) RouterAccesses(namespace string) RouterAccessInterface { return newRouterAccesses(c, namespace) } diff --git a/pkg/generated/client/informers/externalversions/generic.go b/pkg/generated/client/informers/externalversions/generic.go index 455abaf1d..7fefcc80f 100644 --- a/pkg/generated/client/informers/externalversions/generic.go +++ b/pkg/generated/client/informers/externalversions/generic.go @@ -65,12 +65,20 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().Certificates().Informer()}, nil case v2alpha1.SchemeGroupVersion.WithResource("connectors"): return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().Connectors().Informer()}, nil + case v2alpha1.SchemeGroupVersion.WithResource("internetworkingresses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().InterNetworkIngresses().Informer()}, nil case v2alpha1.SchemeGroupVersion.WithResource("links"): return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().Links().Informer()}, nil case v2alpha1.SchemeGroupVersion.WithResource("listeners"): return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().Listeners().Informer()}, nil case v2alpha1.SchemeGroupVersion.WithResource("multikeylisteners"): return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().MultiKeyListeners().Informer()}, nil + case v2alpha1.SchemeGroupVersion.WithResource("networks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().Networks().Informer()}, nil + case v2alpha1.SchemeGroupVersion.WithResource("networkaccesses"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().NetworkAccesses().Informer()}, nil + case v2alpha1.SchemeGroupVersion.WithResource("networklinks"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().NetworkLinks().Informer()}, nil case v2alpha1.SchemeGroupVersion.WithResource("routeraccesses"): return &genericInformer{resource: resource.GroupResource(), informer: f.Skupper().V2alpha1().RouterAccesses().Informer()}, nil case v2alpha1.SchemeGroupVersion.WithResource("securedaccesses"): diff --git a/pkg/generated/client/informers/externalversions/skupper/v2alpha1/interface.go b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/interface.go index 80f43e4eb..034a53987 100644 --- a/pkg/generated/client/informers/externalversions/skupper/v2alpha1/interface.go +++ b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/interface.go @@ -36,12 +36,20 @@ type Interface interface { Certificates() CertificateInformer // Connectors returns a ConnectorInformer. Connectors() ConnectorInformer + // InterNetworkIngresses returns a InterNetworkIngressInformer. + InterNetworkIngresses() InterNetworkIngressInformer // Links returns a LinkInformer. Links() LinkInformer // Listeners returns a ListenerInformer. Listeners() ListenerInformer // MultiKeyListeners returns a MultiKeyListenerInformer. MultiKeyListeners() MultiKeyListenerInformer + // Networks returns a NetworkInformer. + Networks() NetworkInformer + // NetworkAccesses returns a NetworkAccessInformer. + NetworkAccesses() NetworkAccessInformer + // NetworkLinks returns a NetworkLinkInformer. + NetworkLinks() NetworkLinkInformer // RouterAccesses returns a RouterAccessInformer. RouterAccesses() RouterAccessInformer // SecuredAccesses returns a SecuredAccessInformer. @@ -91,6 +99,11 @@ func (v *version) Connectors() ConnectorInformer { return &connectorInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// InterNetworkIngresses returns a InterNetworkIngressInformer. +func (v *version) InterNetworkIngresses() InterNetworkIngressInformer { + return &interNetworkIngressInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // Links returns a LinkInformer. func (v *version) Links() LinkInformer { return &linkInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} @@ -106,6 +119,21 @@ func (v *version) MultiKeyListeners() MultiKeyListenerInformer { return &multiKeyListenerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// Networks returns a NetworkInformer. +func (v *version) Networks() NetworkInformer { + return &networkInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// NetworkAccesses returns a NetworkAccessInformer. +func (v *version) NetworkAccesses() NetworkAccessInformer { + return &networkAccessInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// NetworkLinks returns a NetworkLinkInformer. +func (v *version) NetworkLinks() NetworkLinkInformer { + return &networkLinkInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // RouterAccesses returns a RouterAccessInformer. func (v *version) RouterAccesses() RouterAccessInformer { return &routerAccessInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/generated/client/informers/externalversions/skupper/v2alpha1/internetworkingress.go b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/internetworkingress.go new file mode 100644 index 000000000..6addad42a --- /dev/null +++ b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/internetworkingress.go @@ -0,0 +1,102 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + time "time" + + apisskupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + versioned "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned" + internalinterfaces "github.com/skupperproject/skupper/pkg/generated/client/informers/externalversions/internalinterfaces" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/listers/skupper/v2alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// InterNetworkIngressInformer provides access to a shared informer and lister for +// InterNetworkIngresses. +type InterNetworkIngressInformer interface { + Informer() cache.SharedIndexInformer + Lister() skupperv2alpha1.InterNetworkIngressLister +} + +type interNetworkIngressInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewInterNetworkIngressInformer constructs a new informer for InterNetworkIngress type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewInterNetworkIngressInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredInterNetworkIngressInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredInterNetworkIngressInformer constructs a new informer for InterNetworkIngress type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredInterNetworkIngressInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().InterNetworkIngresses(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().InterNetworkIngresses(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().InterNetworkIngresses(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().InterNetworkIngresses(namespace).Watch(ctx, options) + }, + }, + &apisskupperv2alpha1.InterNetworkIngress{}, + resyncPeriod, + indexers, + ) +} + +func (f *interNetworkIngressInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredInterNetworkIngressInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *interNetworkIngressInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisskupperv2alpha1.InterNetworkIngress{}, f.defaultInformer) +} + +func (f *interNetworkIngressInformer) Lister() skupperv2alpha1.InterNetworkIngressLister { + return skupperv2alpha1.NewInterNetworkIngressLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/client/informers/externalversions/skupper/v2alpha1/network.go b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/network.go new file mode 100644 index 000000000..2ca87a280 --- /dev/null +++ b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/network.go @@ -0,0 +1,102 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + time "time" + + apisskupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + versioned "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned" + internalinterfaces "github.com/skupperproject/skupper/pkg/generated/client/informers/externalversions/internalinterfaces" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/listers/skupper/v2alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// NetworkInformer provides access to a shared informer and lister for +// Networks. +type NetworkInformer interface { + Informer() cache.SharedIndexInformer + Lister() skupperv2alpha1.NetworkLister +} + +type networkInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNetworkInformer constructs a new informer for Network type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewNetworkInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNetworkInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNetworkInformer constructs a new informer for Network type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredNetworkInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().Networks(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().Networks(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().Networks(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().Networks(namespace).Watch(ctx, options) + }, + }, + &apisskupperv2alpha1.Network{}, + resyncPeriod, + indexers, + ) +} + +func (f *networkInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNetworkInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *networkInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisskupperv2alpha1.Network{}, f.defaultInformer) +} + +func (f *networkInformer) Lister() skupperv2alpha1.NetworkLister { + return skupperv2alpha1.NewNetworkLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/client/informers/externalversions/skupper/v2alpha1/networkaccess.go b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/networkaccess.go new file mode 100644 index 000000000..e15f44c6c --- /dev/null +++ b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/networkaccess.go @@ -0,0 +1,102 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + time "time" + + apisskupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + versioned "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned" + internalinterfaces "github.com/skupperproject/skupper/pkg/generated/client/informers/externalversions/internalinterfaces" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/listers/skupper/v2alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// NetworkAccessInformer provides access to a shared informer and lister for +// NetworkAccesses. +type NetworkAccessInformer interface { + Informer() cache.SharedIndexInformer + Lister() skupperv2alpha1.NetworkAccessLister +} + +type networkAccessInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNetworkAccessInformer constructs a new informer for NetworkAccess type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewNetworkAccessInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNetworkAccessInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNetworkAccessInformer constructs a new informer for NetworkAccess type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredNetworkAccessInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkAccesses(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkAccesses(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkAccesses(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkAccesses(namespace).Watch(ctx, options) + }, + }, + &apisskupperv2alpha1.NetworkAccess{}, + resyncPeriod, + indexers, + ) +} + +func (f *networkAccessInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNetworkAccessInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *networkAccessInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisskupperv2alpha1.NetworkAccess{}, f.defaultInformer) +} + +func (f *networkAccessInformer) Lister() skupperv2alpha1.NetworkAccessLister { + return skupperv2alpha1.NewNetworkAccessLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/client/informers/externalversions/skupper/v2alpha1/networklink.go b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/networklink.go new file mode 100644 index 000000000..4c44db02b --- /dev/null +++ b/pkg/generated/client/informers/externalversions/skupper/v2alpha1/networklink.go @@ -0,0 +1,102 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + context "context" + time "time" + + apisskupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + versioned "github.com/skupperproject/skupper/pkg/generated/client/clientset/versioned" + internalinterfaces "github.com/skupperproject/skupper/pkg/generated/client/informers/externalversions/internalinterfaces" + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/generated/client/listers/skupper/v2alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// NetworkLinkInformer provides access to a shared informer and lister for +// NetworkLinks. +type NetworkLinkInformer interface { + Informer() cache.SharedIndexInformer + Lister() skupperv2alpha1.NetworkLinkLister +} + +type networkLinkInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNetworkLinkInformer constructs a new informer for NetworkLink type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewNetworkLinkInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNetworkLinkInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNetworkLinkInformer constructs a new informer for NetworkLink type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredNetworkLinkInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkLinks(namespace).List(context.Background(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkLinks(namespace).Watch(context.Background(), options) + }, + ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkLinks(namespace).List(ctx, options) + }, + WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.SkupperV2alpha1().NetworkLinks(namespace).Watch(ctx, options) + }, + }, + &apisskupperv2alpha1.NetworkLink{}, + resyncPeriod, + indexers, + ) +} + +func (f *networkLinkInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNetworkLinkInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *networkLinkInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisskupperv2alpha1.NetworkLink{}, f.defaultInformer) +} + +func (f *networkLinkInformer) Lister() skupperv2alpha1.NetworkLinkLister { + return skupperv2alpha1.NewNetworkLinkLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/client/listers/skupper/v2alpha1/expansion_generated.go b/pkg/generated/client/listers/skupper/v2alpha1/expansion_generated.go index 14c09efd5..cf63a37dc 100644 --- a/pkg/generated/client/listers/skupper/v2alpha1/expansion_generated.go +++ b/pkg/generated/client/listers/skupper/v2alpha1/expansion_generated.go @@ -66,6 +66,14 @@ type ConnectorListerExpansion interface{} // ConnectorNamespaceLister. type ConnectorNamespaceListerExpansion interface{} +// InterNetworkIngressListerExpansion allows custom methods to be added to +// InterNetworkIngressLister. +type InterNetworkIngressListerExpansion interface{} + +// InterNetworkIngressNamespaceListerExpansion allows custom methods to be added to +// InterNetworkIngressNamespaceLister. +type InterNetworkIngressNamespaceListerExpansion interface{} + // LinkListerExpansion allows custom methods to be added to // LinkLister. type LinkListerExpansion interface{} @@ -90,6 +98,30 @@ type MultiKeyListenerListerExpansion interface{} // MultiKeyListenerNamespaceLister. type MultiKeyListenerNamespaceListerExpansion interface{} +// NetworkListerExpansion allows custom methods to be added to +// NetworkLister. +type NetworkListerExpansion interface{} + +// NetworkNamespaceListerExpansion allows custom methods to be added to +// NetworkNamespaceLister. +type NetworkNamespaceListerExpansion interface{} + +// NetworkAccessListerExpansion allows custom methods to be added to +// NetworkAccessLister. +type NetworkAccessListerExpansion interface{} + +// NetworkAccessNamespaceListerExpansion allows custom methods to be added to +// NetworkAccessNamespaceLister. +type NetworkAccessNamespaceListerExpansion interface{} + +// NetworkLinkListerExpansion allows custom methods to be added to +// NetworkLinkLister. +type NetworkLinkListerExpansion interface{} + +// NetworkLinkNamespaceListerExpansion allows custom methods to be added to +// NetworkLinkNamespaceLister. +type NetworkLinkNamespaceListerExpansion interface{} + // RouterAccessListerExpansion allows custom methods to be added to // RouterAccessLister. type RouterAccessListerExpansion interface{} diff --git a/pkg/generated/client/listers/skupper/v2alpha1/internetworkingress.go b/pkg/generated/client/listers/skupper/v2alpha1/internetworkingress.go new file mode 100644 index 000000000..ce4d2ed73 --- /dev/null +++ b/pkg/generated/client/listers/skupper/v2alpha1/internetworkingress.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// InterNetworkIngressLister helps list InterNetworkIngresses. +// All objects returned here must be treated as read-only. +type InterNetworkIngressLister interface { + // List lists all InterNetworkIngresses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.InterNetworkIngress, err error) + // InterNetworkIngresses returns an object that can list and get InterNetworkIngresses. + InterNetworkIngresses(namespace string) InterNetworkIngressNamespaceLister + InterNetworkIngressListerExpansion +} + +// interNetworkIngressLister implements the InterNetworkIngressLister interface. +type interNetworkIngressLister struct { + listers.ResourceIndexer[*skupperv2alpha1.InterNetworkIngress] +} + +// NewInterNetworkIngressLister returns a new InterNetworkIngressLister. +func NewInterNetworkIngressLister(indexer cache.Indexer) InterNetworkIngressLister { + return &interNetworkIngressLister{listers.New[*skupperv2alpha1.InterNetworkIngress](indexer, skupperv2alpha1.Resource("internetworkingress"))} +} + +// InterNetworkIngresses returns an object that can list and get InterNetworkIngresses. +func (s *interNetworkIngressLister) InterNetworkIngresses(namespace string) InterNetworkIngressNamespaceLister { + return interNetworkIngressNamespaceLister{listers.NewNamespaced[*skupperv2alpha1.InterNetworkIngress](s.ResourceIndexer, namespace)} +} + +// InterNetworkIngressNamespaceLister helps list and get InterNetworkIngresses. +// All objects returned here must be treated as read-only. +type InterNetworkIngressNamespaceLister interface { + // List lists all InterNetworkIngresses in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.InterNetworkIngress, err error) + // Get retrieves the InterNetworkIngress from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*skupperv2alpha1.InterNetworkIngress, error) + InterNetworkIngressNamespaceListerExpansion +} + +// interNetworkIngressNamespaceLister implements the InterNetworkIngressNamespaceLister +// interface. +type interNetworkIngressNamespaceLister struct { + listers.ResourceIndexer[*skupperv2alpha1.InterNetworkIngress] +} diff --git a/pkg/generated/client/listers/skupper/v2alpha1/network.go b/pkg/generated/client/listers/skupper/v2alpha1/network.go new file mode 100644 index 000000000..04b76850c --- /dev/null +++ b/pkg/generated/client/listers/skupper/v2alpha1/network.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// NetworkLister helps list Networks. +// All objects returned here must be treated as read-only. +type NetworkLister interface { + // List lists all Networks in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.Network, err error) + // Networks returns an object that can list and get Networks. + Networks(namespace string) NetworkNamespaceLister + NetworkListerExpansion +} + +// networkLister implements the NetworkLister interface. +type networkLister struct { + listers.ResourceIndexer[*skupperv2alpha1.Network] +} + +// NewNetworkLister returns a new NetworkLister. +func NewNetworkLister(indexer cache.Indexer) NetworkLister { + return &networkLister{listers.New[*skupperv2alpha1.Network](indexer, skupperv2alpha1.Resource("network"))} +} + +// Networks returns an object that can list and get Networks. +func (s *networkLister) Networks(namespace string) NetworkNamespaceLister { + return networkNamespaceLister{listers.NewNamespaced[*skupperv2alpha1.Network](s.ResourceIndexer, namespace)} +} + +// NetworkNamespaceLister helps list and get Networks. +// All objects returned here must be treated as read-only. +type NetworkNamespaceLister interface { + // List lists all Networks in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.Network, err error) + // Get retrieves the Network from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*skupperv2alpha1.Network, error) + NetworkNamespaceListerExpansion +} + +// networkNamespaceLister implements the NetworkNamespaceLister +// interface. +type networkNamespaceLister struct { + listers.ResourceIndexer[*skupperv2alpha1.Network] +} diff --git a/pkg/generated/client/listers/skupper/v2alpha1/networkaccess.go b/pkg/generated/client/listers/skupper/v2alpha1/networkaccess.go new file mode 100644 index 000000000..0de738716 --- /dev/null +++ b/pkg/generated/client/listers/skupper/v2alpha1/networkaccess.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// NetworkAccessLister helps list NetworkAccesses. +// All objects returned here must be treated as read-only. +type NetworkAccessLister interface { + // List lists all NetworkAccesses in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.NetworkAccess, err error) + // NetworkAccesses returns an object that can list and get NetworkAccesses. + NetworkAccesses(namespace string) NetworkAccessNamespaceLister + NetworkAccessListerExpansion +} + +// networkAccessLister implements the NetworkAccessLister interface. +type networkAccessLister struct { + listers.ResourceIndexer[*skupperv2alpha1.NetworkAccess] +} + +// NewNetworkAccessLister returns a new NetworkAccessLister. +func NewNetworkAccessLister(indexer cache.Indexer) NetworkAccessLister { + return &networkAccessLister{listers.New[*skupperv2alpha1.NetworkAccess](indexer, skupperv2alpha1.Resource("networkaccess"))} +} + +// NetworkAccesses returns an object that can list and get NetworkAccesses. +func (s *networkAccessLister) NetworkAccesses(namespace string) NetworkAccessNamespaceLister { + return networkAccessNamespaceLister{listers.NewNamespaced[*skupperv2alpha1.NetworkAccess](s.ResourceIndexer, namespace)} +} + +// NetworkAccessNamespaceLister helps list and get NetworkAccesses. +// All objects returned here must be treated as read-only. +type NetworkAccessNamespaceLister interface { + // List lists all NetworkAccesses in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.NetworkAccess, err error) + // Get retrieves the NetworkAccess from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*skupperv2alpha1.NetworkAccess, error) + NetworkAccessNamespaceListerExpansion +} + +// networkAccessNamespaceLister implements the NetworkAccessNamespaceLister +// interface. +type networkAccessNamespaceLister struct { + listers.ResourceIndexer[*skupperv2alpha1.NetworkAccess] +} diff --git a/pkg/generated/client/listers/skupper/v2alpha1/networklink.go b/pkg/generated/client/listers/skupper/v2alpha1/networklink.go new file mode 100644 index 000000000..3324e36c5 --- /dev/null +++ b/pkg/generated/client/listers/skupper/v2alpha1/networklink.go @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Skupper Authors. + +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. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v2alpha1 + +import ( + skupperv2alpha1 "github.com/skupperproject/skupper/pkg/apis/skupper/v2alpha1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// NetworkLinkLister helps list NetworkLinks. +// All objects returned here must be treated as read-only. +type NetworkLinkLister interface { + // List lists all NetworkLinks in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.NetworkLink, err error) + // NetworkLinks returns an object that can list and get NetworkLinks. + NetworkLinks(namespace string) NetworkLinkNamespaceLister + NetworkLinkListerExpansion +} + +// networkLinkLister implements the NetworkLinkLister interface. +type networkLinkLister struct { + listers.ResourceIndexer[*skupperv2alpha1.NetworkLink] +} + +// NewNetworkLinkLister returns a new NetworkLinkLister. +func NewNetworkLinkLister(indexer cache.Indexer) NetworkLinkLister { + return &networkLinkLister{listers.New[*skupperv2alpha1.NetworkLink](indexer, skupperv2alpha1.Resource("networklink"))} +} + +// NetworkLinks returns an object that can list and get NetworkLinks. +func (s *networkLinkLister) NetworkLinks(namespace string) NetworkLinkNamespaceLister { + return networkLinkNamespaceLister{listers.NewNamespaced[*skupperv2alpha1.NetworkLink](s.ResourceIndexer, namespace)} +} + +// NetworkLinkNamespaceLister helps list and get NetworkLinks. +// All objects returned here must be treated as read-only. +type NetworkLinkNamespaceLister interface { + // List lists all NetworkLinks in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*skupperv2alpha1.NetworkLink, err error) + // Get retrieves the NetworkLink from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*skupperv2alpha1.NetworkLink, error) + NetworkLinkNamespaceListerExpansion +} + +// networkLinkNamespaceLister implements the NetworkLinkNamespaceLister +// interface. +type networkLinkNamespaceLister struct { + listers.ResourceIndexer[*skupperv2alpha1.NetworkLink] +} From 7ed95451186559f04bd8c5db36c9d7ac28c106c3 Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Tue, 28 Jul 2026 17:31:49 -0300 Subject: [PATCH 2/9] ADR explaining multi-van context and decisions --- doc/adr/0011-multi-van-resources.md | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 doc/adr/0011-multi-van-resources.md diff --git a/doc/adr/0011-multi-van-resources.md b/doc/adr/0011-multi-van-resources.md new file mode 100644 index 000000000..ddc55f3d0 --- /dev/null +++ b/doc/adr/0011-multi-van-resources.md @@ -0,0 +1,68 @@ +# 11. Multi-VAN resources + +Date: 2026-07-28 + +## Status + +Proposed + +## Context + +New CRDs have been added to support multi-van management through VMS. +The RouterAccess CRD has also been modified to allow dynamically allocated ports to be persisted into the status field. + +These new CRDs must be in place for a given Site of a VAN to be managed through VMS. + +## Decision + +### New CRDs + +1. Network + +Defines the networkId to be set on the skupper-router configuration. +It is used as a singleton and only reconciled when named: **network**. + +A Site must be in READY state for it to be processed. + +We have also considered adding the networkId field as part of the Site CRD spec, or reading it from settings map, but we ended up with a new CRD as the Site resource is usually created and owned by the Site owner, while the Network resource can be provided by VMS (VAN management system). Keeping it separate prevents potential collisions with GitOps managed sites/vans. + +2. NetworkAccess + +Provides inter-network access to other VANs. +It is handled similarly to the RouterAccess resource, but instead of having spec.roles it has just the port field (which can be dynamically allocated). + +The reason why it is a new CRD instead of a new role into the existing RouterAccess, is just for RBAC flexibility. + +This resource is only processed when the Network resource is READY. + +3. NetworkLink + +Counter-part of the Link resource for inter-network links between VANs. +The reason for it to be a new CRD is again just for RBAC flexibility. + +This resource is only processed when the Network resource is READY. + +4. InterNetworkIngress + +Allows a routingKey, available in the local VAN, to be exposed to another VAN through a NetworkLink or a NetworkAccess. + +It is only processed when the respective NetworkAccess or NetworkLink resource is READY. + +### Update to RouterAccess + +The `.status.roles[]` field has been introduced so that the controller can persist the allocated port, in case a `.spec.roles[]` entry is defined without a port (set to 0). + +When a role is defined without a port, the controller should allocate a port and store it into the `.status.roles[].port`. + +### Make them optional + +The new CRDs as well as the change to the RouterAccess CRD must be handled as optional by the Controller. +Therefore, if the new CRDs as well as the modified version of the RouterAccess are not defined, the respective functionality should be considered as disabled and not cause problems to upgraded or new sites. + +## Consequences + +* Controller will have the ability to handle the new CRDs as well as the updated RouterAccess CRD optionally. If they are not in place, new resources and dynamic port allocation through RouterAccess will be ignored. + +* New deployment YAML files (cluster and namespace scoped), including the multi-van CRDs should be produced as part of the release process. + +* A new helm-chart to install only the CRDs should be provided. Along with it, a flag to optionally install the multi-van resources. From 2debd55049c4a987e728767a8e1e8e2e9177f3b5 Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Thu, 30 Jul 2026 12:18:10 -0300 Subject: [PATCH 3/9] Fixed CEL validation and removed dup code as suggeseted by CodeRabbit --- .../skupper_inter_network_ingress_crd.yaml | 4 +- pkg/apis/skupper/v2alpha1/types.go | 71 +++++++++---------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/config/crd/bases/skupper_inter_network_ingress_crd.yaml b/config/crd/bases/skupper_inter_network_ingress_crd.yaml index 8c34c2ad2..040ba6bae 100644 --- a/config/crd/bases/skupper_inter_network_ingress_crd.yaml +++ b/config/crd/bases/skupper_inter_network_ingress_crd.yaml @@ -40,8 +40,8 @@ spec: additionalProperties: type: string x-kubernetes-validations: - - message: At least one of networkLink or networkAccess must be set - rule: has(self.networkLink) || has(self.networkAccess) + - message: At least one of 'networkLink' or 'networkAccess' must be provided and non-empty. + rule: (has(self.networkLink) && self.networkLink != ”) || (has(self.networkAccess) && self.networkAccess != ”) required: - routingKey status: diff --git a/pkg/apis/skupper/v2alpha1/types.go b/pkg/apis/skupper/v2alpha1/types.go index b014d45b3..9eddc6b63 100644 --- a/pkg/apis/skupper/v2alpha1/types.go +++ b/pkg/apis/skupper/v2alpha1/types.go @@ -924,38 +924,7 @@ func (r *RouterAccess) IsConfigured() bool { // endpoints are assumed all to be from one group func (s *RouterAccessStatus) UpdateEndpointsForGroup(endpoints []Endpoint, group string) bool { - all := []Endpoint{} - updated := false - byName := map[string]Endpoint{} - for _, endpoint := range endpoints { - endpoint.Group = group - byName[endpoint.Name] = endpoint - } - for _, endpoint := range s.Endpoints { - if endpoint.Group != group { - all = append(all, endpoint) - } else if desired, ok := byName[endpoint.Name]; ok { - if desired.MatchHostPort(&endpoint) { - all = append(all, endpoint) - } else { - all = append(all, desired) - updated = true - } - delete(byName, endpoint.Name) - } else { - // endpoint is in group, but not in desired list so don't add it - updated = true - } - } - for _, endpoint := range byName { - all = append(all, endpoint) - updated = true - } - if updated { - s.Endpoints = all - return true - } - return false + return updateEndpointsForGroup(endpoints, group, s) } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -1019,7 +988,8 @@ func (r *RouterAccess) GetAllocatedPorts() []int32 { func (r *RouterAccess) GetUnusedPorts() []int32 { var ports []int32 for _, role := range r.Status.Roles { - if r.FindRole(role.Name) == nil { + specRole := r.FindRole(role.Name) + if specRole == nil || (specRole.Port > 0 && role.Port > 0 && specRole.Port != role.Port) { ports = append(ports, int32(role.Port)) } } @@ -1078,6 +1048,14 @@ type RouterAccessStatus struct { Endpoints []Endpoint `json:"endpoints,omitempty"` } +func (s *RouterAccessStatus) GetEndpoints() []Endpoint { + return s.Endpoints +} + +func (s *RouterAccessStatus) SetEndpoints(endpoints []Endpoint) { + s.Endpoints = endpoints +} + // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -1321,13 +1299,13 @@ type InterNetworkIngressList struct { } // InterNetworkIngressSpec -// +kubebuilder:validation:XValidation:rule="has(self.networkLink) || has(self.networkAccess)",message="At least one of networkLink or networkAccess must be set" +// +kubebuilder:validation:XValidation:rule="(has(self.networkLink) && self.networkLink != ”) || (has(self.networkAccess) && self.networkAccess != ”)",message="At least one of 'networkLink' or 'networkAccess' must be provided and non-empty." type InterNetworkIngressSpec struct { RoutingKey string `json:"routingKey"` // +optional - NetworkLink string `json:"networkLink"` + NetworkLink string `json:"networkLink,omitempty"` // +optional - NetworkAccess string `json:"networkAccess"` + NetworkAccess string `json:"networkAccess,omitempty"` Settings map[string]string `json:"settings,omitempty"` } @@ -1380,6 +1358,15 @@ func (r *NetworkAccess) IsConfigured(networkId string) bool { // endpoints are assumed all to be from one group func (s *NetworkAccessStatus) UpdateEndpointsForGroup(endpoints []Endpoint, group string) bool { + return updateEndpointsForGroup(endpoints, group, s) +} + +type EndpointsHandler interface { + GetEndpoints() []Endpoint + SetEndpoints(endpoints []Endpoint) +} + +func updateEndpointsForGroup(endpoints []Endpoint, group string, h EndpointsHandler) bool { all := []Endpoint{} updated := false byName := map[string]Endpoint{} @@ -1387,7 +1374,7 @@ func (s *NetworkAccessStatus) UpdateEndpointsForGroup(endpoints []Endpoint, grou endpoint.Group = group byName[endpoint.Name] = endpoint } - for _, endpoint := range s.Endpoints { + for _, endpoint := range h.GetEndpoints() { if endpoint.Group != group { all = append(all, endpoint) } else if desired, ok := byName[endpoint.Name]; ok { @@ -1408,7 +1395,7 @@ func (s *NetworkAccessStatus) UpdateEndpointsForGroup(endpoints []Endpoint, grou updated = true } if updated { - s.Endpoints = all + h.SetEndpoints(all) return true } return false @@ -1442,6 +1429,14 @@ type NetworkAccessStatus struct { Endpoints []Endpoint `json:"endpoints,omitempty"` } +func (s *NetworkAccessStatus) GetEndpoints() []Endpoint { + return s.Endpoints +} + +func (s *NetworkAccessStatus) SetEndpoints(endpoints []Endpoint) { + s.Endpoints = endpoints +} + func (n *NetworkAccess) GetPort() int { if n.Spec.Port > 0 { return n.Spec.Port From 12b25f29b34532fcd8f87fdb9e81210d85b24965 Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Thu, 30 Jul 2026 15:28:55 -0300 Subject: [PATCH 4/9] Fixed RelesaedUnusedPorts --- pkg/apis/skupper/v2alpha1/types.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/apis/skupper/v2alpha1/types.go b/pkg/apis/skupper/v2alpha1/types.go index 9eddc6b63..2ee906c4e 100644 --- a/pkg/apis/skupper/v2alpha1/types.go +++ b/pkg/apis/skupper/v2alpha1/types.go @@ -1020,11 +1020,15 @@ func (r *RouterAccess) AllocatePort(role string, port int) bool { func (r *RouterAccess) ReleaseUnusedPorts(unusedPorts []int32) { var ports []RouterAccessRole - for _, port := range unusedPorts { - for _, portStatus := range r.Status.Roles { + for _, portStatus := range r.Status.Roles { + keep := true + for _, port := range unusedPorts { if portStatus.Port == int(port) { - continue + keep = false + break } + } + if keep { ports = append(ports, portStatus) } } From 330be09f9c4d0a64b0b2a4464959e33546aa115e Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Thu, 30 Jul 2026 15:29:31 -0300 Subject: [PATCH 5/9] Added unit tests to modified CRD related Go types --- pkg/apis/skupper/v2alpha1/types_test.go | 490 ++++++++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 pkg/apis/skupper/v2alpha1/types_test.go diff --git a/pkg/apis/skupper/v2alpha1/types_test.go b/pkg/apis/skupper/v2alpha1/types_test.go new file mode 100644 index 000000000..b36f9f030 --- /dev/null +++ b/pkg/apis/skupper/v2alpha1/types_test.go @@ -0,0 +1,490 @@ +package v2alpha1 + +import ( + "errors" + "testing" + + "gotest.tools/v3/assert" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestRouterAccessRole_GetPort(t *testing.T) { + t.Run("defaults to 55671 for inter-router", func(t *testing.T) { + role := RouterAccessRole{Name: "inter-router"} + assert.Equal(t, role.GetPort(), int32(55671)) + }) + t.Run("defaults to 45671 for edge", func(t *testing.T) { + role := RouterAccessRole{Name: "edge"} + assert.Equal(t, role.GetPort(), int32(45671)) + }) + t.Run("returns explicit port when set", func(t *testing.T) { + role := RouterAccessRole{Name: "inter-router", Port: 12345} + assert.Equal(t, role.GetPort(), int32(12345)) + }) +} + +func TestRouterAccess_AllocatePort(t *testing.T) { + t.Run("allocates a new port", func(t *testing.T) { + r := &RouterAccess{} + assert.Assert(t, r.AllocatePort("inter-router", 55671)) + assert.Equal(t, r.GetAllocatedPortForRole("inter-router"), int32(55671)) + }) + t.Run("no change for same port", func(t *testing.T) { + r := &RouterAccess{} + r.AllocatePort("inter-router", 55671) + assert.Assert(t, !r.AllocatePort("inter-router", 55671)) + }) + t.Run("zero port returns false", func(t *testing.T) { + r := &RouterAccess{} + assert.Assert(t, !r.AllocatePort("inter-router", 0)) + }) +} + +func TestRouterAccess_GetAllocatedPorts(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 55671}, + {Name: "edge"}, + }, + }, + } + r.AllocatePort("edge", 45671) + + ports := r.GetAllocatedPorts() + assert.Equal(t, len(ports), 1) + assert.Equal(t, ports[0], int32(45671)) +} + +func TestRouterAccess_GetUnusedPorts(t *testing.T) { + t.Run("status role absent from spec", func(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "inter-router"}, + }, + }, + Status: RouterAccessStatus{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 55671}, + {Name: "edge", Port: 45671}, + }, + }, + } + unused := r.GetUnusedPorts() + assert.Equal(t, len(unused), 1) + assert.Equal(t, unused[0], int32(45671)) + }) + t.Run("status role port mismatches explicit spec port", func(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 55671}, + }, + }, + Status: RouterAccessStatus{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 11111}, + }, + }, + } + unused := r.GetUnusedPorts() + assert.Equal(t, len(unused), 1) + assert.Equal(t, unused[0], int32(11111)) + }) + t.Run("status role port same as explicit spec port", func(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 55671}, + {Name: "edge", Port: 0}, + }, + }, + Status: RouterAccessStatus{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 55671}, + {Name: "edge", Port: 0}, + }, + }, + } + unused := r.GetUnusedPorts() + assert.Equal(t, len(unused), 0) + }) + t.Run("status role dynamic port is kept", func(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "edge", Port: 0}, + }, + }, + Status: RouterAccessStatus{ + Roles: []RouterAccessRole{ + {Name: "edge", Port: 45671}, + }, + }, + } + unused := r.GetUnusedPorts() + assert.Equal(t, len(unused), 0) + }) +} + +func TestRouterAccess_ReleaseUnusedPorts(t *testing.T) { + t.Run("removes a single unused port", func(t *testing.T) { + r := &RouterAccess{} + r.AllocatePort("inter-router", 55671) + r.AllocatePort("edge", 45671) + + r.ReleaseUnusedPorts([]int32{55671}) + + assert.Equal(t, r.GetAllocatedPortForRole("inter-router"), int32(0)) + assert.Equal(t, r.GetAllocatedPortForRole("edge"), int32(45671)) + }) + t.Run("removes multiple unused ports at once", func(t *testing.T) { + r := &RouterAccess{} + r.AllocatePort("inter-router", 55671) + r.AllocatePort("edge", 45671) + + r.ReleaseUnusedPorts([]int32{55671, 45671}) + + assert.Equal(t, len(r.Status.Roles), 0) + }) +} + +func TestRouterAccess_GetPortForRole(t *testing.T) { + t.Run("returns explicit spec port", func(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "inter-router", Port: 12345}, + }, + }, + } + assert.Equal(t, r.GetPortForRole("inter-router"), int32(12345)) + }) + t.Run("falls through to allocated port when spec port is 0", func(t *testing.T) { + r := &RouterAccess{ + Spec: RouterAccessSpec{ + Roles: []RouterAccessRole{ + {Name: "edge"}, + }, + }, + } + r.AllocatePort("edge", 45671) + assert.Equal(t, r.GetPortForRole("edge"), int32(45671)) + }) +} + +func TestRouterAccess_SetConfigured(t *testing.T) { + t.Run("nil error sets Configured=True", func(t *testing.T) { + r := &RouterAccess{} + assert.Assert(t, r.SetConfigured(nil)) + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("repeated call with same state is a no-op", func(t *testing.T) { + r := &RouterAccess{} + r.SetConfigured(nil) + assert.Assert(t, !r.SetConfigured(nil)) + r.SetConfigured(errors.New("some error")) + assert.Assert(t, !r.SetConfigured(errors.New("some error"))) + }) + t.Run("non-nil error sets Configured=False", func(t *testing.T) { + r := &RouterAccess{} + assert.Assert(t, r.SetConfigured(errors.New("some error"))) + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) +} + +func TestRouterAccess_Resolve(t *testing.T) { + t.Run("endpoints present sets Resolved=True", func(t *testing.T) { + r := &RouterAccess{} + r.SetConfigured(nil) + assert.Assert(t, r.Resolve([]Endpoint{{Name: "inter-router", Host: "host1", Port: "443"}}, "skupper-router")) + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_RESOLVED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("no endpoints sets Resolved=Pending", func(t *testing.T) { + r := &RouterAccess{} + r.SetConfigured(nil) + r.Resolve([]Endpoint{{Name: "inter-router", Host: "host1", Port: "443"}}, "skupper-router") + assert.Assert(t, r.Resolve([]Endpoint{}, "skupper-router")) + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_RESOLVED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) +} + +func TestRouterAccess_IsConfigured(t *testing.T) { + r := &RouterAccess{} + assert.Assert(t, !r.IsConfigured()) + r.SetConfigured(nil) + assert.Assert(t, r.IsConfigured()) +} + +func TestNetwork_SetConfigured(t *testing.T) { + t.Run("ready=true sets Configured=True", func(t *testing.T) { + n := &Network{} + assert.Assert(t, n.SetConfigured(true)) + cond := meta.FindStatusCondition(n.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("ready=false sets Configured=Pending", func(t *testing.T) { + n := &Network{} + assert.Assert(t, n.SetConfigured(false)) + cond := meta.FindStatusCondition(n.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) +} + +func TestNetwork_SetError(t *testing.T) { + expectedName := "network" + t.Run("sets Configured=False with expected name in message", func(t *testing.T) { + n := &Network{} + assert.Assert(t, n.SetError(expectedName)) + cond := meta.FindStatusCondition(n.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + assert.Equal(t, cond.Message, "name must be 'network'") + }) + t.Run("repeated call with same state is a no-op", func(t *testing.T) { + n := &Network{} + n.SetError(expectedName) + assert.Assert(t, !n.SetError(expectedName)) + }) +} + +func TestNetworkLink_SetConfigured(t *testing.T) { + t.Run("ready=true sets Configured=True", func(t *testing.T) { + nl := &NetworkLink{} + assert.Assert(t, nl.SetConfigured(true)) + cond := meta.FindStatusCondition(nl.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("ready=false sets Configured=Pending", func(t *testing.T) { + nl := &NetworkLink{} + assert.Assert(t, nl.SetConfigured(false)) + cond := meta.FindStatusCondition(nl.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) +} + +func TestNetworkLink_SetError(t *testing.T) { + t.Run("sets Configured=False", func(t *testing.T) { + nl := &NetworkLink{} + assert.Assert(t, nl.SetError(errors.New("link error"))) + cond := meta.FindStatusCondition(nl.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) + t.Run("repeated call with same state is a no-op", func(t *testing.T) { + nl := &NetworkLink{} + nl.SetError(errors.New("link error")) + assert.Assert(t, !nl.SetError(errors.New("link error"))) + }) +} + +func TestNetworkLink_IsReady(t *testing.T) { + t.Run("false before any condition is set", func(t *testing.T) { + nl := &NetworkLink{} + assert.Assert(t, !nl.IsReady()) + }) + t.Run("true after SetConfigured(true)", func(t *testing.T) { + nl := &NetworkLink{} + nl.SetConfigured(true) + assert.Assert(t, nl.IsReady()) + }) +} + +func TestInterNetworkIngress_SetConfigured(t *testing.T) { + t.Run("ready=true sets Configured=True", func(t *testing.T) { + i := &InterNetworkIngress{} + assert.Assert(t, i.SetConfigured(true)) + cond := meta.FindStatusCondition(i.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("ready=false sets Configured=Pending", func(t *testing.T) { + i := &InterNetworkIngress{} + assert.Assert(t, i.SetConfigured(false)) + cond := meta.FindStatusCondition(i.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) +} + +func TestInterNetworkIngress_SetError(t *testing.T) { + t.Run("sets Configured=False", func(t *testing.T) { + i := &InterNetworkIngress{} + assert.Assert(t, i.SetError(errors.New("ingress error"))) + cond := meta.FindStatusCondition(i.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) + t.Run("repeated call with same state is a no-op", func(t *testing.T) { + i := &InterNetworkIngress{} + i.SetError(errors.New("ingress error")) + assert.Assert(t, !i.SetError(errors.New("ingress error"))) + }) +} + +func TestNetworkAccess_SetConfigured(t *testing.T) { + t.Run("first call stores networkId and sets Configured=True", func(t *testing.T) { + r := &NetworkAccess{} + assert.Assert(t, r.SetConfigured("net-1", nil)) + assert.Equal(t, r.Status.NetworkId, "net-1") + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_CONFIGURED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("identical second call is a no-op", func(t *testing.T) { + r := &NetworkAccess{} + r.SetConfigured("net-1", nil) + assert.Assert(t, !r.SetConfigured("net-1", nil)) + }) + t.Run("changed networkId returns true even when condition already set", func(t *testing.T) { + r := &NetworkAccess{} + r.SetConfigured("net-1", nil) + assert.Assert(t, r.SetConfigured("net-2", nil)) + assert.Equal(t, r.Status.NetworkId, "net-2") + }) +} + +func TestNetworkAccess_Resolve(t *testing.T) { + t.Run("endpoints present sets Resolved=True", func(t *testing.T) { + r := &NetworkAccess{} + r.SetConfigured("net-1", nil) + assert.Assert(t, r.Resolve([]Endpoint{{Name: "inter-router", Host: "host1", Port: "8080"}}, "skupper-router")) + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_RESOLVED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionTrue) + }) + t.Run("no endpoints sets Resolved=Pending", func(t *testing.T) { + r := &NetworkAccess{} + r.SetConfigured("net-1", nil) + r.Resolve([]Endpoint{{Name: "inter-router", Host: "host1", Port: "8080"}}, "skupper-router") + assert.Assert(t, r.Resolve([]Endpoint{}, "skupper-router")) + cond := meta.FindStatusCondition(r.Status.Conditions, CONDITION_TYPE_RESOLVED) + assert.Assert(t, cond != nil) + assert.Equal(t, cond.Status, metav1.ConditionFalse) + }) +} + +func TestNetworkAccess_Resolve_endpointMerge(t *testing.T) { + setup := func() *NetworkAccess { + r := &NetworkAccess{} + r.SetConfigured("net-1", nil) + r.Resolve([]Endpoint{ + {Name: "inter-network", Host: "host-original", Port: "443", Group: "skupper-router"}, + }, "skupper-router") + return r + } + + t.Run("endpoint retained unchanged reports no change", func(t *testing.T) { + r := setup() + assert.Assert(t, !r.Resolve([]Endpoint{ + {Name: "inter-network", Host: "host-original", Port: "443", Group: "skupper-router"}, + }, "skupper-router")) + }) + t.Run("endpoint host updated reports change", func(t *testing.T) { + r := setup() + assert.Assert(t, r.Resolve([]Endpoint{ + {Name: "inter-network", Host: "host-new", Port: "443", Group: "skupper-router"}, + }, "skupper-router")) + found := false + for _, ep := range r.Status.Endpoints { + if ep.Name == "inter-network" { + found = true + assert.Equal(t, ep.Host, "host-new") + } + } + assert.Assert(t, found) + }) + t.Run("endpoint removed from desired list reports change", func(t *testing.T) { + r := setup() + assert.Assert(t, r.Resolve([]Endpoint{ + {Name: "inter-network", Host: "host-replace", Port: "443", Group: "skupper-router"}, + }, "skupper-router")) + for _, ep := range r.Status.Endpoints { + assert.Assert(t, ep.Host != "host-original") + } + }) + t.Run("new endpoint added reports change", func(t *testing.T) { + r := setup() + assert.Assert(t, r.Resolve([]Endpoint{ + {Name: "inter-network", Host: "host-new", Port: "443", Group: "skupper-router-2"}, + }, "skupper-router-2")) + found := false + for _, ep := range r.Status.Endpoints { + if ep.Group == "skupper-router-2" { + found = true + } + } + assert.Assert(t, found) + assert.Equal(t, 2, len(r.Status.Endpoints)) + }) +} + +func TestNetworkAccess_IsConfigured(t *testing.T) { + r := &NetworkAccess{} + r.SetConfigured("net-1", nil) + assert.Assert(t, r.IsConfigured("net-1")) + assert.Assert(t, !r.IsConfigured("net-2")) +} + +func TestNetworkAccess_AllocatePort(t *testing.T) { + t.Run("allocates a new port", func(t *testing.T) { + r := &NetworkAccess{} + assert.Assert(t, r.AllocatePort(8080)) + assert.Equal(t, r.Status.Port, 8080) + }) + t.Run("no change for same port", func(t *testing.T) { + r := &NetworkAccess{} + r.AllocatePort(8080) + assert.Assert(t, !r.AllocatePort(8080)) + }) + t.Run("zero port returns false", func(t *testing.T) { + r := &NetworkAccess{} + assert.Assert(t, !r.AllocatePort(0)) + }) +} + +func TestNetworkAccess_GetPort(t *testing.T) { + t.Run("spec port takes precedence", func(t *testing.T) { + r := &NetworkAccess{ + Spec: NetworkAccessSpec{Port: 9090}, + Status: NetworkAccessStatus{Port: 8080}, + } + assert.Equal(t, r.GetPort(), 9090) + }) + t.Run("falls back to status port when spec port is 0", func(t *testing.T) { + r := &NetworkAccess{ + Status: NetworkAccessStatus{Port: 8080}, + } + assert.Equal(t, r.GetPort(), 8080) + }) +} + +func TestNetworkAccess_HasAllocatedPort(t *testing.T) { + t.Run("false when both spec and status port are 0", func(t *testing.T) { + r := &NetworkAccess{} + assert.Assert(t, !r.HasAllocatedPort()) + }) + t.Run("false when spec port is set (not dynamically allocated)", func(t *testing.T) { + r := &NetworkAccess{Spec: NetworkAccessSpec{Port: 9090}} + assert.Assert(t, !r.HasAllocatedPort()) + }) + t.Run("true when spec port is 0 and status port is set", func(t *testing.T) { + r := &NetworkAccess{} + r.AllocatePort(8080) + assert.Assert(t, r.HasAllocatedPort()) + }) +} From 2139175808c3cd4cea8afe9059e25a6f354b5eee Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Thu, 30 Jul 2026 16:20:00 -0300 Subject: [PATCH 6/9] Fixed conditions description for new CRDs --- config/crd/bases/skupper_inter_network_ingress_crd.yaml | 6 ++---- config/crd/bases/skupper_network_access_crd.yaml | 2 +- config/crd/bases/skupper_network_crd.yaml | 6 ++---- config/crd/bases/skupper_network_link_crd.yaml | 6 ++---- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/config/crd/bases/skupper_inter_network_ingress_crd.yaml b/config/crd/bases/skupper_inter_network_ingress_crd.yaml index 040ba6bae..804adb495 100644 --- a/config/crd/bases/skupper_inter_network_ingress_crd.yaml +++ b/config/crd/bases/skupper_inter_network_ingress_crd.yaml @@ -63,10 +63,8 @@ spec: description: |- A set of named conditions describing the current state of the resource. - - `Configured`: The output resources for this resource have been created. - - `Running`: There is at least one router pod running. - - `Resolved`: The hostname or IP address for link access is available. - - `Ready`: The site is ready for use. All other conditions are true. + - `Configured`: The inter network ingress configuration has been applied to the router. + - `Ready`: Access to the exposed routing key is ready. All other conditions are true. items: type: object properties: diff --git a/config/crd/bases/skupper_network_access_crd.yaml b/config/crd/bases/skupper_network_access_crd.yaml index b3c20f60d..ba4fd152c 100644 --- a/config/crd/bases/skupper_network_access_crd.yaml +++ b/config/crd/bases/skupper_network_access_crd.yaml @@ -117,7 +117,7 @@ spec: - `Configured`: The output resources for this resource have been created. - `Resolved`: The connection endpoints are available. - - `Ready`: The router access is ready for use. All other conditions are true. + - `Ready`: The network access is ready for use. All other conditions are true. items: type: object properties: diff --git a/config/crd/bases/skupper_network_crd.yaml b/config/crd/bases/skupper_network_crd.yaml index 3af570fc6..16984ed84 100644 --- a/config/crd/bases/skupper_network_crd.yaml +++ b/config/crd/bases/skupper_network_crd.yaml @@ -63,10 +63,8 @@ spec: description: |- A set of named conditions describing the current state of the resource. - - `Configured`: The output resources for this resource have been created. - - `Running`: There is at least one router pod running. - - `Resolved`: The hostname or IP address for link access is available. - - `Ready`: The site is ready for use. All other conditions are true. + - `Configured`: The network configuration has been applied to the router. + - `Ready`: Network is ready. All other conditions are true. items: type: object properties: diff --git a/config/crd/bases/skupper_network_link_crd.yaml b/config/crd/bases/skupper_network_link_crd.yaml index 1a4357a8b..e3279c5eb 100644 --- a/config/crd/bases/skupper_network_link_crd.yaml +++ b/config/crd/bases/skupper_network_link_crd.yaml @@ -67,10 +67,8 @@ spec: description: |- A set of named conditions describing the current state of the resource. - - `Configured`: The output resources for this resource have been created. - - `Running`: There is at least one router pod running. - - `Resolved`: The hostname or IP address for link access is available. - - `Ready`: The site is ready for use. All other conditions are true. + - `Configured`: The network link configuration has been applied to the router. + - `Ready`: The network link is ready for use. All other conditions are true. items: type: object properties: From f9d22df35b8e39d6ef2bf7ac0d26a69a1329aa41 Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Thu, 30 Jul 2026 16:25:45 -0300 Subject: [PATCH 7/9] Fixed typo in crd validation rule --- config/crd/bases/skupper_inter_network_ingress_crd.yaml | 2 +- pkg/apis/skupper/v2alpha1/types.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/crd/bases/skupper_inter_network_ingress_crd.yaml b/config/crd/bases/skupper_inter_network_ingress_crd.yaml index 804adb495..fcf49b004 100644 --- a/config/crd/bases/skupper_inter_network_ingress_crd.yaml +++ b/config/crd/bases/skupper_inter_network_ingress_crd.yaml @@ -41,7 +41,7 @@ spec: type: string x-kubernetes-validations: - message: At least one of 'networkLink' or 'networkAccess' must be provided and non-empty. - rule: (has(self.networkLink) && self.networkLink != ”) || (has(self.networkAccess) && self.networkAccess != ”) + rule: (has(self.networkLink) && self.networkLink != "") || (has(self.networkAccess) && self.networkAccess != "") required: - routingKey status: diff --git a/pkg/apis/skupper/v2alpha1/types.go b/pkg/apis/skupper/v2alpha1/types.go index 2ee906c4e..7405e437c 100644 --- a/pkg/apis/skupper/v2alpha1/types.go +++ b/pkg/apis/skupper/v2alpha1/types.go @@ -1303,7 +1303,7 @@ type InterNetworkIngressList struct { } // InterNetworkIngressSpec -// +kubebuilder:validation:XValidation:rule="(has(self.networkLink) && self.networkLink != ”) || (has(self.networkAccess) && self.networkAccess != ”)",message="At least one of 'networkLink' or 'networkAccess' must be provided and non-empty." +// +kubebuilder:validation:XValidation:rule="(has(self.networkLink) && self.networkLink != \"\") || (has(self.networkAccess) && self.networkAccess != \"\")",message="At least one of 'networkLink' or 'networkAccess' must be provided and non-empty." type InterNetworkIngressSpec struct { RoutingKey string `json:"routingKey"` // +optional From cbccb35eea74424bc4be304d01c72be5cd3b847e Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Thu, 30 Jul 2026 18:56:17 -0300 Subject: [PATCH 8/9] Introduced helm chart for skupper-crds --- .gitignore | 4 + Makefile | 7 ++ charts/skupper-crds/Chart.yaml | 5 + charts/skupper-crds/README.md | 106 ++++++++++++++++++ charts/skupper-crds/templates/NOTES.txt | 9 ++ charts/skupper-crds/values.yaml | 6 + config/crd/kustomization.yaml | 4 - config/crd/multi-van/kustomization.yaml | 5 + .../skupper_inter_network_ingress_crd.yaml | 0 .../skupper_network_access_crd.yaml | 0 .../skupper_network_crd.yaml | 0 .../skupper_network_link_crd.yaml | 0 scripts/skupper-crds-helm-chart-generator.sh | 66 +++++++++++ 13 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 charts/skupper-crds/Chart.yaml create mode 100644 charts/skupper-crds/README.md create mode 100644 charts/skupper-crds/templates/NOTES.txt create mode 100644 charts/skupper-crds/values.yaml create mode 100644 config/crd/multi-van/kustomization.yaml rename config/crd/{bases => multi-van}/skupper_inter_network_ingress_crd.yaml (100%) rename config/crd/{bases => multi-van}/skupper_network_access_crd.yaml (100%) rename config/crd/{bases => multi-van}/skupper_network_crd.yaml (100%) rename config/crd/{bases => multi-van}/skupper_network_link_crd.yaml (100%) create mode 100755 scripts/skupper-crds-helm-chart-generator.sh diff --git a/.gitignore b/.gitignore index e3adaedd4..f87cf6df4 100644 --- a/.gitignore +++ b/.gitignore @@ -32,12 +32,16 @@ vendor/ manifest.json oci-archives/ skupper-cluster-scope.yaml +skupper-crds.yaml +skupper-multi-van-crds.yaml skupper-namespace-scope.yaml skupper-network-observer*.yaml bundle.Dockerfile ./bundle/ !charts/skupper/README.md charts/skupper/ +charts/skupper-crds/templates/crds.yaml +charts/skupper-crds/templates/multi-van-crds.yaml skupper-*.tgz artifacthub-repo.yml network-observer-*.tgz diff --git a/Makefile b/Makefile index e7f1ddfc0..f72f8693d 100644 --- a/Makefile +++ b/Makefile @@ -160,6 +160,9 @@ generate-docs: generate-doc generate-skupper-helm-chart: ./scripts/skupper-helm-chart-generator.sh ${IMAGE_TAG} ${ROUTER_IMAGE_TAG} +generate-skupper-crds-helm-chart: + ./scripts/skupper-crds-helm-chart-generator.sh ${IMAGE_TAG} + generate-skupper-deployment-cluster-scoped: ./scripts/skupper-deployment-generator.sh cluster ${IMAGE_TAG} ${ROUTER_IMAGE_TAG} false > skupper-cluster-scope.yaml @@ -168,10 +171,14 @@ generate-skupper-deployment-namespace-scoped: generate-crd-manifest: kubectl kustomize config/crd > skupper-crds.yaml + kubectl kustomize config/crd/multi-van > skupper-multi-van-crds.yaml pack-skupper-helm-chart: generate-skupper-helm-chart helm package ./charts/skupper +pack-skupper-crds-helm-chart: generate-skupper-crds-helm-chart + helm package ./charts/skupper-crds + pack-network-observer-helm-chart: helm package ./charts/network-observer diff --git a/charts/skupper-crds/Chart.yaml b/charts/skupper-crds/Chart.yaml new file mode 100644 index 000000000..b0ab3a0c4 --- /dev/null +++ b/charts/skupper-crds/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: skupper-crds +description: Helm chart for installing and upgrading Skupper CRDs. +version: 0.1.0-dev +appVersion: v2-dev diff --git a/charts/skupper-crds/README.md b/charts/skupper-crds/README.md new file mode 100644 index 000000000..24b2c6402 --- /dev/null +++ b/charts/skupper-crds/README.md @@ -0,0 +1,106 @@ +# skupper-crds + +Helm chart for installing and upgrading [Skupper](https://skupper.io) CRDs. + +Unlike the main `skupper` chart — where CRDs are placed in `crds/` and +therefore only installed on the initial `helm install` — this chart places all +CRDs in `templates/` so that `helm upgrade` applies the latest schemas on every +run. + +## Prerequisites + +- Kubernetes 1.25+ +- Helm 3 + +## Using the chart + +The chart exposes two independent flags that control which CRDs are installed: + +| Value | Default | Description | +|---|---|---| +| `base` | `true` | Install the stable Skupper CRDs. | +| `multiVan` | `false` | Install the 4 multi-VAN CRDs (Network, NetworkLink, InterNetworkIngress, NetworkAccess). | + +### Base CRDs + +The stable Skupper CRDs are installed by default: + +```bash +helm install skupper-crds oci://quay.io/skupper/helm/skupper-crds +``` + +To install only the multi-VAN CRDs and skip the base ones (e.g. base CRDs are +already present in the cluster from a previous install): + +```bash +helm install skupper-crds oci://quay.io/skupper/helm/skupper-crds \ + --set base=false \ + --set multiVan=true +``` + +### Multi-VAN CRDs + +The chart includes 4 additional CRDs that enable multi-VAN (Virtual Application +Network) support: `Network`, `NetworkLink`, `InterNetworkIngress`, and +`NetworkAccess`. These are **disabled by default** and must be opted in +explicitly: + +```bash +helm install skupper-crds oci://quay.io/skupper/helm/skupper-crds \ + --set multiVan=true +``` + +To install both base and multi-VAN CRDs together using an override `values.yaml`: + +```yaml +base: true +multiVan: true +``` + +> **Note:** Once CRDs are installed, removing them (by running `helm upgrade` +> with a flag set to `false`) will **not** delete the CRDs from the cluster. +> Helm never deletes CRDs during an upgrade or uninstall. Remove them manually +> with `kubectl delete crd` if needed. + +## Upgrading the chart + +Because all CRDs are in `templates/`, running `helm upgrade` is sufficient to +apply any schema changes: + +```bash +helm upgrade skupper-crds oci://quay.io/skupper/helm/skupper-crds +``` + +To also upgrade the multi-VAN CRDs: + +```bash +helm upgrade skupper-crds oci://quay.io/skupper/helm/skupper-crds \ + --set multiVan=true +``` + +## Development + +The chart has two parts: + +- **Static** — `Chart.yaml`, `values.yaml`, `README.md`, and + `templates/NOTES.txt` are committed to the repository. +- **Generated** — `templates/crds.yaml` (stable CRDs, gated by `base`) and + `templates/multi-van-crds.yaml` (multi-van CRDs, gated by `multiVan`) are + produced by the generator script from the source files under `config/crd/` + and are gitignored. Both template files are applied on every `helm upgrade` + when their respective flag is `true`. + +To regenerate the chart before packaging or linting, run: + +```bash +make generate-skupper-crds-helm-chart +``` + +This generates `templates/crds.yaml` from `config/crd/bases/` and +`templates/multi-van-crds.yaml` from `config/crd/multi-van/`. + +To package the chart as a `.tgz`: + +```bash +make pack-skupper-crds-helm-chart +``` diff --git a/charts/skupper-crds/templates/NOTES.txt b/charts/skupper-crds/templates/NOTES.txt new file mode 100644 index 000000000..0b8ab6fbf --- /dev/null +++ b/charts/skupper-crds/templates/NOTES.txt @@ -0,0 +1,9 @@ +=========================================================== + skupper-crds chart is now installed in the cluster. + Skupper CRDs are available cluster-wide. +{{- if .Values.multiVan }} + + Multi-VAN CRDs (Network, NetworkLink, InterNetworkIngress, + NetworkAccess) have been installed. +{{- end }} +=========================================================== diff --git a/charts/skupper-crds/values.yaml b/charts/skupper-crds/values.yaml new file mode 100644 index 000000000..683eac3dd --- /dev/null +++ b/charts/skupper-crds/values.yaml @@ -0,0 +1,6 @@ +# When set to true, install the base CRDs +base: true +# When set to true, the 4 multi-VAN CRDs (Network, NetworkLink, +# InterNetworkIngress, NetworkAccess) are installed/upgraded on every +# helm install and helm upgrade. Set to false (the default) to omit them. +multiVan: false diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index e4a17af1d..a78d157cd 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -7,13 +7,9 @@ resources: - bases/skupper_attached_connector_crd.yaml - bases/skupper_certificate_crd.yaml - bases/skupper_connector_crd.yaml -- bases/skupper_inter_network_ingress_crd.yaml - bases/skupper_link_crd.yaml - bases/skupper_listener_crd.yaml - bases/skupper_multikeylistener_crd.yaml -- bases/skupper_network_crd.yaml -- bases/skupper_network_link_crd.yaml -- bases/skupper_network_access_crd.yaml - bases/skupper_router_access_crd.yaml - bases/skupper_secured_access_crd.yaml - bases/skupper_site_crd.yaml diff --git a/config/crd/multi-van/kustomization.yaml b/config/crd/multi-van/kustomization.yaml new file mode 100644 index 000000000..7c61c5296 --- /dev/null +++ b/config/crd/multi-van/kustomization.yaml @@ -0,0 +1,5 @@ +resources: +- skupper_inter_network_ingress_crd.yaml +- skupper_network_access_crd.yaml +- skupper_network_crd.yaml +- skupper_network_link_crd.yaml diff --git a/config/crd/bases/skupper_inter_network_ingress_crd.yaml b/config/crd/multi-van/skupper_inter_network_ingress_crd.yaml similarity index 100% rename from config/crd/bases/skupper_inter_network_ingress_crd.yaml rename to config/crd/multi-van/skupper_inter_network_ingress_crd.yaml diff --git a/config/crd/bases/skupper_network_access_crd.yaml b/config/crd/multi-van/skupper_network_access_crd.yaml similarity index 100% rename from config/crd/bases/skupper_network_access_crd.yaml rename to config/crd/multi-van/skupper_network_access_crd.yaml diff --git a/config/crd/bases/skupper_network_crd.yaml b/config/crd/multi-van/skupper_network_crd.yaml similarity index 100% rename from config/crd/bases/skupper_network_crd.yaml rename to config/crd/multi-van/skupper_network_crd.yaml diff --git a/config/crd/bases/skupper_network_link_crd.yaml b/config/crd/multi-van/skupper_network_link_crd.yaml similarity index 100% rename from config/crd/bases/skupper_network_link_crd.yaml rename to config/crd/multi-van/skupper_network_link_crd.yaml diff --git a/scripts/skupper-crds-helm-chart-generator.sh b/scripts/skupper-crds-helm-chart-generator.sh new file mode 100755 index 000000000..debccc76c --- /dev/null +++ b/scripts/skupper-crds-helm-chart-generator.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Check if the script is executed with one argument +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +APP_VERSION="$1" + +# Set chart name and directories +CHART_NAME="skupper-crds" +DEST_DIR="./charts/$CHART_NAME" +CRD_SOURCE_DIR="./config/crd/bases" +MULTI_VAN_SOURCE_DIR="./config/crd/multi-van" +TEMPLATES_DIR="$DEST_DIR/templates" +STABLE_TEMPLATE="$TEMPLATES_DIR/crds.yaml" +MULTI_VAN_TEMPLATE="$TEMPLATES_DIR/multi-van-crds.yaml" + +if [ ! -d "$CRD_SOURCE_DIR" ]; then + echo "Source directory '$CRD_SOURCE_DIR' does not exist. Exiting." + exit 1 +fi + +if [ ! -d "$MULTI_VAN_SOURCE_DIR" ]; then + echo "Source directory '$MULTI_VAN_SOURCE_DIR' does not exist. Exiting." + exit 1 +fi + +mkdir -p "$TEMPLATES_DIR" +rm -f "$TEMPLATES_DIR"/*yaml + +# Generate templates/crds.yaml — all stable CRDs, conditional on .Values.base +{ + printf '{{- if .Values.base }}\n' + first=true + for f in "$CRD_SOURCE_DIR"/*_crd.yaml; do + if [ "$first" = true ]; then + first=false + else + printf -- '---\n' + fi + cat "$f" + done + printf '{{- end }}\n' +} > "$STABLE_TEMPLATE" + +# Generate templates/multi-van-crds.yaml — multi-van CRDs, conditional on .Values.multiVan +{ + printf '{{- if .Values.multiVan }}\n' + first=true + for f in "$MULTI_VAN_SOURCE_DIR"/*_crd.yaml; do + if [ "$first" = true ]; then + first=false + else + printf -- '---\n' + fi + cat "$f" + done + printf '{{- end }}\n' +} > "$MULTI_VAN_TEMPLATE" + +# Substitute appVersion in Chart.yaml +sed -i "s/^appVersion:.*/appVersion: $APP_VERSION/" "$DEST_DIR/Chart.yaml" + +echo "Helm chart '$CHART_NAME' generated successfully with appVersion=$APP_VERSION." From 1c9762c8605312658f7eef4c093d6de54c16976f Mon Sep 17 00:00:00 2001 From: Fernando Giorgetti Date: Fri, 31 Jul 2026 16:00:40 -0300 Subject: [PATCH 9/9] Keep multi-van resources as part of RBAC --- config/rbac/cluster/clusterrole.yaml | 10 +++++++++- config/rbac/namespace/role.yaml | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/config/rbac/cluster/clusterrole.yaml b/config/rbac/cluster/clusterrole.yaml index 2e1deb9be..d2158f46b 100644 --- a/config/rbac/cluster/clusterrole.yaml +++ b/config/rbac/cluster/clusterrole.yaml @@ -156,10 +156,18 @@ rules: - securedaccesses/status - certificates - certificates/status + - networkaccesses + - networkaccesses/status + - networks + - networks/status + - networklinks + - networklinks/status + - internetworkingresses + - internetworkingresses/status verbs: - get - list - watch - create - update - - delete \ No newline at end of file + - delete diff --git a/config/rbac/namespace/role.yaml b/config/rbac/namespace/role.yaml index 6ef42ece3..6445035d1 100644 --- a/config/rbac/namespace/role.yaml +++ b/config/rbac/namespace/role.yaml @@ -157,6 +157,14 @@ rules: - securedaccesses/status - certificates - certificates/status + - networkaccesses + - networkaccesses/status + - networks + - networks/status + - networklinks + - networklinks/status + - internetworkingresses + - internetworkingresses/status verbs: - get - list