func List(ctx context.Context, cluster *kubernetes.Cluster, namespace string) (models.AppList, error) {
	if namespace != "" {
		exists, err := organizations.Exists(ctx, cluster, namespace)
		if err != nil {
			return models.AppList{}, err
		}
		if !exists {
			return models.AppList{}, epinioerrors.NamespaceMissingError{Namespace: namespace}
		}
	}
	appRefs, err := ListAppRefs(ctx, cluster, namespace)
	if err != nil {
		return models.AppList{}, err
	}
	result := models.AppList{}
	for _, ref := range appRefs {
		app, err := Lookup(ctx, cluster, ref.Org, ref.Name)
		if err != nil {
			return result, err
		}
		result = append(result, *app)
	}
	return result, nil
}
List returns a list of all available apps in the specified namespace. If no namespace is
specified (empty string) then apps across all namespaces are returned.
package application
import (
	"context"
	"fmt"
	"regexp"
	"sync"
	"github.com/epinio/epinio/deployments"
	"github.com/epinio/epinio/helpers/kubernetes"
	"github.com/epinio/epinio/helpers/kubernetes/tailer"
	"github.com/epinio/epinio/helpers/tracelog"
	"github.com/epinio/epinio/internal/duration"
	"github.com/epinio/epinio/internal/organizations"
	"github.com/epinio/epinio/internal/s3manager"
	"github.com/epinio/epinio/pkg/api/core/v1/models"
	"github.com/pkg/errors"
	epinioappv1 "github.com/epinio/application/api/v1"
	epinioerrors "github.com/epinio/epinio/internal/errors"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/selection"
)
func Create(ctx context.Context, cluster *kubernetes.Cluster, app models.AppRef, username string) error {
	client, err := cluster.ClientApp()
	if err != nil {
		return err
	}
	obj := &epinioappv1.App{
		Spec: epinioappv1.AppSpec{},
	}
	u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
	if err != nil {
		return err
	}
	us := &unstructured.Unstructured{Object: u}
	us.SetAPIVersion("application.epinio.io/v1")
	us.SetKind("App")
	us.SetName(app.Name)
	_, err = client.Namespace(app.Org).Create(ctx, us, metav1.CreateOptions{})
	return err
}
func Get(ctx context.Context, cluster *kubernetes.Cluster, app models.AppRef) (*unstructured.Unstructured, error) {
	client, err := cluster.ClientApp()
	if err != nil {
		return nil, err
	}
	return client.Namespace(app.Org).Get(ctx, app.Name, metav1.GetOptions{})
}
func Exists(ctx context.Context, cluster *kubernetes.Cluster, app models.AppRef) (bool, error) {
	_, err := Get(ctx, cluster, app)
	if err != nil {
		if apierrors.IsNotFound(err) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}
func CurrentlyStaging(ctx context.Context, cluster *kubernetes.Cluster, namespace, appName string) (bool, error) {
	tc, err := cluster.ClientTekton()
	if err != nil {
		return false, err
	}
	client := tc.PipelineRuns(deployments.TektonStagingNamespace)
	l, err := client.List(ctx, metav1.ListOptions{
		LabelSelector: fmt.Sprintf("app.kubernetes.io/name=%s,app.kubernetes.io/part-of=%s", appName, namespace),
	})
	if err != nil {
		return false, err
	}
	for _, pr := range l.Items {
		if pr.Status.CompletionTime == nil {
			return true, nil
		}
	}
	return false, nil
}
func Lookup(ctx context.Context, cluster *kubernetes.Cluster, org, appName string) (*models.App, error) {
	meta := models.NewAppRef(appName, org)
	ok, err := Exists(ctx, cluster, meta)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, nil
	}
	app := meta.App()
	err = fetch(ctx, cluster, app)
	if err != nil {
		app.StatusMessage = err.Error()
		app.Status = models.ApplicationError
	} else {
		err = calculateStatus(ctx, cluster, app)
		if err != nil {
			return app, err
		}
	}
	return app, nil
}
func ListAppRefs(ctx context.Context, cluster *kubernetes.Cluster, namespace string) ([]models.AppRef, error) {
	client, err := cluster.ClientApp()
	if err != nil {
		return nil, err
	}
	list, err := client.Namespace(namespace).List(ctx, metav1.ListOptions{})
	if err != nil {
		return nil, err
	}
	apps := make([]models.AppRef, 0, len(list.Items))
	for _, app := range list.Items {
		apps = append(apps, models.NewAppRef(app.GetName(), app.GetNamespace()))
	}
	return apps, nil
}