in cmd/manager/main.go [130:474]
func main() {
flag.Parse()
if *project == "" || *zone == "" || *images == "" {
log.Fatal("Must provide project, zone and images arguments")
return
}
var testProjectsReal []string
if *testProjects == "" {
testProjectsReal = append(testProjectsReal, *project)
} else {
testProjectsReal = strings.Split(*testProjects, ",")
}
log.Printf("Running in project %s zone %s. Tests will run in projects: %s", *project, *zone, testProjectsReal)
if *gcsPath != "" {
log.Printf("gcs_path set to %s", *gcsPath)
}
var filterRegex *regexp.Regexp
if *filter != "" {
var err error
filterRegex, err = regexp.Compile(*filter)
if err != nil {
log.Fatal("-filter flag not valid:", err)
}
log.Printf("using -filter %s", *filter)
}
var excludeRegex *regexp.Regexp
if *exclude != "" {
var err error
excludeRegex, err = regexp.Compile(*exclude)
if err != nil {
log.Fatal("-exclude flag not valid:", err)
}
log.Printf("using -exclude %s", *exclude)
}
if *testExcludeFilter != "" {
log.Printf("Using -exclude_discrete_tests %s", *testExcludeFilter)
}
if *machineType != "" {
log.Printf("The -machine_type flag is deprecated, please use -x86_shape and -arm64_shape instead. Retaining legacy behavior while this is set.")
*x86Shape = *machineType
*arm64Shape = *machineType
}
var reservationURLSlice []string
if *reservationURLs != "" {
reservationURLSlice = strings.Split(*reservationURLs, ",")
}
// Setup tests.
testPackages := []struct {
name string
setupFunc func(*imagetest.TestWorkflow) error
}{
{
acceleratorconfig.Name,
acceleratorconfig.TestSetup,
},
{
acceleratorrdma.Name,
acceleratorrdma.TestSetup,
},
{
cvm.Name,
cvm.TestSetup,
},
{
livemigrate.Name,
livemigrate.TestSetup,
},
{
suspendresume.Name,
suspendresume.TestSetup,
},
{
networkperf.Name,
networkperf.TestSetup,
},
{
networkinterfacenaming.Name,
networkinterfacenaming.TestSetup,
},
{
loadbalancer.Name,
loadbalancer.TestSetup,
},
{
guestagent.Name,
guestagent.TestSetup,
},
{
hostnamevalidation.Name,
hostnamevalidation.TestSetup,
},
{
imageboot.Name,
imageboot.TestSetup,
},
{
licensevalidation.Name,
licensevalidation.TestSetup,
},
{
network.Name,
network.TestSetup,
},
{
security.Name,
security.TestSetup,
},
{
hotattach.Name,
hotattach.TestSetup,
},
{
lssd.Name,
lssd.TestSetup,
},
{
disk.Name,
disk.TestSetup,
},
{
shapevalidation.Name,
shapevalidation.TestSetup,
},
{
packagemanager.Name,
packagemanager.TestSetup,
},
{
packageupgrade.Name,
packageupgrade.TestSetup,
},
{
packagevalidation.Name,
packagevalidation.TestSetup,
},
{
storageperf.Name,
storageperf.TestSetup,
},
{
ssh.Name,
ssh.TestSetup,
},
{
winrm.Name,
winrm.TestSetup,
},
{
sql.Name,
sql.TestSetup,
},
{
metadata.Name,
metadata.TestSetup,
},
{
oslogin.Name,
oslogin.TestSetup,
},
{
mdsmtls.Name,
mdsmtls.TestSetup,
},
{
mdsroutes.Name,
mdsroutes.TestSetup,
},
{
windowscontainers.Name,
windowscontainers.TestSetup,
},
{
vmspec.Name,
vmspec.TestSetup,
},
{
pluginmanager.Name,
pluginmanager.TestSetup,
},
{
compatmanager.Name,
compatmanager.TestSetup,
},
}
ctx := context.Background()
var computeclient compute.Client
var err error
if *computeEndpointOverride != "" {
log.Printf("Using compute endpoint %q", *computeEndpointOverride)
computeclient, err = compute.NewClient(ctx, option.WithEndpoint(*computeEndpointOverride))
} else {
computeclient, err = compute.NewClient(ctx)
}
if err != nil {
log.Fatalf("Could not create compute client:%v", err)
}
var testWorkflows []*imagetest.TestWorkflow
for _, testPackage := range testPackages {
if filterRegex != nil && !filterRegex.MatchString(testPackage.name) {
continue
}
if excludeRegex != nil && excludeRegex.MatchString(testPackage.name) {
continue
}
for _, image := range strings.Split(*images, ",") {
if !strings.Contains(image, "/") {
// Find the project of the image.
project := ""
for k := range projectMap {
if strings.Contains(k, "sap") {
// sap follows a slightly different naming convention.
imageName := strings.Split(k, "-")[0]
if strings.HasPrefix(image, imageName) && strings.Contains(image, "sap") {
project = projectMap[k]
break
}
}
if strings.HasPrefix(image, k) {
project = projectMap[k]
break
}
}
if project == "" {
log.Fatalf("unknown image %s", image)
}
// Check whether the image is an image family or a specific image version.
isMatch, err := regexp.MatchString(".*v([0-9]+)", image)
if err != nil {
log.Fatalf("failed regex: %v", err)
}
if isMatch {
image = fmt.Sprintf("projects/%s/global/images/%s", project, image)
} else {
image = fmt.Sprintf("projects/%s/global/images/family/%s", project, image)
}
}
log.Printf("Add test workflow for test %s on image %s", testPackage.name, image)
test, err := imagetest.NewTestWorkflow(&imagetest.TestWorkflowOpts{
Client: computeclient,
ComputeEndpointOverride: *computeEndpointOverride,
Name: testPackage.name,
Image: image,
Timeout: *timeout,
Project: *project,
Zone: *zone,
ExcludeFilter: *testExcludeFilter,
X86Shape: *x86Shape,
ARM64Shape: *arm64Shape,
UseReservations: *useReservations,
ReservationURLs: reservationURLSlice,
AcceleratorType: *acceleratorType,
})
if err != nil {
log.Fatalf("Failed to create test workflow: %v", err)
}
testWorkflows = append(testWorkflows, test)
if err := testPackage.setupFunc(test); err != nil {
log.Fatalf("%s.TestSetup for %s failed: %v", testPackage.name, image, err)
}
}
}
if len(testWorkflows) == 0 {
log.Fatalf("No workflows to run!")
}
log.Println("Done with setup")
storageclient, err := storage.NewClient(ctx)
if err != nil {
log.Fatalf("failed to set up storage client: %v", err)
}
if *printwf {
imagetest.PrintTests(ctx, storageclient, testWorkflows, *project, *zone, *gcsPath, *localPath)
return
}
if *validate {
if err := imagetest.ValidateTests(ctx, storageclient, testWorkflows, *project, *zone, *gcsPath, *localPath); err != nil {
log.Printf("Validate failed: %v\n", err)
}
return
}
suites, err := imagetest.RunTests(ctx, storageclient, testWorkflows, *project, *zone, *gcsPath, *localPath, *parallelCount, *parallelStagger, testProjectsReal)
if err != nil {
log.Fatalf("Failed to run tests: %v", err)
}
if *writeLocalArtifacts != "" {
var wg sync.WaitGroup
for _, twf := range testWorkflows {
bkt := strings.TrimSuffix(strings.TrimPrefix(regexp.MustCompile(`gs://[a-z0-9][a-z0-9-_.]{2,62}[a-z0-9]/?`).FindString(twf.GCSPath), "gs://"), "/")
if bkt == "" {
log.Printf("could not find gcs bucket from %s for workflow %s", twf.GCSPath, twf.Name)
continue
}
gcsSubfolder := strings.TrimPrefix(twf.GCSPath, "gs://"+bkt+"/")
wg.Add(1)
go func(bucket, folder, dstDir string) {
defer wg.Done()
if err := downloadFolder(ctx, storageclient, bucket, folder, dstDir); err != nil {
log.Printf("failed to download test artifacts from folder %s in bucket %s to %s: %v\n", folder, bucket, dstDir, err)
}
}(bkt, gcsSubfolder, *writeLocalArtifacts)
}
wg.Wait()
}
bytes, err := xml.MarshalIndent(suites, "", "\t")
if err != nil {
log.Fatalf("failed to marshall result: %v", err)
}
bytes = []byte(fmt.Sprintf("%s%s", xml.Header, bytes))
var outFile *os.File
if artifacts := os.Getenv("ARTIFACTS"); artifacts != "" {
outFile, err = os.Create(artifacts + "/junit.xml")
} else {
outFile, err = os.Create(*outPath)
}
if err != nil {
log.Fatalf("failed to create output file: %v", err)
}
defer outFile.Close()
outFile.Write(bytes)
outFile.Write([]byte{'\n'})
fmt.Printf("%s\n", bytes)
if *setExitStatus && (suites.Errors != 0 || suites.Failures != 0) {
log.Fatalf("test suite has error or failure")
}
}