github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/util/v6manifestparser/parser_test.go (about) 1 package v6manifestparser_test 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers" 11 . "code.cloudfoundry.org/cli/util/v6manifestparser" 12 "github.com/cloudfoundry/bosh-cli/director/template" 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 ) 16 17 var _ = Describe("Parser", func() { 18 var parser *Parser 19 20 BeforeEach(func() { 21 parser = NewParser() 22 }) 23 24 Describe("NewParser", func() { 25 It("returns a parser", func() { 26 Expect(parser).ToNot(BeNil()) 27 }) 28 }) 29 30 Describe("AppNames", func() { 31 When("given a valid manifest file", func() { 32 BeforeEach(func() { 33 parser.Applications = []Application{ 34 {ApplicationModel: ApplicationModel{Name: "app-1"}, FullUnmarshalledApplication: nil}, 35 {ApplicationModel: ApplicationModel{Name: "app-2"}, FullUnmarshalledApplication: nil}} 36 }) 37 38 It("gets the app names", func() { 39 appNames := parser.AppNames() 40 Expect(appNames).To(ConsistOf("app-1", "app-2")) 41 }) 42 }) 43 }) 44 45 Describe("ContainsManifest", func() { 46 var ( 47 pathToManifest string 48 ) 49 50 BeforeEach(func() { 51 tempFile, err := ioutil.TempFile("", "contains-manifest-test") 52 Expect(err).ToNot(HaveOccurred()) 53 pathToManifest = tempFile.Name() 54 Expect(tempFile.Close()).ToNot(HaveOccurred()) 55 }) 56 57 AfterEach(func() { 58 err := os.RemoveAll(pathToManifest) 59 Expect(err).ToNot(HaveOccurred()) 60 }) 61 62 Context("when the manifest is parsed successfully", func() { 63 BeforeEach(func() { 64 rawManifest := []byte(`--- 65 applications: 66 - name: spark 67 `) 68 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 69 Expect(err).ToNot(HaveOccurred()) 70 71 err = parser.InterpolateAndParse(pathToManifest, nil, nil, "") 72 Expect(err).ToNot(HaveOccurred()) 73 }) 74 75 It("returns true", func() { 76 Expect(parser.ContainsManifest()).To(BeTrue()) 77 }) 78 }) 79 80 Context("when the manifest is not parsed successfully", func() { 81 BeforeEach(func() { 82 rawManifest := []byte(`--- 83 applications: 84 `) 85 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 86 Expect(err).ToNot(HaveOccurred()) 87 88 err = parser.InterpolateAndParse(pathToManifest, nil, nil, "") 89 Expect(err).To(HaveOccurred()) 90 }) 91 92 It("returns false", func() { 93 Expect(parser.ContainsManifest()).To(BeFalse()) 94 }) 95 }) 96 97 Context("when the manifest has not been parsed", func() { 98 It("returns false", func() { 99 Expect(parser.ContainsManifest()).To(BeFalse()) 100 }) 101 }) 102 }) 103 104 Describe("ContainsMultipleApps", func() { 105 When("given a valid manifest file with multiple apps", func() { 106 BeforeEach(func() { 107 parser.Applications = []Application{ 108 {ApplicationModel: ApplicationModel{Name: "app-1"}, FullUnmarshalledApplication: nil}, 109 {ApplicationModel: ApplicationModel{Name: "app-2"}, FullUnmarshalledApplication: nil}} 110 }) 111 112 It("returns true", func() { 113 Expect(parser.ContainsMultipleApps()).To(BeTrue()) 114 }) 115 }) 116 117 When("given a valid manifest file with a single app", func() { 118 BeforeEach(func() { 119 parser.Applications = []Application{{ApplicationModel: ApplicationModel{Name: "app-1"}, FullUnmarshalledApplication: nil}} 120 }) 121 122 It("returns false", func() { 123 Expect(parser.ContainsMultipleApps()).To(BeFalse()) 124 }) 125 }) 126 }) 127 128 Describe("ContainsPrivateDockerImages", func() { 129 When("the manifest contains a docker image", func() { 130 When("the image is public", func() { 131 BeforeEach(func() { 132 parser.Applications = []Application{ 133 {ApplicationModel: ApplicationModel{Name: "app-1", Docker: &Docker{Image: "image-1"}}, FullUnmarshalledApplication: nil}, 134 {ApplicationModel: ApplicationModel{Name: "app-2", Docker: &Docker{Image: "image-2"}}, FullUnmarshalledApplication: nil}} 135 }) 136 137 It("returns false", func() { 138 Expect(parser.ContainsPrivateDockerImages()).To(BeFalse()) 139 }) 140 }) 141 142 When("the image is private", func() { 143 BeforeEach(func() { 144 parser.Applications = []Application{ 145 {ApplicationModel: ApplicationModel{Name: "app-1", Docker: &Docker{Image: "image-1"}}}, 146 {ApplicationModel: ApplicationModel{Name: "app-2", Docker: &Docker{Image: "image-2", Username: "user"}}}, 147 } 148 }) 149 150 It("returns true", func() { 151 Expect(parser.ContainsPrivateDockerImages()).To(BeTrue()) 152 }) 153 }) 154 }) 155 156 When("the manifest does not contain a docker image", func() { 157 BeforeEach(func() { 158 parser.Applications = []Application{ 159 {ApplicationModel: ApplicationModel{Name: "app-1"}}, 160 {ApplicationModel: ApplicationModel{Name: "app-2"}}, 161 } 162 }) 163 164 It("returns false", func() { 165 Expect(parser.ContainsPrivateDockerImages()).To(BeFalse()) 166 }) 167 }) 168 }) 169 170 Describe("InterpolateAndParse", func() { 171 var ( 172 pathToManifest string 173 pathsToVarsFiles []string 174 vars []template.VarKV 175 appName string 176 177 executeErr error 178 179 rawManifest []byte 180 ) 181 182 BeforeEach(func() { 183 tempFile, err := ioutil.TempFile("", "manifest-test-") 184 Expect(err).ToNot(HaveOccurred()) 185 Expect(tempFile.Close()).ToNot(HaveOccurred()) 186 pathToManifest = tempFile.Name() 187 vars = nil 188 appName = "" 189 190 pathsToVarsFiles = nil 191 }) 192 193 AfterEach(func() { 194 Expect(os.RemoveAll(pathToManifest)).ToNot(HaveOccurred()) 195 for _, path := range pathsToVarsFiles { 196 Expect(os.RemoveAll(path)).ToNot(HaveOccurred()) 197 } 198 }) 199 200 JustBeforeEach(func() { 201 executeErr = parser.InterpolateAndParse(pathToManifest, pathsToVarsFiles, vars, appName) 202 }) 203 204 When("the manifest does *not* need interpolation", func() { 205 BeforeEach(func() { 206 rawManifest = []byte(`--- 207 applications: 208 - name: spark 209 memory: 1G 210 instances: 2 211 - name: flame 212 memory: 1G 213 instances: 2 214 `) 215 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 216 Expect(err).ToNot(HaveOccurred()) 217 }) 218 219 It("parses the manifest properly", func() { 220 Expect(executeErr).ToNot(HaveOccurred()) 221 222 Expect(parser.AppNames()).To(ConsistOf("spark", "flame")) 223 Expect(parser.GetPathToManifest()).To(Equal(pathToManifest)) 224 Expect(parser.FullRawManifest()).To(MatchYAML(rawManifest)) 225 }) 226 }) 227 228 When("the manifest contains variables that need interpolation", func() { 229 BeforeEach(func() { 230 rawManifest = []byte(`--- 231 applications: 232 - name: ((var1)) 233 - name: ((var2)) 234 `) 235 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 236 Expect(err).ToNot(HaveOccurred()) 237 }) 238 239 When("only vars files are provided", func() { 240 var ( 241 varsDir string 242 ) 243 244 BeforeEach(func() { 245 var err error 246 varsDir, err = ioutil.TempDir("", "vars-test") 247 Expect(err).ToNot(HaveOccurred()) 248 249 varsFilePath1 := filepath.Join(varsDir, "vars-1") 250 err = ioutil.WriteFile(varsFilePath1, []byte("var1: spark"), 0666) 251 Expect(err).ToNot(HaveOccurred()) 252 253 varsFilePath2 := filepath.Join(varsDir, "vars-2") 254 err = ioutil.WriteFile(varsFilePath2, []byte("var2: flame"), 0666) 255 Expect(err).ToNot(HaveOccurred()) 256 257 pathsToVarsFiles = append(pathsToVarsFiles, varsFilePath1, varsFilePath2) 258 }) 259 260 AfterEach(func() { 261 Expect(os.RemoveAll(varsDir)).ToNot(HaveOccurred()) 262 }) 263 264 When("multiple values for the same variable(s) are provided", func() { 265 BeforeEach(func() { 266 varsFilePath1 := filepath.Join(varsDir, "vars-1") 267 err := ioutil.WriteFile(varsFilePath1, []byte("var1: garbageapp\nvar1: spark\nvar2: doesn't matter"), 0666) 268 Expect(err).ToNot(HaveOccurred()) 269 270 varsFilePath2 := filepath.Join(varsDir, "vars-2") 271 err = ioutil.WriteFile(varsFilePath2, []byte("var2: flame"), 0666) 272 Expect(err).ToNot(HaveOccurred()) 273 274 pathsToVarsFiles = append(pathsToVarsFiles, varsFilePath1, varsFilePath2) 275 }) 276 277 It("interpolates the placeholder values", func() { 278 Expect(executeErr).ToNot(HaveOccurred()) 279 Expect(parser.AppNames()).To(ConsistOf("spark", "flame")) 280 }) 281 }) 282 283 When("the provided files exists and contain valid yaml", func() { 284 It("interpolates the placeholder values", func() { 285 Expect(executeErr).ToNot(HaveOccurred()) 286 Expect(parser.AppNames()).To(ConsistOf("spark", "flame")) 287 }) 288 }) 289 290 When("a variable in the manifest is not provided in the vars file", func() { 291 BeforeEach(func() { 292 varsFilePath := filepath.Join(varsDir, "vars-1") 293 err := ioutil.WriteFile(varsFilePath, []byte("notvar: foo"), 0666) 294 Expect(err).ToNot(HaveOccurred()) 295 296 pathsToVarsFiles = []string{varsFilePath} 297 }) 298 299 It("returns an error", func() { 300 Expect(executeErr.Error()).To(Equal("Expected to find variables: var1, var2")) 301 }) 302 }) 303 304 When("the provided file path does not exist", func() { 305 BeforeEach(func() { 306 pathsToVarsFiles = []string{"garbagepath"} 307 }) 308 309 It("returns an error", func() { 310 Expect(executeErr).To(HaveOccurred()) 311 Expect(os.IsNotExist(executeErr)).To(BeTrue()) 312 }) 313 }) 314 315 When("the provided file is not a valid yaml file", func() { 316 BeforeEach(func() { 317 varsFilePath := filepath.Join(varsDir, "vars-1") 318 err := ioutil.WriteFile(varsFilePath, []byte(": bad"), 0666) 319 Expect(err).ToNot(HaveOccurred()) 320 321 pathsToVarsFiles = []string{varsFilePath} 322 }) 323 324 It("returns an error", func() { 325 Expect(executeErr).To(HaveOccurred()) 326 Expect(executeErr).To(MatchError(InvalidYAMLError{ 327 Err: errors.New("yaml: did not find expected key"), 328 })) 329 }) 330 }) 331 }) 332 333 When("only vars are provided", func() { 334 BeforeEach(func() { 335 vars = []template.VarKV{ 336 {Name: "var1", Value: "spark"}, 337 {Name: "var2", Value: "flame"}, 338 } 339 }) 340 341 It("interpolates the placeholder values", func() { 342 Expect(executeErr).ToNot(HaveOccurred()) 343 Expect(parser.AppNames()).To(ConsistOf("spark", "flame")) 344 }) 345 }) 346 347 When("vars and vars files are provided", func() { 348 var varsFilePath string 349 BeforeEach(func() { 350 tmp, err := ioutil.TempFile("", "util-manifest-varsilfe") 351 Expect(err).NotTo(HaveOccurred()) 352 Expect(tmp.Close()).NotTo(HaveOccurred()) 353 354 varsFilePath = tmp.Name() 355 err = ioutil.WriteFile(varsFilePath, []byte("var1: spark\nvar2: 12345"), 0666) 356 Expect(err).ToNot(HaveOccurred()) 357 358 pathsToVarsFiles = []string{varsFilePath} 359 vars = []template.VarKV{ 360 {Name: "var2", Value: "flame"}, 361 } 362 }) 363 364 AfterEach(func() { 365 Expect(os.RemoveAll(varsFilePath)).ToNot(HaveOccurred()) 366 }) 367 368 It("interpolates the placeholder values, prioritizing the vars flag", func() { 369 Expect(executeErr).ToNot(HaveOccurred()) 370 Expect(parser.AppNames()).To(ConsistOf("spark", "flame")) 371 }) 372 }) 373 }) 374 375 When("invalid yaml is passed", func() { 376 BeforeEach(func() { 377 rawManifest = []byte("\t\t") 378 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 379 Expect(err).ToNot(HaveOccurred()) 380 }) 381 382 It("parses the manifest properly", func() { 383 Expect(executeErr).To(HaveOccurred()) 384 }) 385 }) 386 387 When("passing an app name override", func() { 388 BeforeEach(func() { 389 appName = "mashed-potato" 390 }) 391 392 When("there is only one app", func() { 393 When("the app has a name", func() { 394 BeforeEach(func() { 395 rawManifest = []byte(`--- 396 applications: 397 - name: spark 398 instances: 2 399 `) 400 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 401 Expect(err).ToNot(HaveOccurred()) 402 }) 403 404 It("sets its name in the raw manifest", func() { 405 Expect(parser.FullRawManifest()).To(MatchYAML(`--- 406 applications: 407 - name: mashed-potato 408 instances: 2 409 `)) 410 }) 411 412 It("sets its name in the application object", func() { 413 Expect(parser.Applications).To(HaveLen(1)) 414 Expect(parser.Applications[0].Name).To(Equal("mashed-potato")) 415 }) 416 }) 417 418 When("the app does *not* have a name", func() { 419 BeforeEach(func() { 420 rawManifest = []byte(`--- 421 applications: 422 - instances: 2 423 `) 424 err := ioutil.WriteFile(pathToManifest, rawManifest, 0666) 425 Expect(err).ToNot(HaveOccurred()) 426 }) 427 428 It("sets its name in the raw manifest", func() { 429 Expect(parser.FullRawManifest()).To(MatchYAML(`--- 430 applications: 431 - name: mashed-potato 432 instances: 2 433 `)) 434 }) 435 436 It("sets its name in the application object", func() { 437 Expect(parser.Applications).To(HaveLen(1)) 438 Expect(parser.Applications[0].Name).To(Equal("mashed-potato")) 439 }) 440 }) 441 }) 442 443 When("there are multiple apps", func() { 444 var ( 445 app1FullPath string 446 app2FullPath string 447 ) 448 449 BeforeEach(func() { 450 manifestDir := filepath.Dir(pathToManifest) 451 app1FullPath = filepath.Join(manifestDir, "app1") 452 app2FullPath = filepath.Join(manifestDir, "app2") 453 454 err := os.MkdirAll(app1FullPath, 0777) 455 Expect(err).ToNot(HaveOccurred()) 456 err = os.MkdirAll(app2FullPath, 0777) 457 Expect(err).ToNot(HaveOccurred()) 458 459 rawManifest = []byte(`--- 460 applications: 461 - name: app-1 462 instances: 2 463 path: ./app1 464 - name: app-2 465 instances: 5 466 path: ./app2 467 `) 468 err = ioutil.WriteFile(pathToManifest, rawManifest, 0666) 469 Expect(err).ToNot(HaveOccurred()) 470 }) 471 472 When("the override matches an app", func() { 473 BeforeEach(func() { 474 appName = "app-2" 475 }) 476 477 It("keeps only the matching app in the raw manifest", func() { 478 Expect(parser.FullRawManifest()).To(MatchYAML(`--- 479 applications: 480 - instances: 5 481 name: app-2 482 path: ./app2 483 `)) 484 }) 485 486 It("keeps only the matching app in the applications list", func() { 487 Expect(parser.Applications).To(HaveLen(1)) 488 Expect(parser.Applications[0].Name).To(Equal("app-2")) 489 Expect(parser.Applications[0].Path).To(matchers.MatchPath(app2FullPath)) 490 }) 491 }) 492 493 When("the override does *not* match an app", func() { 494 BeforeEach(func() { 495 appName = "does-not-exist" 496 }) 497 498 It("returns an error", func() { 499 Expect(executeErr).To(MatchError(AppNotInManifestError{Name: "does-not-exist"})) 500 }) 501 }) 502 }) 503 }) 504 }) 505 506 Describe("RawAppManifest", func() { 507 var ( 508 rawAppManifest []byte 509 appName string 510 executeErr error 511 rawManifest []byte 512 pathToManifest string 513 tmpMyPath string 514 ) 515 516 BeforeEach(func() { 517 var err error 518 519 appName = "spark" 520 521 tmpMyPath, err = ioutil.TempDir("", "") 522 Expect(err).ToNot(HaveOccurred()) 523 524 rawManifest = []byte(fmt.Sprintf(`--- 525 applications: 526 - name: spark 527 memory: 1G 528 instances: 2 529 docker: 530 username: experiment 531 path: %s 532 - name: flame 533 memory: 1G 534 instances: 2 535 docker: 536 username: experiment 537 `, tmpMyPath)) 538 539 }) 540 541 JustBeforeEach(func() { 542 tempFile, err := ioutil.TempFile("", "manifest-test-") 543 Expect(err).ToNot(HaveOccurred()) 544 Expect(tempFile.Close()).ToNot(HaveOccurred()) 545 pathToManifest = tempFile.Name() 546 err = ioutil.WriteFile(pathToManifest, rawManifest, 0666) 547 Expect(err).ToNot(HaveOccurred()) 548 err = parser.InterpolateAndParse(pathToManifest, nil, nil, "") 549 Expect(err).ToNot(HaveOccurred()) 550 rawAppManifest, executeErr = parser.RawAppManifest(appName) 551 }) 552 553 AfterEach(func() { 554 err := os.RemoveAll(pathToManifest) 555 Expect(err).ToNot(HaveOccurred()) 556 }) 557 558 When("marshaling does not error", func() { 559 It("returns just the app's manifest", func() { 560 Expect(executeErr).ToNot(HaveOccurred()) 561 Expect(string(rawAppManifest)).To(MatchYAML(fmt.Sprintf(`applications: 562 - name: spark 563 memory: 1G 564 instances: 2 565 docker: 566 username: experiment 567 path: %s`, tmpMyPath))) 568 }) 569 }) 570 571 When("The app is not present", func() { 572 BeforeEach(func() { 573 appName = "not-here" 574 }) 575 576 It("returns an error", func() { 577 Expect(executeErr).To(MatchError(AppNotInManifestError{Name: "not-here"})) 578 Expect(rawAppManifest).To(BeNil()) 579 }) 580 }) 581 582 }) 583 })