Skip to content

Commit

Permalink
status func could handle error
Browse files Browse the repository at this point in the history
  • Loading branch information
xuzhenglun committed Jan 17, 2022
1 parent fea7e5c commit 653a928
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 27 deletions.
3 changes: 2 additions & 1 deletion pkg/patterns/addon/pkg/status/aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative"
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
)
Expand All @@ -44,7 +45,7 @@ type aggregator struct {
client client.Client
}

func (a *aggregator) Reconciled(ctx context.Context, src declarative.DeclarativeObject, objs *manifest.Objects) error {
func (a *aggregator) Reconciled(ctx context.Context, src declarative.DeclarativeObject, objs *manifest.Objects, _ error) error {
log := log.Log

statusHealthy := true
Expand Down
3 changes: 2 additions & 1 deletion pkg/patterns/addon/pkg/status/kstatus.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/addon/pkg/utils"
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative"
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
Expand All @@ -22,7 +23,7 @@ func NewKstatusAgregator(c client.Client, reconciler *declarative.Reconciler) *k
}

func (k *kstatusAggregator) Reconciled(ctx context.Context, src declarative.DeclarativeObject,
objs *manifest.Objects) error {
objs *manifest.Objects, _ error) error {
log := log.Log

statusMap := make(map[status.Status]bool)
Expand Down
65 changes: 43 additions & 22 deletions pkg/patterns/declarative/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/applier"
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
"sigs.k8s.io/kustomize/api/filesys"
"sigs.k8s.io/kustomize/api/krusty"

"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/applier"
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
)

var _ reconcile.Reconciler = &Reconciler{}
Expand Down Expand Up @@ -73,6 +74,15 @@ type DeclarativeObject interface {
metav1.Object
}

type ErrorResult struct {
Result reconcile.Result
Err error
}

func (e *ErrorResult) Error() string {
return e.Err.Error()
}

// For mocking
var kubectl = applier.NewDirectApplier()

Expand Down Expand Up @@ -118,6 +128,7 @@ func (r *Reconciler) Init(mgr manager.Manager, prototype DeclarativeObject, opts

// +rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (result reconcile.Result, err error) {
var objects *manifest.Objects
log := log.Log
defer r.collectMetrics(request, result, err)

Expand All @@ -134,17 +145,35 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
return reconcile.Result{}, err
}

// status.Reconciled should catch all error
defer func() {
// data is Error
resultErr, ok := err.(*ErrorResult)
if ok {
result = resultErr.Result
err = resultErr.Err
}

if r.options.status != nil {
if err = r.options.status.Reconciled(ctx, instance, objects, err); err != nil {
log.Error(err, "failed to reconcile status")
}
}
}()

if r.options.status != nil {
if err := r.options.status.Preflight(ctx, instance); err != nil {
log.Error(err, "preflight check failed, not reconciling")
return reconcile.Result{}, err
}
}

return r.reconcileExists(ctx, request.NamespacedName, instance)
objects, err = r.reconcileExists(ctx, request.NamespacedName, instance)

return result, err
}

func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedName, instance DeclarativeObject) (reconcile.Result, error) {
func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedName, instance DeclarativeObject) (*manifest.Objects, error) {
log := log.Log
log.WithValues("object", name.String()).Info("reconciling")

Expand All @@ -156,7 +185,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
objects, err := r.BuildDeploymentObjectsWithFs(ctx, name, instance, fs)
if err != nil {
log.Error(err, "building deployment objects")
return reconcile.Result{}, fmt.Errorf("error building deployment objects: %v", err)
return nil, fmt.Errorf("error building deployment objects: %v", err)
}
log.WithValues("objects", fmt.Sprintf("%d", len(objects.Items))).Info("built deployment objects")

Expand All @@ -166,35 +195,27 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
if !isValidVersion {
// r.client isn't exported so can't be updated in version check function
if err := r.client.Status().Update(ctx, instance); err != nil {
return reconcile.Result{}, err
return objects, err
}
r.recorder.Event(instance, "Warning", "Failed version check", err.Error())
log.Error(err, "Version check failed, not reconciling")
return reconcile.Result{}, nil
return objects, nil
}
log.Error(err, "Version check failed, trying to reconcile")
return reconcile.Result{}, err
return objects, err
}
}

defer func() {
if r.options.status != nil {
if err := r.options.status.Reconciled(ctx, instance, objects); err != nil {
log.Error(err, "failed to reconcile status")
}
}
}()

objects, err = parseListKind(objects)

if err != nil {
log.Error(err, "Parsing list kind")
return reconcile.Result{}, fmt.Errorf("error parsing list kind: %v", err)
return objects, fmt.Errorf("error parsing list kind: %v", err)
}

err = r.injectOwnerRef(ctx, instance, objects)
if err != nil {
return reconcile.Result{}, err
return objects, err
}

var newItems []*manifest.Object
Expand All @@ -221,7 +242,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
m, err := objects.JSONManifest()
if err != nil {
log.Error(err, "creating final manifest")
return reconcile.Result{}, fmt.Errorf("error creating manifest: %v", err)
return objects, fmt.Errorf("error creating manifest: %v", err)
}
manifestStr = m

Expand Down Expand Up @@ -267,16 +288,16 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN

if err := r.kubectl.Apply(ctx, applyOpt); err != nil {
log.Error(err, "applying manifest")
return reconcile.Result{}, fmt.Errorf("error applying manifest: %v", err)
return objects, fmt.Errorf("error applying manifest: %v", err)
}

if r.options.sink != nil {
if err := r.options.sink.Notify(ctx, instance, objects); err != nil {
log.Error(err, "notifying sink")
return reconcile.Result{}, err
return objects, err
}
}
return reconcile.Result{}, nil
return objects, nil
}

// BuildDeploymentObjects performs all manifest operations to build a final set of objects for deployment
Expand Down
6 changes: 3 additions & 3 deletions pkg/patterns/declarative/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Reconciled interface {
// Reconciled is triggered when Reconciliation has occured.
// The caller is encouraged to determine and surface the health of the reconcilation
// on the DeclarativeObject.
Reconciled(context.Context, DeclarativeObject, *manifest.Objects) error
Reconciled(context.Context, DeclarativeObject, *manifest.Objects, error) error
}

type Preflight interface {
Expand All @@ -57,9 +57,9 @@ type StatusBuilder struct {
VersionCheckImpl VersionCheck
}

func (s *StatusBuilder) Reconciled(ctx context.Context, src DeclarativeObject, objs *manifest.Objects) error {
func (s *StatusBuilder) Reconciled(ctx context.Context, src DeclarativeObject, objs *manifest.Objects, err error) error {
if s.ReconciledImpl != nil {
return s.ReconciledImpl.Reconciled(ctx, src, objs)
return s.ReconciledImpl.Reconciled(ctx, src, objs, err)
}
return nil
}
Expand Down

0 comments on commit 653a928

Please sign in to comment.