diff --git a/api/v1alpha1/network_types.go b/api/v1alpha1/network_types.go index a5a8f30f..8cbc46dd 100644 --- a/api/v1alpha1/network_types.go +++ b/api/v1alpha1/network_types.go @@ -25,6 +25,8 @@ type NetworkSpec struct { // VNI is the requested network vni. // Pointer to distinguish between explicitly set and unset. VNI *int32 `json:"vni,omitempty"` + // PeerVNIs are VNIs to peer with. + PeerVNIs []int32 `json:"peerVNIs,omitempty"` } type NetworkConditionType string diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9cb26048..72831068 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -107,6 +107,11 @@ func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) { *out = new(int32) **out = **in } + if in.PeerVNIs != nil { + in, out := &in.PeerVNIs, &out.PeerVNIs + *out = make([]int32, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSpec. diff --git a/apinetlet/controllers/network_controller.go b/apinetlet/controllers/network_controller.go index 7ba79e8a..357c1a84 100644 --- a/apinetlet/controllers/network_controller.go +++ b/apinetlet/controllers/network_controller.go @@ -28,6 +28,7 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -205,6 +206,21 @@ func isAPINetNetworkAllocated(apiNetNetwork *onmetalapinetv1alpha1.Network) bool } func (r *NetworkReconciler) applyAPINetNetwork(ctx context.Context, log logr.Logger, network *networkingv1alpha1.Network) (*int32, error) { + var vni *int32 + if handle := network.Spec.Handle; handle != "" { + v, err := strconv.ParseInt(handle, 10, 32) + if err != nil { + return nil, fmt.Errorf("error parsing network handle %s: %w", handle, err) + } + + vni = pointer.Int32(int32(v)) + } + + peerVNIs, err := r.extractPeerVNIs(network) + if err != nil { + return nil, err + } + apiNetNetwork := &onmetalapinetv1alpha1.Network{ TypeMeta: metav1.TypeMeta{ APIVersion: onmetalapinetv1alpha1.GroupVersion.String(), @@ -219,15 +235,10 @@ func (r *NetworkReconciler) applyAPINetNetwork(ctx context.Context, log logr.Log apinetletv1alpha1.NetworkUIDLabel: string(network.UID), }, }, - } - - if handle := network.Spec.Handle; handle != "" { - vni, err := strconv.ParseInt(handle, 10, 32) - if err != nil { - return nil, fmt.Errorf("error parsing network handle %s: %w", handle, err) - } - - apiNetNetwork.Spec.VNI = pointer.Int32(int32(vni)) + Spec: onmetalapinetv1alpha1.NetworkSpec{ + VNI: vni, + PeerVNIs: peerVNIs, + }, } log.V(1).Info("Applying apinet network") @@ -245,6 +256,24 @@ func (r *NetworkReconciler) applyAPINetNetwork(ctx context.Context, log logr.Log return apiNetNetwork.Spec.VNI, nil } +func (r *NetworkReconciler) extractPeerVNIs(network *networkingv1alpha1.Network) ([]int32, error) { + peerVNIs := sets.New[int32]() + for _, peering := range network.Status.Peerings { + if peering.Phase != networkingv1alpha1.NetworkPeeringPhaseBound { + continue + } + + peerVNI, err := strconv.ParseInt(peering.NetworkHandle, 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid peer network handle %q: %w", peering.NetworkHandle, err) + } + + peerVNIs.Insert(int32(peerVNI)) + } + + return sets.List(peerVNIs), nil +} + var apiNetNetworkAllocationChanged = predicate.Funcs{ UpdateFunc: func(event event.UpdateEvent) bool { oldAPINetNetwork, newAPINetNetwork := event.ObjectOld.(*onmetalapinetv1alpha1.Network), event.ObjectNew.(*onmetalapinetv1alpha1.Network) diff --git a/apinetlet/controllers/network_controller_test.go b/apinetlet/controllers/network_controller_test.go index 1276000a..59290173 100644 --- a/apinetlet/controllers/network_controller_test.go +++ b/apinetlet/controllers/network_controller_test.go @@ -90,6 +90,21 @@ var _ = Describe("NetworkController", func() { HaveField("Status.State", Equal(networkingv1alpha1.NetworkStateAvailable)), )) + By("adding a peering status to the network") + baseNetwork := network.DeepCopy() + network.Status.Peerings = []networkingv1alpha1.NetworkPeeringStatus{ + { + Name: "my-peering", + Phase: networkingv1alpha1.NetworkPeeringPhaseBound, + NetworkHandle: "400", + }, + } + Expect(k8sClient.Status().Patch(ctx, network, client.MergeFrom(baseNetwork))).To(Succeed()) + + By("waiting for the apinet network to report the peered vni") + Eventually(Object(apiNetNetwork)). + Should(HaveField("Spec.PeerVNIs", []int32{400})) + By("deleting the network") Expect(k8sClient.Delete(ctx, network)).To(Succeed()) diff --git a/config/apinetlet/rbac/role.yaml b/config/apinetlet/rbac/role.yaml index 2721160d..43a809a8 100644 --- a/config/apinetlet/rbac/role.yaml +++ b/config/apinetlet/rbac/role.yaml @@ -41,6 +41,18 @@ rules: - publicips/status verbs: - get +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create - apiGroups: - certificates.k8s.io resources: diff --git a/config/onmetal-api-net/crd/bases/apinet.api.onmetal.de_networks.yaml b/config/onmetal-api-net/crd/bases/apinet.api.onmetal.de_networks.yaml index fd87117e..0be48760 100644 --- a/config/onmetal-api-net/crd/bases/apinet.api.onmetal.de_networks.yaml +++ b/config/onmetal-api-net/crd/bases/apinet.api.onmetal.de_networks.yaml @@ -44,6 +44,12 @@ spec: type: object spec: properties: + peerVNIs: + description: PeerVNIs are VNIs to peer with. + items: + format: int32 + type: integer + type: array vni: description: VNI is the requested network vni. Pointer to distinguish between explicitly set and unset. diff --git a/go.mod b/go.mod index 9631085c..e7ad7383 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/go-logr/logr v1.2.4 github.com/onmetal/controller-utils v0.7.0 - github.com/onmetal/onmetal-api v0.1.0 + github.com/onmetal/onmetal-api v0.1.1-0.20230411121339-eb0957464d11 github.com/onsi/ginkgo/v2 v2.9.2 github.com/onsi/gomega v1.27.6 github.com/spf13/pflag v1.0.5 @@ -71,7 +71,7 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/oauth2 v0.4.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/sys v0.7.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect @@ -86,7 +86,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/component-base v0.26.3 // indirect - k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-aggregator v0.26.3 // indirect k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.36 // indirect diff --git a/go.sum b/go.sum index 351d52cb..813c4753 100644 --- a/go.sum +++ b/go.sum @@ -207,7 +207,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -253,8 +253,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/onmetal/controller-utils v0.7.0 h1:EHLPb/XimNas1VkeZZLP4g31aSz+ipiwvwWhklaQob0= github.com/onmetal/controller-utils v0.7.0/go.mod h1:91KV/s0VaB8PC+hqsxo6OBsAhi3ICFgIFLv/36V0ng8= -github.com/onmetal/onmetal-api v0.1.0 h1:SOEiBOsLc9RTKpeqaeMe7CLWK2dcVzd0sj4Wj0HhY7U= -github.com/onmetal/onmetal-api v0.1.0/go.mod h1:OPmHPCH/WesxdBF2xVPyjEdD5eTvDKCh3Kh2pfzQRZU= +github.com/onmetal/onmetal-api v0.1.1-0.20230411121339-eb0957464d11 h1:Q48DM7Nr67urjs5sDltEMkQASuVjIPw6Lgtn8GIEHfA= +github.com/onmetal/onmetal-api v0.1.1-0.20230411121339-eb0957464d11/go.mod h1:mql3gEgyCDeqkQbeM62C/FRuCwXSfBVsvg/FiBczN6M= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= @@ -298,7 +298,7 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= @@ -498,8 +498,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= @@ -703,8 +703,8 @@ k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= k8s.io/component-base v0.26.3 h1:oC0WMK/ggcbGDTkdcqefI4wIZRYdK3JySx9/HADpV0g= k8s.io/component-base v0.26.3/go.mod h1:5kj1kZYwSC6ZstHJN7oHBqcJC6yyn41eR+Sqa/mQc8E= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-aggregator v0.26.3 h1:nc4H5ymGkWPU3c9U9UM468JcmNENY/s/mDYVW3t3uRo= k8s.io/kube-aggregator v0.26.3/go.mod h1:SgBESB/+PfZAyceTPIanfQ7GtX9G/+mjfUbTHg3Twbo= k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 h1:8cNCQs+WqqnSpZ7y0LMQPKD+RZUHU17VqLPMW3qxnxc=