github.com/docker/cnab-to-oci@v0.3.0-beta4/e2e/e2e_test.go (about)

     1  package e2e
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  	"testing"
    12  	"text/template"
    13  
    14  	"gotest.tools/assert"
    15  	"gotest.tools/fs"
    16  	"gotest.tools/golden"
    17  	"gotest.tools/icmd"
    18  )
    19  
    20  func TestPushAndPullCNAB(t *testing.T) {
    21  	dir := fs.NewDir(t, t.Name())
    22  	defer dir.Remove()
    23  	r := startRegistry(t)
    24  	defer r.Stop(t)
    25  	registry := r.GetAddress(t)
    26  
    27  	invocationImageName := registry + "/e2e/hello-world:0.1.0-invoc"
    28  	serviceImageName := registry + "/e2e/http-echo"
    29  	appImageName := registry + "/myuser"
    30  
    31  	// Build invocation image
    32  	cmd := icmd.Command("docker", "build", "-f", filepath.Join("testdata", "hello-world", "invocation-image", "Dockerfile"),
    33  		"-t", invocationImageName, filepath.Join("testdata", "hello-world", "invocation-image"))
    34  	cmd.Env = append(os.Environ(), "DOCKER_BUILDKIT=1")
    35  	runCmd(t, cmd)
    36  
    37  	// Fetch service image
    38  	runCmd(t, icmd.Command("docker", "pull", "hashicorp/http-echo"))
    39  	runCmd(t, icmd.Command("docker", "tag", "hashicorp/http-echo", serviceImageName))
    40  
    41  	// Tidy up my room
    42  	defer func() {
    43  		runCmd(t, icmd.Command("docker", "image", "rm", "-f", invocationImageName, "hashicorp/http-echo", serviceImageName))
    44  	}()
    45  
    46  	// Push the images to the registry
    47  	output := runCmd(t, icmd.Command("docker", "push", invocationImageName))
    48  	invocDigest := getDigest(t, output)
    49  
    50  	runCmd(t, icmd.Command("docker", "push", serviceImageName))
    51  
    52  	// Templatize the bundle
    53  	applyTemplate(t, serviceImageName, invocationImageName, invocDigest, filepath.Join("testdata", "hello-world", "bundle.json.template"), dir.Join("bundle.json"))
    54  
    55  	// Save the fixed bundle
    56  	runCmd(t, icmd.Command("cnab-to-oci", "fixup", dir.Join("bundle.json"),
    57  		"--target", appImageName,
    58  		"--insecure-registries", registry,
    59  		"--bundle", dir.Join("fixed-bundle.json"),
    60  		"--relocation-map", dir.Join("relocation.json"),
    61  		"--auto-update-bundle"))
    62  
    63  	// Check the fixed bundle
    64  	applyTemplate(t, serviceImageName, invocationImageName, invocDigest, filepath.Join("testdata", "bundle.json.golden.template"), filepath.Join("testdata", "bundle.json.golden"))
    65  	buf, err := ioutil.ReadFile(dir.Join("fixed-bundle.json"))
    66  	assert.NilError(t, err)
    67  	golden.Assert(t, string(buf), "bundle.json.golden")
    68  
    69  	// Check the relocation map
    70  	checkRelocationMap(t, serviceImageName, invocationImageName, appImageName, dir.Join("relocation.json"))
    71  
    72  	// Re fix-up, checking it works twice
    73  	runCmd(t, icmd.Command("cnab-to-oci", "fixup", dir.Join("bundle.json"),
    74  		"--target", appImageName,
    75  		"--insecure-registries", registry,
    76  		"--bundle", dir.Join("fixed-bundle.json"),
    77  		"--auto-update-bundle"))
    78  
    79  	// Push the CNAB to the registry and get the digest
    80  	out := runCmd(t, icmd.Command("cnab-to-oci", "push", dir.Join("bundle.json"),
    81  		"--target", appImageName,
    82  		"--insecure-registries", registry,
    83  		"--auto-update-bundle"))
    84  	re := regexp.MustCompile(`"(.*)"`)
    85  	digest := re.FindAllStringSubmatch(out, -1)[0][1]
    86  
    87  	// Pull the CNAB from the registry
    88  	runCmd(t, icmd.Command("cnab-to-oci", "pull", fmt.Sprintf("%s@%s", appImageName, digest),
    89  		"--bundle", dir.Join("pulled-bundle.json"),
    90  		"--relocation-map", dir.Join("pulled-relocation.json"),
    91  		"--insecure-registries", registry))
    92  	pulledBundle, err := ioutil.ReadFile(dir.Join("pulled-bundle.json"))
    93  	assert.NilError(t, err)
    94  	pulledRelocation, err := ioutil.ReadFile(dir.Join("pulled-relocation.json"))
    95  	assert.NilError(t, err)
    96  
    97  	// Check the fixed bundle.json is equal to the pulled bundle.json
    98  	golden.Assert(t, string(pulledBundle), dir.Join("fixed-bundle.json"))
    99  	golden.Assert(t, string(pulledRelocation), dir.Join("relocation.json"))
   100  }
   101  
   102  func runCmd(t *testing.T, cmd icmd.Cmd) string {
   103  	fmt.Println("#", strings.Join(cmd.Command, " "))
   104  	result := icmd.RunCmd(cmd)
   105  	fmt.Println(result.Combined())
   106  	result.Assert(t, icmd.Success)
   107  	return result.Stdout()
   108  }
   109  
   110  func applyTemplate(t *testing.T, serviceImageName, invocationImageName, invocationDigest, templateFile, resultFile string) {
   111  	tmpl, err := template.ParseFiles(templateFile)
   112  	assert.NilError(t, err)
   113  	data := struct {
   114  		InvocationImage  string
   115  		InvocationDigest string
   116  		ServiceImage     string
   117  	}{
   118  		invocationImageName,
   119  		invocationDigest,
   120  		serviceImageName,
   121  	}
   122  	f, err := os.Create(resultFile)
   123  	assert.NilError(t, err)
   124  	defer f.Close()
   125  	err = tmpl.Execute(f, data)
   126  	assert.NilError(t, err)
   127  }
   128  
   129  func checkRelocationMap(t *testing.T, serviceImageName, invocationImageName, appImageName, relocationMapFile string) {
   130  	data, err := ioutil.ReadFile(relocationMapFile)
   131  	assert.NilError(t, err)
   132  	relocationMap := map[string]string{}
   133  	err = json.Unmarshal(data, &relocationMap)
   134  	assert.NilError(t, err)
   135  
   136  	// Check the relocated images are in the app repository
   137  	assert.Assert(t, strings.HasPrefix(relocationMap[serviceImageName], appImageName))
   138  	assert.Assert(t, strings.HasPrefix(relocationMap[invocationImageName], appImageName))
   139  }
   140  
   141  func getDigest(t *testing.T, output string) string {
   142  	re := regexp.MustCompile(`digest: (.+) size:`)
   143  	result := re.FindStringSubmatch(output)
   144  	assert.Equal(t, len(result), 2)
   145  	digest := result[1]
   146  	assert.Assert(t, digest != "")
   147  	return digest
   148  }