From 34c7117ffb53566fce9505bd06984b4913d5d35d Mon Sep 17 00:00:00 2001 From: Francesco Cheinasso Date: Tue, 19 Sep 2023 16:33:26 +0200 Subject: [PATCH] Configuration controller --- apis/ipam/v1alpha1/ip_types.go | 6 +- apis/ipam/v1alpha1/network_types.go | 6 +- apis/ipam/v1alpha1/zz_generated.deepcopy.go | 3 +- apis/networking/v1alpha1/common_types.go | 37 +++++ .../v1alpha1/configuration_types.go | 10 +- .../v1alpha1/gatewayserver_types.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 20 +-- cmd/liqo-controller-manager/main.go | 8 ++ .../liqo-crds/crds/ipam.liqo.io_ips.yaml | 3 + .../liqo-crds/crds/ipam.liqo.io_networks.yaml | 2 + .../networking.liqo.io_configurations.yaml | 6 + .../crds/networking.liqo.io_connections.yaml | 2 + .../networking.liqo.io_gatewayservers.yaml | 2 + .../networking.liqo.io_wggatewayservers.yaml | 2 + .../liqo-controller-manager-ClusterRole.yaml | 20 +++ .../configuration-controller.go | 131 ++++++++++++++++++ .../configuration-controller/doc.go | 16 +++ .../configuration-controller/label.go | 86 ++++++++++++ .../configuration-controller/network.go | 96 +++++++++++++ .../ip-controller/exposition.go | 2 +- .../ip-controller/ip_controller.go | 23 +-- .../network-controller/network_controller.go | 27 ++-- pkg/liqo-controller-manager/webhooks/ip/ip.go | 2 +- .../webhooks/network/nw.go | 2 +- pkg/utils/events/doc.go | 16 +++ pkg/utils/events/events.go | 58 ++++++++ pkg/utils/getters/k8sGetters.go | 11 ++ pkg/utils/mapper/mapper.go | 4 + 28 files changed, 556 insertions(+), 47 deletions(-) create mode 100644 apis/networking/v1alpha1/common_types.go create mode 100644 pkg/liqo-controller-manager/external-network/configuration-controller/configuration-controller.go create mode 100644 pkg/liqo-controller-manager/external-network/configuration-controller/doc.go create mode 100644 pkg/liqo-controller-manager/external-network/configuration-controller/label.go create mode 100644 pkg/liqo-controller-manager/external-network/configuration-controller/network.go create mode 100644 pkg/utils/events/doc.go create mode 100644 pkg/utils/events/events.go diff --git a/apis/ipam/v1alpha1/ip_types.go b/apis/ipam/v1alpha1/ip_types.go index 475e9ee3c3..c9e54ba183 100644 --- a/apis/ipam/v1alpha1/ip_types.go +++ b/apis/ipam/v1alpha1/ip_types.go @@ -18,6 +18,8 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" ) var ( @@ -45,7 +47,7 @@ type ServiceTemplate struct { // IPSpec defines a local IP. type IPSpec struct { // IP is the local IP. - IP string `json:"ip"` + IP networkingv1alpha1.IP `json:"ip"` // ServiceTemplate contains the template to create the associated service (and endpointslice) for the IP endopoint. // If empty the creation of the service is disabled (default). // +kubebuilder:validation:Optional @@ -55,7 +57,7 @@ type IPSpec struct { // IPStatus defines remapped IPs. type IPStatus struct { // IPMappings contains the mapping of the local IP for each remote cluster. - IPMappings map[string]string `json:"ipMappings,omitempty"` + IPMappings map[string]networkingv1alpha1.IP `json:"ipMappings,omitempty"` } // +kubebuilder:object:root=true diff --git a/apis/ipam/v1alpha1/network_types.go b/apis/ipam/v1alpha1/network_types.go index 07d16ce748..62c0aa9750 100644 --- a/apis/ipam/v1alpha1/network_types.go +++ b/apis/ipam/v1alpha1/network_types.go @@ -17,6 +17,8 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + + v1alpha1networking "github.com/liqotech/liqo/apis/networking/v1alpha1" ) var ( @@ -36,13 +38,13 @@ var ( // NetworkSpec defines the desired state of Network. type NetworkSpec struct { // CIDR is the desired CIDR for the remote cluster. - CIDR string `json:"cidr"` + CIDR v1alpha1networking.CIDR `json:"cidr"` } // NetworkStatus defines the observed state of Network. type NetworkStatus struct { // CIDR is the remapped CIDR for the remote cluster. - CIDR string `json:"cidr,omitempty"` + CIDR v1alpha1networking.CIDR `json:"cidr,omitempty"` } // +kubebuilder:object:root=true diff --git a/apis/ipam/v1alpha1/zz_generated.deepcopy.go b/apis/ipam/v1alpha1/zz_generated.deepcopy.go index a5836d717c..668fcc1b0a 100644 --- a/apis/ipam/v1alpha1/zz_generated.deepcopy.go +++ b/apis/ipam/v1alpha1/zz_generated.deepcopy.go @@ -19,6 +19,7 @@ package v1alpha1 import ( + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -106,7 +107,7 @@ func (in *IPStatus) DeepCopyInto(out *IPStatus) { *out = *in if in.IPMappings != nil { in, out := &in.IPMappings, &out.IPMappings - *out = make(map[string]string, len(*in)) + *out = make(map[string]networkingv1alpha1.IP, len(*in)) for key, val := range *in { (*out)[key] = val } diff --git a/apis/networking/v1alpha1/common_types.go b/apis/networking/v1alpha1/common_types.go new file mode 100644 index 0000000000..eb2ae4a013 --- /dev/null +++ b/apis/networking/v1alpha1/common_types.go @@ -0,0 +1,37 @@ +// Copyright 2019-2023 The Liqo 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. + +// Package v1alpha1 contains API Schema definitions for the networking v1alpha1 API group. +// +//nolint:lll // ignore long lines given by Kubebuilder marker annotations. +package v1alpha1 + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// CIDR defines a syntax validated CIDR. +// +kubebuilder:validation:Pattern=`^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$` +type CIDR string + +func (c CIDR) String() string { + return string(c) +} + +// IP defines a syntax validated IP. +// +kubebuilder:validation:Pattern=`^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])$` +type IP string + +func (i IP) String() string { + return string(i) +} diff --git a/apis/networking/v1alpha1/configuration_types.go b/apis/networking/v1alpha1/configuration_types.go index f30df97cae..9f2c0c8a50 100644 --- a/apis/networking/v1alpha1/configuration_types.go +++ b/apis/networking/v1alpha1/configuration_types.go @@ -34,18 +34,18 @@ var ConfigurationGroupResource = schema.GroupResource{Group: GroupVersion.Group, // ConfigurationGroupVersionResource is groupResourceVersion used to register these objects. var ConfigurationGroupVersionResource = GroupVersion.WithResource(ConfigurationResource) -// CIDR defines the CIDR of the cluster. -type CIDR struct { +// ClusterConfigCIDR defines the CIDR of the cluster. +type ClusterConfigCIDR struct { // Pod CIDR of the cluster. - Pod string `json:"pod,omitempty"` + Pod CIDR `json:"pod,omitempty"` // External CIDR of the cluster. - External string `json:"external,omitempty"` + External CIDR `json:"external,omitempty"` } // ClusterConfig defines the configuration of a cluster. type ClusterConfig struct { // CIDR of the cluster. - CIDR CIDR `json:"cidr,omitempty"` + CIDR ClusterConfigCIDR `json:"cidr,omitempty"` } // ConfigurationSpec defines the desired state of Configuration. diff --git a/apis/networking/v1alpha1/gatewayserver_types.go b/apis/networking/v1alpha1/gatewayserver_types.go index cd88bf6686..e008d34a50 100644 --- a/apis/networking/v1alpha1/gatewayserver_types.go +++ b/apis/networking/v1alpha1/gatewayserver_types.go @@ -58,7 +58,7 @@ type GatewayServerSpec struct { // EndpointStatus defines the observed state of the endpoint. type EndpointStatus struct { // Addresses specifies the addresses of the endpoint. - Addresses []string `json:"addresses,omitempty"` + Addresses []IP `json:"addresses,omitempty"` // Port specifies the port of the endpoint. Port int32 `json:"port,omitempty"` // Protocol specifies the protocol of the endpoint. diff --git a/apis/networking/v1alpha1/zz_generated.deepcopy.go b/apis/networking/v1alpha1/zz_generated.deepcopy.go index 1512f97544..914f96b6db 100644 --- a/apis/networking/v1alpha1/zz_generated.deepcopy.go +++ b/apis/networking/v1alpha1/zz_generated.deepcopy.go @@ -49,32 +49,32 @@ func (in *AddRemove) DeepCopy() *AddRemove { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CIDR) DeepCopyInto(out *CIDR) { +func (in *ClusterConfig) DeepCopyInto(out *ClusterConfig) { *out = *in + out.CIDR = in.CIDR } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CIDR. -func (in *CIDR) DeepCopy() *CIDR { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfig. +func (in *ClusterConfig) DeepCopy() *ClusterConfig { if in == nil { return nil } - out := new(CIDR) + out := new(ClusterConfig) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterConfig) DeepCopyInto(out *ClusterConfig) { +func (in *ClusterConfigCIDR) DeepCopyInto(out *ClusterConfigCIDR) { *out = *in - out.CIDR = in.CIDR } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfig. -func (in *ClusterConfig) DeepCopy() *ClusterConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfigCIDR. +func (in *ClusterConfigCIDR) DeepCopy() *ClusterConfigCIDR { if in == nil { return nil } - out := new(ClusterConfig) + out := new(ClusterConfigCIDR) in.DeepCopyInto(out) return out } @@ -326,7 +326,7 @@ func (in *EndpointStatus) DeepCopyInto(out *EndpointStatus) { *out = *in if in.Addresses != nil { in, out := &in.Addresses, &out.Addresses - *out = make([]string, len(*in)) + *out = make([]IP, len(*in)) copy(*out, *in) } if in.Protocol != nil { diff --git a/cmd/liqo-controller-manager/main.go b/cmd/liqo-controller-manager/main.go index 24a6c4ffcd..4620da2740 100644 --- a/cmd/liqo-controller-manager/main.go +++ b/cmd/liqo-controller-manager/main.go @@ -53,12 +53,14 @@ import ( discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1" ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1" sharingv1alpha1 "github.com/liqotech/liqo/apis/sharing/v1alpha1" virtualkubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1" "github.com/liqotech/liqo/cmd/virtual-kubelet/root" "github.com/liqotech/liqo/pkg/consts" identitymanager "github.com/liqotech/liqo/pkg/identityManager" + configurationcontroller "github.com/liqotech/liqo/pkg/liqo-controller-manager/external-network/configuration-controller" foreignclusteroperator "github.com/liqotech/liqo/pkg/liqo-controller-manager/foreign-cluster-operator" ipctrl "github.com/liqotech/liqo/pkg/liqo-controller-manager/ip-controller" mapsctrl "github.com/liqotech/liqo/pkg/liqo-controller-manager/namespacemap-controller" @@ -107,6 +109,7 @@ func init() { _ = offloadingv1alpha1.AddToScheme(scheme) _ = virtualkubeletv1alpha1.AddToScheme(scheme) _ = ipamv1alpha1.AddToScheme(scheme) + _ = networkingv1alpha1.AddToScheme(scheme) } func main() { @@ -588,6 +591,11 @@ func main() { klog.Errorf("Unable to start the ipReconciler", err) os.Exit(1) } + cfgr := configurationcontroller.NewConfigurationReconciler(mgr.GetClient(), mgr.GetScheme(), mgr.GetEventRecorderFor("configuration-controller")) + if err = cfgr.SetupWithManager(mgr); err != nil { + klog.Errorf("unable to create controller ConfigurationReconciler: %s", err) + os.Exit(1) + } } klog.Info("starting manager as controller manager") diff --git a/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_ips.yaml b/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_ips.yaml index 8590171c39..d5e4329375 100644 --- a/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_ips.yaml +++ b/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_ips.yaml @@ -49,6 +49,7 @@ spec: properties: ip: description: IP is the local IP. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])$ type: string serviceTemplate: description: ServiceTemplate contains the template to create the associated @@ -424,6 +425,8 @@ spec: properties: ipMappings: additionalProperties: + description: IP defines a syntax validated IP. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])$ type: string description: IPMappings contains the mapping of the local IP for each remote cluster. diff --git a/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_networks.yaml b/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_networks.yaml index d9b5dcdc8b..ff93fcb180 100644 --- a/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_networks.yaml +++ b/deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_networks.yaml @@ -48,6 +48,7 @@ spec: properties: cidr: description: CIDR is the desired CIDR for the remote cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string required: - cidr @@ -57,6 +58,7 @@ spec: properties: cidr: description: CIDR is the remapped CIDR for the remote cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string type: object required: diff --git a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_configurations.yaml b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_configurations.yaml index 00c7801758..57da5c29f4 100644 --- a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_configurations.yaml +++ b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_configurations.yaml @@ -47,9 +47,11 @@ spec: properties: external: description: External CIDR of the cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string pod: description: Pod CIDR of the cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string type: object type: object @@ -61,9 +63,11 @@ spec: properties: external: description: External CIDR of the cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string pod: description: Pod CIDR of the cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string type: object type: object @@ -80,9 +84,11 @@ spec: properties: external: description: External CIDR of the cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string pod: description: Pod CIDR of the cluster. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2][0-9]|3[0-2])$ type: string type: object type: object diff --git a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_connections.yaml b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_connections.yaml index 48c7509a63..342794d185 100644 --- a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_connections.yaml +++ b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_connections.yaml @@ -88,6 +88,8 @@ spec: addresses: description: Addresses specifies the addresses of the endpoint. items: + description: IP defines a syntax validated IP. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])$ type: string type: array port: diff --git a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_gatewayservers.yaml b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_gatewayservers.yaml index 0b73a9b025..9cfbeca582 100644 --- a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_gatewayservers.yaml +++ b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_gatewayservers.yaml @@ -105,6 +105,8 @@ spec: addresses: description: Addresses specifies the addresses of the endpoint. items: + description: IP defines a syntax validated IP. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])$ type: string type: array port: diff --git a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_wggatewayservers.yaml b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_wggatewayservers.yaml index 77d8105c15..aaa49bc315 100644 --- a/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_wggatewayservers.yaml +++ b/deployments/liqo/charts/liqo-crds/crds/networking.liqo.io_wggatewayservers.yaml @@ -8966,6 +8966,8 @@ spec: addresses: description: Addresses specifies the addresses of the endpoint. items: + description: IP defines a syntax validated IP. + pattern: ^(([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]{0,1}[0-9]{0,2}|2[0-4][0-9]|25[0-5])$ type: string type: array port: diff --git a/deployments/liqo/files/liqo-controller-manager-ClusterRole.yaml b/deployments/liqo/files/liqo-controller-manager-ClusterRole.yaml index 6e88c61213..4b0f98373c 100644 --- a/deployments/liqo/files/liqo-controller-manager-ClusterRole.yaml +++ b/deployments/liqo/files/liqo-controller-manager-ClusterRole.yaml @@ -375,6 +375,26 @@ rules: - get - update - watch +- apiGroups: + - networking.liqo.io + resources: + - configurations + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - networking.liqo.io + resources: + - configurations/status + verbs: + - get + - list + - patch + - update + - watch - apiGroups: - offloading.liqo.io resources: diff --git a/pkg/liqo-controller-manager/external-network/configuration-controller/configuration-controller.go b/pkg/liqo-controller-manager/external-network/configuration-controller/configuration-controller.go new file mode 100644 index 0000000000..2385bc305c --- /dev/null +++ b/pkg/liqo-controller-manager/external-network/configuration-controller/configuration-controller.go @@ -0,0 +1,131 @@ +// Copyright 2019-2023 The Liqo 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. + +package configurationcontroller + +import ( + "context" + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" + "github.com/liqotech/liqo/pkg/utils/events" +) + +// ConfigurationReconciler manage Configuration lifecycle. +type ConfigurationReconciler struct { + client.Client + Scheme *runtime.Scheme + EventsRecorder record.EventRecorder +} + +// NewConfigurationReconciler returns a new ConfigurationReconciler. +func NewConfigurationReconciler(cl client.Client, s *runtime.Scheme, er record.EventRecorder) *ConfigurationReconciler { + return &ConfigurationReconciler{ + Client: cl, + Scheme: s, + EventsRecorder: er, + } +} + +// cluster-role +// +kubebuilder:rbac:groups=networking.liqo.io,resources=configurations,verbs=get;list;watch;update;patch +// +kubebuilder:rbac:groups=networking.liqo.io,resources=configurations/status,verbs=get;list;watch;update;patch +// +kubebuilder:rbac:groups=ipam.liqo.io,resources=networks,verbs=get;list;watch;create +// +kubebuilder:rbac:groups=ipam.liqo.io,resources=networks/status,verbs=get;list;watch + +// Reconcile manage Configurations, remapping cidrs with Networks resources. +func (r *ConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + configuration := &networkingv1alpha1.Configuration{} + if err := r.Get(ctx, req.NamespacedName, configuration); err != nil { + if apierrors.IsNotFound(err) { + klog.Infof("There is no a configuration called '%s' in '%s'", req.Name, req.Namespace) + return ctrl.Result{}, nil + } + return ctrl.Result{}, fmt.Errorf(" %w --> Unable to get the configuration '%s'", err, req.Name) + } + events.Event(r.EventsRecorder, configuration, "Processing") + + requeue, err := r.RemapConfiguration(ctx, configuration, r.EventsRecorder) + if err != nil { + return ctrl.Result{}, err + } + + if err = r.UpdateConfigurationStatus(ctx, configuration); err != nil { + return ctrl.Result{}, err + } + + if requeue { + events.Event(r.EventsRecorder, configuration, "Waiting for the network to be ready") + } else { + events.Event(r.EventsRecorder, configuration, "Configuration remapped") + err = SetConfigurationConfigured(ctx, r.Client, configuration) + } + return ctrl.Result{Requeue: requeue}, err +} + +// RemapConfiguration remap the configuration using ipamv1alpha1.Network. +func (r *ConfigurationReconciler) RemapConfiguration(ctx context.Context, cfg *networkingv1alpha1.Configuration, + er record.EventRecorder) (requeue bool, err error) { + // Checks if the configuration is already remapped. + for _, cidrType := range LabelCIDRTypeValues { + network, err := CreateOrGetNetwork(ctx, r.Client, r.Scheme, er, cfg, cidrType) + if err != nil { + return true, fmt.Errorf(" %w --> Unable to create or get the network '%s'", err, cfg.Name) + } + if network.Status.CIDR == "" { + return true, nil + } + ForgeConfigurationStatus(cfg, network, cidrType) + } + return false, nil +} + +// UpdateConfigurationStatus update the configuration. +func (r *ConfigurationReconciler) UpdateConfigurationStatus(ctx context.Context, cfg *networkingv1alpha1.Configuration) error { + if err := r.Client.Status().Update(ctx, cfg); err != nil { + return fmt.Errorf(" %w --> Unable to update the status of the configuration '%s'", err, cfg.Name) + } + return nil +} + +// ForgeConfigurationStatus create the status of the configuration. +func ForgeConfigurationStatus(cfg *networkingv1alpha1.Configuration, net *ipamv1alpha1.Network, cidrType LabelCIDRTypeValue) { + if cfg.Status.Remote == nil { + cfg.Status.Remote = &networkingv1alpha1.ClusterConfig{} + } + var cidrNew, cidrOld networkingv1alpha1.CIDR + cidrNew = net.Status.CIDR + switch cidrType { + case LabelCIDRTypePod: + cidrOld = cfg.Spec.Remote.CIDR.Pod + cfg.Status.Remote.CIDR.Pod = cidrNew + case LabelCIDRTypeExternal: + cidrOld = cfg.Spec.Remote.CIDR.External + cfg.Status.Remote.CIDR.External = cidrNew + } + klog.Infof("Configuration %s/%s %s CIDR: %s -> %s", cfg.Name, cfg.Namespace, cidrType, cidrOld, cidrNew) +} + +// SetupWithManager register the ConfigurationReconciler to the manager. +func (r *ConfigurationReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr).For(&networkingv1alpha1.Configuration{}).Complete(r) +} diff --git a/pkg/liqo-controller-manager/external-network/configuration-controller/doc.go b/pkg/liqo-controller-manager/external-network/configuration-controller/doc.go new file mode 100644 index 0000000000..69b28a4b20 --- /dev/null +++ b/pkg/liqo-controller-manager/external-network/configuration-controller/doc.go @@ -0,0 +1,16 @@ +// Copyright 2019-2023 The Liqo 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. + +// Package configurationcontroller contains the logic to manage the Configuration resource. +package configurationcontroller diff --git a/pkg/liqo-controller-manager/external-network/configuration-controller/label.go b/pkg/liqo-controller-manager/external-network/configuration-controller/label.go new file mode 100644 index 0000000000..73e34cfea0 --- /dev/null +++ b/pkg/liqo-controller-manager/external-network/configuration-controller/label.go @@ -0,0 +1,86 @@ +// Copyright 2019-2023 The Liqo 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. + +package configurationcontroller + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/labels" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" + "github.com/liqotech/liqo/pkg/consts" +) + +// LabelCIDRType is the label used to target a ipamv1alpha1.Network resource that manages a PodCIDR or an ExternalCIDR. +const LabelCIDRType = "configuration.liqo.io/cidr-type" + +// LabelCIDRTypeValue is the value of the LabelCIDRType label. +type LabelCIDRTypeValue string + +const ( + // LabelCIDRTypePod is used to target a ipamv1alpha1.Network resource that manages a PodCIDR. + LabelCIDRTypePod LabelCIDRTypeValue = "pod" + // LabelCIDRTypeExternal is used to target a ipamv1alpha1.Network resource that manages an ExternalCIDR. + LabelCIDRTypeExternal LabelCIDRTypeValue = "external" +) + +// LabelCIDRTypeValues is the list of all the possible values of the LabelCIDRType label. +var LabelCIDRTypeValues = []LabelCIDRTypeValue{LabelCIDRTypePod, LabelCIDRTypeExternal} + +// ForgeNetworkLabel creates a label to target a ipamv1alpha1.Network resource. +// The label is composed by the remote cluster ID and the CIDR type. +func ForgeNetworkLabel(cfg *networkingv1alpha1.Configuration, cidrType LabelCIDRTypeValue) (netLabels map[string]string, err error) { + remoteClusterID, ok := cfg.Labels[consts.RemoteClusterID] + if !ok { + return nil, fmt.Errorf("missing label '%s'", consts.RemoteClusterID) + } + return map[string]string{ + consts.RemoteClusterID: remoteClusterID, + LabelCIDRType: string(cidrType), + }, nil +} + +// ForgeNetworkLabelSelector creates a labels.Selector to target a ipamv1alpha1.Network resource. +// The label is composed by the remote cluster ID and the CIDR type. +func ForgeNetworkLabelSelector(cfg *networkingv1alpha1.Configuration, + cidrType LabelCIDRTypeValue) (labelsSelector labels.Selector, err error) { + result, err := ForgeNetworkLabel(cfg, cidrType) + if err != nil { + return nil, err + } + return labels.SelectorFromSet(result), nil +} + +const ( + // Configured is the label used to mark a configuration as configured. + Configured = "configuration.liqo.io/configured" + // ConfiguredValue is the value of the Configured label. + ConfiguredValue = "true" +) + +// SetConfigurationConfigured sets the Configured label of the given configuration to true. +func SetConfigurationConfigured(ctx context.Context, cl client.Client, cfg *networkingv1alpha1.Configuration) error { + _, err := ctrl.CreateOrUpdate(ctx, cl, cfg, func() error { + if cfg.Labels == nil { + cfg.Labels = map[string]string{} + } + cfg.Labels[Configured] = ConfiguredValue + return nil + }) + return err +} diff --git a/pkg/liqo-controller-manager/external-network/configuration-controller/network.go b/pkg/liqo-controller-manager/external-network/configuration-controller/network.go new file mode 100644 index 0000000000..3b09f146fc --- /dev/null +++ b/pkg/liqo-controller-manager/external-network/configuration-controller/network.go @@ -0,0 +1,96 @@ +// Copyright 2019-2023 The Liqo 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. + +package configurationcontroller + +import ( + "context" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/client" + ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" + "github.com/liqotech/liqo/pkg/utils/events" + "github.com/liqotech/liqo/pkg/utils/getters" +) + +// ForgeNetwork creates a ipamv1alpha1.Network resource. +func ForgeNetwork(cfg *networkingv1alpha1.Configuration, cidrType LabelCIDRTypeValue, + scheme *runtime.Scheme) (network *ipamv1alpha1.Network, err error) { + labels, err := ForgeNetworkLabel(cfg, cidrType) + if err != nil { + return nil, err + } + var cidr networkingv1alpha1.CIDR + switch cidrType { + case LabelCIDRTypePod: + cidr = cfg.Spec.Remote.CIDR.Pod + case LabelCIDRTypeExternal: + cidr = cfg.Spec.Remote.CIDR.External + } + network = &ipamv1alpha1.Network{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s", cfg.Name, cidrType), + Namespace: cfg.Namespace, + Labels: labels, + }, + Spec: ipamv1alpha1.NetworkSpec{ + CIDR: cidr, + }, + } + err = ctrlutil.SetOwnerReference(cfg, network, scheme) + if err != nil { + return nil, err + } + return network, nil +} + +// CreateOrGetNetwork creates or gets a ipamv1alpha1.Network resource. +func CreateOrGetNetwork(ctx context.Context, cl client.Client, scheme *runtime.Scheme, er record.EventRecorder, + cfg *networkingv1alpha1.Configuration, cidrType LabelCIDRTypeValue) (network *ipamv1alpha1.Network, err error) { + ls, err := ForgeNetworkLabelSelector(cfg, cidrType) + if err != nil { + return nil, err + } + ns := cfg.Namespace + list, err := getters.ListNetworkByLabel(ctx, cl, ns, ls) + if err != nil { + return nil, err + } + if len(list.Items) == 1 { + return &list.Items[0], nil + } + if len(list.Items) > 1 { + return nil, fmt.Errorf("multiple networks found with label selector '%s'", ls) + } + + events.Event(er, cfg, fmt.Sprintf("Creating network %s/%s", cfg.Name, cfg.Namespace)) + + network, err = ForgeNetwork(cfg, cidrType, scheme) + if err != nil { + return nil, err + } + + if err := cl.Create(ctx, network); err != nil { + return nil, err + } + + events.Event(er, cfg, fmt.Sprintf("Network %s/%s created", cfg.Name, cfg.Namespace)) + return network, nil +} diff --git a/pkg/liqo-controller-manager/ip-controller/exposition.go b/pkg/liqo-controller-manager/ip-controller/exposition.go index 003b842371..6b8ee713cc 100644 --- a/pkg/liqo-controller-manager/ip-controller/exposition.go +++ b/pkg/liqo-controller-manager/ip-controller/exposition.go @@ -57,7 +57,7 @@ func (r *IPReconciler) handleAssociatedService(ctx context.Context, ip *ipamv1al eps.AddressType = discoveryv1.AddressTypeIPv4 eps.Endpoints = []discoveryv1.Endpoint{ { - Addresses: []string{ip.Spec.IP}, + Addresses: []string{ip.Spec.IP.String()}, Conditions: discoveryv1.EndpointConditions{ Ready: pointer.Bool(true), }, diff --git a/pkg/liqo-controller-manager/ip-controller/ip_controller.go b/pkg/liqo-controller-manager/ip-controller/ip_controller.go index e930792a53..304225dfff 100644 --- a/pkg/liqo-controller-manager/ip-controller/ip_controller.go +++ b/pkg/liqo-controller-manager/ip-controller/ip_controller.go @@ -33,7 +33,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" - "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" + virtualkubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1" "github.com/liqotech/liqo/pkg/liqonet/ipam" "github.com/liqotech/liqo/pkg/utils/getters" ) @@ -59,7 +60,7 @@ type IPReconciler struct { // Reconcile Ip objects. func (r *IPReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { var ip ipamv1alpha1.IP - var desiredIP string + var desiredIP networkingv1alpha1.IP // Fetch the IP instance if err := r.Get(ctx, req.NamespacedName, &ip); err != nil { @@ -158,18 +159,18 @@ func (r *IPReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, w For(&ipamv1alpha1.IP{}). Owns(&v1.Service{}). Owns(&discoveryv1.EndpointSlice{}). - Watches(&v1alpha1.VirtualNode{}, handler.EnqueueRequestsFromMapFunc(enqueuer)). + Watches(&virtualkubeletv1alpha1.VirtualNode{}, handler.EnqueueRequestsFromMapFunc(enqueuer)). WithOptions(controller.Options{MaxConcurrentReconciles: workers}). Complete(r) } // forgeIPMappings forge the IP mappings for each remote cluster. Return true if the status must be updated, false otherwise. -func (r *IPReconciler) forgeIPMappings(ctx context.Context, clusterIDs []string, desiredIP string, ip *ipamv1alpha1.IP) (bool, error) { +func (r *IPReconciler) forgeIPMappings(ctx context.Context, clusterIDs []string, desiredIP networkingv1alpha1.IP, ip *ipamv1alpha1.IP) (bool, error) { // Update IP status for each remote cluster needUpdate := false if ip.Status.IPMappings == nil { - ip.Status.IPMappings = make(map[string]string) + ip.Status.IPMappings = make(map[string]networkingv1alpha1.IP) } for i := range clusterIDs { @@ -203,7 +204,7 @@ func (r *IPReconciler) forgeIPMappings(ctx context.Context, clusterIDs []string, } // handleDelete handles the deletion of the IP resource. It call the IPAM to unmap the IPs of each remote cluster. -func (r *IPReconciler) handleDelete(ctx context.Context, clusterIDs []string, desiredIP string, ip *ipamv1alpha1.IP) error { +func (r *IPReconciler) handleDelete(ctx context.Context, clusterIDs []string, desiredIP networkingv1alpha1.IP, ip *ipamv1alpha1.IP) error { for i := range clusterIDs { remoteClusterID := &clusterIDs[i] if err := deleteRemappedIP(ctx, r.IpamClient, *remoteClusterID, desiredIP); err != nil { @@ -220,7 +221,7 @@ func (r *IPReconciler) handleDelete(ctx context.Context, clusterIDs []string, de } // getRemappedIP returns the remapped IP for the given IP and remote clusterID. -func getRemappedIP(ctx context.Context, ipamClient ipam.IpamClient, remoteClusterID, desiredIP string) (string, error) { +func getRemappedIP(ctx context.Context, ipamClient ipam.IpamClient, remoteClusterID string, desiredIP networkingv1alpha1.IP) (networkingv1alpha1.IP, error) { switch ipamClient.(type) { case nil: // IPAM is not enabled, use original IP from spec @@ -228,18 +229,18 @@ func getRemappedIP(ctx context.Context, ipamClient ipam.IpamClient, remoteCluste default: // interact with the IPAM to retrieve the correct mapping. response, err := ipamClient.MapEndpointIP(ctx, &ipam.MapRequest{ - ClusterID: remoteClusterID, Ip: desiredIP}) + ClusterID: remoteClusterID, Ip: desiredIP.String()}) if err != nil { klog.Errorf("IPAM: error while mapping IP %s for remote cluster %q: %v", desiredIP, remoteClusterID, err) return "", err } klog.Infof("IPAM: mapped IP %s to %s for remote cluster %q", desiredIP, response.Ip, remoteClusterID) - return response.Ip, nil + return networkingv1alpha1.IP(response.Ip), nil } } // deleteRemappedIP unmaps the IP for the given remote clusterID. -func deleteRemappedIP(ctx context.Context, ipamClient ipam.IpamClient, remoteClusterID, desiredIP string) error { +func deleteRemappedIP(ctx context.Context, ipamClient ipam.IpamClient, remoteClusterID string, desiredIP networkingv1alpha1.IP) error { switch ipamClient.(type) { case nil: // If the IPAM is not enabled we do not need to release the translation. @@ -247,7 +248,7 @@ func deleteRemappedIP(ctx context.Context, ipamClient ipam.IpamClient, remoteClu default: // Interact with the IPAM to release the translation. _, err := ipamClient.UnmapEndpointIP(ctx, &ipam.UnmapRequest{ - ClusterID: remoteClusterID, Ip: desiredIP}) + ClusterID: remoteClusterID, Ip: desiredIP.String()}) if err != nil { klog.Errorf("IPAM: error while unmapping IP %s for remote cluster %q: %v", desiredIP, remoteClusterID, err) return err diff --git a/pkg/liqo-controller-manager/network-controller/network_controller.go b/pkg/liqo-controller-manager/network-controller/network_controller.go index c04febfed8..139fe1baea 100644 --- a/pkg/liqo-controller-manager/network-controller/network_controller.go +++ b/pkg/liqo-controller-manager/network-controller/network_controller.go @@ -28,6 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" "github.com/liqotech/liqo/pkg/consts" "github.com/liqotech/liqo/pkg/liqonet/ipam" foreignclusterutils "github.com/liqotech/liqo/pkg/utils/foreignCluster" @@ -52,7 +53,7 @@ type NetworkReconciler struct { // Reconcile Network objects. func (r *NetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { var nw ipamv1alpha1.Network - var desiredCIDR, remappedCIDR string + var desiredCIDR, remappedCIDR networkingv1alpha1.CIDR // Fetch the Network instance if err := r.Get(ctx, req.NamespacedName, &nw); err != nil { @@ -116,13 +117,15 @@ func (r *NetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct // The resource is being deleted and the finalizer is still present. Call the IPAM to unmap the network CIDR. remappedCIDR = nw.Status.CIDR - if _, _, err := net.ParseCIDR(remappedCIDR); err != nil { - klog.Errorf("Unable to unmap CIDR %s of Network %q (inavlid format): %v", remappedCIDR, req.NamespacedName, err) - return ctrl.Result{}, err - } + if remappedCIDR != "" { + if _, _, err := net.ParseCIDR(remappedCIDR.String()); err != nil { + klog.Errorf("Unable to unmap CIDR %s of Network %q (inavlid format): %v", remappedCIDR, req.NamespacedName, err) + return ctrl.Result{}, err + } - if err := deleteRemappedCIDR(ctx, r.IpamClient, remappedCIDR); err != nil { - return ctrl.Result{}, err + if err := deleteRemappedCIDR(ctx, r.IpamClient, remappedCIDR); err != nil { + return ctrl.Result{}, err + } } // Remove status and finalizer, and update the object. @@ -148,32 +151,32 @@ func (r *NetworkReconciler) SetupWithManager(mgr ctrl.Manager, workers int) erro } // getRemappedCIDR returns the remapped CIDR for the given CIDR and remote clusterID. -func getRemappedCIDR(ctx context.Context, ipamClient ipam.IpamClient, desiredCIDR string) (string, error) { +func getRemappedCIDR(ctx context.Context, ipamClient ipam.IpamClient, desiredCIDR networkingv1alpha1.CIDR) (networkingv1alpha1.CIDR, error) { switch ipamClient.(type) { case nil: // IPAM is not enabled, use original CIDR from spec return desiredCIDR, nil default: // interact with the IPAM to retrieve the correct mapping. - response, err := ipamClient.MapNetworkCIDR(ctx, &ipam.MapCIDRRequest{Cidr: desiredCIDR}) + response, err := ipamClient.MapNetworkCIDR(ctx, &ipam.MapCIDRRequest{Cidr: desiredCIDR.String()}) if err != nil { klog.Errorf("IPAM: error while mapping network CIDR %s: %v", desiredCIDR, err) return "", err } klog.Infof("IPAM: mapped network CIDR %s to %s", desiredCIDR, response.Cidr) - return response.Cidr, nil + return networkingv1alpha1.CIDR(response.Cidr), nil } } // deleteRemappedCIDR unmaps the CIDR for the given remote clusterID. -func deleteRemappedCIDR(ctx context.Context, ipamClient ipam.IpamClient, remappedCIDR string) error { +func deleteRemappedCIDR(ctx context.Context, ipamClient ipam.IpamClient, remappedCIDR networkingv1alpha1.CIDR) error { switch ipamClient.(type) { case nil: // If the IPAM is not enabled we do not need to free the network CIDR. return nil default: // Interact with the IPAM to free the network CIDR. - _, err := ipamClient.UnmapNetworkCIDR(ctx, &ipam.UnmapCIDRRequest{Cidr: remappedCIDR}) + _, err := ipamClient.UnmapNetworkCIDR(ctx, &ipam.UnmapCIDRRequest{Cidr: remappedCIDR.String()}) if err != nil { klog.Errorf("IPAM: error while unmapping CIDR %s: %v", remappedCIDR, err) return err diff --git a/pkg/liqo-controller-manager/webhooks/ip/ip.go b/pkg/liqo-controller-manager/webhooks/ip/ip.go index 45b712c31a..effc55f08e 100644 --- a/pkg/liqo-controller-manager/webhooks/ip/ip.go +++ b/pkg/liqo-controller-manager/webhooks/ip/ip.go @@ -82,7 +82,7 @@ func (w *ipwhv) HandleCreate(req *admission.Request) admission.Response { } // Check if the IP provided is a valid IP - if ip := net.ParseIP(ip.Spec.IP); ip == nil { + if ip := net.ParseIP(ip.Spec.IP.String()); ip == nil { return admission.Denied(fmt.Sprintf("Invalid IP: %v", err)) } diff --git a/pkg/liqo-controller-manager/webhooks/network/nw.go b/pkg/liqo-controller-manager/webhooks/network/nw.go index 21452e471e..8c803232fa 100644 --- a/pkg/liqo-controller-manager/webhooks/network/nw.go +++ b/pkg/liqo-controller-manager/webhooks/network/nw.go @@ -89,7 +89,7 @@ func (w *nwwhv) HandleCreate(req *admission.Request) admission.Response { } // Check if the CIDR is a valid network - if _, _, err := net.ParseCIDR(nw.Spec.CIDR); err != nil { + if _, _, err := net.ParseCIDR(nw.Spec.CIDR.String()); err != nil { return admission.Denied(fmt.Sprintf("Invalid CIDR: %v", err)) } diff --git a/pkg/utils/events/doc.go b/pkg/utils/events/doc.go new file mode 100644 index 0000000000..356364e235 --- /dev/null +++ b/pkg/utils/events/doc.go @@ -0,0 +1,16 @@ +// Copyright 2019-2023 The Liqo 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. + +// Package events provides a simple event system for the application. +package events diff --git a/pkg/utils/events/events.go b/pkg/utils/events/events.go new file mode 100644 index 0000000000..25f2b7b771 --- /dev/null +++ b/pkg/utils/events/events.go @@ -0,0 +1,58 @@ +// Copyright 2019-2023 The Liqo 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. + +package events + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" +) + +// EventType is the type used to define the reason of an event. +type EventType string + +const ( + // Normal is the default reason to use. + Normal EventType = "Normal" + // Warning is the default reason to use. + Warning EventType = "Warning" + // Error is the default reason to use. + Error EventType = "Error" +) + +// Reason is the type used to define the reason of an event. +type Reason string + +const ( + // Processing is the default reason to use. + Processing Reason = "Processing" +) + +// Option is the type used to define the options of an event. +type Option struct { + Reason Reason + EventType EventType +} + +// Event is a wrapper around the Event method of the EventRecorder interface. +// It uses the default EventType and Reason. +func Event(er record.EventRecorder, obj runtime.Object, message string) { + er.Event(obj, string(Normal), string(Processing), message) +} + +// EventWithOptions is a wrapper around the Event method of the EventRecorder interface. +// It uses the EventType and Reason passed as parameters in options. +func EventWithOptions(er record.EventRecorder, obj runtime.Object, message string, options *Option) { + er.Event(obj, string(options.EventType), string(options.Reason), message) +} diff --git a/pkg/utils/getters/k8sGetters.go b/pkg/utils/getters/k8sGetters.go index 236e1e07b8..e444395285 100644 --- a/pkg/utils/getters/k8sGetters.go +++ b/pkg/utils/getters/k8sGetters.go @@ -27,6 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1" + ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1" sharingv1alpha1 "github.com/liqotech/liqo/apis/sharing/v1alpha1" @@ -325,3 +326,13 @@ func ListVirtualKubeletPodsFromVirtualNode(ctx context.Context, cl client.Client } return list, nil } + +// ListNetworkByLabel returns the Network resource with the given labels. +func ListNetworkByLabel(ctx context.Context, cl client.Client, ns string, lSelector labels.Selector) (*ipamv1alpha1.NetworkList, error) { + list := &ipamv1alpha1.NetworkList{} + err := cl.List(ctx, list, &client.ListOptions{LabelSelector: lSelector}, client.InNamespace(ns)) + if err != nil { + return nil, err + } + return list, err +} diff --git a/pkg/utils/mapper/mapper.go b/pkg/utils/mapper/mapper.go index dfd2010b79..ffe589c1ad 100644 --- a/pkg/utils/mapper/mapper.go +++ b/pkg/utils/mapper/mapper.go @@ -32,6 +32,7 @@ import ( discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1" ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1" netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" + networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1" offv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1" sharingv1alpha1 "github.com/liqotech/liqo/apis/sharing/v1alpha1" virtualKubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1" @@ -89,6 +90,9 @@ func addDefaults(dClient *discovery.DiscoveryClient, mapper *meta.DefaultRESTMap if err = addGroup(dClient, ipamv1alpha1.GroupVersion, mapper); err != nil { return err } + if err = addGroup(dClient, networkingv1alpha1.GroupVersion, mapper); err != nil { + return err + } // Kubernetes groups if err = addGroup(dClient, corev1.SchemeGroupVersion, mapper); err != nil {