github.com/loafoe/cli@v7.1.0+incompatible/integration/v6/push/docker_test.go (about)

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