github.com/loafoe/cli@v7.1.0+incompatible/util/manifestparser/application_test.go (about) 1 package manifestparser_test 2 3 import ( 4 . "code.cloudfoundry.org/cli/util/manifestparser" 5 "gopkg.in/yaml.v2" 6 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/gomega" 9 ) 10 11 var _ = Describe("Application", func() { 12 Describe("Unmarshal", func() { 13 var ( 14 emptyMap map[string]interface{} 15 rawYAML []byte 16 application Application 17 executeErr error 18 ) 19 20 BeforeEach(func() { 21 emptyMap = make(map[string]interface{}) 22 }) 23 24 JustBeforeEach(func() { 25 application = Application{} 26 executeErr = yaml.Unmarshal(rawYAML, &application) 27 }) 28 29 Context("when a name is provided", func() { 30 BeforeEach(func() { 31 rawYAML = []byte(`--- 32 name: spark 33 `) 34 }) 35 36 It("unmarshals the name", func() { 37 Expect(executeErr).ToNot(HaveOccurred()) 38 Expect(application.Name).To(Equal("spark")) 39 }) 40 }) 41 42 When("a disk quota is provided", func() { 43 When("it has a hyphen (`disk-quota`)", func() { 44 BeforeEach(func() { 45 rawYAML = []byte(`--- 46 disk-quota: 5G 47 `) 48 }) 49 50 It("unmarshals the disk quota", func() { 51 Expect(executeErr).ToNot(HaveOccurred()) 52 Expect(application.DiskQuota).To(Equal("5G")) 53 }) 54 }) 55 When("it has an underscore (`disk_quota`)", func() { 56 BeforeEach(func() { 57 rawYAML = []byte(`--- 58 disk_quota: 5G 59 `) 60 }) 61 62 It("unmarshals the disk quota because we maintain backwards-compatibility with the old style", func() { 63 Expect(executeErr).ToNot(HaveOccurred()) 64 Expect(application.DiskQuota).To(Equal("5G")) 65 }) 66 It("doesn't leave a second version of `disk_quota` in the remaining manifest fields", func() { 67 Expect(application.RemainingManifestFields["disk_quota"]).To(BeNil()) 68 }) 69 }) 70 When("it has an underscore but it isn't a string", func() { 71 BeforeEach(func() { 72 rawYAML = []byte(`--- 73 disk_quota: [1] 74 `) 75 }) 76 77 It("returns an error", func() { 78 Expect(executeErr).To(MatchError("`disk_quota` must be a string")) 79 }) 80 }) 81 When("both underscore and hyphen versions are present", func() { 82 BeforeEach(func() { 83 rawYAML = []byte(`--- 84 disk_quota: 5G 85 disk-quota: 6G 86 `) 87 }) 88 89 It("returns an error", func() { 90 Expect(executeErr).To(MatchError("cannot define both `disk_quota` and `disk-quota`")) 91 }) 92 }) 93 }) 94 95 Context("when default-route is provided", func() { 96 BeforeEach(func() { 97 rawYAML = []byte(`--- 98 default-route: true 99 `) 100 }) 101 102 It("unmarshals the name", func() { 103 Expect(executeErr).ToNot(HaveOccurred()) 104 Expect(application.DefaultRoute).To(BeTrue()) 105 }) 106 }) 107 108 Context("when a path is provided", func() { 109 BeforeEach(func() { 110 rawYAML = []byte(`--- 111 path: /my/path 112 `) 113 }) 114 115 It("unmarshals the path", func() { 116 Expect(executeErr).ToNot(HaveOccurred()) 117 Expect(application.Path).To(Equal("/my/path")) 118 }) 119 }) 120 121 Context("when a docker map is provided", func() { 122 BeforeEach(func() { 123 rawYAML = []byte(`--- 124 docker: 125 image: some-image 126 username: some-username 127 `) 128 }) 129 130 It("unmarshals the docker properties", func() { 131 Expect(executeErr).ToNot(HaveOccurred()) 132 Expect(application.Docker.Image).To(Equal("some-image")) 133 Expect(application.Docker.Username).To(Equal("some-username")) 134 }) 135 }) 136 137 Context("when no-route is provided", func() { 138 BeforeEach(func() { 139 rawYAML = []byte(`--- 140 no-route: true 141 `) 142 }) 143 144 It("unmarshals the no-route property", func() { 145 Expect(executeErr).ToNot(HaveOccurred()) 146 Expect(application.NoRoute).To(BeTrue()) 147 }) 148 }) 149 150 Context("when random-route is provided", func() { 151 BeforeEach(func() { 152 rawYAML = []byte(`--- 153 random-route: true 154 `) 155 }) 156 157 It("unmarshals the random-route property", func() { 158 Expect(executeErr).ToNot(HaveOccurred()) 159 Expect(application.RandomRoute).To(BeTrue()) 160 }) 161 }) 162 163 Context("when buildpacks is provided", func() { 164 BeforeEach(func() { 165 rawYAML = []byte(`--- 166 buildpacks: 167 - ruby_buildpack 168 - java_buildpack 169 `) 170 }) 171 172 It("unmarshals the buildpacks property", func() { 173 Expect(executeErr).ToNot(HaveOccurred()) 174 Expect(application.RemainingManifestFields["buildpacks"]).To(ConsistOf("ruby_buildpack", "java_buildpack")) 175 }) 176 }) 177 178 Context("when stack is provided", func() { 179 BeforeEach(func() { 180 rawYAML = []byte(`--- 181 stack: cflinuxfs3 182 `) 183 }) 184 185 It("unmarshals the stack property", func() { 186 Expect(executeErr).ToNot(HaveOccurred()) 187 Expect(application.Stack).To(Equal("cflinuxfs3")) 188 }) 189 }) 190 191 Context("when an unknown field is provided", func() { 192 BeforeEach(func() { 193 rawYAML = []byte(`--- 194 unknown-key: 2 195 `) 196 }) 197 198 It("unmarshals the unknown field to a map", func() { 199 Expect(executeErr).ToNot(HaveOccurred()) 200 201 mapVal, ok := application.RemainingManifestFields["unknown-key"] 202 Expect(ok).To(BeTrue()) 203 204 mapValAsInt, ok := mapVal.(int) 205 Expect(ok).To(BeTrue()) 206 207 Expect(mapValAsInt).To(Equal(2)) 208 }) 209 }) 210 211 Context("when Processes are provided", func() { 212 BeforeEach(func() { 213 rawYAML = []byte(`--- 214 processes: [] 215 `) 216 }) 217 218 It("unmarshals the processes property", func() { 219 Expect(executeErr).ToNot(HaveOccurred()) 220 Expect(application.Processes).To(Equal([]Process{})) 221 }) 222 }) 223 224 Context("process-level configuration", func() { 225 Context("the Type command is always provided", func() { 226 BeforeEach(func() { 227 rawYAML = []byte(`--- 228 processes: 229 - type: web 230 `) 231 }) 232 233 It("unmarshals the processes property with the type", func() { 234 Expect(executeErr).ToNot(HaveOccurred()) 235 Expect(application.Processes).To(Equal([]Process{ 236 {Type: "web", RemainingManifestFields: emptyMap}, 237 })) 238 }) 239 }) 240 241 Context("when the start command is provided", func() { 242 BeforeEach(func() { 243 rawYAML = []byte(`--- 244 processes: 245 - command: /bin/python 246 `) 247 }) 248 249 It("unmarshals the processes property with the start command", func() { 250 Expect(executeErr).ToNot(HaveOccurred()) 251 Expect(application.Processes[0].RemainingManifestFields["command"]).To(Equal("/bin/python")) 252 }) 253 }) 254 255 Context("when a disk quota is provided", func() { 256 BeforeEach(func() { 257 rawYAML = []byte(`--- 258 processes: 259 - disk_quota: 5GB 260 `) 261 }) 262 263 It("unmarshals the processes property with the disk quota", func() { 264 Expect(executeErr).ToNot(HaveOccurred()) 265 Expect(application.Processes).To(Equal([]Process{ 266 {DiskQuota: "5GB", RemainingManifestFields: emptyMap}, 267 })) 268 }) 269 }) 270 271 Context("when a health check endpoint is provided", func() { 272 BeforeEach(func() { 273 rawYAML = []byte(`--- 274 processes: 275 - health-check-http-endpoint: https://localhost 276 `) 277 }) 278 279 It("unmarshals the processes property with the health check endpoint", func() { 280 Expect(executeErr).ToNot(HaveOccurred()) 281 Expect(application.Processes).To(Equal([]Process{ 282 {HealthCheckEndpoint: "https://localhost", RemainingManifestFields: emptyMap}, 283 })) 284 }) 285 }) 286 287 Context("when a health check timeout is provided", func() { 288 BeforeEach(func() { 289 rawYAML = []byte(`--- 290 processes: 291 - timeout: 42 292 `) 293 }) 294 295 It("unmarshals the processes property with the health check endpoint", func() { 296 Expect(executeErr).ToNot(HaveOccurred()) 297 Expect(application.Processes).To(Equal([]Process{ 298 {HealthCheckTimeout: 42, RemainingManifestFields: emptyMap}, 299 })) 300 }) 301 }) 302 303 Context("when a health check type is provided", func() { 304 BeforeEach(func() { 305 rawYAML = []byte(`--- 306 processes: 307 - health-check-type: http 308 `) 309 }) 310 311 It("unmarshals the processes property with the health check type", func() { 312 Expect(executeErr).ToNot(HaveOccurred()) 313 Expect(application.Processes).To(Equal([]Process{ 314 {HealthCheckType: "http", RemainingManifestFields: emptyMap}, 315 })) 316 }) 317 }) 318 319 Context("when a memory limit is provided", func() { 320 BeforeEach(func() { 321 rawYAML = []byte(`--- 322 processes: 323 - memory: 512M 324 `) 325 }) 326 327 It("unmarshals the processes property with the memory limit", func() { 328 Expect(executeErr).ToNot(HaveOccurred()) 329 Expect(application.Processes).To(Equal([]Process{ 330 {Memory: "512M", RemainingManifestFields: emptyMap}, 331 })) 332 }) 333 }) 334 335 Context("when instances are provided", func() { 336 BeforeEach(func() { 337 rawYAML = []byte(`--- 338 processes: 339 - instances: 4 340 `) 341 }) 342 343 It("unmarshals the processes property with instances", func() { 344 a := 4 345 Expect(executeErr).ToNot(HaveOccurred()) 346 Expect(application.Processes).To(Equal([]Process{ 347 {Instances: &a, RemainingManifestFields: emptyMap}, 348 })) 349 }) 350 }) 351 352 Context("when an unknown field is provided", func() { 353 BeforeEach(func() { 354 rawYAML = []byte(`--- 355 processes: 356 - unknown-key: 2 357 `) 358 }) 359 360 It("unmarshals the unknown field to a map", func() { 361 Expect(executeErr).ToNot(HaveOccurred()) 362 363 mapVal, ok := application.Processes[0].RemainingManifestFields["unknown-key"] 364 Expect(ok).To(BeTrue()) 365 366 mapValAsInt, ok := mapVal.(int) 367 Expect(ok).To(BeTrue()) 368 369 Expect(mapValAsInt).To(Equal(2)) 370 }) 371 }) 372 }) 373 374 Context("marshalling & unmarshalling fields with special-cased empty values", func() { 375 BeforeEach(func() { 376 rawYAML = []byte(`--- 377 name: "" 378 command: null 379 buildpacks: [] 380 processes: 381 - type: web 382 command: null 383 `) 384 }) 385 386 It("preserves the values as-written", func() { 387 Expect(executeErr).NotTo(HaveOccurred()) 388 389 remarshalledYaml, err := yaml.Marshal(&application) 390 Expect(err).NotTo(HaveOccurred()) 391 392 Expect(remarshalledYaml).To(MatchYAML(rawYAML)) 393 }) 394 }) 395 }) 396 397 Describe("SetStartCommand", func() { 398 var ( 399 app Application 400 command string 401 ) 402 403 BeforeEach(func() { 404 app = Application{} 405 command = "./start.sh" 406 }) 407 408 JustBeforeEach(func() { 409 app.SetStartCommand(command) 410 }) 411 412 When("the remaining fields map exists", func() { 413 BeforeEach(func() { 414 app.RemainingManifestFields = map[string]interface{}{} 415 }) 416 417 It("sets the start command in the map", func() { 418 Expect(app.RemainingManifestFields["command"]).To(Equal("./start.sh")) 419 }) 420 421 When("the command is nil", func() { 422 BeforeEach(func() { 423 command = "" 424 }) 425 426 It("sets the start command to nil in the map", func() { 427 Expect(app.RemainingManifestFields["command"]).To(BeNil()) 428 }) 429 }) 430 }) 431 432 When("the remaining fields map does not exist", func() { 433 It("sets the start command in the map", func() { 434 Expect(app.RemainingManifestFields["command"]).To(Equal("./start.sh")) 435 }) 436 }) 437 }) 438 439 Describe("SetBuildpacks", func() { 440 var ( 441 app Application 442 buildpacks []string 443 ) 444 445 BeforeEach(func() { 446 app = Application{} 447 buildpacks = []string{"bp1", "bp2"} 448 }) 449 450 JustBeforeEach(func() { 451 app.SetBuildpacks(buildpacks) 452 }) 453 454 When("the remaining fields map exists", func() { 455 BeforeEach(func() { 456 app.RemainingManifestFields = map[string]interface{}{} 457 }) 458 459 It("sets the buildpackks in the map", func() { 460 Expect(app.RemainingManifestFields["buildpacks"]).To(ConsistOf("bp1", "bp2")) 461 }) 462 463 When("buildpacks is empty", func() { 464 BeforeEach(func() { 465 buildpacks = []string{} 466 }) 467 468 It("sets the buildpacks to empty in the map", func() { 469 Expect(app.RemainingManifestFields["buildpacks"]).To(BeEmpty()) 470 }) 471 }) 472 }) 473 474 When("the remaining fields map does not exist", func() { 475 It("sets the buildpacks in the map", func() { 476 Expect(app.RemainingManifestFields["buildpacks"]).To(ConsistOf("bp1", "bp2")) 477 }) 478 }) 479 }) 480 481 Describe("HasBuildpacks", func() { 482 var ( 483 app Application 484 buildpacks []string 485 ) 486 487 When("the app has buildpacks", func() { 488 BeforeEach(func() { 489 buildpacks = []string{"bp1", "bp2"} 490 app = Application{RemainingManifestFields: map[string]interface{}{"buildpacks": buildpacks}} 491 }) 492 493 It("returns true", func() { 494 Expect(app.HasBuildpacks()).To(BeTrue()) 495 }) 496 }) 497 498 When("the app does not have buildpacks", func() { 499 BeforeEach(func() { 500 app = Application{} 501 }) 502 503 It("returns false", func() { 504 Expect(app.HasBuildpacks()).To(BeFalse()) 505 }) 506 }) 507 }) 508 })