github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/pkg/clients/has/components.go (about) 1 package has 2 3 import ( 4 "context" 5 "fmt" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/devfile/library/v2/pkg/util" 11 . "github.com/onsi/ginkgo/v2" 12 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 13 "github.com/redhat-appstudio/e2e-tests/pkg/clients/tekton" 14 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 15 "github.com/redhat-appstudio/e2e-tests/pkg/logs" 16 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 17 "github.com/redhat-appstudio/e2e-tests/pkg/utils/build" 18 pipeline "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" 19 k8sErrors "k8s.io/apimachinery/pkg/api/errors" 20 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 "k8s.io/apimachinery/pkg/labels" 22 "k8s.io/apimachinery/pkg/types" 23 "k8s.io/apimachinery/pkg/util/wait" 24 "k8s.io/client-go/util/retry" 25 "k8s.io/klog" 26 pointer "k8s.io/utils/ptr" 27 "knative.dev/pkg/apis" 28 rclient "sigs.k8s.io/controller-runtime/pkg/client" 29 "sigs.k8s.io/yaml" 30 ) 31 32 const ( 33 RequiredLabelNotFound = "cannot retrigger PipelineRun - required label %q not found" 34 ) 35 36 // GetComponent return a component object from kubernetes cluster 37 func (h *HasController) GetComponent(name string, namespace string) (*appservice.Component, error) { 38 component := &appservice.Component{} 39 if err := h.KubeRest().Get(context.Background(), types.NamespacedName{Name: name, Namespace: namespace}, component); err != nil { 40 return nil, err 41 } 42 43 return component, nil 44 } 45 46 // GetComponentByApplicationName returns a component from kubernetes cluster given a application name. 47 func (h *HasController) GetComponentByApplicationName(applicationName string, namespace string) (*appservice.Component, error) { 48 components := &appservice.ComponentList{} 49 opts := []rclient.ListOption{ 50 rclient.InNamespace(namespace), 51 } 52 err := h.KubeRest().List(context.Background(), components, opts...) 53 if err != nil { 54 return nil, err 55 } 56 for _, component := range components.Items { 57 if component.Spec.Application == applicationName { 58 return &component, nil 59 } 60 } 61 62 return &appservice.Component{}, fmt.Errorf("no component found %s", utils.GetAdditionalInfo(applicationName, namespace)) 63 } 64 65 // GetComponentPipeline returns the pipeline for a given component labels 66 func (h *HasController) GetComponentPipelineRun(componentName string, applicationName string, namespace, sha string) (*pipeline.PipelineRun, error) { 67 return h.GetComponentPipelineRunWithType(componentName, applicationName, namespace, "", sha) 68 } 69 70 // GetComponentPipeline returns the pipeline for a given component labels with pipeline type within label "pipelines.appstudio.openshift.io/type" ("build", "test") 71 func (h *HasController) GetComponentPipelineRunWithType(componentName string, applicationName string, namespace, pipelineType string, sha string) (*pipeline.PipelineRun, error) { 72 pipelineRunLabels := map[string]string{"appstudio.openshift.io/component": componentName, "appstudio.openshift.io/application": applicationName} 73 if pipelineType != "" { 74 pipelineRunLabels["pipelines.appstudio.openshift.io/type"] = pipelineType 75 } 76 77 if sha != "" { 78 pipelineRunLabels["pipelinesascode.tekton.dev/sha"] = sha 79 } 80 81 list := &pipeline.PipelineRunList{} 82 err := h.KubeRest().List(context.Background(), list, &rclient.ListOptions{LabelSelector: labels.SelectorFromSet(pipelineRunLabels), Namespace: namespace}) 83 84 if err != nil && !k8sErrors.IsNotFound(err) { 85 return nil, fmt.Errorf("error listing pipelineruns in %s namespace: %v", namespace, err) 86 } 87 88 // If we hit any other error, while fetching pipelineRun list 89 if err != nil { 90 return nil, fmt.Errorf("error while trying to get pipelinerun list in %s namespace: %v", namespace, err) 91 } 92 93 if len(list.Items) > 0 { 94 return &list.Items[0], nil 95 } 96 97 return nil, fmt.Errorf("no pipelinerun found for component %s", componentName) 98 } 99 100 // GetAllPipelineRunsForApplication returns the pipelineruns for a given application in the namespace 101 func (h *HasController) GetAllPipelineRunsForApplication(applicationName, namespace string) (*pipeline.PipelineRunList, error) { 102 pipelineRunLabels := map[string]string{"appstudio.openshift.io/application": applicationName} 103 104 list := &pipeline.PipelineRunList{} 105 err := h.KubeRest().List(context.Background(), list, &rclient.ListOptions{LabelSelector: labels.SelectorFromSet(pipelineRunLabels), Namespace: namespace}) 106 107 if err != nil && !k8sErrors.IsNotFound(err) { 108 return nil, fmt.Errorf("error listing pipelineruns in %s namespace: %v", namespace, err) 109 } 110 111 if len(list.Items) > 0 { 112 return list, nil 113 } 114 115 return nil, fmt.Errorf("no pipelinerun found for application %s", applicationName) 116 } 117 118 // Set of options to retrigger pipelineRuns in CI to fight against flakynes 119 type RetryOptions struct { 120 // Indicate how many times a pipelineRun should be retriggered in case of flakines 121 Retries int 122 123 // If is set to true the PipelineRun will be retriggered always in case if pipelinerun fail for any reason. Time to time in RHTAP CI 124 // we see that there are a lot of components which fail with QPS in build-container which cannot be controlled. 125 // By default is false will retrigger a pipelineRun only when meet CouldntGetTask or TaskRunImagePullFailed conditions 126 Always bool 127 } 128 129 // WaitForComponentPipelineToBeFinished waits for a given component PipelineRun to be finished 130 // In case of hitting issues like `TaskRunImagePullFailed` or `CouldntGetTask` it will re-trigger the PLR. 131 // Due to re-trigger mechanism this function can invalidate the related PLR object which might be used later in the test 132 // (by deleting the original PLR and creating a new one in case the PLR fails on one of the attempts). 133 // For that case this function gives an option to pass in a pointer to a related PLR object (`prToUpdate`) which will be updated (with a valid PLR object) before the end of this function 134 // and the PLR object can be then used for making assertions later in the test. 135 // If there's no intention for using the original PLR object later in the test, use `nil` instead of the pointer. 136 func (h *HasController) WaitForComponentPipelineToBeFinished(component *appservice.Component, sha string, t *tekton.TektonController, r *RetryOptions, prToUpdate *pipeline.PipelineRun) error { 137 attempts := 1 138 app := component.Spec.Application 139 pr := &pipeline.PipelineRun{} 140 141 for { 142 err := wait.PollUntilContextTimeout(context.Background(), constants.PipelineRunPollingInterval, 30*time.Minute, true, func(ctx context.Context) (done bool, err error) { 143 pr, err = h.GetComponentPipelineRun(component.GetName(), app, component.GetNamespace(), sha) 144 145 if err != nil { 146 GinkgoWriter.Printf("PipelineRun has not been created yet for the Component %s/%s\n", component.GetNamespace(), component.GetName()) 147 return false, nil 148 } 149 150 GinkgoWriter.Printf("PipelineRun %s reason: %s\n", pr.Name, pr.GetStatusCondition().GetCondition(apis.ConditionSucceeded).GetReason()) 151 152 if !pr.IsDone() { 153 return false, nil 154 } 155 156 if pr.GetStatusCondition().GetCondition(apis.ConditionSucceeded).IsTrue() { 157 return true, nil 158 } 159 160 var prLogs string 161 if err = t.StorePipelineRun(pr); err != nil { 162 GinkgoWriter.Printf("failed to store PipelineRun %s:%s: %s\n", pr.GetNamespace(), pr.GetName(), err.Error()) 163 } 164 if prLogs, err = t.GetPipelineRunLogs(pr.Name, pr.Namespace); err != nil { 165 GinkgoWriter.Printf("failed to get logs for PipelineRun %s:%s: %s\n", pr.GetNamespace(), pr.GetName(), err.Error()) 166 } 167 168 return false, fmt.Errorf(prLogs) 169 }) 170 171 if err != nil { 172 GinkgoWriter.Printf("attempt %d/%d: PipelineRun %q failed: %+v", attempts, r.Retries+1, pr.GetName(), err) 173 // CouldntGetTask: Retry the PipelineRun only in case we hit the known issue https://issues.redhat.com/browse/SRVKP-2749 174 // TaskRunImagePullFailed: Retry in case of https://issues.redhat.com/browse/RHTAPBUGS-985 and https://github.com/tektoncd/pipeline/issues/7184 175 if attempts == r.Retries+1 || (!r.Always && pr.GetStatusCondition().GetCondition(apis.ConditionSucceeded).GetReason() != "CouldntGetTask" && pr.GetStatusCondition().GetCondition(apis.ConditionSucceeded).GetReason() != "TaskRunImagePullFailed") { 176 return err 177 } 178 if err = t.RemoveFinalizerFromPipelineRun(pr, constants.E2ETestFinalizerName); err != nil { 179 return fmt.Errorf("failed to remove the finalizer from pipelinerun %s:%s in order to retrigger it: %+v", pr.GetNamespace(), pr.GetName(), err) 180 } 181 if err = h.PipelineClient().TektonV1().PipelineRuns(pr.GetNamespace()).Delete(context.Background(), pr.GetName(), metav1.DeleteOptions{}); err != nil { 182 return fmt.Errorf("failed to delete PipelineRun %q from %q namespace with error: %v", pr.GetName(), pr.GetNamespace(), err) 183 } 184 if sha, err = h.RetriggerComponentPipelineRun(component, pr); err != nil { 185 return fmt.Errorf("unable to retrigger pipelinerun for component %s:%s: %+v", component.GetNamespace(), component.GetName(), err) 186 } 187 attempts++ 188 } else { 189 break 190 } 191 } 192 193 // If prToUpdate variable was passed to this function, update it with the latest version of the PipelineRun object 194 if prToUpdate != nil { 195 pr.DeepCopyInto(prToUpdate) 196 } 197 198 return nil 199 } 200 201 // Universal method to create a component in the kubernetes clusters. 202 func (h *HasController) CreateComponent(componentSpec appservice.ComponentSpec, namespace string, outputContainerImage string, secret string, applicationName string, skipInitialChecks bool, annotations map[string]string) (*appservice.Component, error) { 203 componentObject := &appservice.Component{ 204 ObjectMeta: metav1.ObjectMeta{ 205 // adding default label because of the BuildPipelineSelector in build test 206 Labels: constants.ComponentDefaultLabel, 207 Name: componentSpec.ComponentName, 208 Namespace: namespace, 209 Annotations: map[string]string{ 210 "skip-initial-checks": strconv.FormatBool(skipInitialChecks), 211 }, 212 }, 213 Spec: componentSpec, 214 } 215 componentObject.Spec.Secret = secret 216 componentObject.Spec.Application = applicationName 217 218 if len(annotations) > 0 { 219 componentObject.Annotations = utils.MergeMaps(componentObject.Annotations, annotations) 220 221 } 222 223 if componentObject.Spec.TargetPort == 0 { 224 componentObject.Spec.TargetPort = 8081 225 } 226 if outputContainerImage != "" { 227 componentObject.Spec.ContainerImage = outputContainerImage 228 } else if componentObject.Annotations["image.redhat.com/generate"] == "" { 229 // Generate default public image repo since nothing is mentioned specifically 230 componentObject.Annotations = utils.MergeMaps(componentObject.Annotations, constants.ImageControllerAnnotationRequestPublicRepo) 231 } 232 233 ctx, cancel := context.WithTimeout(context.Background(), time.Minute*1) 234 defer cancel() 235 if err := h.KubeRest().Create(ctx, componentObject); err != nil { 236 return nil, err 237 } 238 if err := utils.WaitUntil(h.ComponentReady(componentObject), time.Minute*10); err != nil { 239 componentObject = h.refreshComponentForErrorDebug(componentObject) 240 return nil, fmt.Errorf("timed out when waiting for component %s to be ready in %s namespace. component: %s", componentSpec.ComponentName, namespace, utils.ToPrettyJSONString(componentObject)) 241 } 242 243 if utils.WaitUntil(h.CheckForImageAnnotation(componentObject), time.Minute*5) != nil { 244 componentObject = h.refreshComponentForErrorDebug(componentObject) 245 return nil, fmt.Errorf("timed out when waiting for image-controller annotations to be updated on component %s in namespace %s. component: %s", componentSpec.ComponentName, namespace, utils.ToPrettyJSONString(componentObject)) 246 } 247 return componentObject, nil 248 } 249 250 // CreateComponentWithDockerSource creates a component based on container image source. 251 func (h *HasController) CreateComponentWithDockerSource(applicationName, componentName, namespace, gitSourceURL, containerImageSource, outputContainerImage, secret string) (*appservice.Component, error) { 252 component := &appservice.Component{ 253 ObjectMeta: metav1.ObjectMeta{ 254 Name: componentName, 255 Namespace: namespace, 256 }, 257 Spec: appservice.ComponentSpec{ 258 ComponentName: componentName, 259 Application: applicationName, 260 Source: appservice.ComponentSource{ 261 ComponentSourceUnion: appservice.ComponentSourceUnion{ 262 GitSource: &appservice.GitSource{ 263 URL: gitSourceURL, 264 DockerfileURL: containerImageSource, 265 }, 266 }, 267 }, 268 Secret: secret, 269 ContainerImage: outputContainerImage, 270 Replicas: pointer.To[int](1), 271 TargetPort: 8081, 272 Route: "", 273 }, 274 } 275 err := h.KubeRest().Create(context.Background(), component) 276 if err != nil { 277 return nil, err 278 } 279 return component, nil 280 } 281 282 // ScaleDeploymentReplicas scales the replicas of a given deployment 283 func (h *HasController) ScaleComponentReplicas(component *appservice.Component, replicas *int) (*appservice.Component, error) { 284 component.Spec.Replicas = replicas 285 286 err := h.KubeRest().Update(context.Background(), component, &rclient.UpdateOptions{}) 287 if err != nil { 288 return &appservice.Component{}, err 289 } 290 return component, nil 291 } 292 293 // DeleteComponent delete an has component from a given name and namespace 294 func (h *HasController) DeleteComponent(name string, namespace string, reportErrorOnNotFound bool) error { 295 // temporary logs 296 start := time.Now() 297 GinkgoWriter.Printf("Start to delete component '%s' at %s\n", name, start.Format(time.RFC3339)) 298 299 component := appservice.Component{ 300 ObjectMeta: metav1.ObjectMeta{ 301 Name: name, 302 Namespace: namespace, 303 }, 304 } 305 if err := h.KubeRest().Delete(context.Background(), &component); err != nil { 306 if !k8sErrors.IsNotFound(err) || (k8sErrors.IsNotFound(err) && reportErrorOnNotFound) { 307 return fmt.Errorf("error deleting a component: %+v", err) 308 } 309 } 310 311 // RHTAPBUGS-978: temporary timeout to 15min 312 err := utils.WaitUntil(h.ComponentDeleted(&component), 15*time.Minute) 313 314 // temporary logs 315 deletionTime := time.Since(start).Minutes() 316 GinkgoWriter.Printf("Finish to delete component '%s' at %s. It took '%f' minutes\n", name, time.Now().Format(time.RFC3339), deletionTime) 317 318 return err 319 } 320 321 // DeleteAllComponentsInASpecificNamespace removes all component CRs from a specific namespace. Useful when creating a lot of resources and want to remove all of them 322 func (h *HasController) DeleteAllComponentsInASpecificNamespace(namespace string, timeout time.Duration) error { 323 // temporary logs 324 start := time.Now() 325 GinkgoWriter.Println("Start to delete all components in namespace '%s' at %s", namespace, start.String()) 326 327 if err := h.KubeRest().DeleteAllOf(context.Background(), &appservice.Component{}, rclient.InNamespace(namespace)); err != nil { 328 return fmt.Errorf("error deleting components from the namespace %s: %+v", namespace, err) 329 } 330 331 componentList := &appservice.ComponentList{} 332 333 err := utils.WaitUntil(func() (done bool, err error) { 334 if err := h.KubeRest().List(context.Background(), componentList, &rclient.ListOptions{Namespace: namespace}); err != nil { 335 return false, nil 336 } 337 return len(componentList.Items) == 0, nil 338 }, timeout) 339 340 // temporary logs 341 deletionTime := time.Since(start).Minutes() 342 GinkgoWriter.Println("Finish to delete all components in namespace '%s' at %s. It took '%f' minutes", namespace, time.Now().Format(time.RFC3339), deletionTime) 343 344 return err 345 } 346 347 // Waits for a component to be reconciled in the application service. 348 func (h *HasController) ComponentReady(component *appservice.Component) wait.ConditionFunc { 349 return func() (bool, error) { 350 messages, err := h.GetComponentConditionStatusMessages(component.Name, component.Namespace) 351 if err != nil { 352 return false, nil 353 } 354 for _, m := range messages { 355 if strings.Contains(m, "success") { 356 return true, nil 357 } 358 } 359 return false, nil 360 } 361 } 362 363 // Waits for a component until is deleted and if not will return an error 364 func (h *HasController) ComponentDeleted(component *appservice.Component) wait.ConditionFunc { 365 return func() (bool, error) { 366 _, err := h.GetComponent(component.Name, component.Namespace) 367 return err != nil && k8sErrors.IsNotFound(err), nil 368 } 369 } 370 371 // Get the message from the status of a component. Usefull for debugging purposes. 372 func (h *HasController) GetComponentConditionStatusMessages(name, namespace string) (messages []string, err error) { 373 c, err := h.GetComponent(name, namespace) 374 if err != nil { 375 return messages, fmt.Errorf("error getting HAS component: %v", err) 376 } 377 for _, condition := range c.Status.Conditions { 378 messages = append(messages, condition.Message) 379 } 380 return 381 } 382 383 // Universal method to retrigger pipelineruns in kubernetes cluster 384 func (h *HasController) RetriggerComponentPipelineRun(component *appservice.Component, pr *pipeline.PipelineRun) (sha string, err error) { 385 prLabels := pr.GetLabels() 386 // In case of PipelineRun managed by PaC we are able to retrigger the pipeline only 387 // by updating the related branch 388 if prLabels["app.kubernetes.io/managed-by"] == "pipelinesascode.tekton.dev" { 389 var ok bool 390 var repoName, eventType, branchName string 391 pacRepoNameLabelName := "pipelinesascode.tekton.dev/url-repository" 392 pacEventTypeLabelName := "pipelinesascode.tekton.dev/event-type" 393 componentLabelName := "appstudio.openshift.io/component" 394 targetBranchAnnotationName := "build.appstudio.redhat.com/target_branch" 395 396 if repoName, ok = prLabels[pacRepoNameLabelName]; !ok { 397 return "", fmt.Errorf(RequiredLabelNotFound, pacRepoNameLabelName) 398 } 399 if eventType, ok = prLabels[pacEventTypeLabelName]; !ok { 400 return "", fmt.Errorf(RequiredLabelNotFound, pacEventTypeLabelName) 401 } 402 // PipelineRun is triggered from a pull request, need to update the PaC PR source branch 403 if eventType == "pull_request" { 404 if len(prLabels[componentLabelName]) < 1 { 405 return "", fmt.Errorf(RequiredLabelNotFound, componentLabelName) 406 } 407 branchName = constants.PaCPullRequestBranchPrefix + prLabels[componentLabelName] 408 } else { 409 // No straightforward way to get a target branch from PR labels -> using annotation 410 if branchName, ok = pr.GetAnnotations()[targetBranchAnnotationName]; !ok { 411 return "", fmt.Errorf("cannot retrigger PipelineRun - required annotation %q not found", targetBranchAnnotationName) 412 } 413 } 414 file, err := h.Github.CreateFile(repoName, util.GenerateRandomString(5), "test", branchName) 415 if err != nil { 416 return "", fmt.Errorf("failed to retrigger PipelineRun %s in %s namespace: %+v", pr.GetName(), pr.GetNamespace(), err) 417 } 418 sha = file.GetSHA() 419 420 // To retrigger simple build PipelineRun we just need to update the initial build annotation 421 // in Component CR 422 } else { 423 err := retry.RetryOnConflict(retry.DefaultRetry, func() error { 424 component, err := h.GetComponent(component.GetName(), component.GetNamespace()) 425 if err != nil { 426 return fmt.Errorf("failed to get component for PipelineRun %q in %q namespace: %+v", pr.GetName(), pr.GetNamespace(), err) 427 } 428 component.Annotations = utils.MergeMaps(component.Annotations, constants.ComponentTriggerSimpleBuildAnnotation) 429 if err = h.KubeRest().Update(context.Background(), component); err != nil { 430 return fmt.Errorf("failed to update Component %q in %q namespace", component.GetName(), component.GetNamespace()) 431 } 432 return err 433 }) 434 435 if err != nil { 436 return "", err 437 } 438 } 439 watch, err := h.PipelineClient().TektonV1().PipelineRuns(component.GetNamespace()).Watch(context.Background(), metav1.ListOptions{}) 440 if err != nil { 441 return "", fmt.Errorf("error when initiating watch for new PipelineRun after retriggering it for component %s:%s", component.GetNamespace(), component.GetName()) 442 } 443 newPRFound := false 444 for { 445 select { 446 case <-time.After(5 * time.Minute): 447 return "", fmt.Errorf("timed out waiting for new PipelineRun to appear after retriggering it for component %s:%s", component.GetNamespace(), component.GetName()) 448 case event := <-watch.ResultChan(): 449 if event.Object == nil { 450 continue 451 } 452 newPR, ok := event.Object.(*pipeline.PipelineRun) 453 if !ok { 454 continue 455 } 456 if pr.GetGenerateName() == newPR.GetGenerateName() && pr.GetName() != newPR.GetName() { 457 newPRFound = true 458 } 459 } 460 if newPRFound { 461 break 462 } 463 } 464 465 return sha, nil 466 } 467 468 // refreshComponentForErrorDebug returns the latest component object from the kubernetes cluster. 469 func (h *HasController) refreshComponentForErrorDebug(component *appservice.Component) *appservice.Component { 470 retComp := &appservice.Component{} 471 key := rclient.ObjectKeyFromObject(component) 472 err := h.KubeRest().Get(context.Background(), key, retComp) 473 if err != nil { 474 //TODO let's log this somehow, but return the original component obj, as that is better than nothing 475 return component 476 } 477 return retComp 478 } 479 480 func (h *HasController) CheckForImageAnnotation(component *appservice.Component) wait.ConditionFunc { 481 return func() (bool, error) { 482 componentCR, err := h.GetComponent(component.Name, component.Namespace) 483 if err != nil { 484 klog.Errorf("failed to get component %s with error: %+v", component.Name, err) 485 return false, nil 486 } 487 annotations := componentCR.GetAnnotations() 488 return build.IsImageAnnotationPresent(annotations) && build.ImageRepoCreationSucceeded(annotations), nil 489 } 490 } 491 492 // Gets value of a specified annotation in a component 493 func (h *HasController) GetComponentAnnotation(componentName, annotationKey, namespace string) (string, error) { 494 component, err := h.GetComponent(componentName, namespace) 495 if err != nil { 496 return "", fmt.Errorf("error when getting component: %+v", err) 497 } 498 return component.Annotations[annotationKey], nil 499 } 500 501 // Sets annotation in a component 502 func (h *HasController) SetComponentAnnotation(componentName, annotationKey, annotationValue, namespace string) error { 503 component, err := h.GetComponent(componentName, namespace) 504 if err != nil { 505 return fmt.Errorf("error when getting component: %+v", err) 506 } 507 newAnnotations := component.GetAnnotations() 508 newAnnotations[annotationKey] = annotationValue 509 component.SetAnnotations(newAnnotations) 510 err = h.KubeRest().Update(context.Background(), component) 511 if err != nil { 512 return fmt.Errorf("error when updating component: %+v", err) 513 } 514 return nil 515 } 516 517 // StoreComponent stores a given Component as an artifact. 518 func (h *HasController) StoreComponent(component *appservice.Component) error { 519 artifacts := make(map[string][]byte) 520 521 componentConditionStatus, err := h.GetComponentConditionStatusMessages(component.Name, component.Namespace) 522 if err != nil { 523 return err 524 } 525 artifacts["component-condition-status-"+component.Name+".log"] = []byte(strings.Join(componentConditionStatus, "\n")) 526 527 componentYaml, err := yaml.Marshal(component) 528 if err != nil { 529 return err 530 } 531 artifacts["component-"+component.Name+".yaml"] = componentYaml 532 533 if err := logs.StoreArtifacts(artifacts); err != nil { 534 return err 535 } 536 537 return nil 538 } 539 540 // StoreAllComponents stores all Components in a given namespace. 541 func (h *HasController) StoreAllComponents(namespace string) error { 542 componentList := &appservice.ComponentList{} 543 if err := h.KubeRest().List(context.Background(), componentList, &rclient.ListOptions{Namespace: namespace}); err != nil { 544 return err 545 } 546 547 for _, component := range componentList.Items { 548 if err := h.StoreComponent(&component); err != nil { 549 return err 550 } 551 } 552 return nil 553 } 554 555 // specific for tests/remote-secret/image-repository-cr-image-pull-remote-secret.go 556 func (h *HasController) CreateComponentWithoutGenerateAnnotation(componentSpec appservice.ComponentSpec, namespace string, secret string, applicationName string, skipInitialChecks bool) (*appservice.Component, error) { 557 componentObject := &appservice.Component{ 558 ObjectMeta: metav1.ObjectMeta{ 559 // adding default label because of the BuildPipelineSelector in build test 560 Labels: constants.ComponentDefaultLabel, 561 Name: componentSpec.ComponentName, 562 Namespace: namespace, 563 Annotations: map[string]string{ 564 "skip-initial-checks": strconv.FormatBool(skipInitialChecks), 565 }, 566 }, 567 Spec: componentSpec, 568 } 569 componentObject.Spec.Secret = secret 570 componentObject.Spec.Application = applicationName 571 572 if componentObject.Spec.TargetPort == 0 { 573 componentObject.Spec.TargetPort = 8081 574 } 575 576 if err := h.KubeRest().Create(context.Background(), componentObject); err != nil { 577 return nil, err 578 } 579 580 if err := utils.WaitUntil(h.ComponentReady(componentObject), time.Minute*10); err != nil { 581 componentObject = h.refreshComponentForErrorDebug(componentObject) 582 return nil, fmt.Errorf("timed out when waiting for component %s to be ready in %s namespace. component: %s", componentSpec.ComponentName, namespace, utils.ToPrettyJSONString(componentObject)) 583 } 584 585 return componentObject, nil 586 }