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 }