github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/integration/v6/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  	. "github.com/onsi/ginkgo"
     7  	. "github.com/onsi/gomega"
     8  	. "github.com/onsi/gomega/gbytes"
     9  	. "github.com/onsi/gomega/gexec"
    10  	"io/ioutil"
    11  	"os"
    12  	"path/filepath"
    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  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
    54  				privateDockerImage, privateDockerUsername, privateDockerPassword = helpers.SkipIfPrivateDockerInfoNotSet()
    55  			})
    56  
    57  			When("CF_DOCKER_PASSWORD is set", func() {
    58  				It("push the docker image with those credentials", func() {
    59  					session := helpers.CustomCF(
    60  						helpers.CFEnv{
    61  							EnvVars: map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword},
    62  						},
    63  						PushCommandName,
    64  						appName,
    65  						"--docker-username", privateDockerUsername,
    66  						"--docker-image", privateDockerImage,
    67  					)
    68  					validateDockerPush(session, appName, privateDockerImage)
    69  				})
    70  			})
    71  
    72  			When("the CF_DOCKER_PASSWORD is not set", func() {
    73  				var buffer *Buffer
    74  
    75  				BeforeEach(func() {
    76  					buffer = NewBuffer()
    77  					_, err := buffer.Write([]byte(privateDockerPassword + "\n"))
    78  					Expect(err).NotTo(HaveOccurred())
    79  				})
    80  
    81  				It("prompts for the docker password", func() {
    82  					session := helpers.CFWithStdin(buffer,
    83  						PushCommandName,
    84  						appName,
    85  						"--docker-username", privateDockerUsername,
    86  						"--docker-image", privateDockerImage,
    87  					)
    88  
    89  					validateDockerPassword(session, true)
    90  					validateDockerPush(session, appName, privateDockerImage)
    91  				})
    92  			})
    93  		})
    94  	})
    95  
    96  	Describe("docker image in the manifest is provided", func() {
    97  		var appManifest map[string]interface{}
    98  
    99  		BeforeEach(func() {
   100  			appManifest = map[string]interface{}{
   101  				"applications": []map[string]interface{}{
   102  					{
   103  						"name": appName,
   104  						"docker": map[string]string{
   105  							"image": PublicDockerImage,
   106  						},
   107  					},
   108  				},
   109  			}
   110  		})
   111  
   112  		It("uses the docker image when pushing", func() {
   113  			withManifest(appManifest, func(manifestDir string) {
   114  				session := helpers.CustomCF(
   115  					helpers.CFEnv{WorkingDirectory: manifestDir},
   116  					PushCommandName,
   117  				)
   118  
   119  				validateDockerPush(session, appName, PublicDockerImage)
   120  			})
   121  		})
   122  
   123  		When("buildpack is set", func() {
   124  			BeforeEach(func() {
   125  				appManifest = map[string]interface{}{
   126  					"applications": []map[string]interface{}{
   127  						{
   128  							"name":      appName,
   129  							"buildpack": "some-buildpack",
   130  							"docker": map[string]string{
   131  								"image": PublicDockerImage,
   132  							},
   133  						},
   134  					},
   135  				}
   136  			})
   137  
   138  			It("returns an error", func() {
   139  				withManifest(appManifest, func(manifestDir string) {
   140  					session := helpers.CustomCF(
   141  						helpers.CFEnv{WorkingDirectory: manifestDir},
   142  						PushCommandName,
   143  					)
   144  
   145  					Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: docker, buildpack", appName))
   146  					Eventually(session).Should(Exit(1))
   147  				})
   148  			})
   149  		})
   150  
   151  		When("path is set", func() {
   152  			BeforeEach(func() {
   153  				appManifest = map[string]interface{}{
   154  					"applications": []map[string]interface{}{
   155  						{
   156  							"name": appName,
   157  							"docker": map[string]string{
   158  								"image": PublicDockerImage,
   159  							},
   160  							"path": "some-path",
   161  						},
   162  					},
   163  				}
   164  			})
   165  
   166  			It("returns an error", func() {
   167  				withManifest(appManifest, func(manifestDir string) {
   168  					session := helpers.CustomCF(
   169  						helpers.CFEnv{WorkingDirectory: manifestDir},
   170  						PushCommandName,
   171  					)
   172  
   173  					Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: docker, path", appName))
   174  					Eventually(session).Should(Exit(1))
   175  				})
   176  			})
   177  		})
   178  
   179  		When("user is provided in the manifest", func() {
   180  			BeforeEach(func() {
   181  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
   182  				privateDockerImage, privateDockerUsername, privateDockerPassword = helpers.SkipIfPrivateDockerInfoNotSet()
   183  
   184  				appManifest = map[string]interface{}{
   185  					"applications": []map[string]interface{}{
   186  						{
   187  							"name": appName,
   188  							"docker": map[string]string{
   189  								"image":    privateDockerImage,
   190  								"username": privateDockerUsername,
   191  							},
   192  						},
   193  					},
   194  				}
   195  			})
   196  
   197  			When("password is provided in the enviornment", func() {
   198  				It("uses the docker image and credentials when pushing", func() {
   199  					withManifest(appManifest, func(manifestDir string) {
   200  						session := helpers.CustomCF(
   201  							helpers.CFEnv{
   202  								WorkingDirectory: manifestDir,
   203  								EnvVars:          map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword},
   204  							},
   205  							PushCommandName,
   206  						)
   207  
   208  						validateDockerPassword(session, false)
   209  						validateDockerPush(session, appName, privateDockerImage)
   210  					})
   211  				})
   212  			})
   213  
   214  			When("password is not provided in the enviornment", func() {
   215  				It("errors out", func() {
   216  					withManifest(appManifest, func(manifestDir string) {
   217  						session := helpers.CustomCF(
   218  							helpers.CFEnv{WorkingDirectory: manifestDir},
   219  							PushCommandName,
   220  						)
   221  
   222  						Eventually(session.Err).Should(Say(`Environment variable CF_DOCKER_PASSWORD not set\.`))
   223  						Eventually(session).Should(Exit(1))
   224  					})
   225  				})
   226  			})
   227  		})
   228  	})
   229  
   230  	Describe("command line and manifest interaction", func() {
   231  		var appManifest map[string]interface{}
   232  
   233  		When("the image and username are provided by both manifest and command line", func() {
   234  			BeforeEach(func() {
   235  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
   236  				privateDockerImage, privateDockerUsername, privateDockerPassword = helpers.SkipIfPrivateDockerInfoNotSet()
   237  
   238  				appManifest = map[string]interface{}{
   239  					"applications": []map[string]interface{}{
   240  						{
   241  							"name": appName,
   242  							"docker": map[string]string{
   243  								"image":    "junk",
   244  								"username": "junk",
   245  							},
   246  						},
   247  					},
   248  				}
   249  			})
   250  
   251  			It("command line takes precidence", func() {
   252  				withManifest(appManifest, func(manifestDir string) {
   253  					session := helpers.CustomCF(
   254  						helpers.CFEnv{
   255  							WorkingDirectory: manifestDir,
   256  							EnvVars:          map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword},
   257  						},
   258  						PushCommandName,
   259  						"--docker-username", privateDockerUsername,
   260  						"--docker-image", privateDockerImage,
   261  					)
   262  
   263  					validateDockerPassword(session, false)
   264  					validateDockerPush(session, appName, privateDockerImage)
   265  				})
   266  			})
   267  		})
   268  	})
   269  })
   270  
   271  func validateDockerPassword(session *Session, passwordFromPrompt bool) {
   272  	if passwordFromPrompt {
   273  		Eventually(session).Should(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   274  		Eventually(session).Should(Say("Docker password"))
   275  	} else {
   276  		Eventually(session).Should(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD."))
   277  	}
   278  }
   279  
   280  func validateDockerPush(session *Session, appName string, dockerImage string) {
   281  	Eventually(session).Should(Say(`Getting app info\.\.\.`))
   282  	Eventually(session).Should(Say(`Creating app with these attributes\.\.\.`))
   283  	Eventually(session).Should(Say(`\+\s+name:\s+%s`, appName))
   284  	Eventually(session).Should(Say(`\s+docker image:\s+%s`, dockerImage))
   285  	helpers.ConfirmStagingLogs(session)
   286  	Eventually(session).Should(Say(`Waiting for app to start\.\.\.`))
   287  	Eventually(session).Should(Say(`requested state:\s+started`))
   288  	Eventually(session).Should(Exit(0))
   289  
   290  	session = helpers.CF("app", appName)
   291  	Eventually(session).Should(Say(`name:\s+%s`, appName))
   292  	Eventually(session).Should(Exit(0))
   293  }
   294  
   295  func withManifest(manifest map[string]interface{}, f func(manifestDir string)) {
   296  	dir, err := ioutil.TempDir("", "simple-app")
   297  	Expect(err).ToNot(HaveOccurred())
   298  	defer os.RemoveAll(dir)
   299  
   300  	helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), manifest)
   301  	f(dir)
   302  }