Using the GitOps Toolkit APIs with Go

The GitOps Toolkit client libraries documentation.

While you can use the GitOps Toolkit APIs in a declarative manner with kubectl apply, we provide client library code for all our toolkit APIs that makes it easier to access them from Go.

Go Packages

The GitOps Toolkit Go modules and controllers are released by following the semver conventions.

The API schema definitions modules have the following dependencies:

The APIs can be consumed with the controller-runtime client.

source.toolkit.fluxcd.io

Download package

go get github.com/fluxcd/source-controller/api

Import package

import sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"

API Types

Name Version
GitRepository v1beta1
HelmRepository v1beta1
HelmChart v1beta1
Bucket v1beta1

kustomize.toolkit.fluxcd.io

Download package

go get github.com/fluxcd/kustomize-controller/api

Import package

import kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"

API Types

Name Version
Kustomization v1beta1

helm.toolkit.fluxcd.io

Download package

go get github.com/fluxcd/helm-controller/api

Import package

import helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"

API Types

Name Version
HelmRelease v2beta1

notification.toolkit.fluxcd.io

Download package

go get github.com/fluxcd/notification-controller/api

Import package

import helmv2 "github.com/fluxcd/notification-controller/api/v1beta1"

API Types

Name Version
Receiver v1beta1
Provider v1beta1
Alert v1beta1

image.toolkit.fluxcd.io

Download package

go get github.com/fluxcd/image-reflector-controller/api
go get github.com/fluxcd/image-automation-controller/api

Import package

import (
	imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
	autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
)

API Types

Name Version
ImageRepository v1alpha2
ImagePolicy v1alpha2
ImageUpdateAutomation v1alpha2

CRUD Example

Here is an example of how to create a Helm release, wait for it to install, then delete it:

package main

import (
  "context"
  "fmt"
  "time"

  apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
  "k8s.io/apimachinery/pkg/api/meta"
  metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  "k8s.io/apimachinery/pkg/runtime"
  "k8s.io/apimachinery/pkg/types"
  "k8s.io/apimachinery/pkg/util/wait"
  _ "k8s.io/client-go/plugin/pkg/client/auth"
  ctrl "sigs.k8s.io/controller-runtime"
  "sigs.k8s.io/controller-runtime/pkg/client"

  helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
  apimeta "github.com/fluxcd/pkg/apis/meta"
  sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)

func main() {
  // register the GitOps Toolkit schema definitions
  scheme := runtime.NewScheme()
  _ = sourcev1.AddToScheme(scheme)
  _ = helmv2.AddToScheme(scheme)

  // init Kubernetes client
  kubeClient, err := client.New(ctrl.GetConfigOrDie(), client.Options{Scheme: scheme})
  if err != nil {
    panic(err)
  }

  // set a deadline for the Kubernetes API operations
  ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
  defer cancel()

  // create a Helm repository pointing to Bitnami
  helmRepository := &sourcev1.HelmRepository{
    ObjectMeta: metav1.ObjectMeta{
      Name:      "bitnami",
      Namespace: "default",
    },
    Spec: sourcev1.HelmRepositorySpec{
      URL: "https://charts.bitnami.com/bitnami",
      Interval: metav1.Duration{
        Duration: 30 * time.Minute,
      },
    },
  }
  if err := kubeClient.Create(ctx, helmRepository); err != nil {
    fmt.Println(err)
  } else {
    fmt.Println("HelmRepository bitnami created")
  }

  // create a Helm release for nginx
  helmRelease := &helmv2.HelmRelease{
    ObjectMeta: metav1.ObjectMeta{
      Name:      "nginx",
      Namespace: "default",
    },
    Spec: helmv2.HelmReleaseSpec{
      ReleaseName: "nginx",
      Interval: metav1.Duration{
        Duration: 5 + time.Minute,
      },
      Chart: helmv2.HelmChartTemplate{
        Spec: helmv2.HelmChartTemplateSpec{
          Chart:   "nginx",
          Version: "8.x",
          SourceRef: helmv2.CrossNamespaceObjectReference{
            Kind: sourcev1.HelmRepositoryKind,
            Name: "bitnami",
          },
        },
      },
      Values: &apiextensionsv1.JSON{Raw: []byte(`{"service": {"type": "ClusterIP"}}`)},
    },
  }
  if err := kubeClient.Create(ctx, helmRelease); err != nil {
    fmt.Println(err)
  } else {
    fmt.Println("HelmRelease nginx created")
  }

  // wait for the a Helm release to be reconciled
  fmt.Println("Waiting for nginx to be installed")
  if err := wait.PollImmediate(2*time.Second, 1*time.Minute,
    func() (done bool, err error) {
      namespacedName := types.NamespacedName{
        Namespace: helmRelease.GetNamespace(),
        Name:      helmRelease.GetName(),
      }
      if err := kubeClient.Get(ctx, namespacedName, helmRelease); err != nil {
        return false, err
      }
      return meta.IsStatusConditionTrue(helmRelease.Status.Conditions, apimeta.ReadyCondition), nil
    }); err != nil {
    fmt.Println(err)
  }

  // print the reconciliation status
  fmt.Println(meta.FindStatusCondition(helmRelease.Status.Conditions, apimeta.ReadyCondition).Message)

  // uninstall the release and delete the repository
  if err := kubeClient.Delete(ctx, helmRelease); err != nil {
    fmt.Println(err)
  }
  if err := kubeClient.Delete(ctx, helmRepository); err != nil {
    fmt.Println(err)
  }
  fmt.Println("Helm repository and release deleted")
}

For an example on how to build a Kubernetes controller that interacts with the GitOps Toolkit APIs see source-watcher.

Last modified 2021-09-02 : docs: Change word imame to image (7854d4d)