func ExtractTgz()

in internal/apiclient/bundles.go [121:226]


func ExtractTgz(gcsURL string) (folder string, err error) {
	ctx := context.Background()

	folder, err = os.MkdirTemp("", "integration")
	if err != nil {
		return "", err
	}

	// Parse the GCS URL
	parsedURL, err := url.Parse(gcsURL)
	if err != nil {
		return "", fmt.Errorf("Error parsing GCS URL:", err)
	}
	if parsedURL.Scheme != "gs" {
		return "", fmt.Errorf("Invalid GCS URL scheme. Should be 'gs://'")
	}

	bucketName := parsedURL.Host
	objectName := strings.TrimPrefix(parsedURL.Path, "/")
	fileName := filepath.Base(gcsURL)

	// Create a Google Cloud Storage client
	client, err := storage.NewClient(ctx)
	if err != nil {
		return "", fmt.Errorf("Error creating GCS client:", err)
	}
	defer client.Close()

	// Get a handle to the bucket and the object
	bucket := client.Bucket(bucketName)
	object := bucket.Object(objectName)

	// Create a reader to stream the object's content
	reader, err := object.NewReader(ctx)
	if err != nil {
		return "", fmt.Errorf("Error creating object reader:", err)
	}
	defer reader.Close()

	// Create the local file to save the download
	localFile, err := os.Create(path.Join(folder, fileName))
	if err != nil {
		return "", fmt.Errorf("Error creating local file:", err)
	}
	defer localFile.Close()

	// Download the object and save it to the local file
	if _, err := io.Copy(localFile, reader); err != nil {
		return "", fmt.Errorf("Error downloading object:", err)
	}

	// Open the .tgz file
	file, err := os.Open(path.Join(folder, fileName))
	if err != nil {
		return "", fmt.Errorf("Error opening file:", err)
	}
	defer file.Close() // Ensure file closure

	// Create a gzip reader
	gzipReader, err := gzip.NewReader(file)
	if err != nil {
		return "", fmt.Errorf("Error creating gzip reader:", err)
	}
	defer gzipReader.Close() // Ensure closure

	// Create a tar reader
	tarReader := tar.NewReader(gzipReader)

	// Extract each file from the tar archive
	for {
		header, err := tarReader.Next()
		if err == io.EOF {
			break // End of archive
		}
		if err != nil {
			return "", fmt.Errorf("Error reading tar entry:", err)
		}
		if strings.Contains(header.Name, "..") {
			continue
		}

		// Process the file header
		switch header.Typeflag {
		case tar.TypeDir:
			// Create directory
			if err := os.Mkdir(path.Join(folder, header.Name), 0o755); err != nil {
				return "", fmt.Errorf("Error creating directory:", err)
			}
		case tar.TypeReg:
			// Create output file
			outFile, err := os.Create(path.Join(folder, header.Name))
			if err != nil {
				return "", fmt.Errorf("Error creating file:", err)
			}
			defer outFile.Close()

			// Copy contents from the tar to the output file
			if _, err := io.Copy(outFile, tarReader); err != nil {
				return "", fmt.Errorf("Error writing file:", err)
			}
		default:
			return "", fmt.Errorf("Unsupported type: %b in %s\n", header.Typeflag, header.Name)
		}
	}
	return folder, nil
}