Skip to content

Commit

Permalink
add health-check-http-endpoint to app manifest
Browse files Browse the repository at this point in the history
[finishes #138204973]

Signed-off-by: Matthew Boedicker <[email protected]>
  • Loading branch information
Alex Melnik authored and mmb committed Feb 8, 2017
1 parent 96158d3 commit f85408e
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 76 deletions.
4 changes: 4 additions & 0 deletions cf/actors/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ func (actor PushActorImpl) ValidateAppParams(apps []models.AppParams) []error {
for _, app := range apps {
appName := app.Name

if app.HealthCheckType != nil && *app.HealthCheckType != "http" && app.HealthCheckHTTPEndpoint != nil {
errs = append(errs, fmt.Errorf(T("Health check type must be 'http' to set a health check HTTP endpoint.")))
}

if app.Routes != nil {
if app.Hosts != nil {
errs = append(errs, fmt.Errorf(T("Application {{.AppName}} must not be configured with both 'routes' and 'host'/'hosts'", map[string]interface{}{"AppName": appName})))
Expand Down
20 changes: 20 additions & 0 deletions cf/actors/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,26 @@ var _ = Describe("Push Actor", func() {
Describe("ValidateAppParams", func() {
var apps []models.AppParams

Context("when HealthCheckType is not http", func() {
Context("when HealthCheckHTTPEndpoint is provided", func() {
BeforeEach(func() {
healthCheckType := "port"
endpoint := "/some-endpoint"
apps = []models.AppParams{
models.AppParams{
HealthCheckType: &healthCheckType,
HealthCheckHTTPEndpoint: &endpoint,
},
}
})
It("displays error", func() {
errs := actor.ValidateAppParams(apps)
Expect(errs).To(HaveLen(1))
Expect(errs[0].Error()).To(Equal("Health check type must be 'http' to set a health check HTTP endpoint."))
})
})
})

Context("when 'routes' is provided", func() {
BeforeEach(func() {
appName := "my-app"
Expand Down
8 changes: 7 additions & 1 deletion cf/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,15 @@ func mapToAppParams(basePath string, yamlMap generic.Map) (models.AppParams, err
appParams.ServicesToBind = sliceOrNil(yamlMap, "services", &errs)
appParams.EnvironmentVars = envVarOrEmptyMap(yamlMap, &errs)
appParams.HealthCheckType = stringVal(yamlMap, "health-check-type", &errs)
appParams.HealthCheckHTTPEndpoint = stringVal(yamlMap, "health-check-http-endpoint", &errs)

if appParams.HealthCheckType != nil && *appParams.HealthCheckType == "http" {
healthCheckHTTPEndpoint := "/"
var healthCheckHTTPEndpoint string
if appParams.HealthCheckHTTPEndpoint != nil {
healthCheckHTTPEndpoint = *appParams.HealthCheckHTTPEndpoint
} else {
healthCheckHTTPEndpoint = "/"
}
appParams.HealthCheckHTTPEndpoint = &healthCheckHTTPEndpoint
}

Expand Down
76 changes: 37 additions & 39 deletions cf/manifest/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,47 +315,45 @@ var _ = Describe("Manifests", func() {
Expect(apps[0].UseRandomRoute).To(BeTrue())
})

It("sets http-health-check-endpoint to '/' when the health-check-type is 'http'", func() {
m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
"applications": []interface{}{
map[interface{}]interface{}{
"buildpack": "my-buildpack",
"disk_quota": "512M",
"domain": "my-domain",
"domains": []interface{}{"domain1.test", "domain2.test"},
"host": "my-hostname",
"hosts": []interface{}{"host-1", "host-2"},
"name": "my-app-name",
"stack": "my-stack",
"memory": "256M",
"health-check-type": "http",
"instances": 1,
"timeout": 11,
"no-route": true,
"no-hostname": true,
"random-route": true,
},
},
}))
Context("when the health-check-type is 'http'", func() {
Context("when health-check-http-endpoint is NOT provided", func() {
It("sets http-health-check-endpoint to '/'", func() {
m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
"applications": []interface{}{
map[interface{}]interface{}{
"health-check-type": "http",
},
},
}))

apps, err := m.Applications()
Expect(err).NotTo(HaveOccurred())
Expect(len(apps)).To(Equal(1))
apps, err := m.Applications()
Expect(err).NotTo(HaveOccurred())
Expect(len(apps)).To(Equal(1))

Expect(*apps[0].BuildpackURL).To(Equal("my-buildpack"))
Expect(*apps[0].DiskQuota).To(Equal(int64(512)))
Expect(apps[0].Domains).To(ConsistOf([]string{"domain1.test", "domain2.test", "my-domain"}))
Expect(apps[0].Hosts).To(ConsistOf([]string{"host-1", "host-2", "my-hostname"}))
Expect(*apps[0].Name).To(Equal("my-app-name"))
Expect(*apps[0].StackName).To(Equal("my-stack"))
Expect(*apps[0].HealthCheckType).To(Equal("http"))
Expect(*apps[0].HealthCheckHTTPEndpoint).To(Equal("/"))
Expect(*apps[0].Memory).To(Equal(int64(256)))
Expect(*apps[0].InstanceCount).To(Equal(1))
Expect(*apps[0].HealthCheckTimeout).To(Equal(11))
Expect(apps[0].NoRoute).To(BeTrue())
Expect(*apps[0].NoHostname).To(BeTrue())
Expect(apps[0].UseRandomRoute).To(BeTrue())
Expect(*apps[0].HealthCheckType).To(Equal("http"))
Expect(*apps[0].HealthCheckHTTPEndpoint).To(Equal("/"))
})
})

Context("when health-check-http-endpoint IS provided", func() {
It("sets http-health-check-endpoint to the provided endpoint", func() {
m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{
"applications": []interface{}{
map[interface{}]interface{}{
"health-check-type": "http",
"health-check-http-endpoint": "/some-endpoint",
},
},
}))

apps, err := m.Applications()
Expect(err).NotTo(HaveOccurred())
Expect(len(apps)).To(Equal(1))

Expect(*apps[0].HealthCheckType).To(Equal("http"))
Expect(*apps[0].HealthCheckHTTPEndpoint).To(Equal("/some-endpoint"))
})
})
})

It("removes duplicated values in 'hosts' and 'domains'", func() {
Expand Down
144 changes: 108 additions & 36 deletions integration/isolated/push_command_with_health_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ var _ = Describe("Push with health check", func() {

appGUID := helpers.AppGUID(appName)
session := helpers.CF("curl", fmt.Sprintf("/v2/apps/%s", appGUID))
Eventually(session).Should(Exit(0))
Eventually(session.Out).Should(Say(`"health_check_http_endpoint": "/some-endpoint"`))
Eventually(session).Should(Exit(0))
})

Context("when the health check type is set to 'http'", func() {
Expand All @@ -116,8 +116,8 @@ var _ = Describe("Push with health check", func() {
It("preserves the existing endpoint", func() {
appGUID := helpers.AppGUID(appName)
session := helpers.CF("curl", fmt.Sprintf("/v2/apps/%s", appGUID))
Eventually(session).Should(Exit(0))
Eventually(session.Out).Should(Say(`"health_check_http_endpoint": "/some-endpoint"`))
Eventually(session).Should(Exit(0))
})
})

Expand All @@ -131,65 +131,137 @@ var _ = Describe("Push with health check", func() {
It("preserves the existing endpoint", func() {
appGUID := helpers.AppGUID(appName)
session := helpers.CF("curl", fmt.Sprintf("/v2/apps/%s", appGUID))
Eventually(session).Should(Exit(0))
Eventually(session.Out).Should(Say(`"health_check_http_endpoint": "/some-endpoint"`))
Eventually(session).Should(Exit(0))
})
})
})
})

Context("when pushing with manifest", func() {
Context("when setting the health check", func() {
DescribeTable("displays the correct health check type",
func(healthCheckType string, endpoint string) {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
Context("when the health type is http and an endpoint is provided", func() {
FIt("sets the health check type and endpoint", func() {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: %s
memory: 128M
health-check-type: http
health-check-http-endpoint: /some-endpoint
`, appName))
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())

Eventually(helpers.CF("push", "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0))
})

session := helpers.CF("get-health-check", appName)
Eventually(session.Out).Should(Say("Health check type:\\s+http"))
Eventually(session.Out).Should(Say("Endpoint \\(for http type\\):\\s+/some-endpoint\n"))
Eventually(session).Should(Exit(0))
})
})

Context("when the health type is not http and an endpoint is provided", func() {
FIt("displays an error", func() {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: %s
memory: 128M
health-check-type: port
health-check-http-endpoint: /some-endpoint
`, appName))
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())

session := helpers.CF("push", "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")
Eventually(session.Out).Should(Say("Health check type must be 'http' to set a health check HTTP endpoint."))
Eventually(session).Should(Exit(1))
})
})
})

Context("when passing an 'http' health check type with the -u option", func() {
It("resets the endpoint to the default", func() {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: %s
memory: 128M
health-check-type: http
health-check-http-endpoint: /some-endpoint
`, appName))
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())

Eventually(helpers.CF("push", "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack", "-u", "http")).Should(Exit(0))
})

session := helpers.CF("get-health-check", appName)
Eventually(session.Out).Should(Say("Health check type:\\s+http"))
Eventually(session.Out).Should(Say("Endpoint \\(for http type\\):\\s+/\n"))
Eventually(session).Should(Exit(0))
})
})
})

Context("when the manifest contains the health check type attribute", func() {
DescribeTable("displays the correct health check type",
func(healthCheckType string, endpoint string) {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: %s
memory: 128M
health-check-type: %s
`, appName, healthCheckType))
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())

Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0))
})
Eventually(helpers.CF("push", "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0))
})

session := helpers.CF("get-health-check", appName)
Eventually(session.Out).Should(Say("Health check type:\\s+%s", healthCheckType))
Eventually(session.Out).Should(Say("Endpoint \\(for http type\\):\\s+%s\n", endpoint))
Eventually(session).Should(Exit(0))
},
session := helpers.CF("get-health-check", appName)
Eventually(session.Out).Should(Say("Health check type:\\s+%s", healthCheckType))
Eventually(session.Out).Should(Say("Endpoint \\(for http type\\):\\s+%s\n", endpoint))
Eventually(session).Should(Exit(0))
},

Entry("when the health check type is none", "none", ""),
Entry("when the health check type is process", "process", ""),
Entry("when the health check type is port", "port", ""),
Entry("when the health check type is http", "http", "/"),
)
Entry("when the health check type is none", "none", ""),
Entry("when the health check type is process", "process", ""),
Entry("when the health check type is port", "port", ""),
Entry("when the health check type is http", "http", "/"),
)

Context("when passing a health check type with the -u option", func() {
It("overrides any health check types in the manifest", func() {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
Context("when passing a health check type with the -u option", func() {
It("overrides any health check types in the manifest", func() {
helpers.WithHelloWorldApp(func(appDir string) {
manifestContents := []byte(fmt.Sprintf(`
---
applications:
- name: %s
memory: 128M
health-check-type: port
`, appName))
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())

Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack", "-u", "http")).Should(Exit(0))
})
manifestPath := filepath.Join(appDir, "manifest.yml")
err := ioutil.WriteFile(manifestPath, manifestContents, 0666)
Expect(err).ToNot(HaveOccurred())

session := helpers.CF("get-health-check", appName)
Eventually(session.Out).Should(Say("Health check type:\\s+http"))
Eventually(session).Should(Exit(0))
Eventually(helpers.CF("push", "--no-start", "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack", "-u", "http")).Should(Exit(0))
})

session := helpers.CF("get-health-check", appName)
Eventually(session.Out).Should(Say("Health check type:\\s+http"))
Eventually(session).Should(Exit(0))
})
})
})
Expand Down
1 change: 1 addition & 0 deletions strings/excluded.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@
"no-start",
"security-group-rules",
"health-check-type",
"health-check-http-endpoint",
"disallow-paid-service-plans",
"map-route",
"delete-quota",
Expand Down

0 comments on commit f85408e

Please sign in to comment.