github.com/Thanhphan1147/cloudfoundry-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  })