github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/build/multi-platform.go (about)

     1  package build
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/redhat-appstudio/e2e-tests/pkg/clients/has"
    13  	"github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton"
    14  	"golang.org/x/crypto/ssh"
    15  	v1 "k8s.io/api/core/v1"
    16  
    17  	"github.com/devfile/library/v2/pkg/util"
    18  	. "github.com/onsi/ginkgo/v2"
    19  	. "github.com/onsi/gomega"
    20  	appservice "github.com/redhat-appstudio/application-api/api/v1alpha1"
    21  	buildservice "github.com/redhat-appstudio/build-service/api/v1alpha1"
    22  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
    23  	"github.com/redhat-appstudio/e2e-tests/pkg/framework"
    24  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    25  	pipeline "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/types"
    28  
    29  	"github.com/aws/aws-sdk-go-v2/aws"
    30  	"github.com/aws/aws-sdk-go-v2/config"
    31  	"github.com/aws/aws-sdk-go-v2/service/ec2"
    32  	ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
    33  
    34  	"github.com/IBM/go-sdk-core/v5/core"
    35  	"github.com/IBM/vpc-go-sdk/vpcv1"
    36  )
    37  
    38  const (
    39  	Ec2ArmTag              = "multi-platform-e2e-arm64"
    40  	HostConfig             = "host-config"
    41  	ControllerNamespace    = "multi-platform-controller"
    42  	AwsSecretName          = "awskeys"
    43  	IbmSecretName          = "ibmkey"
    44  	IbmKey                 = "multi-platform-tests"
    45  	SshSecretName          = "sshkeys"
    46  	Ec2User                = "ec2-user"
    47  	AwsRegion              = "us-east-1"
    48  	AwsPlatform            = "linux/arm64"
    49  	DynamicMaxInstances    = "1"
    50  	IbmZUrl                = "https://us-east.iaas.cloud.ibm.com/v1"
    51  	IbmPUrl                = "https://us-south.power-iaas.cloud.ibm.com"
    52  	CRN                    = "crn:v1:bluemix:public:power-iaas:dal10:a/934e118c399b4a28a70afdf2210d708f:8c9ef568-16a5-4aa2-bfd5-946349c9aeac::"
    53  	MultiPlatformSecretKey = "build.appstudio.redhat.com/multi-platform-secret"
    54  	MultiPlatformConfigKey = "build.appstudio.redhat.com/multi-platform-config"
    55  )
    56  
    57  var (
    58  	IbmVpc                       = "us-east-default-vpc"
    59  	multiPlatformProjectGitUrl   = utils.GetEnv("MULTI_PLATFORM_TEST_REPO_URL", "https://github.com/devfile-samples/devfile-sample-go-basic")
    60  	multiPlatformProjectRevision = utils.GetEnv("MULTI_PLATFORM_TEST_REPO_REVISION", "c713067b0e65fb3de50d1f7c457eb51c2ab0dbb0")
    61  	timeout                      = 20 * time.Minute
    62  	interval                     = 10 * time.Second
    63  )
    64  
    65  var _ = framework.MultiPlatformBuildSuiteDescribe("Multi Platform Controller E2E tests", Pending, Label("multi-platform"), func() {
    66  	var f *framework.Framework
    67  	AfterEach(framework.ReportFailure(&f))
    68  	var err error
    69  
    70  	defer GinkgoRecover()
    71  
    72  	Describe("aws host-pool allocation", Label("aws-host-pool"), func() {
    73  
    74  		var testNamespace, applicationName, componentName, multiPlatformSecretName, host, userDir string
    75  		var component *appservice.Component
    76  
    77  		AfterAll(func() {
    78  			// Cleanup aws secet and host-config
    79  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, AwsSecretName)).To(Succeed())
    80  			Expect(f.AsKubeAdmin.CommonController.DeleteConfigMap(HostConfig, ControllerNamespace, true)).To(Succeed())
    81  
    82  			if !CurrentSpecReport().Failed() {
    83  				Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed())
    84  				Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed())
    85  				Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed())
    86  			} else {
    87  				Expect(f.AsKubeAdmin.CommonController.StoreAllPods(testNamespace)).To(Succeed())
    88  				Expect(f.AsKubeAdmin.TektonController.StoreAllPipelineRuns(testNamespace)).To(Succeed())
    89  			}
    90  		})
    91  
    92  		BeforeAll(func() {
    93  
    94  			f, err = framework.NewFramework(utils.GetGeneratedNamespace("multi-platform-host"))
    95  			Expect(err).NotTo(HaveOccurred())
    96  			testNamespace = f.UserNamespace
    97  			Expect(testNamespace).NotTo(BeNil(), "failed to create sandbox user namespace")
    98  
    99  			Expect(err).ShouldNot(HaveOccurred())
   100  
   101  			err = createConfigMapForHostPool(f)
   102  			Expect(err).ShouldNot(HaveOccurred())
   103  
   104  			err = createSecretForHostPool(f)
   105  			Expect(err).ShouldNot(HaveOccurred())
   106  
   107  			err = createBuildPipelineSelector(f, testNamespace, "ARM64")
   108  			Expect(err).ShouldNot(HaveOccurred())
   109  
   110  			component, applicationName, componentName = createApplicationAndComponent(f, testNamespace)
   111  		})
   112  
   113  		When("the Component with multi-platform-build is created", func() {
   114  			It("a PipelineRun is triggered", func() {
   115  				validatePipelineRunIsRunning(f, componentName, applicationName, testNamespace)
   116  			})
   117  
   118  			It("the build-container task from component pipelinerun is buildah-remote", func() {
   119  				_, multiPlatformSecretName = validateBuildContainerTaskIsBuildahRemote(f, componentName, applicationName, testNamespace)
   120  			})
   121  			It("The multi platform secret is populated", func() {
   122  				var secret *v1.Secret
   123  				Eventually(func() error {
   124  					secret, err = f.AsKubeAdmin.CommonController.GetSecret(testNamespace, multiPlatformSecretName)
   125  					if err != nil {
   126  						return err
   127  					}
   128  					return nil
   129  				}, timeout, interval).Should(Succeed(), "timed out when verifying the secret is created")
   130  
   131  				// Get the host and the user directory so we can verify they are cleaned up at the end of the run
   132  				fullHost, present := secret.Data["host"]
   133  				Expect(present).To(BeTrue())
   134  
   135  				userDirTmp, present := secret.Data["user-dir"]
   136  				Expect(present).To(BeTrue())
   137  				userDir = string(userDirTmp)
   138  				hostParts := strings.Split(string(fullHost), "@")
   139  				host = strings.TrimSpace(hostParts[1])
   140  			})
   141  
   142  			It("that PipelineRun completes successfully", func() {
   143  				Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, nil)).To(Succeed())
   144  			})
   145  
   146  			It("test that cleanup happened successfully", func() {
   147  
   148  				// Parse the private key
   149  				signer, err := ssh.ParsePrivateKey([]byte(os.Getenv("MULTI_PLATFORM_AWS_SSH_KEY")))
   150  				if err != nil {
   151  					log.Fatalf("Unable to parse private key: %v", err)
   152  				}
   153  				// SSH configuration using public key authentication
   154  				config := &ssh.ClientConfig{
   155  					User: Ec2User,
   156  					Auth: []ssh.AuthMethod{
   157  						ssh.PublicKeys(signer),
   158  					},
   159  					HostKeyCallback: ssh.InsecureIgnoreHostKey(), // #nosec
   160  				}
   161  				Eventually(func() error {
   162  					client, err := ssh.Dial("tcp", host+":22", config)
   163  					if err != nil {
   164  						return err
   165  					}
   166  					defer client.Close()
   167  
   168  					// Create a new session
   169  					session, err := client.NewSession()
   170  					if err != nil {
   171  						return err
   172  					}
   173  					defer session.Close()
   174  
   175  					// Check if the file exists
   176  					if dirExists(session, userDir) {
   177  						return fmt.Errorf("cleanup not successful, user dir still exists")
   178  					}
   179  					return nil
   180  				}, timeout, interval).Should(Succeed(), "timed out when verifying that the remote host was cleaned up correctly")
   181  			})
   182  		})
   183  	})
   184  	Describe("aws dynamic allocation", Label("aws-dynamic"), func() {
   185  		var testNamespace, applicationName, componentName, multiPlatformSecretName, multiPlatformTaskName, dynamicInstanceTag, instanceId string
   186  		var component *appservice.Component
   187  
   188  		AfterAll(func() {
   189  			// Cleanup aws&ssh secrets and host-config
   190  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, AwsSecretName)).To(Succeed())
   191  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, SshSecretName)).To(Succeed())
   192  			Expect(f.AsKubeAdmin.CommonController.DeleteConfigMap(HostConfig, ControllerNamespace, true)).To(Succeed())
   193  
   194  			//Forcefully remove instance incase it is not removed by multi-platform-controller
   195  			err = terminateAwsInstance(instanceId)
   196  			if err != nil {
   197  				GinkgoWriter.Printf("error terminating instance again: %v", err)
   198  			}
   199  
   200  			if !CurrentSpecReport().Failed() {
   201  				Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed())
   202  				Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed())
   203  				Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed())
   204  			} else {
   205  				Expect(f.AsKubeAdmin.CommonController.StoreAllPods(testNamespace)).To(Succeed())
   206  				Expect(f.AsKubeAdmin.TektonController.StoreAllPipelineRuns(testNamespace)).To(Succeed())
   207  			}
   208  		})
   209  
   210  		BeforeAll(func() {
   211  
   212  			f, err = framework.NewFramework(utils.GetGeneratedNamespace("multi-platform-dynamic"))
   213  			Expect(err).NotTo(HaveOccurred())
   214  			testNamespace = f.UserNamespace
   215  			Expect(testNamespace).NotTo(BeNil(), "failed to create sandbox user namespace")
   216  			Expect(err).ShouldNot(HaveOccurred())
   217  
   218  			dynamicInstanceTag := "dynamic-instance-" + util.GenerateRandomString(4)
   219  			GinkgoWriter.Printf("Generated dynamic instance tag: %q\n", dynamicInstanceTag)
   220  
   221  			// Restart multi-platform-controller pod to reload configMap again
   222  			restartMultiPlatformControllerPod(f)
   223  
   224  			err = createConfigMapForDynamicInstance(f, dynamicInstanceTag)
   225  			Expect(err).ShouldNot(HaveOccurred())
   226  
   227  			err = createSecretsForDynamicInstance(f)
   228  			Expect(err).ShouldNot(HaveOccurred())
   229  
   230  			err = createBuildPipelineSelector(f, testNamespace, "ARM64")
   231  			Expect(err).ShouldNot(HaveOccurred())
   232  
   233  			component, applicationName, componentName = createApplicationAndComponent(f, testNamespace)
   234  		})
   235  
   236  		When("the Component with multi-platform-build is created", func() {
   237  			It("a PipelineRun is triggered", func() {
   238  				validatePipelineRunIsRunning(f, componentName, applicationName, testNamespace)
   239  			})
   240  
   241  			It("the build-container task from component pipelinerun is buildah-remote", func() {
   242  				multiPlatformTaskName, multiPlatformSecretName = validateBuildContainerTaskIsBuildahRemote(f, componentName, applicationName, testNamespace)
   243  			})
   244  
   245  			It("The multi platform secret is populated", func() {
   246  				instanceId = validateMultiPlatformSecretIsPopulated(f, testNamespace, multiPlatformTaskName, multiPlatformSecretName)
   247  			})
   248  
   249  			It("that PipelineRun completes successfully", func() {
   250  				Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, nil)).To(Succeed())
   251  			})
   252  
   253  			It("check cleanup happened successfully", func() {
   254  				Eventually(func() error {
   255  					instances, err := getDynamicAwsInstance(dynamicInstanceTag)
   256  					if err != nil {
   257  						return err
   258  					}
   259  					if len(instances) != 0 {
   260  						return fmt.Errorf("instance is not cleaned up properly, current running instances: %v", instances)
   261  					}
   262  					return nil
   263  				}, timeout, interval).Should(Succeed(), "timed out when verifying that the remote host was cleaned up correctly")
   264  			})
   265  
   266  		})
   267  	})
   268  	// TODO: Enable the test after https://issues.redhat.com/browse/KFLUXBUGS-1179 is fixed
   269  	Describe("ibm system z dynamic allocation", Label("ibmz-dynamic"), Pending, func() {
   270  		var testNamespace, applicationName, componentName, multiPlatformSecretName, multiPlatformTaskName, dynamicInstanceTag, instanceId string
   271  		var component *appservice.Component
   272  
   273  		AfterAll(func() {
   274  			//Cleanup ibm&ssh secrets and host-config
   275  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, IbmSecretName)).To(Succeed())
   276  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, SshSecretName)).To(Succeed())
   277  			Expect(f.AsKubeAdmin.CommonController.DeleteConfigMap(HostConfig, ControllerNamespace, true)).To(Succeed())
   278  
   279  			//Forcefully remove instance incase it is not removed by multi-platform-controller
   280  			err = terminateIbmZInstance(instanceId)
   281  			if err != nil {
   282  				GinkgoWriter.Printf("error terminating instance again: %v", err)
   283  			}
   284  
   285  			if !CurrentSpecReport().Failed() {
   286  				Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed())
   287  				Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed())
   288  				Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed())
   289  			} else {
   290  				Expect(f.AsKubeAdmin.CommonController.StoreAllPods(testNamespace)).To(Succeed())
   291  				Expect(f.AsKubeAdmin.TektonController.StoreAllPipelineRuns(testNamespace)).To(Succeed())
   292  			}
   293  		})
   294  
   295  		BeforeAll(func() {
   296  
   297  			f, err = framework.NewFramework(utils.GetGeneratedNamespace("multi-platform-ibmz"))
   298  			Expect(err).NotTo(HaveOccurred())
   299  			testNamespace = f.UserNamespace
   300  			Expect(testNamespace).NotTo(BeNil(), "failed to create sandbox user namespace")
   301  			Expect(err).ShouldNot(HaveOccurred())
   302  
   303  			restartMultiPlatformControllerPod(f)
   304  
   305  			dynamicInstanceTag = "ibmz-instance-" + util.GenerateRandomString(4)
   306  			err = createConfigMapForIbmZDynamicInstance(f, dynamicInstanceTag)
   307  			Expect(err).ShouldNot(HaveOccurred())
   308  
   309  			err = createSecretsForIbmDynamicInstance(f)
   310  			Expect(err).ShouldNot(HaveOccurred())
   311  
   312  			err = createBuildPipelineSelector(f, testNamespace, "S390X")
   313  			Expect(err).ShouldNot(HaveOccurred())
   314  
   315  			component, applicationName, componentName = createApplicationAndComponent(f, testNamespace)
   316  		})
   317  
   318  		When("the Component with multi-platform-build is created", func() {
   319  			It("a PipelineRun is triggered", func() {
   320  				validatePipelineRunIsRunning(f, componentName, applicationName, testNamespace)
   321  			})
   322  
   323  			It("the build-container task from component pipelinerun is buildah-remote", func() {
   324  				multiPlatformTaskName, multiPlatformSecretName = validateBuildContainerTaskIsBuildahRemote(f, componentName, applicationName, testNamespace)
   325  			})
   326  
   327  			It("The multi platform secret is populated", func() {
   328  				instanceId = validateMultiPlatformSecretIsPopulated(f, testNamespace, multiPlatformTaskName, multiPlatformSecretName)
   329  			})
   330  
   331  			It("that PipelineRun completes successfully", func() {
   332  				Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, nil)).To(Succeed())
   333  			})
   334  
   335  			It("check cleanup happened successfully", func() {
   336  				Eventually(func() error {
   337  					instances, err := getIbmZDynamicInstances(dynamicInstanceTag)
   338  					if err != nil {
   339  						return err
   340  					}
   341  					if len(instances) != 0 {
   342  						return fmt.Errorf("instance is not cleaned up properly, current running instances: %v", instances)
   343  					}
   344  					return nil
   345  				}, timeout, interval).Should(Succeed(), "timed out when verifying that the remote host was cleaned up correctly")
   346  			})
   347  
   348  		})
   349  	})
   350  	// TODO: Enable the test after https://issues.redhat.com/browse/KFLUXBUGS-1179 is fixed
   351  	Describe("ibm power pc dynamic allocation", Label("ibmp-dynamic"), Pending, func() {
   352  		var testNamespace, applicationName, componentName, multiPlatformSecretName, multiPlatformTaskName, dynamicInstanceTag, instanceId string
   353  		var component *appservice.Component
   354  
   355  		AfterAll(func() {
   356  			// Cleanup ibm key & ssh secrets and host-config
   357  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, IbmSecretName)).To(Succeed())
   358  			Expect(f.AsKubeAdmin.CommonController.DeleteSecret(ControllerNamespace, SshSecretName)).To(Succeed())
   359  			Expect(f.AsKubeAdmin.CommonController.DeleteConfigMap(HostConfig, ControllerNamespace, true)).To(Succeed())
   360  
   361  			//Forcefully remove instance incase it is not removed by multi-platform-controller
   362  			err = terminateIbmPInstance(instanceId)
   363  			if err != nil {
   364  				GinkgoWriter.Printf("error terminating instance again: %v", err)
   365  			}
   366  
   367  			if !CurrentSpecReport().Failed() {
   368  				Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed())
   369  				Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed())
   370  				Expect(f.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(testNamespace)).To(Succeed())
   371  			} else {
   372  				Expect(f.AsKubeAdmin.CommonController.StoreAllPods(testNamespace)).To(Succeed())
   373  				Expect(f.AsKubeAdmin.TektonController.StoreAllPipelineRuns(testNamespace)).To(Succeed())
   374  			}
   375  		})
   376  
   377  		BeforeAll(func() {
   378  
   379  			f, err = framework.NewFramework(utils.GetGeneratedNamespace("multi-platform-ibmp"))
   380  			Expect(err).NotTo(HaveOccurred())
   381  			testNamespace = f.UserNamespace
   382  			Expect(testNamespace).NotTo(BeNil(), "failed to create sandbox user namespace")
   383  			Expect(err).ShouldNot(HaveOccurred())
   384  
   385  			// Restart multi-platform-controller pod to reload configMap again
   386  			restartMultiPlatformControllerPod(f)
   387  
   388  			dynamicInstanceTag = "ibmp-instance-" + util.GenerateRandomString(4)
   389  			err = createConfigMapForIbmPDynamicInstance(f, dynamicInstanceTag)
   390  			Expect(err).ShouldNot(HaveOccurred())
   391  
   392  			err = createSecretsForIbmDynamicInstance(f)
   393  			Expect(err).ShouldNot(HaveOccurred())
   394  
   395  			err = createBuildPipelineSelector(f, testNamespace, "PPC64LE")
   396  			Expect(err).ShouldNot(HaveOccurred())
   397  
   398  			component, applicationName, componentName = createApplicationAndComponent(f, testNamespace)
   399  		})
   400  
   401  		When("the Component with multi-platform-build is created", func() {
   402  			It("a PipelineRun is triggered", func() {
   403  				validatePipelineRunIsRunning(f, componentName, applicationName, testNamespace)
   404  			})
   405  
   406  			It("the build-container task from component pipelinerun is buildah-remote", func() {
   407  				multiPlatformTaskName, multiPlatformSecretName = validateBuildContainerTaskIsBuildahRemote(f, componentName, applicationName, testNamespace)
   408  			})
   409  
   410  			It("The multi platform secret is populated", func() {
   411  				instanceId = validateMultiPlatformSecretIsPopulated(f, testNamespace, multiPlatformTaskName, multiPlatformSecretName)
   412  			})
   413  
   414  			It("that PipelineRun completes successfully", func() {
   415  				Expect(f.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, nil)).To(Succeed())
   416  			})
   417  
   418  			It("check cleanup happened successfully", func() {
   419  				Eventually(func() error {
   420  					count, err := getIbmPDynamicInstanceCount(dynamicInstanceTag)
   421  					if err != nil {
   422  						return err
   423  					}
   424  					if count != 0 {
   425  						return fmt.Errorf("instance is not cleaned up properly, running instances count: %d", count)
   426  					}
   427  					return nil
   428  				}, timeout, interval).Should(Succeed(), "timed out when verifying that the remote host was cleaned up correctly")
   429  			})
   430  
   431  		})
   432  	})
   433  })
   434  
   435  func createApplicationAndComponent(f *framework.Framework, testNamespace string) (component *appservice.Component, applicationName, componentName string) {
   436  	applicationName = fmt.Sprintf("multi-platform-suite-application-%s", util.GenerateRandomString(4))
   437  	_, err := f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace)
   438  	Expect(err).NotTo(HaveOccurred())
   439  
   440  	componentName = fmt.Sprintf("multi-platform-suite-component-%s", util.GenerateRandomString(4))
   441  
   442  	// Create a component with Git Source URL being defined
   443  	componentObj := appservice.ComponentSpec{
   444  		ComponentName: componentName,
   445  		Source: appservice.ComponentSource{
   446  			ComponentSourceUnion: appservice.ComponentSourceUnion{
   447  				GitSource: &appservice.GitSource{
   448  					URL:      multiPlatformProjectGitUrl,
   449  					Revision: multiPlatformProjectRevision,
   450  				},
   451  			},
   452  		},
   453  	}
   454  	component, err = f.AsKubeAdmin.HasController.CreateComponent(componentObj, testNamespace, "", "", applicationName, true, map[string]string{})
   455  	Expect(err).ShouldNot(HaveOccurred())
   456  	return
   457  }
   458  
   459  func validateMultiPlatformSecretIsPopulated(f *framework.Framework, testNamespace, multiPlatformTaskName, multiPlatformSecretName string) (instanceId string) {
   460  	Eventually(func() error {
   461  		_, err := f.AsKubeAdmin.CommonController.GetSecret(testNamespace, multiPlatformSecretName)
   462  		if err != nil {
   463  			return err
   464  		}
   465  		return nil
   466  	}, timeout, interval).Should(Succeed(), "timed out when verifying the secret is created")
   467  
   468  	// Get the instance id from the task so that we can check during cleanup
   469  	taskRun, err := f.AsKubeDeveloper.TektonController.GetTaskRun(multiPlatformTaskName, testNamespace)
   470  	Expect(err).ShouldNot(HaveOccurred())
   471  	instanceId = taskRun.Annotations["build.appstudio.redhat.com/cloud-instance-id"]
   472  	GinkgoWriter.Printf("INSTANCE ID: %s\n", instanceId)
   473  	Expect(instanceId).ShouldNot(BeEmpty())
   474  	return
   475  }
   476  
   477  func validateBuildContainerTaskIsBuildahRemote(f *framework.Framework, componentName, applicationName, testNamespace string) (multiPlatformTaskName, multiPlatformSecretName string) {
   478  	Eventually(func() error {
   479  		pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "")
   480  		Expect(err).ShouldNot(HaveOccurred())
   481  
   482  		for _, chr := range pr.Status.ChildReferences {
   483  			taskRun := &pipeline.TaskRun{}
   484  			taskRunKey := types.NamespacedName{Namespace: pr.Namespace, Name: chr.Name}
   485  			err := f.AsKubeAdmin.CommonController.KubeRest().Get(context.TODO(), taskRunKey, taskRun)
   486  			Expect(err).ShouldNot(HaveOccurred())
   487  
   488  			prTrStatus := &pipeline.PipelineRunTaskRunStatus{
   489  				PipelineTaskName: chr.PipelineTaskName,
   490  				Status:           &taskRun.Status,
   491  			}
   492  
   493  			if chr.PipelineTaskName == constants.BuildTaskRunName && prTrStatus.Status != nil && prTrStatus.Status.TaskSpec != nil && prTrStatus.Status.TaskSpec.Volumes != nil {
   494  				multiPlatformTaskName = chr.Name
   495  				for _, vol := range prTrStatus.Status.TaskSpec.Volumes {
   496  					if vol.Secret != nil && strings.HasPrefix(vol.Secret.SecretName, "multi-platform-ssh-") {
   497  						multiPlatformSecretName = vol.Secret.SecretName
   498  						return nil
   499  					}
   500  				}
   501  			}
   502  		}
   503  		return fmt.Errorf("couldn't find a matching step buildah-remote or ssh secret attached as a volume in the task %s in PipelineRun %s/%s", constants.BuildTaskRunName, testNamespace, pr.GetName())
   504  	}, timeout, interval).Should(Succeed(), "timed out when verifying the buildah-remote image reference in pipelinerun")
   505  	return
   506  }
   507  
   508  func validatePipelineRunIsRunning(f *framework.Framework, componentName, applicationName, testNamespace string) {
   509  	Eventually(func() error {
   510  		pr, err := f.AsKubeAdmin.HasController.GetComponentPipelineRun(componentName, applicationName, testNamespace, "")
   511  		if err != nil {
   512  			GinkgoWriter.Printf("PipelineRun has not been created yet for the component %s/%s", testNamespace, componentName)
   513  			return err
   514  		}
   515  		if !pr.HasStarted() {
   516  			return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pr.GetNamespace(), pr.GetName())
   517  		}
   518  		return nil
   519  	}, timeout, constants.PipelineRunPollingInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the PipelineRun to start for the component %s/%s", testNamespace, componentName))
   520  }
   521  
   522  func restartMultiPlatformControllerPod(f *framework.Framework) {
   523  	// Restart multi-platform-controller pod to reload configMap again
   524  	podList, err := f.AsKubeAdmin.CommonController.ListAllPods(ControllerNamespace)
   525  	Expect(err).ShouldNot(HaveOccurred())
   526  	for i := range podList.Items {
   527  		podName := podList.Items[i].Name
   528  		if strings.HasPrefix(podName, ControllerNamespace) {
   529  			err := f.AsKubeAdmin.CommonController.DeletePod(podName, ControllerNamespace)
   530  			Expect(err).ShouldNot(HaveOccurred())
   531  		}
   532  	}
   533  	time.Sleep(10 * time.Second)
   534  	//check that multi-platform-controller pod is running
   535  	Eventually(func() (bool, error) {
   536  		podList, err := f.AsKubeAdmin.CommonController.ListAllPods(ControllerNamespace)
   537  		if err != nil {
   538  			return false, err
   539  		}
   540  		for i := range podList.Items {
   541  			podName := podList.Items[i].Name
   542  			if strings.HasPrefix(podName, ControllerNamespace) {
   543  				pod, err := f.AsKubeAdmin.CommonController.GetPod(ControllerNamespace, podName)
   544  				if err != nil {
   545  					return false, err
   546  				}
   547  				if pod.Status.Phase == v1.PodRunning {
   548  					return true, nil
   549  				}
   550  			}
   551  		}
   552  		return false, nil
   553  	}, 1*time.Minute, 5*time.Second).Should(BeTrue(), "timed out while checking if the pod is running")
   554  }
   555  
   556  func pCloudId() string {
   557  	return strings.Split(strings.Split(CRN, "/")[1], ":")[1]
   558  }
   559  
   560  func getIbmPDynamicInstanceCount(instanceTag string) (int, error) {
   561  	apiKey := os.Getenv("MULTI_PLATFORM_IBM_API_KEY")
   562  	serviceOptions := &core.ServiceOptions{
   563  		URL: IbmPUrl,
   564  		Authenticator: &core.IamAuthenticator{
   565  			ApiKey: apiKey,
   566  		},
   567  	}
   568  	baseService, err := core.NewBaseService(serviceOptions)
   569  	if err != nil {
   570  		return 0, err
   571  	}
   572  
   573  	builder := core.NewRequestBuilder(core.GET)
   574  	builder = builder.WithContext(context.Background())
   575  	builder.EnableGzipCompression = baseService.GetEnableGzipCompression()
   576  
   577  	pathParamsMap := map[string]string{
   578  		"cloud": pCloudId(),
   579  	}
   580  	_, err = builder.ResolveRequestURL(IbmPUrl, `/pcloud/v1/cloud-instances/{cloud}/pvm-instances`, pathParamsMap)
   581  	if err != nil {
   582  		return 0, err
   583  	}
   584  	builder.AddHeader("CRN", CRN)
   585  	builder.AddHeader("Accept", "application/json")
   586  
   587  	request, err := builder.Build()
   588  	if err != nil {
   589  		return 0, err
   590  	}
   591  
   592  	var rawResponse map[string]json.RawMessage
   593  	_, err = baseService.Request(request, &rawResponse)
   594  	if err != nil {
   595  		return 0, err
   596  	}
   597  	instancesData := rawResponse["pvmInstances"]
   598  	instances := []json.RawMessage{}
   599  	err = json.Unmarshal(instancesData, &instances)
   600  	if err != nil {
   601  		return 0, err
   602  	}
   603  	count := 0
   604  	type Instance struct {
   605  		ServerName string
   606  	}
   607  	singleInstance := &Instance{}
   608  	for i := range instances {
   609  		err = json.Unmarshal(instances[i], singleInstance)
   610  		if err != nil {
   611  			return 0, err
   612  		}
   613  		if strings.HasPrefix(singleInstance.ServerName, instanceTag) {
   614  			count++
   615  		}
   616  	}
   617  	return count, nil
   618  }
   619  
   620  func terminateIbmPInstance(instanceId string) error {
   621  	apiKey := os.Getenv("MULTI_PLATFORM_IBM_API_KEY")
   622  	serviceOptions := &core.ServiceOptions{
   623  		URL: IbmPUrl,
   624  		Authenticator: &core.IamAuthenticator{
   625  			ApiKey: apiKey,
   626  		},
   627  	}
   628  	baseService, err := core.NewBaseService(serviceOptions)
   629  	if err != nil {
   630  		return err
   631  	}
   632  
   633  	builder := core.NewRequestBuilder(core.DELETE)
   634  	builder = builder.WithContext(context.Background())
   635  	builder.EnableGzipCompression = baseService.GetEnableGzipCompression()
   636  
   637  	pathParamsMap := map[string]string{
   638  		"cloud":           pCloudId(),
   639  		"pvm_instance_id": instanceId,
   640  	}
   641  	_, err = builder.ResolveRequestURL(IbmPUrl, `/pcloud/v1/cloud-instances/{cloud}/pvm-instances/{pvm_instance_id}`, pathParamsMap)
   642  	if err != nil {
   643  		return err
   644  	}
   645  	builder.AddQuery("delete_data_volumes", "true")
   646  	builder.AddHeader("CRN", CRN)
   647  	builder.AddHeader("Accept", "application/json")
   648  
   649  	request, err := builder.Build()
   650  	if err != nil {
   651  		return err
   652  	}
   653  
   654  	var rawResponse map[string]json.RawMessage
   655  	_, err = baseService.Request(request, &rawResponse)
   656  	if err != nil {
   657  		if err.Error() == "pvm-instance not found" {
   658  			return nil
   659  		}
   660  		return err
   661  	}
   662  	return nil
   663  }
   664  func getIbmZDynamicInstances(instanceTag string) ([]string, error) {
   665  	apiKey := os.Getenv("MULTI_PLATFORM_IBM_API_KEY")
   666  	if apiKey == "" {
   667  		return nil, fmt.Errorf("ibm api key is not set")
   668  	}
   669  	// Instantiate the service with an API key based IAM authenticator
   670  	vpcService, err := vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
   671  		URL: IbmZUrl,
   672  		Authenticator: &core.IamAuthenticator{
   673  			ApiKey: apiKey,
   674  		},
   675  	})
   676  	if err != nil {
   677  		return nil, err
   678  	}
   679  	// Lookup VPC
   680  	vpcs, _, err := vpcService.ListVpcs(&vpcv1.ListVpcsOptions{})
   681  	if err != nil {
   682  		return nil, err
   683  	}
   684  	var vpc *vpcv1.VPC
   685  	for i := range vpcs.Vpcs {
   686  		//GinkgoWriter.Println("VPC: " + *vpcs.Vpcs[i].Name)
   687  		if *vpcs.Vpcs[i].Name == IbmVpc {
   688  			vpc = &vpcs.Vpcs[i]
   689  			break
   690  		}
   691  	}
   692  	if vpc == nil {
   693  		return nil, fmt.Errorf("failed to find VPC %s", IbmVpc)
   694  	}
   695  
   696  	instances, _, err := vpcService.ListInstances(&vpcv1.ListInstancesOptions{ResourceGroupID: vpc.ResourceGroup.ID, VPCName: &IbmVpc})
   697  	if err != nil {
   698  		return nil, err
   699  	}
   700  	var instanceIds []string
   701  	for _, instance := range instances.Instances {
   702  		if strings.HasPrefix(*instance.Name, instanceTag) {
   703  			instanceIds = append(instanceIds, *instance.ID)
   704  		}
   705  	}
   706  	return instanceIds, nil
   707  }
   708  
   709  func terminateIbmZInstance(instanceId string) error {
   710  	apiKey := os.Getenv("MULTI_PLATFORM_IBM_API_KEY")
   711  	if apiKey == "" {
   712  		return fmt.Errorf("ibm api key is not set correctly")
   713  	}
   714  	vpcService, err := vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
   715  		URL: IbmZUrl,
   716  		Authenticator: &core.IamAuthenticator{
   717  			ApiKey: apiKey,
   718  		},
   719  	})
   720  	if err != nil {
   721  		return err
   722  	}
   723  	instance, _, err := vpcService.GetInstance(&vpcv1.GetInstanceOptions{ID: &instanceId})
   724  	if err != nil {
   725  		if err.Error() == "Instance not found" {
   726  			return nil
   727  		}
   728  		GinkgoWriter.Printf("failed to delete system z instance, unable to get instance with error: %v\n", err)
   729  		return err
   730  	}
   731  	_, err = vpcService.DeleteInstance(&vpcv1.DeleteInstanceOptions{ID: instance.ID})
   732  	if err != nil {
   733  		GinkgoWriter.Printf("failed to delete system z instance: %v\n", err)
   734  		return err
   735  	}
   736  	return nil
   737  }
   738  
   739  func createConfigMapForIbmZDynamicInstance(f *framework.Framework, instanceTag string) error {
   740  	hostConfig := &v1.ConfigMap{}
   741  	hostConfig.Name = HostConfig
   742  	hostConfig.Namespace = ControllerNamespace
   743  	hostConfig.Labels = map[string]string{MultiPlatformConfigKey: "hosts"}
   744  
   745  	hostConfig.Data = map[string]string{}
   746  	hostConfig.Data["dynamic-platforms"] = "linux/s390x"
   747  	hostConfig.Data["instance-tag"] = instanceTag
   748  	hostConfig.Data["dynamic.linux-s390x.type"] = "ibmz"
   749  	hostConfig.Data["dynamic.linux-s390x.ssh-secret"] = SshSecretName
   750  	hostConfig.Data["dynamic.linux-s390x.secret"] = IbmSecretName
   751  	hostConfig.Data["dynamic.linux-s390x.vpc"] = IbmVpc
   752  	hostConfig.Data["dynamic.linux-s390x.key"] = IbmKey
   753  	hostConfig.Data["dynamic.linux-s390x.subnet"] = "us-east-2-default-subnet"
   754  	hostConfig.Data["dynamic.linux-s390x.image-id"] = "r014-17c957e0-01a1-4f7f-bc24-191f5f10eba8"
   755  	hostConfig.Data["dynamic.linux-s390x.region"] = "us-east-2"
   756  	hostConfig.Data["dynamic.linux-s390x.url"] = IbmZUrl
   757  	hostConfig.Data["dynamic.linux-s390x.profile"] = "bz2-1x4"
   758  	hostConfig.Data["dynamic.linux-s390x.max-instances"] = "1"
   759  
   760  	_, err := f.AsKubeAdmin.CommonController.CreateConfigMap(hostConfig, ControllerNamespace)
   761  	if err != nil {
   762  		return fmt.Errorf("error while creating config map for dynamic instance: %v", err)
   763  	}
   764  	return nil
   765  }
   766  
   767  func createSecretsForIbmDynamicInstance(f *framework.Framework) error {
   768  	ibmKey := v1.Secret{}
   769  	ibmKey.Name = "ibmkey"
   770  	ibmKey.Namespace = ControllerNamespace
   771  	ibmKey.Labels = map[string]string{MultiPlatformSecretKey: "true"}
   772  	ibmKey.StringData = map[string]string{
   773  		"api-key": os.Getenv("MULTI_PLATFORM_IBM_API_KEY"),
   774  	}
   775  	_, err := f.AsKubeAdmin.CommonController.CreateSecret(ControllerNamespace, &ibmKey)
   776  	if err != nil {
   777  		return fmt.Errorf("error creating secret with api_key: %v", err)
   778  	}
   779  
   780  	sshKeys := v1.Secret{}
   781  	sshKeys.Name = SshSecretName
   782  	sshKeys.Namespace = ControllerNamespace
   783  	sshKeys.Labels = map[string]string{MultiPlatformSecretKey: "true"}
   784  	sshKeys.StringData = map[string]string{"id_rsa": os.Getenv("MULTI_PLATFORM_AWS_SSH_KEY")}
   785  	_, err = f.AsKubeAdmin.CommonController.CreateSecret(ControllerNamespace, &sshKeys)
   786  	if err != nil {
   787  		return fmt.Errorf("error creating secret with ssh private key: %v", err)
   788  	}
   789  	return nil
   790  }
   791  
   792  func createConfigMapForIbmPDynamicInstance(f *framework.Framework, instanceTag string) error {
   793  	hostConfig := &v1.ConfigMap{}
   794  	hostConfig.Name = HostConfig
   795  	hostConfig.Namespace = ControllerNamespace
   796  	hostConfig.Labels = map[string]string{MultiPlatformConfigKey: "hosts"}
   797  
   798  	hostConfig.Data = map[string]string{}
   799  	hostConfig.Data["dynamic-platforms"] = "linux/ppc64le"
   800  	hostConfig.Data["instance-tag"] = instanceTag
   801  	hostConfig.Data["dynamic.linux-ppc64le.type"] = "ibmp"
   802  	hostConfig.Data["dynamic.linux-ppc64le.ssh-secret"] = SshSecretName
   803  	hostConfig.Data["dynamic.linux-ppc64le.secret"] = "ibmkey"
   804  	hostConfig.Data["dynamic.linux-ppc64le.key"] = IbmKey
   805  	hostConfig.Data["dynamic.linux-ppc64le.image"] = "sdouglas-rhel-test"
   806  	hostConfig.Data["dynamic.linux-ppc64le.crn"] = CRN
   807  	hostConfig.Data["dynamic.linux-ppc64le.url"] = IbmPUrl
   808  	hostConfig.Data["dynamic.linux-ppc64le.network"] = "dff71085-73da-49f5-9bf2-5ea60c66c99b"
   809  	hostConfig.Data["dynamic.linux-ppc64le.system"] = "e980"
   810  	hostConfig.Data["dynamic.linux-ppc64le.cores"] = "0.25"
   811  	hostConfig.Data["dynamic.linux-ppc64le.memory"] = "2"
   812  	hostConfig.Data["dynamic.linux-ppc64le.max-instances"] = "2"
   813  
   814  	_, err := f.AsKubeAdmin.CommonController.CreateConfigMap(hostConfig, ControllerNamespace)
   815  	if err != nil {
   816  		return fmt.Errorf("error while creating config map for dynamic instance: %v", err)
   817  	}
   818  	return nil
   819  }
   820  
   821  // Function to check if a file exists on the remote host
   822  func dirExists(session *ssh.Session, dirPath string) bool {
   823  	cmd := fmt.Sprintf("[ -d %s ] && echo 'exists'", dirPath)
   824  	output, err := session.CombinedOutput(cmd)
   825  	if err != nil {
   826  		fmt.Fprintf(os.Stderr, "Error running command: %s\n", err)
   827  		return false
   828  	}
   829  	return string(output) == "exists\n"
   830  }
   831  
   832  // Get AWS instances that are running
   833  // These are identified by tag
   834  func getHostPoolAwsInstances() ([]string, error) {
   835  	cfg, err := config.LoadDefaultConfig(context.TODO(),
   836  		config.WithCredentialsProvider(EnvCredentialsProvider{}),
   837  		config.WithRegion(AwsRegion))
   838  	if err != nil {
   839  		return nil, err
   840  	}
   841  
   842  	// Create an EC2 client
   843  	ec2Client := ec2.NewFromConfig(cfg)
   844  	res, err := ec2Client.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{Filters: []ec2types.Filter{{Name: aws.String("tag:" + Ec2ArmTag), Values: []string{"true"}}}})
   845  	if err != nil {
   846  		return nil, err
   847  	}
   848  	ret := []string{}
   849  	for _, res := range res.Reservations {
   850  		for _, inst := range res.Instances {
   851  			if inst.State.Name != ec2types.InstanceStateNameTerminated {
   852  				ret = append(ret, *inst.PublicDnsName)
   853  			}
   854  		}
   855  	}
   856  	return ret, nil
   857  }
   858  
   859  func createConfigMapForHostPool(f *framework.Framework) error {
   860  	armInstances, err := getHostPoolAwsInstances()
   861  	if err != nil {
   862  		return fmt.Errorf("error getting aws host pool instances: %v", err)
   863  	}
   864  	hostConfig := &v1.ConfigMap{}
   865  	hostConfig.Name = HostConfig
   866  	hostConfig.Namespace = ControllerNamespace
   867  	hostConfig.Labels = map[string]string{MultiPlatformConfigKey: "hosts"}
   868  
   869  	hostConfig.Data = map[string]string{}
   870  	count := 0
   871  	for _, instance := range armInstances {
   872  		hostConfig.Data[fmt.Sprintf("host.aws-arm64-%d.address", count)] = instance
   873  		hostConfig.Data[fmt.Sprintf("host.aws-arm64-%d.platform", count)] = AwsPlatform
   874  		hostConfig.Data[fmt.Sprintf("host.aws-arm64-%d.user", count)] = Ec2User
   875  		hostConfig.Data[fmt.Sprintf("host.aws-arm64-%d.secret", count)] = AwsSecretName
   876  		hostConfig.Data[fmt.Sprintf("host.aws-arm64-%d.concurrency", count)] = "4"
   877  		count++
   878  	}
   879  
   880  	_, err = f.AsKubeAdmin.CommonController.CreateConfigMap(hostConfig, ControllerNamespace)
   881  	if err != nil {
   882  		return fmt.Errorf("error creating host-pool config map: %v", err)
   883  	}
   884  	return nil
   885  }
   886  
   887  func createConfigMapForDynamicInstance(f *framework.Framework, instanceTag string) error {
   888  	hostConfig := &v1.ConfigMap{}
   889  	hostConfig.Name = HostConfig
   890  	hostConfig.Namespace = ControllerNamespace
   891  	hostConfig.Labels = map[string]string{MultiPlatformConfigKey: "hosts"}
   892  
   893  	hostConfig.Data = map[string]string{}
   894  	hostConfig.Data["dynamic-platforms"] = AwsPlatform
   895  	hostConfig.Data["instance-tag"] = instanceTag
   896  	hostConfig.Data["dynamic.linux-arm64.type"] = "aws"
   897  	hostConfig.Data["dynamic.linux-arm64.region"] = AwsRegion
   898  	hostConfig.Data["dynamic.linux-arm64.ami"] = "ami-09d5d0912f52f9514"
   899  	hostConfig.Data["dynamic.linux-arm64.instance-type"] = "t4g.micro"
   900  	hostConfig.Data["dynamic.linux-arm64.key-name"] = "multi-platform-e2e"
   901  	hostConfig.Data["dynamic.linux-arm64.aws-secret"] = AwsSecretName
   902  	hostConfig.Data["dynamic.linux-arm64.ssh-secret"] = SshSecretName
   903  	hostConfig.Data["dynamic.linux-arm64.security-group"] = "launch-wizard-7"
   904  	hostConfig.Data["dynamic.linux-arm64.max-instances"] = DynamicMaxInstances
   905  
   906  	_, err := f.AsKubeAdmin.CommonController.CreateConfigMap(hostConfig, ControllerNamespace)
   907  	if err != nil {
   908  		return fmt.Errorf("error while creating config map for dynamic instance: %v", err)
   909  	}
   910  	return nil
   911  }
   912  
   913  func createSecretForHostPool(f *framework.Framework) error {
   914  	keys := v1.Secret{}
   915  	keys.Name = AwsSecretName
   916  	keys.Namespace = ControllerNamespace
   917  	keys.Labels = map[string]string{MultiPlatformSecretKey: "true"}
   918  	keys.StringData = map[string]string{"id_rsa": os.Getenv("MULTI_PLATFORM_AWS_SSH_KEY")}
   919  	_, err := f.AsKubeAdmin.CommonController.CreateSecret(ControllerNamespace, &keys)
   920  	if err != nil {
   921  		return fmt.Errorf("error while creating host-pool secret: %v", err)
   922  	}
   923  	return nil
   924  }
   925  
   926  func createSecretsForDynamicInstance(f *framework.Framework) error {
   927  	awsKeys := v1.Secret{}
   928  	awsKeys.Name = AwsSecretName
   929  	awsKeys.Namespace = ControllerNamespace
   930  	awsKeys.Labels = map[string]string{MultiPlatformSecretKey: "true"}
   931  	awsKeys.StringData = map[string]string{
   932  		"access-key-id":     os.Getenv("MULTI_PLATFORM_AWS_ACCESS_KEY"),
   933  		"secret-access-key": os.Getenv("MULTI_PLATFORM_AWS_SECRET_ACCESS_KEY"),
   934  	}
   935  	_, err := f.AsKubeAdmin.CommonController.CreateSecret(ControllerNamespace, &awsKeys)
   936  	if err != nil {
   937  		return fmt.Errorf("error creating secret with access_key and secret_key: %v", err)
   938  	}
   939  
   940  	sshKeys := v1.Secret{}
   941  	sshKeys.Name = SshSecretName
   942  	sshKeys.Namespace = ControllerNamespace
   943  	sshKeys.Labels = map[string]string{MultiPlatformSecretKey: "true"}
   944  	sshKeys.StringData = map[string]string{"id_rsa": os.Getenv("MULTI_PLATFORM_AWS_SSH_KEY")}
   945  	_, err = f.AsKubeAdmin.CommonController.CreateSecret(ControllerNamespace, &sshKeys)
   946  	if err != nil {
   947  		return fmt.Errorf("error creating secret with ssh private key: %v", err)
   948  	}
   949  	return nil
   950  }
   951  
   952  func createBuildPipelineSelector(f *framework.Framework, namespace string, platform string) error {
   953  	trueBool := true
   954  	customBuildahRemotePipeline := os.Getenv(constants.CUSTOM_BUILDAH_REMOTE_PIPELINE_BUILD_BUNDLE_ENV + "_" + platform)
   955  	Expect(customBuildahRemotePipeline).ShouldNot(BeEmpty())
   956  	if customBuildahRemotePipeline == "" {
   957  		return fmt.Errorf("remote build pipeline bundle is empty")
   958  	}
   959  	ps := &buildservice.BuildPipelineSelector{
   960  		ObjectMeta: metav1.ObjectMeta{
   961  			Name:      "build-pipeline-selector",
   962  			Namespace: namespace,
   963  		},
   964  		Spec: buildservice.BuildPipelineSelectorSpec{Selectors: []buildservice.PipelineSelector{
   965  			{
   966  				Name:           "custom remote-buildah selector",
   967  				PipelineRef:    *tekton.NewBundleResolverPipelineRef("buildah-remote-pipeline", customBuildahRemotePipeline),
   968  				WhenConditions: buildservice.WhenCondition{DockerfileRequired: &trueBool},
   969  			},
   970  		}},
   971  	}
   972  	err := f.AsKubeAdmin.CommonController.KubeRest().Create(context.TODO(), ps)
   973  	if err != nil {
   974  		return fmt.Errorf("error creating build pipeline selector: %v", err)
   975  	}
   976  	return nil
   977  }
   978  
   979  func terminateAwsInstance(instanceId string) error {
   980  	cfg, err := config.LoadDefaultConfig(context.TODO(),
   981  		config.WithCredentialsProvider(EnvCredentialsProvider{}),
   982  		config.WithRegion(AwsRegion))
   983  	if err != nil {
   984  		return err
   985  	}
   986  	// Create an EC2 client
   987  	ec2Client := ec2.NewFromConfig(cfg)
   988  	//Terminate Instance
   989  	_, err = ec2Client.TerminateInstances(context.TODO(), &ec2.TerminateInstancesInput{InstanceIds: []string{string(instanceId)}})
   990  	return err
   991  }
   992  
   993  func getDynamicAwsInstance(tagName string) ([]string, error) {
   994  	cfg, err := config.LoadDefaultConfig(context.TODO(),
   995  		config.WithCredentialsProvider(EnvCredentialsProvider{}),
   996  		config.WithRegion(AwsRegion))
   997  	if err != nil {
   998  		return nil, err
   999  	}
  1000  
  1001  	// Create an EC2 client
  1002  	ec2Client := ec2.NewFromConfig(cfg)
  1003  	res, err := ec2Client.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{Filters: []ec2types.Filter{{Name: aws.String("tag:" + "multi-platform-instance"), Values: []string{tagName}}}})
  1004  	if err != nil {
  1005  		return nil, err
  1006  	}
  1007  	ret := []string{}
  1008  	for _, res := range res.Reservations {
  1009  		for _, inst := range res.Instances {
  1010  			if inst.State.Name != ec2types.InstanceStateNameTerminated {
  1011  				ret = append(ret, *inst.PublicDnsName)
  1012  			}
  1013  		}
  1014  	}
  1015  	return ret, nil
  1016  }
  1017  
  1018  type EnvCredentialsProvider struct {
  1019  }
  1020  
  1021  func (r EnvCredentialsProvider) Retrieve(ctx context.Context) (aws.Credentials, error) {
  1022  	return aws.Credentials{AccessKeyID: os.Getenv("MULTI_PLATFORM_AWS_ACCESS_KEY"), SecretAccessKey: os.Getenv("MULTI_PLATFORM_AWS_SECRET_ACCESS_KEY")}, nil
  1023  }