controllers/helper/helper.go (208 lines of code) (raw):

package helper import ( "context" coreerrors "errors" "fmt" "os" "path/filepath" "strconv" "strings" "github.com/pkg/errors" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" gerritApi "github.com/epam/edp-gerrit-operator/v2/api/v1" gerritClient "github.com/epam/edp-gerrit-operator/v2/pkg/client/gerrit" gerritService "github.com/epam/edp-gerrit-operator/v2/pkg/service/gerrit" ) const ( platformType = "PLATFORM_TYPE" watchNamespaceEnvVar = "WATCH_NAMESPACE" debugModeEnvVar = "DEBUG_MODE" inClusterNamespacePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" DefaultRequeueTime = 30 ) // GetWatchNamespace returns the namespace the operator should be watching for changes. func GetWatchNamespace() (string, error) { ns, found := os.LookupEnv(watchNamespaceEnvVar) if !found { return "", fmt.Errorf("%s must be set", watchNamespaceEnvVar) } return ns, nil } // GetDebugMode returns the debug mode value. func GetDebugMode() (bool, error) { mode, found := os.LookupEnv(debugModeEnvVar) if !found { return false, nil } b, err := strconv.ParseBool(mode) if err != nil { return false, fmt.Errorf("failed to parse bool value %q for debug mode: %w", mode, err) } return b, nil } // RunningInCluster check whether the operator is running in cluster or locally. func RunningInCluster() bool { _, err := os.Stat(inClusterNamespacePath) return !os.IsNotExist(err) } func NewTrue() *bool { value := true return &value } func GetPlatformTypeEnv() string { platformType, found := os.LookupEnv(platformType) if !found { panic("Environment variable PLATFORM_TYPE is not defined") } return platformType } func GetExecutableFilePath() (string, error) { executableFilePath, err := os.Executable() if err != nil { return "", fmt.Errorf("failed to get path for the executable that started process: %w", err) } return filepath.Dir(executableFilePath), nil } func FileExists(filename string) bool { info, err := os.Stat(filename) if os.IsNotExist(err) { return false } return !info.IsDir() } func SetOwnerReference(child metaV1.Object, parentType metaV1.TypeMeta, parentObject *metaV1.ObjectMeta) { var listOwnReference []metaV1.OwnerReference ownRef := metaV1.OwnerReference{ APIVersion: parentType.APIVersion, Kind: parentType.Kind, Name: parentObject.Name, UID: parentObject.UID, BlockOwnerDeletion: NewTrue(), Controller: NewTrue(), } listOwnReference = append(listOwnReference, ownRef) child.SetOwnerReferences(listOwnReference) } func IsInstanceOwnerSet(config metaV1.Object) bool { ows := config.GetOwnerReferences() return len(ows) != 0 } func FindCROwnerName(ownerName string) *string { if ownerName == "" { return nil } own := strings.ToLower(ownerName) return &own } func GetInstanceOwner(ctx context.Context, k8sClient client.Client, config metaV1.Object) (*gerritApi.Gerrit, error) { ows := config.GetOwnerReferences() gerritOwner := GetGerritOwner(ows) if gerritOwner == nil { return nil, coreerrors.New("gerrit replication config cr does not have gerrit cr owner references") } nsn := types.NamespacedName{ Namespace: config.GetNamespace(), Name: gerritOwner.Name, } ownerCr := &gerritApi.Gerrit{} if err := k8sClient.Get(ctx, nsn, ownerCr); err != nil { return nil, errors.Wrap(err, "unable to get gerrit owner") } return ownerCr, nil } func GetGerritOwner(references []metaV1.OwnerReference) *metaV1.OwnerReference { for _, el := range references { if el.Kind == "Gerrit" { return &el } } return nil } func GetGerritInstance(ctx context.Context, k8sClient client.Client, ownerName *string, namespace string, ) (*gerritApi.Gerrit, error) { if ownerName == nil { var list gerritApi.GerritList err := k8sClient.List(ctx, &list, &client.ListOptions{Namespace: namespace}) if err != nil { return nil, errors.Wrap(err, "unable to list gerrits") } if len(list.Items) == 0 { return nil, errors.New("no root gerrits found") } return &list.Items[0], nil } var gerritInstance gerritApi.Gerrit if err := k8sClient.Get(ctx, client.ObjectKey{ Namespace: namespace, Name: *ownerName, }, &gerritInstance); err != nil { return nil, errors.Wrap(err, "unable to get gerrit instance") } return &gerritInstance, nil } func ContainsString(slice []string, s string) bool { for _, item := range slice { if item == s { return true } } return false } func RemoveString(slice []string, s string) (result []string) { for _, item := range slice { if item == s { continue } result = append(result, item) } return } func GetGerritClient(ctx context.Context, cl client.Client, instance client.Object, ownerName string, service gerritService.Interface, ) (gerritClient.ClientInterface, error) { if !IsInstanceOwnerSet(instance) { ownerReference := FindCROwnerName(ownerName) gerritInstance, err := GetGerritInstance(ctx, cl, ownerReference, instance.GetNamespace()) if err != nil { return nil, errors.Wrap(err, "unable to get gerrit instance") } SetOwnerReference(instance, gerritInstance.TypeMeta, &gerritInstance.ObjectMeta) if err := cl.Update(ctx, instance); err != nil { return nil, errors.Wrap(err, "unable to update instance owner refs") } } gerritInstance, err := GetInstanceOwner(ctx, cl, instance) if err != nil { return nil, errors.Wrap(err, "unable to get instance owner") } gerritCl, err := service.GetRestClient(gerritInstance) if err != nil { return nil, errors.Wrap(err, "unable to get rest client") } return gerritCl, nil } func TryToDelete(ctx context.Context, k8sClient client.Client, instance client.Object, finalizerName string, deleteFunc func() error, ) error { if instance.GetDeletionTimestamp().IsZero() { finalizers := instance.GetFinalizers() if !ContainsString(finalizers, finalizerName) { finalizers = append(finalizers, finalizerName) instance.SetFinalizers(finalizers) if err := k8sClient.Update(ctx, instance); err != nil { return errors.Wrap(err, "unable to update instance finalizer") } } return nil } if err := deleteFunc(); err != nil { return errors.Wrap(err, "unable to perform delete function") } finalizers := instance.GetFinalizers() finalizers = RemoveString(finalizers, finalizerName) instance.SetFinalizers(finalizers) if err := k8sClient.Update(ctx, instance); err != nil { return errors.Wrap(err, "unable to remove finalizer from instance") } return nil }