controllers/cnimanager/server.go (74 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
package cnimanager
//+kubebuilder:rbac:groups=egressgateway.kubernetes.azure.com,resources=staticgatewayconfigurations,verbs=get;list;watch
//+kubebuilder:rbac:groups=egressgateway.kubernetes.azure.com,resources=staticgatewayconfigurations/status,verbs=get;
//+kubebuilder:rbac:groups=egressgateway.kubernetes.azure.com,resources=podendpoints,verbs=list;watch;create;update;patch;delete;
//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch
//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch
//+kubebuilder:rbac:groups=core,resources=nodes,verbs=get;list;watch;update;patch
import (
"context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
current "github.com/Azure/kube-egress-gateway/api/v1alpha1"
cniprotocol "github.com/Azure/kube-egress-gateway/pkg/cniprotocol/v1"
)
type NicService struct {
k8sClient client.Client
cniprotocol.UnimplementedNicServiceServer
}
func NewNicService(k8sClient client.Client) *NicService {
return &NicService{k8sClient: k8sClient}
}
// NicAdd add nic
func (s *NicService) NicAdd(ctx context.Context, in *cniprotocol.NicAddRequest) (*cniprotocol.NicAddResponse, error) {
gwConfig := ¤t.StaticGatewayConfiguration{}
if err := s.k8sClient.Get(ctx, client.ObjectKey{Name: in.GetGatewayName(), Namespace: in.GetPodConfig().GetPodNamespace()}, gwConfig); err != nil {
return nil, status.Errorf(codes.Unknown, "failed to retrieve StaticGatewayConfiguration %s/%s: %s", in.GetPodConfig().GetPodNamespace(), in.GetGatewayName(), err)
}
if len(gwConfig.Status.EgressIpPrefix) == 0 {
return nil, status.Errorf(codes.FailedPrecondition, "the egress IP prefix is not ready yet.")
}
pod := &corev1.Pod{}
if err := s.k8sClient.Get(ctx, client.ObjectKey{Name: in.GetPodConfig().GetPodName(), Namespace: in.GetPodConfig().GetPodNamespace()}, pod); err != nil {
return nil, status.Errorf(codes.Unknown, "failed to retrieve pod %s/%s: %s", in.GetPodConfig().GetPodNamespace(), in.GetPodConfig().GetPodName(), err)
}
podEndpoint := ¤t.PodEndpoint{ObjectMeta: metav1.ObjectMeta{Name: in.GetPodConfig().GetPodName(), Namespace: in.GetPodConfig().GetPodNamespace()}}
if _, err := controllerutil.CreateOrUpdate(ctx, s.k8sClient, podEndpoint, func() error {
if err := controllerutil.SetControllerReference(pod, podEndpoint, s.k8sClient.Scheme()); err != nil {
return err
}
podEndpoint.Spec.PodIpAddress = in.GetAllowedIp()
podEndpoint.Spec.StaticGatewayConfiguration = in.GetGatewayName()
podEndpoint.Spec.PodPublicKey = in.PublicKey
return nil
}); err != nil {
return nil, status.Errorf(codes.Unknown, "failed to update PodEndpoint %s/%s: %s", in.GetPodConfig().GetPodNamespace(), in.GetPodConfig().GetPodName(), err)
}
defaultRoute := cniprotocol.DefaultRoute_DEFAULT_ROUTE_STATIC_EGRESS_GATEWAY
if gwConfig.Spec.DefaultRoute == current.RouteAzureNetworking {
defaultRoute = cniprotocol.DefaultRoute_DEFAULT_ROUTE_AZURE_NETWORKING
}
return &cniprotocol.NicAddResponse{
EndpointIp: gwConfig.Status.Ip,
ListenPort: gwConfig.Status.Port,
PublicKey: gwConfig.Status.PublicKey,
ExceptionCidrs: gwConfig.Spec.ExcludeCidrs,
DefaultRoute: defaultRoute,
}, nil
}
func (s *NicService) NicDel(ctx context.Context, in *cniprotocol.NicDelRequest) (*cniprotocol.NicDelResponse, error) {
podEndpoint := ¤t.PodEndpoint{ObjectMeta: metav1.ObjectMeta{Name: in.GetPodConfig().GetPodName(), Namespace: in.GetPodConfig().GetPodNamespace()}}
if err := s.k8sClient.Delete(ctx, podEndpoint); err != nil {
if !apierrors.IsNotFound(err) {
return nil, status.Errorf(codes.Unknown, "failed to delete PodEndpoint %s/%s: %s", in.GetPodConfig().GetPodNamespace(), in.GetPodConfig().GetPodName(), err)
}
}
return &cniprotocol.NicDelResponse{}, nil
}
func (s *NicService) PodRetrieve(ctx context.Context, in *cniprotocol.PodRetrieveRequest) (*cniprotocol.PodRetrieveResponse, error) {
pod := &corev1.Pod{}
if err := s.k8sClient.Get(ctx, client.ObjectKey{Name: in.GetPodConfig().GetPodName(), Namespace: in.GetPodConfig().GetPodNamespace()}, pod); err != nil {
return nil, status.Errorf(codes.Unknown, "failed to retrieve pod %s/%s: %s", in.GetPodConfig().GetPodNamespace(), in.GetPodConfig().GetPodName(), err)
}
return &cniprotocol.PodRetrieveResponse{
Annotations: pod.ObjectMeta.GetAnnotations(),
}, nil
}