"error": "ats.cnat.programming-kubernetes.info \"example-at\" not found"
ishankhare07 opened this issue · 1 comments
ishankhare07 commented
I'm getting the following error
2020-09-19T13:16:17.164+0530 INFO controller-runtime.controller Starting EventSource {"controller": "at", "source": "kind source: /, Kind="}
2020-09-19T13:16:17.164+0530 INFO controller-runtime.manager starting metrics server {"path": "/metrics"}
2020-09-19T13:16:17.365+0530 INFO controller-runtime.controller Starting Controller {"controller": "at"}
2020-09-19T13:16:17.365+0530 INFO controller-runtime.controller Starting workers {"controller": "at", "worker count": 1}
2020-09-19T13:16:17.366+0530 INFO controllers.At === Reconciling At {"namespace": "cnat", "at": "example-at"}
2020-09-19T13:16:17.366+0530 INFO controllers.At Phase: PENDING {"namespace": "cnat", "at": "example-at"}
2020-09-19T13:16:17.366+0530 INFO controllers.At Checking schedule {"namespace": "cnat", "at": "example-at", "Target": "2019-04-12T10:12:00Z"}
2020-09-19T13:16:17.366+0530 INFO controllers.At It's time! {"namespace": "cnat", "at": "example-at", "ready to execute": "echo YAY!"}
2020-09-19T13:16:17.366+0530 INFO controllers.At === Updating status {"namespace": "cnat", "at": "example-at"}
2020-09-19T13:16:17.682+0530 ERROR controller-runtime.controller Reconciler error {"controller": "at", "request": "cnat/example-at", "error": "ats.cnat.programming-kubernetes.info \"example-at\" not found"}
github.com/go-logr/zapr.(*zapLogger).Error
/Users/ishankhare/godev/pkg/mod/github.com/go-logr/zapr@v0.1.0/zapr.go:128
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
/Users/ishankhare/godev/pkg/mod/sigs.k8s.io/controller-runtime@v0.5.0/pkg/internal/controller/controller.go:258
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
/Users/ishankhare/godev/pkg/mod/sigs.k8s.io/controller-runtime@v0.5.0/pkg/internal/controller/controller.go:232
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker
/Users/ishankhare/godev/pkg/mod/sigs.k8s.io/controller-runtime@v0.5.0/pkg/internal/controller/controller.go:211
k8s.io/apimachinery/pkg/util/wait.JitterUntil.func1
/Users/ishankhare/godev/pkg/mod/k8s.io/apimachinery@v0.17.2/pkg/util/wait/wait.go:152
k8s.io/apimachinery/pkg/util/wait.JitterUntil
/Users/ishankhare/godev/pkg/mod/k8s.io/apimachinery@v0.17.2/pkg/util/wait/wait.go:153
k8s.io/apimachinery/pkg/util/wait.Until
/Users/ishankhare/godev/pkg/mod/k8s.io/apimachinery@v0.17.2/pkg/util/wait/wait.go:88
^Cmake: *** [run] Error 1
I can find the said cr if i run kubectl get at example-at
. But controller reports not found .
The specific line causing the error in my opinion is err = r.Status().Update(context.TODO(), instance)
Below is my whole code for at_controllers.go
package controllers
import (
"context"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
cnatv1alpha1 "cnat-controller/api/v1alpha1"
"cnat-controller/pkg/scheduler"
"cnat-controller/pkg/spawn"
corev1 "k8s.io/api/core/v1"
)
// AtReconciler reconciles a At object
type AtReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=cnat.programming-kubernetes.info,resources=ats,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=cnat.programming-kubernetes.info,resources=ats/status,verbs=get;update;patch
func (r *AtReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
_ = context.Background()
reqLogger := r.Log.WithValues("namespace", req.Namespace, "at", req.Name)
reqLogger.Info("=== Reconciling At")
// your logic here
// fetch the At instance
instance := &cnatv1alpha1.At{}
err := r.Get(context.TODO(), req.NamespacedName, instance)
if err != nil {
if errors.IsNotFound(err) {
return reconcile.Result{}, nil
}
return reconcile.Result{}, err
}
// if no phase set, default to pending (the initial phase):
if instance.Status.Phase == "" {
instance.Status.Phase = cnatv1alpha1.PhasePending
}
// the state diagram PENDING -> RUNNING -> DONE
switch instance.Status.Phase {
case cnatv1alpha1.PhasePending:
reqLogger.Info("Phase: PENDING")
reqLogger.Info("Checking schedule", "Target", instance.Spec.Schedule)
// check with a tolerance of 2 seconds
d, err := scheduler.TimeUntilSchedule(instance.Spec.Schedule)
if err != nil {
reqLogger.Error(err, "Schedule parsing failure")
return reconcile.Result{}, err
}
// reqLogger.Info("Schedule parsing done", "Result", "diff", fmt.Sprintf("%v", d))
if d > 0 {
// Not yet time to execute, wait until scheduled time
return reconcile.Result{RequeueAfter: d}, nil
}
reqLogger.Info("It's time!", "ready to execute", instance.Spec.Command)
instance.Status.Phase = cnatv1alpha1.PhaseRunning
case cnatv1alpha1.PhaseRunning:
reqLogger.Info("Phase: RUNNING")
pod := spawn.NewPodForCR(instance)
// set At instance as owner and controller
err := controllerutil.SetControllerReference(instance, pod, r.Scheme)
if err != nil {
return reconcile.Result{}, err
}
query := &corev1.Pod{}
nsName := types.NamespacedName{Name: pod.Name, Namespace: pod.Namespace}
err = r.Get(context.TODO(), nsName, query)
if err != nil && errors.IsNotFound(err) {
// create the pod
err = r.Create(context.TODO(), pod)
if err != nil {
return reconcile.Result{}, err
}
reqLogger.Info("Pod Launched", "name", pod.Name)
} else if err != nil {
return reconcile.Result{}, err
} else if query.Status.Phase == corev1.PodFailed ||
query.Status.Phase == corev1.PodSucceeded {
reqLogger.Info("Container terminated", "reason",
query.Status.Reason, "message", query.Status.Message)
instance.Status.Phase = cnatv1alpha1.PhaseDone
} else {
// don't requeue, it will happen automatically when pod status changes
return reconcile.Result{}, nil
}
case cnatv1alpha1.PhaseDone:
reqLogger.Info("Phase: DONE")
return reconcile.Result{}, nil
default:
reqLogger.Info("NOP")
return reconcile.Result{}, nil
}
// update the At instance
reqLogger.Info("=== Updating status")
err = r.Status().Update(context.TODO(), instance)
if err != nil {
reqLogger.Info("Unable to update status")
return reconcile.Result{}, err
}
return reconcile.Result{}, nil
}
func (r *AtReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&cnatv1alpha1.At{}).
Complete(r)
}
SachinMaharana commented
@ishankhare07 In your, at_types.go file, add
// +kubebuilder:subresource:status
above the At struct. For example,
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// At is the Schema for the cnats API
type At struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AtSpec `json:"spec,omitempty"`
Status AtStatus `json:"status,omitempty"`
}
make sure to delete the existing crd, then make manifests
to generate crd again and the usual commands after that.