Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Network Peering in apinetlet and metalnetlet #262

Merged
merged 9 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions api/core/v1alpha1/network_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,45 @@ import (
type NetworkSpec struct {
// ID is the ID of the network.
ID string `json:"id,omitempty"`
// Peerings are the network peerings with this network
Peerings []NetworkPeering `json:"peerings,omitempty"`
}

// NetworkPeering defines a network peering with another network.
type NetworkPeering struct {
// Name is the semantical name of the network peering.
Name string `json:"name"`
// ID is the ID of the network to peer with.
ID string `json:"id"`
}

type NetworkStatus struct {
// Peerings contains the states of the network peerings for the network.
Peerings []NetworkPeeringStatus `json:"peerings,omitempty"`
}

// NetworkState is the state of a network.
// +enum
type NetworkState string

// NetworkPeeringState is the state a NetworkPeering can be in
type NetworkPeeringState string

const (
// NetworkPeeringStatePending signals that the network peering is not applied.
NetworkPeeringStatePending NetworkPeeringState = "Pending"
// NetworkPeeringStateReady signals that the network peering is ready.
NetworkPeeringStateReady NetworkPeeringState = "Ready"
// NetworkPeeringStateError signals that the network peering is in error state.
NetworkPeeringStateError NetworkPeeringState = "Error"
)

// NetworkPeeringStatus is the status of a network peering.
type NetworkPeeringStatus struct {
// ID is the ID of network
ID int32 `json:"id"`
// State represents the network peering state
State NetworkPeeringState `json:"state,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
46 changes: 44 additions & 2 deletions api/core/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions apinetlet/controllers/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package controllers

import (
"fmt"
"slices"
"strconv"

apinetv1alpha1 "github.com/ironcore-dev/ironcore-net/api/core/v1alpha1"
"github.com/ironcore-dev/ironcore-net/apimachinery/api/net"
Expand Down Expand Up @@ -69,3 +71,19 @@ func apiNetNetworkInterfaceStateToNetworkInterfaceState(state apinetv1alpha1.Net
return networkingv1alpha1.NetworkInterfaceStatePending
}
}

func apiNetNetworkPeeringsStatusToNetworkPeeringsStatus(peerings []apinetv1alpha1.NetworkPeeringStatus, specPeerings []apinetv1alpha1.NetworkPeering) []networkingv1alpha1.NetworkPeeringStatus {
networkPeeringsStatus := []networkingv1alpha1.NetworkPeeringStatus{}
for _, peering := range peerings {
idx := slices.IndexFunc(specPeerings, func(specPeering apinetv1alpha1.NetworkPeering) bool {
return specPeering.ID == strconv.Itoa(int(peering.ID))
})
if idx != -1 {
networkPeeringsStatus = append(networkPeeringsStatus, networkingv1alpha1.NetworkPeeringStatus{
Name: specPeerings[idx].Name,
State: networkingv1alpha1.NetworkPeeringState(peering.State),
})
}
}
return networkPeeringsStatus
}
30 changes: 27 additions & 3 deletions apinetlet/controllers/network_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package controllers
import (
"context"
"fmt"
"slices"

"github.com/go-logr/logr"
"github.com/ironcore-dev/controller-utils/clientutils"
Expand Down Expand Up @@ -114,9 +115,10 @@ func (r *NetworkReconciler) delete(ctx context.Context, log logr.Logger, network
return ctrl.Result{Requeue: true}, nil
}

func (r *NetworkReconciler) updateNetworkStatus(ctx context.Context, network *networkingv1alpha1.Network, state networkingv1alpha1.NetworkState) error {
func (r *NetworkReconciler) updateNetworkStatus(ctx context.Context, network *networkingv1alpha1.Network, apiNetNetwork *apinetv1alpha1.Network, state networkingv1alpha1.NetworkState) error {
networkBase := network.DeepCopy()
network.Status.State = state
network.Status.Peerings = apiNetNetworkPeeringsStatusToNetworkPeeringsStatus(apiNetNetwork.Status.Peerings, apiNetNetwork.Spec.Peerings)
if err := r.Status().Patch(ctx, network, client.MergeFrom(networkBase)); err != nil {
return fmt.Errorf("unable to patch network: %w", err)
}
Expand All @@ -139,7 +141,7 @@ func (r *NetworkReconciler) reconcile(ctx context.Context, log logr.Logger, netw
apiNetNetwork, err := r.applyAPINetNetwork(ctx, log, network)
if err != nil {
if network.Status.State != networkingv1alpha1.NetworkStateAvailable {
if err := r.updateNetworkStatus(ctx, network, networkingv1alpha1.NetworkStatePending); err != nil {
if err := r.updateNetworkStatus(ctx, network, apiNetNetwork, networkingv1alpha1.NetworkStatePending); err != nil {
log.Error(err, "Error updating network state")
}
}
Expand All @@ -159,9 +161,10 @@ func (r *NetworkReconciler) reconcile(ctx context.Context, log logr.Logger, netw
}

log.V(1).Info("Updating network status")
if err := r.updateNetworkStatus(ctx, network, networkingv1alpha1.NetworkStateAvailable); err != nil {
if err := r.updateNetworkStatus(ctx, network, apiNetNetwork, networkingv1alpha1.NetworkStateAvailable); err != nil {
return ctrl.Result{}, fmt.Errorf("error updating network status: %w", err)
}
log.V(1).Info("Updated network status")

log.V(1).Info("Reconciled")
return ctrl.Result{}, nil
Expand Down Expand Up @@ -193,6 +196,27 @@ func (r *NetworkReconciler) applyAPINetNetwork(ctx context.Context, log logr.Log
},
}

var peerings []apinetv1alpha1.NetworkPeering
for _, peeringClaimRef := range network.Spec.PeeringClaimRefs {
log.V(1).Info("Get apinet network for target network")
targetApinetNetwork := &apinetv1alpha1.Network{}
if err := r.APINetClient.Get(ctx, client.ObjectKey{Namespace: r.APINetNamespace, Name: string(peeringClaimRef.UID)}, targetApinetNetwork); err != nil {
log.V(1).Info("target apinet network is not created yet")
break
}

idx := slices.IndexFunc(network.Spec.Peerings, func(peering networkingv1alpha1.NetworkPeering) bool {
return peering.NetworkRef.Name == peeringClaimRef.Name
})
if idx != -1 {
peerings = append(peerings, apinetv1alpha1.NetworkPeering{
Name: network.Spec.Peerings[idx].Name,
ID: targetApinetNetwork.Spec.ID,
})
}
}
apiNetNetwork.Spec.Peerings = peerings

log.V(1).Info("Applying APINet network")
if err := r.APINetClient.Patch(ctx, apiNetNetwork, client.Apply, fieldOwner, client.ForceOwnership); err != nil {
return nil, fmt.Errorf("error applying apinet network: %w", err)
Expand Down
Loading