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 }