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)
}
}