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 }