Skip to content

Instantly share code, notes, and snippets.

@sanchezl
Last active July 6, 2022 02:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sanchezl/1f607056e8539c0f25252ec88a12cf2d to your computer and use it in GitHub Desktop.
Save sanchezl/1f607056e8539c0f25252ec88a12cf2d to your computer and use it in GitHub Desktop.
New Operator Guide

New Operator Guide

Minimal Directory Structure

new-operator/
├── bindata ➊
│   └── new-operand/
│       └── resource.yaml
├── manifests/ ➋
├── images/ ➌
├── cmd/ ➍
│   └── new-operator/
│       └── main.go
├── pkg/
│   ├── cmd/ ➎
│   │   └── start.go
│   ├── tools/
│   │   └── tools.go ➏
│   ├── version/
│   │   └── version.go ➐
│   └── operator/
│       ├── assets/
│       │   └── bindata.go ➑
│       └── starter.go ➒
├── Makefile ➓
├── go.mod ⓫
└── vendor/
    └── github.com/
        └── openshift/
            └── library-go/
                └── alpha-build-machinery/ ⓬
File Description
/bindata Contains resource files used by the operator to manage the operand.
/manifests Contains resource files that deploy the operator.
/images Contains the files needed to build the operator image.
/cmd Contains the source code for the operator executable.
/pkg/cmd Contains the source code for the operator executable's sub-commands.
/pkg/tools/tools.go Imports tool packages that are needed at build time.
/pkg/version.go Contains version information injected at compile time.
/pkg/operator/assets/bindata.go Contains the code generated to embed the static files from /bindata
/pkg/operator/starter.go Contains the code that starts the operator.
/Makefile Makefile
/go.mod Go module definition file.
/vendor/github.com/openshift/library-go/alpha-build-machinery Contains common Makefile scripts.

Go Module

Run go mod init to initialize your go.mod file. Provide your module name as a parameter.

Vendoring

We recommend that you use vendoring. Vendoring is required if you want to make use of the make scripts provided by library-go. Run go mod vendor after updating the go.mod file to sync the contents of the /vendor folder.

Alpha-Build-Machinery

The github.com/openshift/library-go/alpha-build-machinery package contains some Makefile "libraries" that can be imported into your Makefile to enable some common targets.

This package expects to be imported by your Makefile from within the /vendor directory. go mod vendor will not import packages that are not actually used. To get around this, create the /pkg/tools/tools.go file with the following contents:

// +build tools

package tools

import (
    _ "github.com/jteeuwen/go-bindata/go-bindata"
    _ "github.com/openshift/library-go/alpha-build-machinery"
)

Running go mod vendor will update your go.mod file and copy the pakages into the /vendor directory.

NOTE: You need the go-bindata package for some of the make targets enabled by alpha-build-machinery.

Makefile

Create a Makefile at /Makefile. Use an include directive in your makefile to add some of the predefined targets from alpha-build-machinery:

Makefile Description Targets Added
golang.mk General targets for a Go project. all,build,clean,clean-binaries,help,test,test-unit,update,update-gofmt,verify,verify-gofmt,verify-golint,verify-govet
targets/openshift/bindata.mk Targets for embedding static resources. update-bindataupdate-generatedverify-bindataverify-generated
targets/openshift/images.mk Targets for building images. images

Example Makefile:

# Include the library makefiles
include $(addprefix ./vendor/github.com/openshift/library-go/alpha-build-machinery/make/, \
    golang.mk \
    targets/openshift/bindata.mk \
    targets/openshift/images.mk \
)

# generate a target named `bindata-assets` which:
#  Given the input directory of ./bindata/... will
#   Then strip the prefix `bindata` from the static asset name
#    And generate static resources into an `assets` package
#    And output the code to the `pkg/operator/assets/bindata.go` file
$(call add-bindata,assets,./bindata/...,bindata,assets,pkg/operator/assets/bindata.go)

# generate a target named `image-operator` which:
#  Given the Dockerfile at ./images/ci/Dockerfile
#    And the specifying the projecy root dir `.` as the docker context will
#   Then build the image
#    And tag it as `operator`
$(call build-image,operator,operator,./images/ci/Dockerfile,.)

NOTE about building images:

The lifecycle of an openshift project will require that you define how to build your images multiple times:

Installation Manifests

Create a /manifests directory and populate with the resources the CVO will need to deploy the operator.

Refer to the Operator integration with CVO documentation for details on what these manifests should contain.

Referencing Images in Manifests

Create a /manifest/image-references file containing an ImageStream resource that only defines some external image tags:

kind: ImageStream
apiVersion: image.openshift.io/v1
spec:
  tags:
  - name: release-tag-name
    from:
      kind: DockerImage
      Name: pseudo-image-name-in-manifest

When building a release or CI image, any instance of pseudo-image-name-in-manifest will be replaced (via sed text search/replace) with the appropriate image repository:tag corresponding to release-tag-name.

Typically, you should use the published Origin development image name for your image as the pseudo-image-name-in-manifest. Development images are typically published to quay.io/openshift/origin-*, Where '*' is a release tag name.

See How do I ensure the right images get used by my manifests? for more details.

Operand Resources

Place resources your operator will use to manage the operand in the /bindata directory. Create sub-directories for you operand under /bindata.

Image Dockerfiles

Create an /images directory to store any Dockerfile files needed to create images. Distinct Dockerfiles can be specified for images built during CI and images built for release.

Writing the Operator

RunOperator

In /pkg/operator/starter.go:

func RunOperator(ctx *controllercmd.ControllerContext) error {

    // initialize clients

    // initialize informer factories

    // initialize cluster operator status controller

    // initialize cluster operator logging controller

    // (Optional) initialize custom config observation controller

    // (Optional) initialize custom target controller

    // (Optional) initialize other custom controlleers

    // start the informer factories

    // start the controllers

    <-ctx.Done()
    return fmt.Errorf("stopped")
}

Target Controller

Applying Static Resource Directly

TODO

Appliying Static Resources with Dynamic Values

TODO

Config Observation Controller

TODO

Reporting Status

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment