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