github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/integration/push/docker_test.go (about)

     1  package push
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
     5  	"code.cloudfoundry.org/cli/integration/helpers"
     6  
     7  	. "github.com/onsi/ginkgo"
     8  	. "github.com/onsi/gomega"
     9  	. "github.com/onsi/gomega/gbytes"
    10  	. "github.com/onsi/gomega/gexec"
    11  )
    12  
    13  var _ = Describe("pushing a docker image", func() {
    14  	var (
    15  		appName               string
    16  		privateDockerImage    string
    17  		privateDockerUsername string
    18  		privateDockerPassword string
    19  	)
    20  
    21  	BeforeEach(func() {
    22  		appName = helpers.NewAppName()
    23  	})
    24  
    25  	Describe("when the docker image is provided via command line", func() {
    26  		Describe("a public docker image", func() {
    27  			Describe("app existence", func() {
    28  				Context("when the app does not exist", func() {
    29  					It("creates the app", func() {
    30  						session := helpers.CF(PushCommandName, appName, "-o", PublicDockerImage)
    31  						validateDockerPush(session, appName, PublicDockerImage)
    32  					})
    33  				})
    34  
    35  				Context("when the app exists", func() {
    36  					BeforeEach(func() {
    37  						Eventually(helpers.CF(PushCommandName, appName, "-o", PublicDockerImage)).Should(Exit(0))
    38  					})
    39  
    40  					It("updates the app", func() {
    41  						session := helpers.CF(PushCommandName, appName, "-o", PublicDockerImage)
    42  						Eventually(session).Should(Say("Updating app with these attributes\\.\\.\\."))
    43  						Eventually(session).Should(Exit(0))
    44  					})
    45  				})
    46  			})
    47  		})
    48  
    49  		Describe("private docker image with a username", func() {
    50  			BeforeEach(func() {
    51  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
    52  				privateDockerImage, privateDockerUsername, privateDockerPassword = helpers.SkipIfPrivateDockerInfoNotSet()
    53  			})
    54  
    55  			Context("when CF_DOCKER_PASSWORD is set", func() {
    56  				It("push the docker image with those credentials", func() {
    57  					session := helpers.CustomCF(
    58  						helpers.CFEnv{
    59  							EnvVars: map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword},
    60  						},
    61  						PushCommandName,
    62  						appName,
    63  						"--docker-username", privateDockerUsername,
    64  						"--docker-image", privateDockerImage,
    65  					)
    66  					validateDockerPush(session, appName, privateDockerImage)
    67  				})
    68  			})
    69  
    70  			Context("when the CF_DOCKER_PASSWORD is not set", func() {
    71  				var buffer *Buffer
    72  
    73  				BeforeEach(func() {
    74  					buffer = NewBuffer()
    75  					_, err := buffer.Write([]byte(privateDockerPassword + "\n"))
    76  					Expect(err).NotTo(HaveOccurred())
    77  				})
    78  
    79  				It("prompts for the docker password", func() {
    80  					session := helpers.CFWithStdin(buffer,
    81  						PushCommandName,
    82  						appName,
    83  						"--docker-username", privateDockerUsername,
    84  						"--docker-image", privateDockerImage,
    85  					)
    86  
    87  					validateDockerPassword(session, true)
    88  					validateDockerPush(session, appName, privateDockerImage)
    89  				})
    90  			})
    91  		})
    92  	})
    93  
    94  	Describe("docker image in the manifest is provided", func() {
    95  		var appManifest map[string]interface{}
    96  
    97  		BeforeEach(func() {
    98  			appManifest = map[string]interface{}{
    99  				"applications": []map[string]interface{}{
   100  					{
   101  						"name": appName,
   102  						"docker": map[string]string{
   103  							"image": PublicDockerImage,
   104  						},
   105  					},
   106  				},
   107  			}
   108  		})
   109  
   110  		It("uses the docker image when pushing", func() {
   111  			helpers.WithManifest(appManifest, func(manifestDir string) {
   112  				session := helpers.CustomCF(
   113  					helpers.CFEnv{WorkingDirectory: manifestDir},
   114  					PushCommandName,
   115  				)
   116  
   117  				validateDockerPush(session, appName, PublicDockerImage)
   118  			})
   119  		})
   120  
   121  		Context("when buildpack is set", func() {
   122  			BeforeEach(func() {
   123  				appManifest = map[string]interface{}{
   124  					"applications": []map[string]interface{}{
   125  						{
   126  							"name":      appName,
   127  							"buildpack": "some-buildpack",
   128  							"docker": map[string]string{
   129  								"image": PublicDockerImage,
   130  							},
   131  						},
   132  					},
   133  				}
   134  			})
   135  
   136  			It("returns an error", func() {
   137  				helpers.WithManifest(appManifest, func(manifestDir string) {
   138  					session := helpers.CustomCF(
   139  						helpers.CFEnv{WorkingDirectory: manifestDir},
   140  						PushCommandName,
   141  					)
   142  
   143  					Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: docker, buildpack", appName))
   144  					Eventually(session).Should(Exit(1))
   145  				})
   146  			})
   147  		})
   148  
   149  		Context("when path is set", func() {
   150  			BeforeEach(func() {
   151  				appManifest = map[string]interface{}{
   152  					"applications": []map[string]interface{}{
   153  						{
   154  							"name": appName,
   155  							"docker": map[string]string{
   156  								"image": PublicDockerImage,
   157  							},
   158  							"path": "some-path",
   159  						},
   160  					},
   161  				}
   162  			})
   163  
   164  			It("returns an error", func() {
   165  				helpers.WithManifest(appManifest, func(manifestDir string) {
   166  					session := helpers.CustomCF(
   167  						helpers.CFEnv{WorkingDirectory: manifestDir},
   168  						PushCommandName,
   169  					)
   170  
   171  					Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: docker, path", appName))
   172  					Eventually(session).Should(Exit(1))
   173  				})
   174  			})
   175  		})
   176  
   177  		Context("when user is provided in the manifest", func() {
   178  			BeforeEach(func() {
   179  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
   180  				privateDockerImage, privateDockerUsername, privateDockerPassword = helpers.SkipIfPrivateDockerInfoNotSet()
   181  
   182  				appManifest = map[string]interface{}{
   183  					"applications": []map[string]interface{}{
   184  						{
   185  							"name": appName,
   186  							"docker": map[string]string{
   187  								"image":    privateDockerImage,
   188  								"username": privateDockerUsername,
   189  							},
   190  						},
   191  					},
   192  				}
   193  			})
   194  
   195  			Context("when password is provided in the enviornment", func() {
   196  				It("uses the docker image and credentials when pushing", func() {
   197  					helpers.WithManifest(appManifest, func(manifestDir string) {
   198  						session := helpers.CustomCF(
   199  							helpers.CFEnv{
   200  								WorkingDirectory: manifestDir,
   201  								EnvVars:          map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword},
   202  							},
   203  							PushCommandName,
   204  						)
   205  
   206  						validateDockerPassword(session, false)
   207  						validateDockerPush(session, appName, privateDockerImage)
   208  					})
   209  				})
   210  			})
   211  
   212  			Context("when password is not provided in the enviornment", func() {
   213  				It("errors out", func() {
   214  					helpers.WithManifest(appManifest, func(manifestDir string) {
   215  						session := helpers.CustomCF(
   216  							helpers.CFEnv{WorkingDirectory: manifestDir},
   217  							PushCommandName,
   218  						)
   219  
   220  						Eventually(session.Err).Should(Say("Environment variable CF_DOCKER_PASSWORD not set\\."))
   221  						Eventually(session).Should(Exit(1))
   222  					})
   223  				})
   224  			})
   225  		})
   226  	})
   227  
   228  	Describe("command line and manifest interaction", func() {
   229  		var appManifest map[string]interface{}
   230  
   231  		Context("when the image and username are provided by both manifest and command line", func() {
   232  			BeforeEach(func() {
   233  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
   234  				privateDockerImage, privateDockerUsername, privateDockerPassword = helpers.SkipIfPrivateDockerInfoNotSet()
   235  
   236  				appManifest = map[string]interface{}{
   237  					"applications": []map[string]interface{}{
   238  						{
   239  							"name": appName,
   240  							"docker": map[string]string{
   241  								"image":    "junk",
   242  								"username": "junk",
   243  							},
   244  						},
   245  					},
   246  				}
   247  			})
   248  
   249  			It("command line takes precidence", func() {
   250  				helpers.WithManifest(appManifest, func(manifestDir string) {
   251  					session := helpers.CustomCF(
   252  						helpers.CFEnv{
   253  							WorkingDirectory: manifestDir,
   254  							EnvVars:          map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword},
   255  						},
   256  						PushCommandName,
   257  						"--docker-username", privateDockerUsername,
   258  						"--docker-image", privateDockerImage,
   259  					)
   260  
   261  					validateDockerPassword(session, false)
   262  					validateDockerPush(session, appName, privateDockerImage)
   263  				})
   264  			})
   265  		})
   266  	})
   267  })
   268  
   269  func validateDockerPassword(session *Session, passwordFromPrompt bool) {
   270  	if passwordFromPrompt {
   271  		Eventually(session).Should(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   272  		Eventually(session).Should(Say("Docker password"))
   273  	} else {
   274  		Eventually(session).Should(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD."))
   275  	}
   276  }
   277  
   278  func validateDockerPush(session *Session, appName string, dockerImage string) {
   279  	Eventually(session).Should(Say("Getting app info\\.\\.\\."))
   280  	Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\."))
   281  	Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName))
   282  	Eventually(session).Should(Say("\\s+docker image:\\s+%s", dockerImage))
   283  	helpers.ConfirmStagingLogs(session)
   284  	Eventually(session).Should(Say("Waiting for app to start\\.\\.\\."))
   285  	Eventually(session).Should(Say("requested state:\\s+started"))
   286  	Eventually(session).Should(Exit(0))
   287  
   288  	session = helpers.CF("app", appName)
   289  	Eventually(session).Should(Say("name:\\s+%s", appName))
   290  	Eventually(session).Should(Exit(0))
   291  }