cos_gpu_driver_builder: Fix precompiled driver output URL parsing and
add dryrun mode

BUG=b/267382645

Change-Id: Id368642cf587c5ac6dc78d239b6e226f3d66831e
Reviewed-on: https://cos-review.googlesource.com/c/cos/tools/+/45747
Tested-by: Arnav Kansal <rnv@google.com>
Cloud-Build: GCB Service account <228075978874@cloudbuild.gserviceaccount.com>
Reviewed-by: He Gao <hegao@google.com>
Reviewed-by: Meena Shanmugam <meenashanmugam@google.com>
diff --git a/src/cmd/cos_gpu_driver_builder/internal/config/configs.go b/src/cmd/cos_gpu_driver_builder/internal/config/configs.go
index d5655d5..80f7567 100644
--- a/src/cmd/cos_gpu_driver_builder/internal/config/configs.go
+++ b/src/cmd/cos_gpu_driver_builder/internal/config/configs.go
@@ -4,6 +4,7 @@
 	"context"
 	"fmt"
 	"log"
+	"net/url"
 	"os"
 	"path/filepath"
 
@@ -18,7 +19,7 @@
 	return fmt.Sprintf("%s/%s", config.ProtoConfig.GetDriverOutputGcsDir(), driverRunfile)
 }
 
-func ProcessConfigs(ctx context.Context, client *storage.Client, configs []gpuconfig.GPUPrecompilationConfig) error {
+func ProcessConfigs(ctx context.Context, client *storage.Client, configs []gpuconfig.GPUPrecompilationConfig, dryRun bool) error {
 	for _, config := range configs {
 		log.Printf("building precompiled GPU driver for %s:%s, driver version %s\n", config.VersionType, config.Version, config.DriverVersion)
 		if processed, _ := gcs.GCSObjectExists(ctx, client, outputDriverFile(config)); processed {
@@ -27,13 +28,21 @@
 		dir, precompiledDriver, err := builder.BuildPrecompiledDriver(ctx, client, config)
 		defer os.RemoveAll(dir)
 		if err != nil {
-			log.Printf("precompilation failed for: %s, driver version %s\n", config.Version, config.DriverVersion)
+			log.Printf("precompilation failed for: %s, driver version %s: %v\n", config.Version, config.DriverVersion, err)
 			continue
 		}
-		outputDriverFile := filepath.Join(config.ProtoConfig.GetDriverOutputGcsDir(), precompiledDriver)
-		if err := gcs.UploadGCSObject(ctx, client, filepath.Join(dir, precompiledDriver), outputDriverFile); err != nil {
-			log.Printf("export failed for: %s, driver version %s\n", config.Version, config.DriverVersion)
-			continue
+		outputURL, err := url.Parse(config.ProtoConfig.GetDriverOutputGcsDir())
+		if err != nil {
+			log.Printf("failed to parse driver output gcs dir: %v\n", err)
+		}
+		outputURL.Path = filepath.Join(outputURL.Path, precompiledDriver)
+		outputDriverFile := outputURL.String()
+		if !dryRun {
+
+			if err := gcs.UploadGCSObject(ctx, client, filepath.Join(dir, precompiledDriver), outputDriverFile); err != nil {
+				log.Printf("export failed for: %s, driver version %s: %v\n", config.Version, config.DriverVersion, err)
+				continue
+			}
 		}
 	}
 	return nil
diff --git a/src/cmd/cos_gpu_driver_builder/main.go b/src/cmd/cos_gpu_driver_builder/main.go
index 2bffd62..fdc93d3 100644
--- a/src/cmd/cos_gpu_driver_builder/main.go
+++ b/src/cmd/cos_gpu_driver_builder/main.go
@@ -17,7 +17,8 @@
 	bucket    = flag.String("watcher-gcs", "", "GCS bucket to watch for unprocessed configs.")
 	lookBack  = flag.Int("lookBackDays", 7, "read configs produced within the past <lookBack> days.")
 	// default to only building image CI precompiled drivers
-	mode = flag.String("mode", "image", "image, kernel, or both for processing image CI/kernel CI configs. Works only with watcher-gcs arg")
+	mode   = flag.String("mode", "image", "image, kernel, or both for processing image CI/kernel CI configs. Works only with watcher-gcs arg")
+	dryRun = flag.Bool("dry-run", false, "invoking the driver builder with -dry-run will not upload any build precompiled outputs")
 )
 
 func main() {
@@ -47,5 +48,5 @@
 		configs = append(configs, config)
 	}
 
-	config.ProcessConfigs(ctx, client, configs)
+	config.ProcessConfigs(ctx, client, configs, *dryRun)
 }