@@ -305,53 +305,35 @@ func testDockerAppLifecycle(t *testing.T, useBindMount bool) {
305305 cmd , cleanup := dockerCli .createTestCmd ()
306306 defer cleanup ()
307307 appName := strings .Replace (t .Name (), "/" , "_" , 1 )
308-
309308 tmpDir := fs .NewDir (t , appName )
310309 defer tmpDir .Remove ()
311-
312- cmd .Env = append (cmd .Env , "DOCKER_TARGET_CONTEXT=swarm-target-context" )
313-
314310 // Running a swarm using docker in docker to install the application
315311 // and run the invocation image
316312 swarm := NewContainer ("docker:18.09-dind" , 2375 )
317313 swarm .Start (t )
318314 defer swarm .Stop (t )
315+ initializeDockerAppEnvironment (t , & cmd , tmpDir , swarm , useBindMount )
319316
320- // The dind doesn't have the cnab-app-base image so we save it in order to load it later
321- icmd .RunCommand (dockerCli .path , "save" , fmt .Sprintf ("docker/cnab-app-base:%s" , internal .Version ), "--output" , tmpDir .Join ("cnab-app-base.tar.gz" )).Assert (t , icmd .Success )
322-
323- // We need two contexts:
324- // - one for `docker` so that it connects to the dind swarm created before
325- // - the target context for the invocation image to install within the swarm
326- cmd .Command = dockerCli .Command ("context" , "create" , "swarm-context" , "--docker" , fmt .Sprintf (`"host=tcp://%s"` , swarm .GetAddress (t )), "--default-stack-orchestrator" , "swarm" )
327- icmd .RunCmd (cmd ).Assert (t , icmd .Success )
328-
329- // When creating a context on a Windows host we cannot use
330- // the unix socket but it's needed inside the invocation image.
331- // The workaround is to create a context with an empty host.
332- // This host will default to the unix socket inside the
333- // invocation image
334- host := "host="
335- if ! useBindMount {
336- host += fmt .Sprintf ("tcp://%s" , swarm .GetPrivateAddress (t ))
337- }
338-
339- cmd .Command = dockerCli .Command ("context" , "create" , "swarm-target-context" , "--docker" , host , "--default-stack-orchestrator" , "swarm" )
340- icmd .RunCmd (cmd ).Assert (t , icmd .Success )
341-
342- // Initialize the swarm
343- cmd .Env = append (cmd .Env , "DOCKER_CONTEXT=swarm-context" )
344- cmd .Command = dockerCli .Command ("swarm" , "init" )
345- icmd .RunCmd (cmd ).Assert (t , icmd .Success )
317+ // Install an illformed Docker Application Package
318+ cmd .Command = dockerCli .Command ("app" , "install" , "testdata/simple/simple.dockerapp" , "--set" , "web_port=-1" , "--name" , appName )
319+ icmd .RunCmd (cmd ).Assert (t , icmd.Expected {
320+ ExitCode : 1 ,
321+ Err : "error decoding 'Ports': Invalid hostPort: -1" ,
322+ })
323+ // TODO: List the installation and check the failed status
346324
347- // Load the needed base cnab image into the swarm docker engine
348- cmd .Command = dockerCli .Command ("load" , "--input" , tmpDir .Join ("cnab-app-base.tar.gz" ))
349- icmd .RunCmd (cmd ).Assert (t , icmd .Success )
325+ // Upgrading a failed installation is not allowed
326+ cmd .Command = dockerCli .Command ("app" , "upgrade" , appName )
327+ icmd .RunCmd (cmd ).Assert (t , icmd.Expected {
328+ ExitCode : 1 ,
329+ Err : fmt .Sprintf ("Installation %q has failed and cannot be upgraded, reinstall it using 'docker app install'" , appName ),
330+ })
350331
351- // Install a Docker Application Package
332+ // Install a Docker Application Package with an existing failed installation is fine
352333 cmd .Command = dockerCli .Command ("app" , "install" , "testdata/simple/simple.dockerapp" , "--name" , appName )
353334 checkContains (t , icmd .RunCmd (cmd ).Assert (t , icmd .Success ).Combined (),
354335 []string {
336+ fmt .Sprintf ("WARNING: installing over previously failed installation %q" , appName ),
355337 fmt .Sprintf ("Creating network %s_back" , appName ),
356338 fmt .Sprintf ("Creating network %s_front" , appName ),
357339 fmt .Sprintf ("Creating service %s_db" , appName ),
@@ -368,6 +350,13 @@ func testDockerAppLifecycle(t *testing.T, useBindMount bool) {
368350 fmt .Sprintf ("[[:alnum:]]+ %s_api replicated [0-1]/1 python:3.6" , appName ),
369351 })
370352
353+ // Installing again the same application is forbidden
354+ cmd .Command = dockerCli .Command ("app" , "install" , "testdata/simple/simple.dockerapp" , "--name" , appName )
355+ icmd .RunCmd (cmd ).Assert (t , icmd.Expected {
356+ ExitCode : 1 ,
357+ Err : fmt .Sprintf ("Installation %q already exists, use 'docker app upgrade' instead" , appName ),
358+ })
359+
371360 // Upgrade the application, changing the port
372361 cmd .Command = dockerCli .Command ("app" , "upgrade" , appName , "--set" , "web_port=8081" )
373362 checkContains (t , icmd .RunCmd (cmd ).Assert (t , icmd .Success ).Combined (),
@@ -393,6 +382,41 @@ func testDockerAppLifecycle(t *testing.T, useBindMount bool) {
393382 })
394383}
395384
385+ func initializeDockerAppEnvironment (t * testing.T , cmd * icmd.Cmd , tmpDir * fs.Dir , swarm * Container , useBindMount bool ) {
386+ cmd .Env = append (cmd .Env , "DOCKER_TARGET_CONTEXT=swarm-target-context" )
387+
388+ // The dind doesn't have the cnab-app-base image so we save it in order to load it later
389+ icmd .RunCommand (dockerCli .path , "save" , fmt .Sprintf ("docker/cnab-app-base:%s" , internal .Version ), "--output" , tmpDir .Join ("cnab-app-base.tar.gz" )).Assert (t , icmd .Success )
390+
391+ // We need two contexts:
392+ // - one for `docker` so that it connects to the dind swarm created before
393+ // - the target context for the invocation image to install within the swarm
394+ cmd .Command = dockerCli .Command ("context" , "create" , "swarm-context" , "--docker" , fmt .Sprintf (`"host=tcp://%s"` , swarm .GetAddress (t )), "--default-stack-orchestrator" , "swarm" )
395+ icmd .RunCmd (* cmd ).Assert (t , icmd .Success )
396+
397+ // When creating a context on a Windows host we cannot use
398+ // the unix socket but it's needed inside the invocation image.
399+ // The workaround is to create a context with an empty host.
400+ // This host will default to the unix socket inside the
401+ // invocation image
402+ host := "host="
403+ if ! useBindMount {
404+ host += fmt .Sprintf ("tcp://%s" , swarm .GetPrivateAddress (t ))
405+ }
406+
407+ cmd .Command = dockerCli .Command ("context" , "create" , "swarm-target-context" , "--docker" , host , "--default-stack-orchestrator" , "swarm" )
408+ icmd .RunCmd (* cmd ).Assert (t , icmd .Success )
409+
410+ // Initialize the swarm
411+ cmd .Env = append (cmd .Env , "DOCKER_CONTEXT=swarm-context" )
412+ cmd .Command = dockerCli .Command ("swarm" , "init" )
413+ icmd .RunCmd (* cmd ).Assert (t , icmd .Success )
414+
415+ // Load the needed base cnab image into the swarm docker engine
416+ cmd .Command = dockerCli .Command ("load" , "--input" , tmpDir .Join ("cnab-app-base.tar.gz" ))
417+ icmd .RunCmd (* cmd ).Assert (t , icmd .Success )
418+ }
419+
396420func checkContains (t * testing.T , combined string , expectedLines []string ) {
397421 for _ , expected := range expectedLines {
398422 exp := regexp .MustCompile (expected )
0 commit comments