github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/cf/manifest/manifest_test.go (about)

     1  package manifest_test
     2  
     3  import (
     4  	"runtime"
     5  	"strings"
     6  
     7  	"code.cloudfoundry.org/cli/cf/manifest"
     8  	"code.cloudfoundry.org/cli/utils/generic"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  
    12  	. "code.cloudfoundry.org/cli/testhelpers/matchers"
    13  )
    14  
    15  func NewManifest(path string, data generic.Map) (m *manifest.Manifest) {
    16  	return &manifest.Manifest{Path: path, Data: data}
    17  }
    18  
    19  var _ = Describe("Manifests", func() {
    20  	It("merges global properties into each app's properties", func() {
    21  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
    22  			"instances": "3",
    23  			"memory":    "512M",
    24  			"applications": []interface{}{
    25  				map[interface{}]interface{}{
    26  					"name":     "bitcoin-miner",
    27  					"no-route": true,
    28  				},
    29  			},
    30  		}))
    31  
    32  		apps, err := m.Applications()
    33  		Expect(err).NotTo(HaveOccurred())
    34  
    35  		Expect(*apps[0].InstanceCount).To(Equal(3))
    36  		Expect(*apps[0].Memory).To(Equal(int64(512)))
    37  		Expect(apps[0].NoRoute).To(BeTrue())
    38  	})
    39  
    40  	Context("when there is no applications block", func() {
    41  		It("returns a single application with the global properties", func() {
    42  			m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
    43  				"instances": "3",
    44  				"memory":    "512M",
    45  			}))
    46  
    47  			apps, err := m.Applications()
    48  			Expect(err).NotTo(HaveOccurred())
    49  
    50  			Expect(len(apps)).To(Equal(1))
    51  			Expect(*apps[0].InstanceCount).To(Equal(3))
    52  			Expect(*apps[0].Memory).To(Equal(int64(512)))
    53  		})
    54  	})
    55  
    56  	It("returns an error when the memory limit doesn't have a unit", func() {
    57  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
    58  			"instances": "3",
    59  			"memory":    "512",
    60  			"applications": []interface{}{
    61  				map[interface{}]interface{}{
    62  					"name": "bitcoin-miner",
    63  				},
    64  			},
    65  		}))
    66  
    67  		_, err := m.Applications()
    68  		Expect(err).To(HaveOccurred())
    69  		Expect(err.Error()).To(ContainSubstring("Invalid value for 'memory': 512"))
    70  	})
    71  
    72  	It("returns an error when the memory limit is a non-string", func() {
    73  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
    74  			"instances": "3",
    75  			"memory":    128,
    76  			"applications": []interface{}{
    77  				map[interface{}]interface{}{
    78  					"name": "bitcoin-miner",
    79  				},
    80  			},
    81  		}))
    82  
    83  		_, err := m.Applications()
    84  		Expect(err).To(HaveOccurred())
    85  		Expect(err.Error()).To(ContainSubstring("Invalid value for 'memory': 128"))
    86  	})
    87  
    88  	It("sets applications' health check timeouts", func() {
    89  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
    90  			"applications": []interface{}{
    91  				map[interface{}]interface{}{
    92  					"name":    "bitcoin-miner",
    93  					"timeout": "360",
    94  				},
    95  			},
    96  		}))
    97  
    98  		apps, err := m.Applications()
    99  		Expect(err).NotTo(HaveOccurred())
   100  		Expect(*apps[0].HealthCheckTimeout).To(Equal(360))
   101  	})
   102  
   103  	It("allows boolean env var values", func() {
   104  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   105  			"env": generic.NewMap(map[interface{}]interface{}{
   106  				"bar": true,
   107  			}),
   108  		}))
   109  
   110  		_, err := m.Applications()
   111  		Expect(err).ToNot(HaveOccurred())
   112  	})
   113  
   114  	It("does not allow nil values for environment variables", func() {
   115  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   116  			"env": generic.NewMap(map[interface{}]interface{}{
   117  				"bar": nil,
   118  			}),
   119  			"applications": []interface{}{
   120  				map[interface{}]interface{}{
   121  					"name": "bad app",
   122  				},
   123  			},
   124  		}))
   125  
   126  		_, err := m.Applications()
   127  		Expect(err).To(HaveOccurred())
   128  		Expect(err.Error()).To(ContainSubstring("env var 'bar' should not be null"))
   129  	})
   130  
   131  	It("returns an empty map when no env was present in the manifest", func() {
   132  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   133  			"applications": []interface{}{
   134  				map[interface{}]interface{}{"name": "no-env-vars"},
   135  			},
   136  		}))
   137  
   138  		apps, err := m.Applications()
   139  		Expect(err).NotTo(HaveOccurred())
   140  		Expect(*apps[0].EnvironmentVars).NotTo(BeNil())
   141  	})
   142  
   143  	It("allows applications to have absolute paths", func() {
   144  		if runtime.GOOS == "windows" {
   145  			m := NewManifest(`C:\some\path\manifest.yml`, generic.NewMap(map[interface{}]interface{}{
   146  				"applications": []interface{}{
   147  					map[interface{}]interface{}{
   148  						"path": `C:\another\path`,
   149  					},
   150  				},
   151  			}))
   152  
   153  			apps, err := m.Applications()
   154  			Expect(err).NotTo(HaveOccurred())
   155  			Expect(*apps[0].Path).To(Equal(`C:\another\path`))
   156  		} else {
   157  			m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   158  				"applications": []interface{}{
   159  					map[interface{}]interface{}{
   160  						"path": "/another/path-segment",
   161  					},
   162  				},
   163  			}))
   164  
   165  			apps, err := m.Applications()
   166  			Expect(err).NotTo(HaveOccurred())
   167  			Expect(*apps[0].Path).To(Equal("/another/path-segment"))
   168  		}
   169  	})
   170  
   171  	It("expands relative app paths based on the manifest's path", func() {
   172  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   173  			"applications": []interface{}{
   174  				map[interface{}]interface{}{
   175  					"path": "../another/path-segment",
   176  				},
   177  			},
   178  		}))
   179  
   180  		apps, err := m.Applications()
   181  		Expect(err).NotTo(HaveOccurred())
   182  		if runtime.GOOS == "windows" {
   183  			Expect(*apps[0].Path).To(Equal("\\some\\another\\path-segment"))
   184  		} else {
   185  			Expect(*apps[0].Path).To(Equal("/some/another/path-segment"))
   186  		}
   187  	})
   188  
   189  	It("returns errors when there are null values", func() {
   190  		m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   191  			"applications": []interface{}{
   192  				map[interface{}]interface{}{
   193  					"disk_quota":   nil,
   194  					"domain":       nil,
   195  					"host":         nil,
   196  					"name":         nil,
   197  					"path":         nil,
   198  					"stack":        nil,
   199  					"memory":       nil,
   200  					"instances":    nil,
   201  					"timeout":      nil,
   202  					"no-route":     nil,
   203  					"no-hostname":  nil,
   204  					"services":     nil,
   205  					"env":          nil,
   206  					"random-route": nil,
   207  				},
   208  			},
   209  		}))
   210  
   211  		_, err := m.Applications()
   212  		Expect(err).To(HaveOccurred())
   213  		errorSlice := strings.Split(err.Error(), "\n")
   214  		manifestKeys := []string{"disk_quota", "domain", "host", "name", "path", "stack",
   215  			"memory", "instances", "timeout", "no-route", "no-hostname", "services", "env", "random-route"}
   216  
   217  		for _, key := range manifestKeys {
   218  			Expect(errorSlice).To(ContainSubstrings([]string{key, "not be null"}))
   219  		}
   220  	})
   221  
   222  	It("returns errors when hosts/domains is not valid slice", func() {
   223  		m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   224  			"applications": []interface{}{
   225  				map[interface{}]interface{}{
   226  					"hosts":   "bad-value",
   227  					"domains": []interface{}{"val1", "val2", false, true},
   228  				},
   229  			},
   230  		}))
   231  
   232  		_, err := m.Applications()
   233  		Expect(err).To(HaveOccurred())
   234  		errorSlice := strings.Split(err.Error(), "\n")
   235  
   236  		Expect(errorSlice).To(ContainSubstrings([]string{"hosts", "to be a list of strings"}))
   237  		Expect(errorSlice).To(ContainSubstrings([]string{"domains", "to be a list of strings"}))
   238  	})
   239  
   240  	It("parses known manifest keys", func() {
   241  		m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   242  			"applications": []interface{}{
   243  				map[interface{}]interface{}{
   244  					"buildpack":         "my-buildpack",
   245  					"disk_quota":        "512M",
   246  					"domain":            "my-domain",
   247  					"domains":           []interface{}{"domain1.test", "domain2.test"},
   248  					"host":              "my-hostname",
   249  					"hosts":             []interface{}{"host-1", "host-2"},
   250  					"name":              "my-app-name",
   251  					"stack":             "my-stack",
   252  					"memory":            "256M",
   253  					"health-check-type": "none",
   254  					"instances":         1,
   255  					"timeout":           11,
   256  					"no-route":          true,
   257  					"no-hostname":       true,
   258  					"random-route":      true,
   259  				},
   260  			},
   261  		}))
   262  
   263  		apps, err := m.Applications()
   264  		Expect(err).NotTo(HaveOccurred())
   265  		Expect(len(apps)).To(Equal(1))
   266  
   267  		Expect(*apps[0].BuildpackURL).To(Equal("my-buildpack"))
   268  		Expect(*apps[0].DiskQuota).To(Equal(int64(512)))
   269  		Expect(apps[0].Domains).To(ConsistOf([]string{"domain1.test", "domain2.test", "my-domain"}))
   270  		Expect(apps[0].Hosts).To(ConsistOf([]string{"host-1", "host-2", "my-hostname"}))
   271  		Expect(*apps[0].Name).To(Equal("my-app-name"))
   272  		Expect(*apps[0].StackName).To(Equal("my-stack"))
   273  		Expect(*apps[0].HealthCheckType).To(Equal("none"))
   274  		Expect(*apps[0].Memory).To(Equal(int64(256)))
   275  		Expect(*apps[0].InstanceCount).To(Equal(1))
   276  		Expect(*apps[0].HealthCheckTimeout).To(Equal(11))
   277  		Expect(apps[0].NoRoute).To(BeTrue())
   278  		Expect(*apps[0].NoHostname).To(BeTrue())
   279  		Expect(apps[0].UseRandomRoute).To(BeTrue())
   280  	})
   281  
   282  	It("removes duplicated values in 'hosts' and 'domains'", func() {
   283  		m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   284  			"applications": []interface{}{
   285  				map[interface{}]interface{}{
   286  					"domain":  "my-domain",
   287  					"domains": []interface{}{"my-domain", "domain1.test", "domain1.test", "domain2.test"},
   288  					"host":    "my-hostname",
   289  					"hosts":   []interface{}{"my-hostname", "host-1", "host-1", "host-2"},
   290  					"name":    "my-app-name",
   291  				},
   292  			},
   293  		}))
   294  
   295  		apps, err := m.Applications()
   296  		Expect(err).NotTo(HaveOccurred())
   297  		Expect(len(apps)).To(Equal(1))
   298  
   299  		Expect(len(apps[0].Domains)).To(Equal(3))
   300  		Expect(apps[0].Domains).To(ConsistOf([]string{"my-domain", "domain1.test", "domain2.test"}))
   301  		Expect(len(apps[0].Hosts)).To(Equal(3))
   302  		Expect(apps[0].Hosts).To(ConsistOf([]string{"my-hostname", "host-1", "host-2"}))
   303  	})
   304  
   305  	Context("old-style property syntax", func() {
   306  		It("returns an error when the manifest contains non-whitelist properties", func() {
   307  			m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   308  				"applications": []interface{}{
   309  					generic.NewMap(map[interface{}]interface{}{
   310  						"env": generic.NewMap(map[interface{}]interface{}{
   311  							"bar": "many-${some_property-name}-are-cool",
   312  						}),
   313  					}),
   314  				},
   315  			}))
   316  
   317  			_, err := m.Applications()
   318  			Expect(err).To(HaveOccurred())
   319  			Expect(err.Error()).To(ContainSubstring("'${some_property-name}'"))
   320  		})
   321  
   322  		It("replaces the '${random-word} with a combination of 2 random words", func() {
   323  			m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   324  				"applications": []interface{}{
   325  					generic.NewMap(map[interface{}]interface{}{
   326  						"env": generic.NewMap(map[interface{}]interface{}{
   327  							"bar": "prefix_${random-word}_suffix",
   328  							"foo": "some-value",
   329  						}),
   330  					}),
   331  				},
   332  			}))
   333  
   334  			apps, err := m.Applications()
   335  			Expect(err).NotTo(HaveOccurred())
   336  			Expect((*apps[0].EnvironmentVars)["bar"]).To(MatchRegexp(`prefix_\w+-\w+_suffix`))
   337  			Expect((*apps[0].EnvironmentVars)["foo"]).To(Equal("some-value"))
   338  
   339  			apps2, _ := m.Applications()
   340  			Expect((*apps2[0].EnvironmentVars)["bar"]).To(MatchRegexp(`prefix_\w+-\w+_suffix`))
   341  			Expect((*apps2[0].EnvironmentVars)["bar"]).NotTo(Equal((*apps[0].EnvironmentVars)["bar"]))
   342  		})
   343  	})
   344  
   345  	It("sets the command and buildpack to blank when their values are null in the manifest", func() {
   346  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   347  			"applications": []interface{}{
   348  				generic.NewMap(map[interface{}]interface{}{
   349  					"buildpack": nil,
   350  					"command":   nil,
   351  				}),
   352  			},
   353  		}))
   354  
   355  		apps, err := m.Applications()
   356  		Expect(err).NotTo(HaveOccurred())
   357  		Expect(*apps[0].Command).To(Equal(""))
   358  		Expect(*apps[0].BuildpackURL).To(Equal(""))
   359  	})
   360  
   361  	It("sets the command and buildpack to blank when their values are 'default' in the manifest", func() {
   362  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   363  			"applications": []interface{}{
   364  				generic.NewMap(map[interface{}]interface{}{
   365  					"command":   "default",
   366  					"buildpack": "default",
   367  				}),
   368  			},
   369  		}))
   370  
   371  		apps, err := m.Applications()
   372  		Expect(err).NotTo(HaveOccurred())
   373  		Expect(*apps[0].Command).To(Equal(""))
   374  		Expect(*apps[0].BuildpackURL).To(Equal(""))
   375  	})
   376  
   377  	It("does not set the start command when the manifest doesn't have the 'command' key", func() {
   378  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   379  			"applications": []interface{}{
   380  				map[interface{}]interface{}{},
   381  			},
   382  		}))
   383  
   384  		apps, err := m.Applications()
   385  		Expect(err).NotTo(HaveOccurred())
   386  		Expect(apps[0].Command).To(BeNil())
   387  	})
   388  
   389  	It("can build the applications multiple times", func() {
   390  		m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   391  			"memory": "254m",
   392  			"applications": []interface{}{
   393  				map[interface{}]interface{}{
   394  					"name": "bitcoin-miner",
   395  				},
   396  				map[interface{}]interface{}{
   397  					"name": "bitcoin-miner",
   398  				},
   399  			},
   400  		}))
   401  
   402  		apps1, err := m.Applications()
   403  		Expect(err).NotTo(HaveOccurred())
   404  
   405  		apps2, err := m.Applications()
   406  		Expect(err).NotTo(HaveOccurred())
   407  		Expect(apps1).To(Equal(apps2))
   408  	})
   409  
   410  	Context("parsing app ports", func() {
   411  		It("parses app ports", func() {
   412  			m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   413  				"applications": []interface{}{
   414  					map[interface{}]interface{}{
   415  						"app-ports": []interface{}{
   416  							8080,
   417  							9090,
   418  						},
   419  					},
   420  				},
   421  			}))
   422  
   423  			apps, err := m.Applications()
   424  			Expect(err).NotTo(HaveOccurred())
   425  
   426  			Expect(apps[0].AppPorts).NotTo(BeNil())
   427  			Expect(*(apps[0].AppPorts)).To(Equal([]int{8080, 9090}))
   428  		})
   429  
   430  		It("handles omitted field", func() {
   431  			m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   432  				"applications": []interface{}{
   433  					map[interface{}]interface{}{},
   434  				},
   435  			}))
   436  
   437  			apps, err := m.Applications()
   438  			Expect(err).NotTo(HaveOccurred())
   439  
   440  			Expect(apps[0].AppPorts).To(BeNil())
   441  		})
   442  
   443  		It("handles mixed arrays", func() {
   444  			m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   445  				"applications": []interface{}{
   446  					map[interface{}]interface{}{
   447  						"app-ports": []interface{}{
   448  							8080,
   449  							"potato",
   450  						},
   451  					},
   452  				},
   453  			}))
   454  
   455  			_, err := m.Applications()
   456  			Expect(err).To(HaveOccurred())
   457  			Expect(err.Error()).To(ContainSubstring("Expected app-ports to be a list of integers."))
   458  		})
   459  
   460  		It("handles non-array values", func() {
   461  			m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
   462  				"applications": []interface{}{
   463  					map[interface{}]interface{}{
   464  						"app-ports": "potato",
   465  					},
   466  				},
   467  			}))
   468  
   469  			_, err := m.Applications()
   470  			Expect(err).To(HaveOccurred())
   471  			Expect(err.Error()).To(ContainSubstring("Expected app-ports to be a list of integers."))
   472  		})
   473  	})
   474  
   475  	Context("parsing env vars", func() {
   476  		It("handles values that are not strings", func() {
   477  			m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   478  				"applications": []interface{}{
   479  					generic.NewMap(map[interface{}]interface{}{
   480  						"env": map[interface{}]interface{}{
   481  							"string-key": "value",
   482  							"int-key":    1,
   483  							"float-key":  11.1,
   484  						},
   485  					}),
   486  				},
   487  			}))
   488  
   489  			app, err := m.Applications()
   490  			Expect(err).NotTo(HaveOccurred())
   491  
   492  			Expect((*app[0].EnvironmentVars)["string-key"]).To(Equal("value"))
   493  			Expect((*app[0].EnvironmentVars)["int-key"]).To(Equal(1))
   494  			Expect((*app[0].EnvironmentVars)["float-key"]).To(Equal(11.1))
   495  		})
   496  	})
   497  
   498  	Context("parsing services", func() {
   499  		It("can read a list of service instance names", func() {
   500  			m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   501  				"services": []interface{}{"service-1", "service-2"},
   502  			}))
   503  
   504  			app, err := m.Applications()
   505  			Expect(err).NotTo(HaveOccurred())
   506  
   507  			Expect(app[0].ServicesToBind).To(Equal([]string{"service-1", "service-2"}))
   508  		})
   509  	})
   510  
   511  	Context("when routes are provided", func() {
   512  		var manifest *manifest.Manifest
   513  
   514  		Context("when passed 'routes'", func() {
   515  			Context("valid 'routes'", func() {
   516  				BeforeEach(func() {
   517  					manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   518  						"applications": []interface{}{
   519  							generic.NewMap(map[interface{}]interface{}{
   520  								"routes": []interface{}{
   521  									map[interface{}]interface{}{"route": "route1.example.com"},
   522  									map[interface{}]interface{}{"route": "route2.example.com"},
   523  								},
   524  							}),
   525  						},
   526  					}))
   527  				})
   528  
   529  				It("parses routes into app params", func() {
   530  					apps, err := manifest.Applications()
   531  					Expect(err).NotTo(HaveOccurred())
   532  					Expect(apps).To(HaveLen(1))
   533  
   534  					routes := apps[0].Routes
   535  					Expect(routes).To(HaveLen(2))
   536  					Expect(routes[0].Route).To(Equal("route1.example.com"))
   537  					Expect(routes[1].Route).To(Equal("route2.example.com"))
   538  				})
   539  			})
   540  
   541  			Context("invalid 'routes'", func() {
   542  				Context("'routes' is formatted incorrectly", func() {
   543  					BeforeEach(func() {
   544  						manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   545  							"applications": []interface{}{
   546  								generic.NewMap(map[interface{}]interface{}{
   547  									"routes": []string{},
   548  								}),
   549  							},
   550  						}))
   551  					})
   552  
   553  					It("errors out", func() {
   554  						_, err := manifest.Applications()
   555  						Expect(err).To(HaveOccurred())
   556  						Expect(err.Error()).To(MatchRegexp("should be a list"))
   557  					})
   558  				})
   559  
   560  				Context("an individual 'route' is formatted incorrectly", func() {
   561  					BeforeEach(func() {
   562  						manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   563  							"applications": []interface{}{
   564  								generic.NewMap(map[interface{}]interface{}{
   565  									"routes": []interface{}{
   566  										map[interface{}]interface{}{"routef": "route1.example.com"},
   567  									},
   568  								}),
   569  							},
   570  						}))
   571  					})
   572  
   573  					It("parses routes into app params", func() {
   574  						_, err := manifest.Applications()
   575  						Expect(err).To(HaveOccurred())
   576  						Expect(err.Error()).To(MatchRegexp("each route in 'routes' must have a 'route' property"))
   577  					})
   578  				})
   579  			})
   580  		})
   581  
   582  		Context("when there are no routes", func() {
   583  			BeforeEach(func() {
   584  				manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   585  					"applications": []interface{}{
   586  						generic.NewMap(map[interface{}]interface{}{
   587  							"buildpack": nil,
   588  							"command":   "echo banana",
   589  						}),
   590  					},
   591  				}))
   592  			})
   593  
   594  			It("sets routes to be nil", func() {
   595  				apps, err := manifest.Applications()
   596  				Expect(err).NotTo(HaveOccurred())
   597  				Expect(apps).To(HaveLen(1))
   598  				Expect(apps[0].Routes).To(BeNil())
   599  			})
   600  		})
   601  
   602  		Context("when no-hostname is not specified in the manifest", func() {
   603  			BeforeEach(func() {
   604  				manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   605  					"applications": []interface{}{
   606  						generic.NewMap(map[interface{}]interface{}{
   607  							"buildpack": nil,
   608  							"command":   "echo banana",
   609  						}),
   610  					},
   611  				}))
   612  			})
   613  
   614  			It("sets no-hostname to be nil", func() {
   615  				apps, err := manifest.Applications()
   616  				Expect(err).NotTo(HaveOccurred())
   617  				Expect(apps).To(HaveLen(1))
   618  				Expect(apps[0].NoHostname).To(BeNil())
   619  			})
   620  		})
   621  
   622  		Context("when no-hostname is specified in the manifest", func() {
   623  			Context("and it is set to true", func() {
   624  				Context("and the value is a boolean", func() {
   625  					BeforeEach(func() {
   626  						manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   627  							"applications": []interface{}{
   628  								generic.NewMap(map[interface{}]interface{}{
   629  									"buildpack":   nil,
   630  									"command":     "echo banana",
   631  									"no-hostname": true,
   632  								}),
   633  							},
   634  						}))
   635  					})
   636  
   637  					It("sets no-hostname to be true", func() {
   638  						apps, err := manifest.Applications()
   639  						Expect(err).NotTo(HaveOccurred())
   640  						Expect(apps).To(HaveLen(1))
   641  						Expect(*apps[0].NoHostname).To(BeTrue())
   642  					})
   643  				})
   644  				Context("and the value is a string", func() {
   645  					BeforeEach(func() {
   646  						manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   647  							"applications": []interface{}{
   648  								generic.NewMap(map[interface{}]interface{}{
   649  									"buildpack":   nil,
   650  									"command":     "echo banana",
   651  									"no-hostname": "true",
   652  								}),
   653  							},
   654  						}))
   655  					})
   656  
   657  					It("sets no-hostname to be true", func() {
   658  						apps, err := manifest.Applications()
   659  						Expect(err).NotTo(HaveOccurred())
   660  						Expect(apps).To(HaveLen(1))
   661  						Expect(*apps[0].NoHostname).To(BeTrue())
   662  					})
   663  				})
   664  			})
   665  			Context("and it is set to false", func() {
   666  				BeforeEach(func() {
   667  					manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{
   668  						"applications": []interface{}{
   669  							generic.NewMap(map[interface{}]interface{}{
   670  								"buildpack":   nil,
   671  								"command":     "echo banana",
   672  								"no-hostname": false,
   673  							}),
   674  						},
   675  					}))
   676  				})
   677  				It("sets no-hostname to be false", func() {
   678  					apps, err := manifest.Applications()
   679  					Expect(err).NotTo(HaveOccurred())
   680  					Expect(apps).To(HaveLen(1))
   681  					Expect(*apps[0].NoHostname).To(BeFalse())
   682  				})
   683  			})
   684  		})
   685  	})
   686  })