...

Source file src/sigs.k8s.io/controller-runtime/examples/crd/main.go

Documentation: sigs.k8s.io/controller-runtime/examples/crd

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"context"
    21  	"math/rand"
    22  	"os"
    23  	"time"
    24  
    25  	corev1 "k8s.io/api/core/v1"
    26  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
    29  	ctrl "sigs.k8s.io/controller-runtime"
    30  	api "sigs.k8s.io/controller-runtime/examples/crd/pkg"
    31  	"sigs.k8s.io/controller-runtime/pkg/client"
    32  	"sigs.k8s.io/controller-runtime/pkg/log"
    33  	"sigs.k8s.io/controller-runtime/pkg/log/zap"
    34  )
    35  
    36  var (
    37  	setupLog = ctrl.Log.WithName("setup")
    38  )
    39  
    40  type reconciler struct {
    41  	client.Client
    42  	scheme *runtime.Scheme
    43  }
    44  
    45  func (r *reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    46  	log := log.FromContext(ctx).WithValues("chaospod", req.NamespacedName)
    47  	log.V(1).Info("reconciling chaos pod")
    48  
    49  	var chaospod api.ChaosPod
    50  	if err := r.Get(ctx, req.NamespacedName, &chaospod); err != nil {
    51  		log.Error(err, "unable to get chaosctl")
    52  		return ctrl.Result{}, err
    53  	}
    54  
    55  	var pod corev1.Pod
    56  	podFound := true
    57  	if err := r.Get(ctx, req.NamespacedName, &pod); err != nil {
    58  		if !apierrors.IsNotFound(err) {
    59  			log.Error(err, "unable to get pod")
    60  			return ctrl.Result{}, err
    61  		}
    62  		podFound = false
    63  	}
    64  
    65  	if podFound {
    66  		shouldStop := chaospod.Spec.NextStop.Time.Before(time.Now())
    67  		if !shouldStop {
    68  			return ctrl.Result{RequeueAfter: chaospod.Spec.NextStop.Sub(time.Now()) + 1*time.Second}, nil
    69  		}
    70  
    71  		if err := r.Delete(ctx, &pod); err != nil {
    72  			log.Error(err, "unable to delete pod")
    73  			return ctrl.Result{}, err
    74  		}
    75  
    76  		return ctrl.Result{Requeue: true}, nil
    77  	}
    78  
    79  	templ := chaospod.Spec.Template.DeepCopy()
    80  	pod.ObjectMeta = templ.ObjectMeta
    81  	pod.Name = req.Name
    82  	pod.Namespace = req.Namespace
    83  	pod.Spec = templ.Spec
    84  
    85  	if err := ctrl.SetControllerReference(&chaospod, &pod, r.scheme); err != nil {
    86  		log.Error(err, "unable to set pod's owner reference")
    87  		return ctrl.Result{}, err
    88  	}
    89  
    90  	if err := r.Create(ctx, &pod); err != nil {
    91  		log.Error(err, "unable to create pod")
    92  		return ctrl.Result{}, err
    93  	}
    94  
    95  	chaospod.Spec.NextStop.Time = time.Now().Add(time.Duration(10*(rand.Int63n(2)+1)) * time.Second)
    96  	chaospod.Status.LastRun = pod.CreationTimestamp
    97  	if err := r.Update(ctx, &chaospod); err != nil {
    98  		log.Error(err, "unable to update chaosctl status")
    99  		return ctrl.Result{}, err
   100  	}
   101  	return ctrl.Result{}, nil
   102  }
   103  
   104  func main() {
   105  	ctrl.SetLogger(zap.New())
   106  
   107  	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
   108  	if err != nil {
   109  		setupLog.Error(err, "unable to start manager")
   110  		os.Exit(1)
   111  	}
   112  
   113  	// in a real controller, we'd create a new scheme for this
   114  	err = api.AddToScheme(mgr.GetScheme())
   115  	if err != nil {
   116  		setupLog.Error(err, "unable to add scheme")
   117  		os.Exit(1)
   118  	}
   119  
   120  	err = ctrl.NewControllerManagedBy(mgr).
   121  		For(&api.ChaosPod{}).
   122  		Owns(&corev1.Pod{}).
   123  		Complete(&reconciler{
   124  			Client: mgr.GetClient(),
   125  			scheme: mgr.GetScheme(),
   126  		})
   127  	if err != nil {
   128  		setupLog.Error(err, "unable to create controller")
   129  		os.Exit(1)
   130  	}
   131  
   132  	err = ctrl.NewWebhookManagedBy(mgr).
   133  		For(&api.ChaosPod{}).
   134  		Complete()
   135  	if err != nil {
   136  		setupLog.Error(err, "unable to create webhook")
   137  		os.Exit(1)
   138  	}
   139  
   140  	setupLog.Info("starting manager")
   141  	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
   142  		setupLog.Error(err, "problem running manager")
   143  		os.Exit(1)
   144  	}
   145  }
   146  

View as plain text