This library layers on top of the Operator SDK, having set of utilities function as a library to easily create Kubernetes operators.
In July of 2020, our team moved away from using the term master
for our default branch. As a result, our branching scheme is as follows:
- The main (default) branch supports OCP 4.13 (K8S 1.26)
- For versions of
operator-utils
targeting any release of OCP (starting with 4.2), please refer to the tags section.- tag
v1.X.Y
indicates support for OCPvX.Y
- tag
- With each General Availability release of OCP a new tag will be created from the
v1.X.Y.x
branch then themain
branch will point to the latest OCP version.
All bugs, tasks, fixes or enhancements should be tracked as GitHub Issues & Pull Requests.
- To contribute features targeting OCP 4.13 only, use a local feature branch based off of & targeting
origin/main
with any PR's, Reference any JIRA/GitHub issues in PR's where applicable. - To contribute features targeting both currently supported versions, first complete the commit/PR work targeting
main
. Once that PR is merged tomain
, create a new PR with cherry-pick of the commit targeting the branch of the specific OCP version that it should be backported to.
Regardless of dependency framework, we suggest following the best practice of declaring any and all dependencies your project utilizes regardless of target branch, tag, or revision.
With regards to operator-utils
, please carefully consider the given version support information above when declaring your dependency, as depending on or defaulting to main
branch will likely result in future build complications as our project continues to evolve and cycle minor version support.
- Go.mod example specifying REVISION:
github.com/RHsyseng/operator-utils v0.0.0-20200108204558-82090ef57586
- managing CR and CRD validation
- pods deployment status
- resource comparison, adding, updating and deleting
- platform detection Kubernetes VS Openshift
Operator util library use package validation
for validate the CRD and CR file, these function use as a unit test within operator
CRD validation Usage:
schema := getCompleteSchema(t)
missingEntries := schema.GetMissingEntries(&sampleApp{})
for _, missing := range missingEntries {
if strings.HasPrefix(missing.Path, "/status") {
//Not using subresources, so status is not expected to appear in CRD
} else {
assert.Fail(t, "Discrepancy between CRD and Struct", "Missing or incorrect schema validation at %v, expected type %v", missing.Path, missing.Type)
}
}
CR validation Usage:
schema, err := New([]byte(schemaYaml))
assert.NoError(t, err)
type myAppSpec struct {
Number float64 `json:"number,omitempty"`
}
type myApp struct {
Spec myAppSpec `json:"spec,omitempty"`
}
cr := myApp{
Spec: myAppSpec{
Number: float64(23),
},
}
missingEntries := schema.GetMissingEntries(&cr)
assert.Len(t, missingEntries, 0, "Expect no missing entries in CRD for this struct: %v", missingEntries)
A full example is provided here
showes the status of the deployment on OLM UI in the form of PI chart, as seen in below screenshot
Usage:
Below seen line required to add into types.go status structure
PodStatus olm.DeploymentStatus `json:"podStatus"`
Add these lines into CSV file inside statusDescriptors section:
statusDescriptors:
- description: The current pods
displayName: Pods Status
path: podStatus
x-descriptors:
- "urn:alm:descriptor:com.tectonic.ui:podStatuses"
For DeploymentConfig deployment status:
var dcs []oappsv1.DeploymentConfig
deploymentStatus := olm.GetDeploymentConfigStatus(dcs)
if !reflect.DeepEqual(instance.Status.Deployments, deploymentStatus) {
r.reqLogger.Info("Deployment status will be updated")
instance.Status.Deployments = deploymentStatus
err = r.client.Status().Update(context.TODO(), instance)
if err != nil {
r.reqLogger.Error(err, "Failed to update deployment status")
return err
}
}
For StatefulSet Deployment status:
var status olm.DeploymentStatus
sfsFound := &appsv1.StatefulSet{}
err := client.Get(context.TODO(), namespacedName, sfsFound)
if err == nil {
status = olm.GetSingleStatefulSetStatus(*sfsFound)
} else {
dsFound := &appsv1.DaemonSet{}
err = client.Get(context.TODO(), namespacedName, dsFound)
if err == nil {
status = olm.GetSingleDaemonSetStatus(*dsFound)
}
}
Common function for listing, adding, updating, deleting kubernetes objects like seen below:
List of objects that are deployed
reader := read.New(client).WithNamespace(instance.Namespace).WithOwnerObject(instance)
resourceMap, err := reader.ListAll(
&corev1.PersistentVolumeClaimList{},
&corev1.ServiceList{},
&appsv1.StatefulSetList{},
&routev1.RouteList{},
)
Compare what's deployed with what should be deployed
requested := compare.NewMapBuilder().Add(requestedResources...).ResourceMap()
comparator := compare.NewMapComparator()
deltas := comparator.Compare(deployed, requested)
Adding the objects:
added, err := writer.AddResources(delta.Added)
Updating the objects:
updated, err := writer.UpdateResources(deployed[resourceType], delta.Updated)
Removing the objects:
removed, err := writer.RemoveResources(delta.Removed)
A full usage is provided here
To detect platform whether operator is running on kuberenete or openshift or what version of openshift is using
info, err := pv.GetPlatformInfo(c.discoverer, c.config)
A full example is provided here
operator-utils is used by several Red Hat product & community operators, including the following:
- 3scale APIcast Operator
- 3scale Operator
- ActiveMQ Artemis Operator
- ActiveMQ Artemis Broker Test Suite
- AtlasMap Operator
- Barometer Operator
- Infinispan Operator
- Integreatly Operator
- Kie Cloud Operator
- Kogito Operator
- KubeDB Operator
- KubeVirt Containerized Data Importer
- KubeVirt Hyperconverged Operator
- Nexus Operator
- OCS Meta Operator
- Performance Addon Operator
- QDR Interconnect Operator
- RHI Operator
- Serverless Orchestration
- ShipShape Testing Operator
- Teiid Operator
- Wildfly Operator