github.com/docker/app@v0.9.1-beta3.0.20210611140623-a48f773ab002/e2e/compatibility_test.go (about) 1 package e2e 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net/http" 9 "os" 10 "path/filepath" 11 "regexp" 12 "strings" 13 "testing" 14 "time" 15 16 "github.com/opencontainers/go-digest" 17 18 "gotest.tools/assert" 19 "k8s.io/apimachinery/pkg/util/wait" 20 21 "gotest.tools/fs" 22 ) 23 24 const ( 25 pollTimeout = 30 * time.Second 26 ) 27 28 func loadAndTagImage(info dindSwarmAndRegistryInfo, tmpDir *fs.Dir, tag string, url string) error { 29 err := downloadImageTarball(tmpDir.Join("image.tar"), url) 30 if err != nil { 31 return err 32 } 33 34 digest := "" 35 combined := info.dockerCmd("load", "-q", "-i", tmpDir.Join("image.tar")) 36 for _, line := range strings.Split(combined, "\n") { 37 if strings.Contains(line, "sha256:") { 38 digest = strings.Split(line, "sha256:")[1] 39 } 40 } 41 if digest == "" { 42 return errors.New("Image digest not found in docker load's stdout") 43 } 44 45 digest = strings.Trim(digest, " \r\n") 46 info.dockerCmd("tag", digest, tag) 47 48 return nil 49 } 50 51 func downloadImageTarball(filepath string, url string) error { 52 client := http.Client{Timeout: time.Minute * 1} 53 res, err := client.Get(url) 54 if err != nil { 55 return err 56 } 57 defer res.Body.Close() 58 59 // Create the file 60 out, err := os.Create(filepath) 61 if err != nil { 62 return err 63 } 64 defer out.Close() 65 // Write the body to file 66 _, err = io.Copy(out, res.Body) 67 return err 68 } 69 70 func TestBackwardsCompatibilityV1(t *testing.T) { 71 runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) { 72 appName := "app-e2e" 73 74 data, err := ioutil.ReadFile(filepath.Join("testdata", "compatibility", "bundle-v0.9.0.json")) 75 assert.NilError(t, err) 76 // update bundle 77 dg := digest.SHA256.FromBytes(data) 78 bundleDir := filepath.Join(info.configDir, "app", "bundles", "contents", dg.Algorithm().String(), dg.Encoded()) 79 assert.NilError(t, os.MkdirAll(bundleDir, os.FileMode(0777))) 80 assert.NilError(t, ioutil.WriteFile(filepath.Join(bundleDir, "bundle.json"), data, os.FileMode(0644))) 81 metadata := filepath.Join(info.configDir, "app", "bundles", "repositories.json") 82 json := fmt.Sprintf("{\"Repositories\":{\"app-e2e\":{\"app-e2e:v0.9.0\":\"%s\"}}}", dg.String()) 83 assert.NilError(t, ioutil.WriteFile(metadata, []byte(json), 0777)) 84 85 // load images build with an old Docker App version 86 assert.NilError(t, loadAndTagImage(info, info.tmpDir, "app-e2e:0.1.0-invoc", "https://github.com/docker/app-e2e/raw/master/images/v0.9.0/app-e2e-invoc.tar")) 87 assert.NilError(t, loadAndTagImage(info, info.tmpDir, "app-e2e/backend", "https://github.com/docker/app-e2e/raw/master/images/v0.9.0/backend.tar")) 88 assert.NilError(t, loadAndTagImage(info, info.tmpDir, "app-e2e/frontend", "https://github.com/docker/app-e2e/raw/master/images/v0.9.0/frontend.tar")) 89 90 // list images 91 output := info.dockerCmd("app", "image", "ls") 92 checkContains(t, output, []string{appName}) 93 // inspect bundle 94 output = info.dockerCmd("app", "image", "inspect", "app-e2e:v0.9.0", "--pretty") 95 checkContains(t, output, 96 []string{ 97 `name:\s+app-e2e`, 98 `backend\s+1\s+app-e2e/backend`, 99 `frontend\s+1\s+8080\s+app-e2e/frontend`, 100 `ports.frontend\s+8080`, 101 }) 102 103 // render bundle 104 output = info.dockerCmd("app", "image", "render", "app-e2e:v0.9.0") 105 checkContains(t, output, 106 []string{ 107 "image: app-e2e/frontend", 108 "image: app-e2e/backend", 109 "published: 8080", 110 "target: 80", 111 }) 112 113 // Install app 114 output = info.dockerCmd("app", "run", "app-e2e:v0.9.0", "--name", appName) 115 checkContains(t, output, 116 []string{ 117 fmt.Sprintf("Creating service %s_backend", appName), 118 fmt.Sprintf("Creating service %s_frontend", appName), 119 fmt.Sprintf("Creating network %s_default", appName), 120 }) 121 122 // Status check -- poll app list 123 checkStatus := func(lastAction string) { 124 err = wait.Poll(2*time.Second, pollTimeout, func() (bool, error) { 125 output = info.dockerCmd("app", "ls") 126 expectedLines := []string{ 127 `RUNNING APP\s+APP NAME\s+SERVICES\s+LAST ACTION\s+RESULT\s+CREATED\s+MODIFIED\s+REFERENCE`, 128 fmt.Sprintf(`%s\s+%s \(0.1.0\)\s+2/2\s+%s\s+success\s+.+second[s]?\sago\s+.+second[s]?\sago\s+`, appName, appName, lastAction), 129 } 130 matches := true 131 for _, expected := range expectedLines { 132 exp := regexp.MustCompile(expected) 133 matches = matches && exp.MatchString(output) 134 } 135 return matches, nil 136 }) 137 assert.NilError(t, err) 138 } 139 140 queryService := func(port string) { 141 err = wait.Poll(2*time.Second, pollTimeout, func() (bool, error) { 142 // Check the frontend service responds 143 url := `http://localhost:` + port 144 output = info.execCmd("/usr/bin/wget", "-O", "-", url) 145 return strings.Contains(output, `Hi there, I love Docker!`), nil 146 }) 147 output = "" 148 if err != nil { 149 output = info.dockerCmd("stack", "ps", appName) 150 } 151 assert.NilError(t, err, output) 152 } 153 154 // Check status on install 155 checkStatus("install") 156 157 // query deployed service 158 queryService("8080") 159 160 // Inspect app 161 output = info.dockerCmd("app", "inspect", appName, "--pretty") 162 checkContains(t, output, 163 []string{ 164 "Running App:", 165 fmt.Sprintf("Name: %s", appName), 166 "Result: success", 167 `ports.frontend: "8080"`, 168 }) 169 170 // Update the application, changing the port 171 output = info.dockerCmd("app", "update", appName, "--set", "ports.frontend=8081") 172 checkContains(t, output, 173 []string{ 174 fmt.Sprintf("Updating service %s_backend", appName), 175 fmt.Sprintf("Updating service %s_frontend", appName), 176 }) 177 178 // check status on upgrade 179 checkStatus("upgrade") 180 181 // Check the frontend service responds on the new port 182 queryService("8081") 183 184 // Uninstall the application 185 output = info.dockerCmd("app", "rm", appName) 186 checkContains(t, output, 187 []string{ 188 fmt.Sprintf("Removing service %s_backend", appName), 189 fmt.Sprintf("Removing service %s_frontend", appName), 190 fmt.Sprintf("Removing network %s_default", appName), 191 }) 192 }) 193 }