func ProvisionImages()

in internal/acceptance/acceptance.go [597:695]


func ProvisionImages(t *testing.T) (ImageContext, func()) {
	t.Helper()

	if err := checktools.Installed(); err != nil {
		t.Fatalf("Error checking tools: %v", err)
	}
	if err := checktools.PackVersion(); err != nil {
		t.Fatalf("Error checking pack version: %v", err)
	}

	builderName := generateRandomImageName(builderPrefix)
	if builderImage != "" {
		t.Logf("Testing existing builder image: %s", builderImage)
		if pullImages {
			if _, err := runOutput("docker", "pull", builderImage); err != nil {
				t.Fatalf("Error pulling %s: %v", builderImage, err)
			}
		}
		// Pack cache is based on builder name; retag with a unique name.
		if _, err := runOutput("docker", "tag", builderImage, builderName); err != nil {
			t.Fatalf("Error tagging %s as %s: %v", builderImage, builderName, err)
		}
		runName, cleanUpRun, err := provisionRunImageFromBuilder(builderName)
		if err != nil {
			t.Fatalf("Error provisioning run image for builder %q: %v", builderName, err)
		}
		stackID, err := getImageStackID(builderName)
		if err != nil {
			t.Fatalf("Getting stack ID from builder %q: %v", builderName, err)
		}
		imageCtx := ImageContext{
			StackID:      stackID,
			BuilderImage: builderName,
			RunImage:     runName,
		}
		return imageCtx, func() {
			cleanUpImage(t, builderName)
			cleanUpRun(t)
		}
	}

	builderLoc, cleanUpBuilder := extractBuilder(t, builderSource)
	config := filepath.Join(builderLoc, "builder.toml")

	if lifecycle != "" {
		t.Logf("Using lifecycle location: %s", lifecycle)
		if c, err := updateLifecycle(config, lifecycle); err != nil {
			t.Fatalf("Error updating lifecycle location: %v", err)
		} else {
			config = c
		}
	}

	builderConfig, err := readBuilderTOML(config)
	if err != nil {
		t.Fatalf("Error reading builder.toml: %v", err)
	}
	// Pull images once in the beginning to prevent them from changing in the middle of testing.
	// The images are intentionally not cleaned up to prevent conflicts across different test targets.
	if pullImages {
		buildName := builderConfig.Stack.BuildImage
		if _, err := runOutput("docker", "pull", buildName); err != nil {
			t.Fatalf("Error pulling %s: %v", buildName, err)
		}
	}
	runName, cleanUpRun, err := provisionRunImageFromTOML(builderConfig)
	if err != nil {
		t.Fatalf("Error provisioning run image: %v", err)
	}

	// Pack command to create the builder.
	args := strings.Fields(fmt.Sprintf("builder create %s --config %s --pull-policy never --verbose --no-color", builderName, config))
	cmd := exec.Command(packBin, args...)

	outFile, errFile, cleanup := outFiles(t, builderName, "pack", "create-builder")
	defer cleanup()
	var outb, errb bytes.Buffer
	cmd.Stdout = io.MultiWriter(outFile, &outb) // pack emits some errors to stdout.
	cmd.Stderr = io.MultiWriter(errFile, &errb) // pack emits buildpack output to stderr.

	start := time.Now()
	t.Logf("Creating builder (logs %s)", filepath.Dir(outFile.Name()))
	if err := cmd.Run(); err != nil {
		t.Fatalf("Error creating builder: %v, logs:\nstdout: %s\nstderr:%s", err, outb.String(), errb.String())
	}
	t.Logf("Successfully created builder: %s (in %s)", builderName, time.Since(start))

	imageCtx := ImageContext{
		StackID:      builderConfig.Stack.ID,
		BuilderImage: builderName,
		RunImage:     runName,
	}

	return imageCtx, func() {
		cleanUpImage(t, builderName)
		cleanUpBuilder()
		cleanUpRun(t)
	}
}