blob: 521127de47eb268e7a3cd5563076eb75ebcbc2a9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package kubernetes
import (
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/apache/incubator-kie-kogito-serverless-operator/api/metadata"
ctrl "sigs.k8s.io/controller-runtime/pkg/client"
operatorapi "github.com/apache/incubator-kie-kogito-serverless-operator/api/v1alpha08"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
routev1 "github.com/openshift/api/route/v1"
)
// A Collection is a container of Kubernetes resources.
type Collection struct {
items []ctrl.Object
}
// NewCollection creates a new empty collection.
func NewCollection(objects ...ctrl.Object) *Collection {
collection := Collection{
items: make([]ctrl.Object, 0, len(objects)),
}
collection.items = append(collection.items, objects...)
return &collection
}
// Size returns the number of resources belonging to the collection.
func (c *Collection) Size() int {
return len(c.items)
}
// Items returns all resources belonging to the collection.
func (c *Collection) Items() []ctrl.Object {
return c.items
}
// AsKubernetesList returns all resources wrapped in a Kubernetes list.
func (c *Collection) AsKubernetesList() *corev1.List {
lst := corev1.List{
TypeMeta: metav1.TypeMeta{
Kind: "List",
APIVersion: "v1",
},
Items: make([]runtime.RawExtension, 0, len(c.items)),
}
for _, res := range c.items {
raw := runtime.RawExtension{
Object: res,
}
lst.Items = append(lst.Items, raw)
}
return &lst
}
// Add adds a resource to the collection.
func (c *Collection) Add(resource ctrl.Object) {
if resource != nil {
c.items = append(c.items, resource)
}
}
// AddFirst adds a resource to the head of the collection.
func (c *Collection) AddFirst(resource ctrl.Object) {
if resource != nil {
c.items = append([]ctrl.Object{resource}, c.items...)
}
}
// AddAll adds all resources to the collection.
func (c *Collection) AddAll(resource []ctrl.Object) {
c.items = append(c.items, resource...)
}
// VisitDeployment executes the visitor function on all Deployment resources.
func (c *Collection) VisitDeployment(visitor func(*appsv1.Deployment)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*appsv1.Deployment); ok {
visitor(conv)
}
})
}
// VisitDeploymentE executes the visitor function on all Deployment resources.
func (c *Collection) VisitDeploymentE(visitor func(*appsv1.Deployment) error) error {
return c.VisitE(func(res runtime.Object) error {
if conv, ok := res.(*appsv1.Deployment); ok {
return visitor(conv)
}
return nil
})
}
// GetDeployment returns a Deployment that matches the given function.
func (c *Collection) GetDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment {
var retValue *appsv1.Deployment
c.VisitDeployment(func(re *appsv1.Deployment) {
if filter(re) {
retValue = re
}
})
return retValue
}
// GetDeploymentForWorkflow returns a Deployment for the given workflow.
func (c *Collection) GetDeploymentForWorkflow(workflow *operatorapi.SonataFlow) *appsv1.Deployment {
if workflow == nil {
return nil
}
return c.GetDeployment(func(d *appsv1.Deployment) bool {
return d.ObjectMeta.Labels[metadata.Name] == workflow.Name
})
}
// HasDeployment returns true if a deployment matching the given condition is present.
func (c *Collection) HasDeployment(filter func(*appsv1.Deployment) bool) bool {
return c.GetDeployment(filter) != nil
}
// RemoveDeployment removes and returns a Deployment that matches the given function.
func (c *Collection) RemoveDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment {
res := c.Remove(func(res runtime.Object) bool {
if conv, ok := res.(*appsv1.Deployment); ok {
return filter(conv)
}
return false
})
if res == nil {
return nil
}
deploy, ok := res.(*appsv1.Deployment)
if !ok {
return nil
}
return deploy
}
// VisitConfigMap executes the visitor function on all ConfigMap resources.
func (c *Collection) VisitConfigMap(visitor func(*corev1.ConfigMap)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*corev1.ConfigMap); ok {
visitor(conv)
}
})
}
// GetConfigMap returns a ConfigMap that matches the given function.
func (c *Collection) GetConfigMap(filter func(*corev1.ConfigMap) bool) *corev1.ConfigMap {
var retValue *corev1.ConfigMap
c.VisitConfigMap(func(re *corev1.ConfigMap) {
if filter(re) {
retValue = re
}
})
return retValue
}
// RemoveConfigMap removes and returns a ConfigMap that matches the given function.
func (c *Collection) RemoveConfigMap(filter func(*corev1.ConfigMap) bool) *corev1.ConfigMap {
res := c.Remove(func(res runtime.Object) bool {
if conv, ok := res.(*corev1.ConfigMap); ok {
return filter(conv)
}
return false
})
if res == nil {
return nil
}
cm, ok := res.(*corev1.ConfigMap)
if !ok {
return nil
}
return cm
}
// VisitService executes the visitor function on all Service resources.
func (c *Collection) VisitService(visitor func(*corev1.Service)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*corev1.Service); ok {
visitor(conv)
}
})
}
// GetService returns a Service that matches the given function.
func (c *Collection) GetService(filter func(*corev1.Service) bool) *corev1.Service {
var retValue *corev1.Service
c.VisitService(func(re *corev1.Service) {
if filter(re) {
retValue = re
}
})
return retValue
}
// GetServiceForWorkflow returns a user Service for the given workflow.
func (c *Collection) GetServiceForWorkflow(workflow *operatorapi.SonataFlow) *corev1.Service {
if workflow == nil {
return nil
}
return c.GetService(func(s *corev1.Service) bool {
return s.ObjectMeta.Labels != nil && s.ObjectMeta.Labels[metadata.Label] == workflow.Name
})
}
// VisitRoute executes the visitor function on all Route resources.
func (c *Collection) VisitRoute(visitor func(*routev1.Route)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*routev1.Route); ok {
visitor(conv)
}
})
}
// GetRoute returns a Route that matches the given function.
func (c *Collection) GetRoute(filter func(*routev1.Route) bool) *routev1.Route {
var retValue *routev1.Route
c.VisitRoute(func(re *routev1.Route) {
if filter(re) {
retValue = re
}
})
return retValue
}
// GetCronJob returns a CronJob that matches the given function.
func (c *Collection) GetCronJob(filter func(job *batchv1.CronJob) bool) *batchv1.CronJob {
var retValue *batchv1.CronJob
c.VisitCronJob(func(re *batchv1.CronJob) {
if filter(re) {
retValue = re
}
})
return retValue
}
// VisitCronJob executes the visitor function on all CronJob resources.
func (c *Collection) VisitCronJob(visitor func(*batchv1.CronJob)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*batchv1.CronJob); ok {
visitor(conv)
}
})
}
// VisitCronJobE executes the visitor function on all CronJob resources.
func (c *Collection) VisitCronJobE(visitor func(*batchv1.CronJob) error) error {
return c.VisitE(func(res runtime.Object) error {
if conv, ok := res.(*batchv1.CronJob); ok {
return visitor(conv)
}
return nil
})
}
// GetContainer --.
func (c *Collection) GetContainer(filter func(container *corev1.Container) bool) *corev1.Container {
var retValue *corev1.Container
c.VisitContainer(func(container *corev1.Container) {
if filter(container) {
retValue = container
}
})
return retValue
}
// GetContainerByName --.
func (c *Collection) GetContainerByName(name string) *corev1.Container {
return c.GetContainer(func(c *corev1.Container) bool {
return c.Name == name
})
}
// VisitContainer executes the visitor function on all Containers inside deployments or other resources.
func (c *Collection) VisitContainer(visitor func(container *corev1.Container)) {
c.VisitDeployment(func(d *appsv1.Deployment) {
for idx := range d.Spec.Template.Spec.Containers {
cntref := &d.Spec.Template.Spec.Containers[idx]
visitor(cntref)
}
})
}
// GetController returns the controller associated with the workflow (e.g. Deployment).
func (c *Collection) GetController(filter func(object ctrl.Object) bool) ctrl.Object {
d := c.GetDeployment(func(deployment *appsv1.Deployment) bool {
return filter(deployment)
})
if d != nil {
return d
}
return nil
}
// VisitPodSpec executes the visitor function on all PodSpec inside deployments or other resources.
func (c *Collection) VisitPodSpec(visitor func(container *corev1.PodSpec)) {
c.VisitDeployment(func(d *appsv1.Deployment) {
visitor(&d.Spec.Template.Spec)
})
}
// VisitPodTemplateMeta executes the visitor function on all PodTemplate metadata inside deployments or other resources.
func (c *Collection) VisitPodTemplateMeta(visitor func(meta *metav1.ObjectMeta)) {
c.VisitDeployment(func(d *appsv1.Deployment) {
visitor(&d.Spec.Template.ObjectMeta)
})
}
// VisitMetaObject executes the visitor function on all meta.Object resources.
func (c *Collection) VisitMetaObject(visitor func(metav1.Object)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(metav1.Object); ok {
visitor(conv)
}
})
}
// Visit executes the visitor function on all resources.
func (c *Collection) Visit(visitor func(runtime.Object)) {
for _, res := range c.items {
visitor(res)
}
}
// VisitE executes the visitor function on all resources breaking if the visitor function
// returns an error.
func (c *Collection) VisitE(visitor func(runtime.Object) error) error {
for _, res := range c.items {
if err := visitor(res); err != nil {
return err
}
}
return nil
}
// Remove removes the given element from the collection and returns it.
func (c *Collection) Remove(selector func(runtime.Object) bool) runtime.Object {
for idx, res := range c.items {
if selector(res) {
c.items = append(c.items[0:idx], c.items[idx+1:]...)
return res
}
}
return nil
}
func (c *Collection) VisitPodMonitor(visitor func(*monitoringv1.PodMonitor)) {
c.Visit(func(res runtime.Object) {
if conv, ok := res.(*monitoringv1.PodMonitor); ok {
visitor(conv)
}
})
}
func (c *Collection) GetPodMonitor(filter func(*monitoringv1.PodMonitor) bool) *monitoringv1.PodMonitor {
var retValue *monitoringv1.PodMonitor
c.VisitPodMonitor(func(podMonitor *monitoringv1.PodMonitor) {
if filter(podMonitor) {
retValue = podMonitor
}
})
return retValue
}