Skip to content

Commit

Permalink
Added Reconcile logic for the operator
Browse files Browse the repository at this point in the history
Signed-off-by: Prateek Singh <[email protected]>
  • Loading branch information
prateek041 authored and michi-covalent committed Aug 11, 2023
1 parent f141807 commit c128c91
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 11 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/containerd/cgroups v1.1.0
github.com/containerd/containerd v1.7.3
github.com/fatih/color v1.15.0
github.com/go-logr/logr v1.2.4
github.com/go-openapi/strfmt v0.21.7
github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.3
Expand Down Expand Up @@ -82,7 +83,6 @@ require (
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
Expand Down
144 changes: 134 additions & 10 deletions tetragonpod/controller/tetragonpod_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"context"

ciliumiov1alpha1 "github.com/cilium/tetragon/tetragonpod/api/v1alpha1"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -39,28 +41,150 @@ type TetragonPodReconciler struct {

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the TetragonPod object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile

// Reconcile is the main loop of the controller that something changes with the pod resources in the cluster.
func (r *TetragonPodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
l := log.FromContext(ctx)

// Get the Pod.
pod := &corev1.Pod{}
if err := r.Get(ctx, req.NamespacedName, pod); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)

// CASE 1: Pod is deleted, therefore delete the corresponding tetragonPod resource.
if client.IgnoreNotFound(err) == nil {
l.Info("Pod Deleted: ", "Name", req.Name, " Namespace", req.Namespace)
deleteTetragonPod(ctx, r, req, l)
return ctrl.Result{}, nil
}
}

// CASE 2: Pod is created or updated.
// wait until the pod is running for cleaner logs.
if pod.Status.Phase != corev1.PodRunning {
return ctrl.Result{}, nil
}

// Check if corresponsind tetragonPod already exists.
tetragonPod, exists := checkIfAlreadyExists(ctx, req, r, l)
if exists {
// CASE 2.1: TetragonPod already exists, update it.
l.Info("Pod Updated: ", "Name", req.Name, "Namespace", req.Namespace)
updateTetragonPod(ctx, r, l, pod, tetragonPod)
return ctrl.Result{}, nil
}

// CASE 2.2: TetragonPod does not exist, create new.
l.Info("Pod Created: ", "Name", req.Name, "Namespace", req.Namespace)
createTetragonPod(ctx, pod, r, l)
return ctrl.Result{}, nil
}

// deleteTetragonPod deletes the corresponding tetragonPod resource.
func deleteTetragonPod(ctx context.Context, r *TetragonPodReconciler, req ctrl.Request, l logr.Logger) (ctrl.Result, error) {
l.Info("Deleting the corresponding tetragonPod resource")

// create the pod to be deleted
tetragonPodToDelete := &ciliumiov1alpha1.TetragonPod{
ObjectMeta: metav1.ObjectMeta{
Name: req.Name,
Namespace: req.Namespace,
},
}

// Check if corresponding tetragonPod resource exists
if err := r.Get(ctx, req.NamespacedName, tetragonPodToDelete); err != nil {
l.Error(err, "Corresponding tetragonPod Resource does not exist")
return ctrl.Result{}, err
}

// Delete the Pod
if err := r.Delete(ctx, tetragonPodToDelete); err != nil {
l.Error(err, "Failed to delete the tetragonPod resource")
return ctrl.Result{}, err
}

// Pod deleted successfully.
l.Info("TetragonPod deleted successfully")
return ctrl.Result{}, nil
}

// updateTetragonPod updates the corresponding tetragonPod resource.
func updateTetragonPod(ctx context.Context, r *TetragonPodReconciler, l logr.Logger, pod *corev1.Pod, tetragonPod *ciliumiov1alpha1.TetragonPod) (ctrl.Result, error) {
l.Info("Updating the corresponding tetragonPod resource")

// get the new IP address of the Pod.
newIP := ciliumiov1alpha1.PodIP{IP: pod.Status.PodIP}
tetragonPod.Status.PodIP = newIP.IP
// add the new IP to the beginning of the array.
tetragonPod.Status.PodIPs = append([]ciliumiov1alpha1.PodIP{newIP}, tetragonPod.Status.PodIPs...)

// Update the tetragonPod resource.
if err := r.Update(ctx, tetragonPod); err != nil {
l.Error(err, "Failed to update the tetragonPod resource")
return ctrl.Result{}, err
}
l.Info("TetragonPod updated successfully")
return ctrl.Result{}, nil
}

l.Info("Reconcile this pod", "Name", pod.Name, "Namespace", pod.Namespace)
// checkIfAlreadyExists checks if the corresponding tetragonPod resource already exists.
func checkIfAlreadyExists(ctx context.Context, req ctrl.Request, r *TetragonPodReconciler, l logr.Logger) (*ciliumiov1alpha1.TetragonPod, bool) {

// TODO(user): your logic here
// check if the tetragonPod already exists for that pod.
tetragonPod, err := getTetragonPod(ctx, req, r, l)
if err != nil {
return nil, false
}
return tetragonPod, true
}

// createTetragonPod creates a tetragonPod resource.
func createTetragonPod(ctx context.Context, pod *corev1.Pod, r *TetragonPodReconciler, l logr.Logger) (ctrl.Result, error) {
// create the tetragon pod since the pod exists
if pod.Status.Phase == corev1.PodRunning {
l.Info("Creating the corresponding tetragonPod resource")
// get the new IP address of the Pod.
newIP := ciliumiov1alpha1.PodIP{IP: pod.Status.PodIP}
tetragonPod := &ciliumiov1alpha1.TetragonPod{

// create the tetragonPod with the same name and namespace as the pod.
ObjectMeta: metav1.ObjectMeta{
Name: pod.Name,
Namespace: pod.Namespace,
},
Status: ciliumiov1alpha1.TetragonPodStatus{
PodIP: newIP.IP,
PodIPs: make([]ciliumiov1alpha1.PodIP, 0),
},
}

if err := r.Create(ctx, tetragonPod); err != nil {
l.Error(err, "Failed to create TetragonPod")
return ctrl.Result{}, err
}
l.Info("New TetragonPod creation Successful")
return ctrl.Result{}, nil
}

// There are too many logs for pending pods, so commenting it out for now.
// if pod.Status.Phase == corev1.PodPending {
// l.Info("Pod is in pending state, waiting for it to be running")
// }
return ctrl.Result{}, nil
}

// getTetragonPod gets the tetragonPod resource
func getTetragonPod(ctx context.Context, req ctrl.Request, r *TetragonPodReconciler, l logr.Logger) (*ciliumiov1alpha1.TetragonPod, error) {
tetragonPod := &ciliumiov1alpha1.TetragonPod{}
if err := r.Get(ctx, req.NamespacedName, tetragonPod); err != nil {
if client.IgnoreNotFound(err) == nil {
l.Info("Unable to fetch the tetragonPod: Name=", req.Name, " Namespace=", req.Namespace)
return nil, err
}
}
return tetragonPod, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *TetragonPodReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Expand Down

0 comments on commit c128c91

Please sign in to comment.