8000 GitHub - cisco-open/operator-tools at v0.2.0
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
8000

Speed up the implementation and composition of Kubernetes Operators

License

Notifications You must be signed in to change notification settings

cisco-open/operator-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

operator-tools

This is a collection of tools to speed up the implementation of Kubernetes Operators on top of controller-runtime.

GenericResourceReconciler

GenericResourceReconciler reconciles a single Kubernetes object against the API Server.

It creates the object if it doesn't exist or removes it in case its desired state is absent.

It uses the ObjectMatcher library to be able to tell if an already existing object needs to be updated or not.

It depends on logr logger and the controller-runtime client that is available in a typical kubebuilder or operator-sdk project.

Example:

package main

import (
	corev1 "k8s.io/api/core/v1"
	github.com/go-logr/logr
	"github.com/banzaicloud/operator-tools/pkg/reconciler"
	runtimeClient "sigs.k8s.io/controller-runtime/pkg/client"
)

func example(client runtimeClient.Client, logger logr.Logger) {
	
  resourceReconciler := reconciler.NewReconciler(client, logger, reconciler.ReconcilerOpts{})
  
  serviceObject := &corev1.Service{
    Spec: corev1.ServiceSpec{
      Ports: []corev1.ServicePort{
        {
          Protocol:		corev1.ProtocolTCP,
          Name:				"example",
          Port:				80,
          TargetPort: 8080,
        },
      },
      Selector:	map[string]string{
        "app": "example",
      },
      Type:			corev1.ServiceTypeClusterIP,
      ClusterIP: "None",
    },
  }
  
  result, err := resourceReconciler.ReconcileResource(serviceObject, reconciler.StatePresent)
}

This feature is currently only covered with tests in the logging operator, but this is a subject to change soon.

Secret & SecretLoader

Secret is a type to be used in CRDs to abstract the concept of loading a secret item instead of defining it with it's value directly.

Currently it support Kubernetes secrets only, but it can be extended to refer to secrets in custom secret stores as well.

There are two main approaches to load secrets and one for testing.

  1. Load the secrets and return with their value directly if ValueFrom is set.
  2. Load the secrets in the background if MountFrom is set, but return only the full path where they should be available in a container. It's the callers responsibility to make those secrets available on that given path, e.g. by creating an aggregated secret with all the referenced secrets and mount it into the container through a secret volume (this is how we use it).
  3. Load the value directly if Value is set. (This is only good for testing.)

Once you're done with configuration you can create the SecretLoader and load your secrets through it.

mountSecrets := &secret.MountSecrets{}
secretLoader := secret.NewSecretLoader(client, namespace, "/path/to/mount", mountSecrets)

Then you can load the secrets. The following steps can be made more dynamic, like it is beeing used in the logging operator: https://github.com/banzaicloud/logging-operator/blob/master/pkg/sdk/model/types/stringmaps.go

// get the secretValue and use it as you like in an application configuration template for example
secretValue, err := secretLoader.Load(yourCustomResourceType.Spec.ExampleSecretField)

// get the path to the mount secret and use it as you like in an application configuration template for example
secretPath, err := secretLoader.Load(yourCustomResourceType.Spec.ExampleMountSecretField)

// render the configuration template and create a new secret from it that will be mounted into the container
appConfigSecret := &corev1.Secret{}
renderedTemplate := renderTemplate(secretValue, secretPath)
appConfigSecret.Data["app.conf"] = renderedTemplate

// create the combined secret to be mounted to the container on "/path/to/mount"
combinedSecret := &corev1.Secret{}
for _, secret := range *mountSecrets {
  combinedSecret.Data[secret.MappedKey] = secret.Value
}

For a full example please check out the logging operator code.

Also, this feature is currently only covered with tests in the logging operator, but this is a subject to change soon.

About

Speed up the implementation and composition of Kubernetes Operators

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published
0