github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/pkg/clients/has/applications.go (about)

     1  package has
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	appservice "github.com/redhat-appstudio/application-api/api/v1alpha1"
     9  	"github.com/redhat-appstudio/e2e-tests/pkg/logs"
    10  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    11  	k8sErrors "k8s.io/apimachinery/pkg/api/errors"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	"k8s.io/apimachinery/pkg/types"
    14  	"k8s.io/apimachinery/pkg/util/wait"
    15  	rclient "sigs.k8s.io/controller-runtime/pkg/client"
    16  )
    17  
    18  // GetApplication returns an application given a name and namespace from kubernetes cluster.
    19  func (h *HasController) GetApplication(name string, namespace string) (*appservice.Application, error) {
    20  	application := appservice.Application{
    21  		Spec: appservice.ApplicationSpec{},
    22  	}
    23  	if err := h.KubeRest().Get(context.Background(), types.NamespacedName{Name: name, Namespace: namespace}, &application); err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	return &application, nil
    28  }
    29  
    30  // ApplicationDevfilePresent check if devfile exists in the application status.
    31  func (h *HasController) ApplicationDevfilePresent(application *appservice.Application) wait.ConditionFunc {
    32  	return func() (bool, error) {
    33  		app, err := h.GetApplication(application.Name, application.Namespace)
    34  		if err != nil {
    35  			return false, nil
    36  		}
    37  		application.Status = app.Status
    38  		return application.Status.Devfile != "", nil
    39  	}
    40  }
    41  
    42  // CreateApplication creates an application in the kubernetes cluster with 10 minutes default time for creation.
    43  func (h *HasController) CreateApplication(name string, namespace string) (*appservice.Application, error) {
    44  	return h.CreateApplicationWithTimeout(name, namespace, time.Minute*10)
    45  }
    46  
    47  // CreateHasApplicationWithTimeout creates an application in the kubernetes cluster with a custom default time for creation.
    48  func (h *HasController) CreateApplicationWithTimeout(name string, namespace string, timeout time.Duration) (*appservice.Application, error) {
    49  	application := &appservice.Application{
    50  		ObjectMeta: metav1.ObjectMeta{
    51  			Name:      name,
    52  			Namespace: namespace,
    53  		},
    54  		Spec: appservice.ApplicationSpec{
    55  			DisplayName: name,
    56  		},
    57  	}
    58  
    59  	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*1)
    60  	defer cancel()
    61  	if err := h.KubeRest().Create(ctx, application); err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	if err := utils.WaitUntil(h.ApplicationDevfilePresent(application), timeout); err != nil {
    66  		application = h.refreshApplicationForErrorDebug(application)
    67  		return nil, fmt.Errorf("timed out when waiting for devfile content creation for application %s in %s namespace: %+v. applicattion: %s", name, namespace, err, utils.ToPrettyJSONString(application))
    68  	}
    69  
    70  	return application, nil
    71  }
    72  
    73  // DeleteApplication delete a HAS Application resource from the namespace.
    74  // Optionally, it can avoid returning an error if the resource did not exist:
    75  // - specify 'false', if it's likely the Application has already been deleted (for example, because the Namespace was deleted)
    76  func (h *HasController) DeleteApplication(name string, namespace string, reportErrorOnNotFound bool) error {
    77  	application := appservice.Application{
    78  		ObjectMeta: metav1.ObjectMeta{
    79  			Name:      name,
    80  			Namespace: namespace,
    81  		},
    82  	}
    83  	if err := h.KubeRest().Delete(context.Background(), &application); err != nil {
    84  		if !k8sErrors.IsNotFound(err) || (k8sErrors.IsNotFound(err) && reportErrorOnNotFound) {
    85  			return fmt.Errorf("error deleting an application: %+v", err)
    86  		}
    87  	}
    88  	return utils.WaitUntil(h.ApplicationDeleted(&application), 1*time.Minute)
    89  }
    90  
    91  // ApplicationDeleted check if a given application object was deleted successfully from the kubernetes cluster.
    92  func (h *HasController) ApplicationDeleted(application *appservice.Application) wait.ConditionFunc {
    93  	return func() (bool, error) {
    94  		_, err := h.GetApplication(application.Name, application.Namespace)
    95  		return err != nil && k8sErrors.IsNotFound(err), nil
    96  	}
    97  }
    98  
    99  // DeleteAllApplicationsInASpecificNamespace removes all application CRs from a specific namespace. Useful when creating a lot of resources and want to remove all of them
   100  func (h *HasController) DeleteAllApplicationsInASpecificNamespace(namespace string, timeout time.Duration) error {
   101  	if err := h.KubeRest().DeleteAllOf(context.Background(), &appservice.Application{}, rclient.InNamespace(namespace)); err != nil {
   102  		return fmt.Errorf("error deleting applications from the namespace %s: %+v", namespace, err)
   103  	}
   104  
   105  	return utils.WaitUntil(func() (done bool, err error) {
   106  		applicationList, err := h.ListAllApplications(namespace)
   107  		if err != nil {
   108  			return false, nil
   109  		}
   110  		return len(applicationList.Items) == 0, nil
   111  	}, timeout)
   112  }
   113  
   114  // refreshApplicationForErrorDebug return the latest application object from the kubernetes cluster.
   115  func (h *HasController) refreshApplicationForErrorDebug(application *appservice.Application) *appservice.Application {
   116  	retApp := &appservice.Application{}
   117  
   118  	if err := h.KubeRest().Get(context.Background(), rclient.ObjectKeyFromObject(application), retApp); err != nil {
   119  		return application
   120  	}
   121  
   122  	return retApp
   123  }
   124  
   125  // ListAllApplications returns a list of all Applications in a given namespace.
   126  func (h *HasController) ListAllApplications(namespace string) (*appservice.ApplicationList, error) {
   127  	applicationList := &appservice.ApplicationList{}
   128  	err := h.KubeRest().List(context.Background(), applicationList, &rclient.ListOptions{Namespace: namespace})
   129  
   130  	return applicationList, err
   131  }
   132  
   133  // StoreApplication stores a given Application as an artifact.
   134  func (h *HasController) StoreApplication(application *appservice.Application) error {
   135  	return logs.StoreResourceYaml(application, "application-"+application.Name)
   136  }
   137  
   138  // StoreAllApplications stores all Applications in a given namespace.
   139  func (h *HasController) StoreAllApplications(namespace string) error {
   140  	applicationList, err := h.ListAllApplications(namespace)
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	for _, application := range applicationList.Items {
   146  		if err := h.StoreApplication(&application); err != nil {
   147  			return err
   148  		}
   149  	}
   150  	return nil
   151  }