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 }