github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/pkg/utils/gitops/controller.go (about) 1 package gitops 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "net/http" 8 "time" 9 10 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 11 12 routev1 "github.com/openshift/api/route/v1" 13 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 14 kubeCl "github.com/redhat-appstudio/e2e-tests/pkg/apis/kubernetes" 15 managedgitopsv1alpha1 "github.com/redhat-appstudio/managed-gitops/backend/apis/managed-gitops/v1alpha1" 16 appsv1 "k8s.io/api/apps/v1" 17 k8sErrors "k8s.io/apimachinery/pkg/api/errors" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 "k8s.io/apimachinery/pkg/types" 20 "sigs.k8s.io/controller-runtime/pkg/client" 21 ) 22 23 type SuiteController struct { 24 *kubeCl.CustomClient 25 } 26 27 func NewSuiteController(kube *kubeCl.CustomClient) (*SuiteController, error) { 28 return &SuiteController{ 29 kube, 30 }, nil 31 } 32 33 func (h *SuiteController) CreateGitOpsCR(name string, namespace string, repoUrl string, repoPath string, repoRevision string) (*managedgitopsv1alpha1.GitOpsDeployment, error) { 34 gitOpsDeployment := &managedgitopsv1alpha1.GitOpsDeployment{ 35 ObjectMeta: metav1.ObjectMeta{ 36 GenerateName: name, 37 Namespace: namespace, 38 }, 39 Spec: managedgitopsv1alpha1.GitOpsDeploymentSpec{ 40 Source: managedgitopsv1alpha1.ApplicationSource{ 41 RepoURL: repoUrl, 42 Path: repoPath, 43 TargetRevision: repoRevision, 44 }, 45 Type: managedgitopsv1alpha1.GitOpsDeploymentSpecType_Automated, 46 }, 47 } 48 49 err := h.KubeRest().Create(context.TODO(), gitOpsDeployment) 50 if err != nil { 51 return nil, err 52 } 53 return gitOpsDeployment, nil 54 } 55 56 // DeleteGitOpsDeployment deletes an gitops deployment from a given name and namespace 57 func (h *SuiteController) DeleteGitOpsCR(name string, namespace string) error { 58 gitOpsDeployment := &managedgitopsv1alpha1.GitOpsDeployment{ 59 ObjectMeta: metav1.ObjectMeta{ 60 Name: name, 61 Namespace: namespace, 62 }, 63 } 64 return h.KubeRest().Delete(context.TODO(), gitOpsDeployment) 65 } 66 67 // GetGitOpsDeployedImage return the image used by the given component deployment 68 func (h *SuiteController) GetGitOpsDeployedImage(deployment *appsv1.Deployment) (string, error) { 69 if len(deployment.Spec.Template.Spec.Containers) > 0 { 70 return deployment.Spec.Template.Spec.Containers[0].Image, nil 71 } else { 72 return "", fmt.Errorf("error when getting the deployed image") 73 } 74 } 75 76 // Checks that the deployed backend component is actually reachable and returns 200 77 func (h *SuiteController) CheckGitOpsEndpoint(route *routev1.Route, endpoint string) error { 78 if len(route.Spec.Host) > 0 { 79 routeUrl := "https://" + route.Spec.Host + endpoint 80 81 http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} 82 resp, err := http.Get(routeUrl) 83 if err != nil { 84 return err 85 } 86 if resp.StatusCode != 200 { 87 return fmt.Errorf("route responded with '%d' status code", resp.StatusCode) 88 } 89 } else { 90 return fmt.Errorf("route is invalid: '%s'", route.Spec.Host) 91 } 92 93 return nil 94 } 95 96 // Remove all gitopsdeployments from a given namespace. Useful when creating a lot of resources and want to remove all of them 97 func (h *SuiteController) DeleteAllGitOpsDeploymentInASpecificNamespace(namespace string, timeout time.Duration) error { 98 if err := h.KubeRest().DeleteAllOf(context.TODO(), &managedgitopsv1alpha1.GitOpsDeployment{}, client.InNamespace(namespace)); err != nil { 99 return fmt.Errorf("error when deleting gitopsdeployments in %s namespace: %+v", namespace, err) 100 } 101 102 gdList := &managedgitopsv1alpha1.GitOpsDeploymentList{} 103 return utils.WaitUntil(func() (done bool, err error) { 104 if err = h.KubeRest().List(context.Background(), gdList, client.InNamespace(namespace)); err != nil { 105 return false, nil 106 } 107 return len(gdList.Items) == 0, nil 108 }, timeout) 109 } 110 111 /* 112 * CreateEphemeralEnvironment: create an RHTAP environment pointing to a valid Kubernetes/Openshift cluster 113 * Args: 114 * - name: Environment name 115 * - namespace: Namespace where to create the environment. Note: Should be in the same namespace where cluster credential secret it is 116 * - targetNamespace: Cluster namespace where to create Gitops resources 117 * - serverApi: A valid API kubernetes server for a specific Kubernetes/Openshift cluster 118 * - clusterCredentialsSecret: Secret with a valid kubeconfig credentials 119 * - clusterType: Openshift/Kubernetes 120 * - kubeIngressDomain: If clusterType == "Kubernetes", ingressDomain is mandatory and is enforced by the webhook validation 121 */ 122 func (h *SuiteController) CreateEphemeralEnvironment(name string, namespace string, targetNamespace string, serverApi string, clusterCredentialsSecret string, clusterType appservice.ConfigurationClusterType, kubeIngressDomain string) (*appservice.Environment, error) { 123 ephemeralEnvironmentObj := &appservice.Environment{ 124 ObjectMeta: metav1.ObjectMeta{ 125 Name: name, 126 Namespace: namespace, 127 }, 128 Spec: appservice.EnvironmentSpec{ 129 DeploymentStrategy: appservice.DeploymentStrategy_AppStudioAutomated, 130 Configuration: appservice.EnvironmentConfiguration{ 131 Env: []appservice.EnvVarPair{ 132 { 133 Name: "POC", 134 Value: "POC", 135 }, 136 }, 137 }, 138 UnstableConfigurationFields: &appservice.UnstableEnvironmentConfiguration{ 139 ClusterType: clusterType, 140 KubernetesClusterCredentials: appservice.KubernetesClusterCredentials{ 141 TargetNamespace: targetNamespace, 142 APIURL: serverApi, 143 ClusterCredentialsSecret: clusterCredentialsSecret, 144 AllowInsecureSkipTLSVerify: true, 145 }, 146 }, 147 }, 148 } 149 150 if clusterType == appservice.ConfigurationClusterType_Kubernetes { 151 ephemeralEnvironmentObj.Spec.UnstableConfigurationFields.IngressDomain = kubeIngressDomain 152 } 153 154 if err := h.KubeRest().Create(context.TODO(), ephemeralEnvironmentObj); err != nil { 155 if err != nil { 156 if k8sErrors.IsAlreadyExists(err) { 157 environment := &appservice.Environment{} 158 159 err := h.KubeRest().Get(context.TODO(), types.NamespacedName{ 160 Name: name, 161 Namespace: namespace, 162 }, environment) 163 164 return environment, err 165 } else { 166 return nil, err 167 } 168 } 169 } 170 171 return ephemeralEnvironmentObj, nil 172 } 173 174 // CreateEnvironment creates a new environment 175 func (h *SuiteController) CreateEnvironment(name, namespace string) (*appservice.Environment, error) { 176 environment := &appservice.Environment{ 177 ObjectMeta: metav1.ObjectMeta{ 178 Name: name, 179 Namespace: namespace, 180 }, 181 Spec: appservice.EnvironmentSpec{ 182 Configuration: appservice.EnvironmentConfiguration{ 183 Env: []appservice.EnvVarPair{}, 184 }, 185 DeploymentStrategy: appservice.DeploymentStrategy_Manual, 186 DisplayName: name, 187 Type: appservice.EnvironmentType_POC, 188 ParentEnvironment: "non-existent-environment-to-fool-integration-service", 189 }, 190 } 191 192 err := h.KubeRest().Create(context.TODO(), environment) 193 if err != nil { 194 return nil, err 195 } 196 return environment, nil 197 } 198 199 // DeleteAllEnvironmentsInASpecificNamespace removes all environments from a specific namespace. Useful when creating a lot of resources and want to remove all of them 200 func (h *SuiteController) DeleteAllEnvironmentsInASpecificNamespace(namespace string, timeout time.Duration) error { 201 if err := h.KubeRest().DeleteAllOf(context.TODO(), &appservice.Environment{}, client.InNamespace(namespace)); err != nil { 202 return fmt.Errorf("error deleting environments from the namespace %s: %+v", namespace, err) 203 } 204 205 environmentList := &appservice.EnvironmentList{} 206 return utils.WaitUntil(func() (done bool, err error) { 207 if err := h.KubeRest().List(context.Background(), environmentList, &client.ListOptions{Namespace: namespace}); err != nil { 208 return false, nil 209 } 210 return len(environmentList.Items) == 0, nil 211 }, timeout) 212 }