Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add openshift monitoring label to targetNamespace #1530

Merged
merged 1 commit into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 132 additions & 15 deletions pkg/reconciler/common/targetnamespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,150 @@ package common

import (
"context"
"fmt"

"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"knative.dev/pkg/logging"
)

func CreateTargetNamespace(ctx context.Context, labels map[string]string, obj v1alpha1.TektonComponent, kubeClientSet kubernetes.Interface) error {
ownerRef := *metav1.NewControllerRef(obj, obj.GroupVersionKind())
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: obj.GetSpec().GetTargetNamespace(),
Labels: map[string]string{
"operator.tekton.dev/targetNamespace": "true",
},
OwnerReferences: []metav1.OwnerReference{ownerRef},
},
const (
labelKeyTargetNamespace = "operator.tekton.dev/targetNamespace"
)

func ReconcileTargetNamespace(ctx context.Context, labels map[string]string, tektonComponent v1alpha1.TektonComponent, kubeClientSet kubernetes.Interface) error {
// get logger
logger := logging.FromContext(ctx)

logger.Debugw("reconciling target namespace",
"targetNamespace", tektonComponent.GetSpec().GetTargetNamespace(),
)

// ensure only one namespace with the specified targetNamespace label
nsList, err := kubeClientSet.CoreV1().Namespaces().List(ctx, metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=true", labelKeyTargetNamespace)})
if err != nil {
logger.Errorw("error on listing namespaces",
"targetNamespace", tektonComponent.GetSpec().GetTargetNamespace(),
err,
)
return err
}

if len(labels) > 0 {
for key, value := range labels {
namespace.Labels[key] = value
var targetNamespace *corev1.Namespace
namespaceDeletionInProgress := false
for _, namespace := range nsList.Items {
if namespace.Name == tektonComponent.GetSpec().GetTargetNamespace() && namespace.DeletionTimestamp == nil {
_targetNamespace := namespace.DeepCopy()
targetNamespace = _targetNamespace
} else {
// delete irrelevant namespaces
// if deletionTimestamp is not nil, that indicates, the namespace is in deletion state
if namespace.DeletionTimestamp == nil {
if err := kubeClientSet.CoreV1().Namespaces().Delete(ctx, namespace.Name, metav1.DeleteOptions{}); err != nil {
logger.Errorw("error on deleting a namespace",
"namespace", namespace.Name,
err,
)
return err
}
} else {
logger.Infof("'%v' namespace is in deletion state", namespace.Name)
namespaceDeletionInProgress = true
}
}
}

if _, err := kubeClientSet.CoreV1().Namespaces().Create(ctx, namespace, metav1.CreateOptions{}); err != nil {
return err
// if some of the namespaces are in deletion state, requeue and try again on next reconcile cycle
if namespaceDeletionInProgress {
return v1alpha1.REQUEUE_EVENT_AFTER
}

// verify the target namespace exists, now get with targetNamespace name
if targetNamespace == nil {
_targetNamespace, err := kubeClientSet.CoreV1().Namespaces().Get(ctx, tektonComponent.GetSpec().GetTargetNamespace(), metav1.GetOptions{})
if err == nil {
if _targetNamespace.DeletionTimestamp != nil {
logger.Infof("'%v' namespace is in deletion state", tektonComponent.GetSpec().GetTargetNamespace())
return v1alpha1.REQUEUE_EVENT_AFTER
}
targetNamespace = _targetNamespace
} else if !errors.IsNotFound(err) {
return err
}
}

// owner reference used for target namespace
ownerRef := *metav1.NewControllerRef(tektonComponent, tektonComponent.GroupVersionKind())

// update required labels
if labels == nil {
labels = map[string]string{}
}
labels[labelKeyTargetNamespace] = "true" // include target namespace label

// if a namespace found, update the required fields
if targetNamespace != nil {
// verify the existing namespace has the required fields, if not update
updateRequired := false

// update owner reference, if no one is owned
if len(targetNamespace.GetOwnerReferences()) == 0 {
targetNamespace.OwnerReferences = []metav1.OwnerReference{ownerRef}
updateRequired = true
}

// update labels
for expectedLabelKey, expectedLabelValue := range labels {
expectedLabelFound := false
for actualLabelKey, actualLabelValue := range targetNamespace.GetLabels() {
if expectedLabelKey == actualLabelKey && expectedLabelValue == actualLabelValue {
expectedLabelFound = true
break
}
}
// update label if not found
if !expectedLabelFound {
if targetNamespace.Labels == nil {
targetNamespace.Labels = map[string]string{}
}
targetNamespace.Labels[expectedLabelKey] = expectedLabelValue
updateRequired = true
}
}

// update the namespace, if required
if updateRequired {
_, err = kubeClientSet.CoreV1().Namespaces().Update(ctx, targetNamespace, metav1.UpdateOptions{})
if err != nil {
logger.Errorw("error on updating target namespace",
"targetNamespace", tektonComponent.GetSpec().GetTargetNamespace(),
err,
)
}
return err
}

} else {
// create target namespace
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: tektonComponent.GetSpec().GetTargetNamespace(),
Labels: labels,
OwnerReferences: []metav1.OwnerReference{ownerRef},
},
}

if _, err := kubeClientSet.CoreV1().Namespaces().Create(ctx, namespace, metav1.CreateOptions{}); err != nil {
logger.Errorw("error on creating target namespace",
"targetNamespace", tektonComponent.GetSpec().GetTargetNamespace(),
err,
)
return err
}
}

return nil
}
Loading