Skip to content

Commit

Permalink
Merge pull request #15 from Financial-Times/update-agg-hc
Browse files Browse the repository at this point in the history
Update agg hc
  • Loading branch information
tamas-molnar authored Jan 16, 2018
2 parents c3cedd4 + e71eadd commit c4cb6b5
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 17 deletions.
5 changes: 3 additions & 2 deletions checkerService.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ func (hs *k8sHealthcheckService) checkServiceHealth(service service) (string, er
}
}

totalNoOfPods :=len(pods)
totalNoOfPods := len(pods)
outputMsg := fmt.Sprintf("%v/%v pods available", totalNoOfPods - noOfUnavailablePods, totalNoOfPods)
if totalNoOfPods==0 || noOfUnavailablePods != 0 {
if totalNoOfPods == 0 || noOfUnavailablePods != 0 {
return "", errors.New(outputMsg)
}

Expand Down Expand Up @@ -83,6 +83,7 @@ func (hs *k8sHealthcheckService) getHealthChecksForPod(pod pod, appPort int32) (
return healthcheckResponse{}, errors.New("Error constructing healthcheck request: " + err.Error())
}

req.Header.Set("Accept", "application/json")
resp, err := hs.httpClient.Do(req)
if err != nil {
return healthcheckResponse{}, errors.New("Error performing healthcheck request: " + err.Error())
Expand Down
29 changes: 24 additions & 5 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
type httpHandler struct {
controller controller
pathPrefix string
clusterURL string
}

//IndividualHealthcheckParams struct used to populate HTML template with individual checks
Expand Down Expand Up @@ -89,9 +90,9 @@ func (h *httpHandler) handleEnableCategory(w http.ResponseWriter, r *http.Reques
}

func (h *httpHandler) handleRemoveAck(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control","no-cache, no-store, must-revalidate")
w.Header().Set("Pragma","no-cache")
w.Header().Set("Expires","0")
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
serviceName := getServiceNameFromURL(r.URL)
if serviceName == "" {
w.WriteHeader(http.StatusBadRequest)
Expand Down Expand Up @@ -187,6 +188,11 @@ func (h *httpHandler) handleServicesHealthCheck(w http.ResponseWriter, r *http.R
}

if r.Header.Get("Accept") == jsonContentType {
for i, serviceCheck := range healthResult.Checks {
serviceHealthcheckURL := getServiceHealthcheckURL(h.clusterURL, h.pathPrefix, serviceCheck.Name)
healthResult.Checks[i].TechnicalSummary = fmt.Sprintf("%s Service healthcheck: %s", serviceCheck.TechnicalSummary, serviceHealthcheckURL)
}

buildHealthcheckJSONResponse(w, healthResult)
} else {
env := h.controller.getEnvironment()
Expand Down Expand Up @@ -219,6 +225,11 @@ func (h *httpHandler) handlePodsHealthCheck(w http.ResponseWriter, r *http.Reque
}

if r.Header.Get("Accept") == jsonContentType {
for i, podCheck := range healthResult.Checks {
serviceHealthcheckURL := getIndividualPodHealthcheckURL(h.clusterURL, h.pathPrefix, podCheck.Name)
healthResult.Checks[i].TechnicalSummary = fmt.Sprintf("%s Pod healthcheck: %s", podCheck.TechnicalSummary, serviceHealthcheckURL)
}

buildHealthcheckJSONResponse(w, healthResult)
} else {
env := h.controller.getEnvironment()
Expand Down Expand Up @@ -438,7 +449,7 @@ func populateIndividualPodChecks(checks []fthealth.CheckResult, pathPrefix strin
Name: check.Name,
Status: getServiceStatusFromCheck(check),
LastUpdated: check.LastUpdated.Format(timeLayout),
MoreInfoPath: fmt.Sprintf("%s/__pod-individual-health?pod-name=%s", pathPrefix, podName),
MoreInfoPath: getIndividualPodHealthcheckURL("", pathPrefix, podName),
AckMessage: check.Ack,
Output: check.Output,
}
Expand All @@ -449,6 +460,10 @@ func populateIndividualPodChecks(checks []fthealth.CheckResult, pathPrefix strin
return indiviualServiceChecks, ackCount
}

func getIndividualPodHealthcheckURL(clusterURL, pathPrefix, podName string) string {
return fmt.Sprintf("%s%s/__pod-individual-health?pod-name=%s", clusterURL, pathPrefix, podName)
}

func extractPodName(checkName string) string {
s := strings.Split(checkName, " ")

Expand All @@ -464,7 +479,7 @@ func populateAggregatePodChecks(healthResult fthealth.HealthResult, environment
aggregateChecks := &AggregateHealthcheckParams{
PageTitle: fmt.Sprintf("UPP %s cluster's pods of service %s", environment, serviceName),
GeneralStatus: getGeneralStatus(healthResult),
RefreshFromCachePath: fmt.Sprintf("%s/__pods-health?service-name=%s", pathPrefix, serviceName),
RefreshFromCachePath: getServiceHealthcheckURL("", pathPrefix, serviceName),
RefreshWithoutCachePath: fmt.Sprintf("%s/__pods-health?cache=false&service-name=%s", pathPrefix, serviceName),
IndividualHealthChecks: individualChecks,
AckCount: ackCount,
Expand All @@ -473,6 +488,10 @@ func populateAggregatePodChecks(healthResult fthealth.HealthResult, environment
return aggregateChecks
}

func getServiceHealthcheckURL(hostURL, pathPrefix, serviceName string) string {
return fmt.Sprintf("%s%s/__pods-health?service-name=%s", hostURL, pathPrefix, serviceName)
}

func buildPageTitle(environment string, categories string) string {
return fmt.Sprintf("UPP %s cluster's services from categories %s", environment, categories)
}
Expand Down
5 changes: 5 additions & 0 deletions helm/upp-aggregate-healthcheck/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ spec:
configMapKeyRef:
name: global-config
key: environment
- name: CLUSTER_URL
valueFrom:
configMapKeyRef:
name: global-config
key: cluster.url
- name: GRAPHITE_URL
valueFrom:
configMapKeyRef:
Expand Down
8 changes: 8 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ func main() {
EnvVar: "GRAPHITE_URL",
})

clusterURL := app.String(cli.StringOpt{
Name: "cluster-url",
Value: "",
Desc: "Cluster URL",
EnvVar: "CLUSTER_URL",
})

app.Action = func() {
initLogs(os.Stdout, os.Stdout, os.Stderr)
infoLogger.Printf("Starting app with params: [environment: %s], [pathPrefix: %s], [graphiteURL: %s]", *environment, *pathPrefix, *graphiteURL)
Expand All @@ -48,6 +55,7 @@ func main() {
handler := &httpHandler{
controller: controller,
pathPrefix: *pathPrefix,
clusterURL: *clusterURL,
}

graphiteFeeder := newGraphiteFeeder(*graphiteURL, *environment, controller)
Expand Down
24 changes: 14 additions & 10 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import (
)

type k8sHealthcheckService struct {
k8sClient kubernetes.Interface
httpClient *http.Client
services servicesMap
k8sClient kubernetes.Interface
httpClient *http.Client
services servicesMap
acks map[string]string
}

type healthcheckService interface {
Expand Down Expand Up @@ -47,7 +48,7 @@ const (
func (hs *k8sHealthcheckService) updateAcksForServices(acksMap map[string]string) {
hs.services.Lock()
for serviceName, service := range hs.services.m {
if ackMsg, ok := acksMap[serviceName]; ok {
if ackMsg, found := acksMap[serviceName]; found {
service.ack = ackMsg
} else {
service.ack = ""
Expand All @@ -71,8 +72,10 @@ func (hs *k8sHealthcheckService) watchAcks() {
case watch.Added, watch.Modified:
k8sConfigMap := msg.Object.(*v1.ConfigMap)
hs.updateAcksForServices(k8sConfigMap.Data)
hs.acks = k8sConfigMap.Data
infoLogger.Printf("Acks configMap has been updated: %s", k8sConfigMap.Data)
case watch.Deleted:
hs.acks = make(map[string]string)
errorLogger.Print("Acks configMap has been deleted. From now on the acks will no longer be available.")
default:
errorLogger.Print("Error received on watch acks configMap. Channel may be full")
Expand All @@ -95,7 +98,7 @@ func (hs *k8sHealthcheckService) watchServices() {
switch msg.Type {
case watch.Added, watch.Modified:
k8sService := msg.Object.(*v1.Service)
service := populateService(k8sService)
service := populateService(k8sService, hs.acks)

hs.services.Lock()
hs.services.m[service.name] = service
Expand Down Expand Up @@ -142,13 +145,13 @@ func initializeHealthCheckService() *k8sHealthcheckService {
services := make(map[string]service)

k8sService := &k8sHealthcheckService{
httpClient: httpClient,
k8sClient: k8sClient,
services: servicesMap{m: services},
httpClient: httpClient,
k8sClient: k8sClient,
services: servicesMap{m: services},
}

go k8sService.watchServices()
go k8sService.watchAcks()
go k8sService.watchServices()

return k8sService
}
Expand Down Expand Up @@ -341,7 +344,7 @@ func populatePod(k8sPod v1.Pod) pod {
}
}

func populateService(k8sService *v1.Service) service {
func populateService(k8sService *v1.Service, acks map[string]string) service {
//services are resilient by default.
isResilient := true
isDaemon := false
Expand All @@ -366,6 +369,7 @@ func populateService(k8sService *v1.Service) service {
appPort: getAppPortForService(k8sService),
isDaemon: isDaemon,
isResilient: isResilient,
ack: acks[serviceName],
}
}

Expand Down

0 comments on commit c4cb6b5

Please sign in to comment.