Giter Site home page Giter Site logo

imikushin / controllers-af Goto Github PK

View Code? Open in Web Editor NEW
8.0 2.0 2.0 76 KB

A tiny Go library for building Kubernetes Controllers - As Functions

License: Apache License 2.0

Dockerfile 3.02% Makefile 7.86% Go 89.11%
go kubernetes controller-runtime

controllers-af's Introduction

Controllers AF

A Go library for building Kubernetes Controllers - As Functions

Why

Building Kubernetes controllers is hard. One of the reasons is: it is very hard to write unit-tests for controllers. Why is that? Controllers need to talk to the Kubernetes API all the time, and it takes enormous discipline to mock out these interactions. So, what ends up happening: we don't do it, and our controllers become branching spaghetti monsters.

Enter Controllers AF. It is a tiny library (or micro-framework) built on top of controller-runtime and is designed to do one thing: separate controller logic from interactions with Kubernetes API. Usage section below illustrates how to use it. We also provide a fully functioning example.

Usage

package yourcontroller

import (
	"context"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/source"

	"github.com/imikushin/controllers-af/function"
	"github.com/imikushin/controllers-af/reconciler"

	yourapiv1alpha1 "github.com/your/awesome-controller/api/v1alpha1"
)

func SetupWithManager(mgr ctrl.Manager) error {
	theClient := mgr.GetClient()
	log := ctrl.Log.WithName("controllers").WithName("YourObject")

	yourReconciler := reconciler.New(theClient, log, &yourapiv1alpha1.YourObject{}, ReconcileFun)
	
	return ctrl.NewControllerManagedBy(mgr).For(&yourapiv1alpha1.YourObject{}).Complete(yourReconciler)
}

func ReconcileFun(_ context.Context, object client.Object, getDetails function.GetDetails) (*function.Effects, error) {
	yourObject := object.(*yourapiv1alpha1.YourObject)
	
	yourOtherObjects := getDetails(function.Query{
		Namespace: yourObject.Namespace,
		Type:      &yourapiv1alpha1.YourOtherObjectList{},
		Selector:  metav1.LabelSelectorAsSelector(yourObject.Spec.YourOtherObjectSelector),
	}).(*YourOtherObjectList)
	
	// calculate your effects - no need to talk to the API!

	return &function.Effects{
		Persists: []client.Object{create, or, update, these},
		Deletes: []client.Object{things, toDelete},
	}, nil
}

controllers-af's People

Contributors

imikushin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

controllers-af's Issues

logging from within the ReconcileFunc?

Hi, I'm trying out this library for the first time.

What's a good way to get a logger from within the Reconcile callback?

Could I pull one off the context somehow (first function argument)?

occasional error when patching status

My controller logs occasionally show errors like this:

ERROR   controller-runtime.manager.controller.servicedirectory  Reconciler error        {"reconciler group": "connectivity.tanzu.vmware.com", "reconciler kind": "ServiceDirectory", "name": "foo", "namespace": "some-service-provider", "error": "servicedirectories.connectivity.tanzu.vmware.com \"foo\" not found"}
github.com/go-logr/zapr.(*zapLogger).Error
        /home/kokoni/.asdf/installs/golang/1.16.3/packages/pkg/mod/github.com/go-logr/[email protected]/zapr.go:132
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler
        /home/kokoni/.asdf/installs/golang/1.16.3/packages/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:302
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem
        /home/kokoni/.asdf/installs/golang/1.16.3/packages/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:253
...

When I add various fmt.Errorf() wrapping inside this library, then I see a bit more of where it's coming from:

ERROR   controller-runtime.manager.controller.servicedirectory  Reconciler error        {"reconciler group": "connectivity.tanzu.vmware.com", "reconciler kind": "ServiceDirectory", "name": "foo", "namespace": "some-service-provider", "error": "controllers-af persist: persistObjects patch: status patch: servicedirectories.connectivity.tanzu.vmware.com \"foo\" not found"}

This seems to happen the first time the library tries to patch the status for a resource, but then it retriggers and gets past it.

I haven't had a chance to dig into this too much now, but in case there's an easy/obvious fix, I wanted to report it early.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.