This repository has been archived by the owner on Nov 3, 2021. It is now read-only.
/
process_handler.go
136 lines (116 loc) · 3.79 KB
/
process_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package apis
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"code.cloudfoundry.org/cf-k8s-api/presenter"
"code.cloudfoundry.org/cf-k8s-api/repositories"
"github.com/go-logr/logr"
"github.com/gorilla/mux"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
ProcessGetEndpoint = "/v3/processes/{guid}"
ProcessGetSidecarsEndpoint = "/v3/processes/{guid}/sidecars"
)
//counterfeiter:generate -o fake -fake-name CFProcessRepository . CFProcessRepository
type CFProcessRepository interface {
FetchProcess(context.Context, client.Client, string) (repositories.ProcessRecord, error)
FetchProcessesForApp(context.Context, client.Client, string, string) ([]repositories.ProcessRecord, error)
}
type ProcessHandler struct {
logger logr.Logger
serverURL url.URL
processRepo CFProcessRepository
buildClient ClientBuilder
k8sConfig *rest.Config // TODO: this would be global for all requests, not what we want
}
func NewProcessHandler(
logger logr.Logger,
serverURL url.URL,
processRepo CFProcessRepository,
buildClient ClientBuilder,
k8sConfig *rest.Config) *ProcessHandler {
return &ProcessHandler{
logger: logger,
serverURL: serverURL,
processRepo: processRepo,
buildClient: buildClient,
k8sConfig: k8sConfig,
}
}
func (h *ProcessHandler) processGetHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
processGUID := vars["guid"]
client, err := h.buildClient(h.k8sConfig)
if err != nil {
h.logger.Error(err, "Unable to create Kubernetes client", "ProcessGUID", processGUID)
writeUnknownErrorResponse(w)
return
}
process, err := h.processRepo.FetchProcess(ctx, client, processGUID)
if err != nil {
h.LogError(w, processGUID, err)
return
}
responseBody, err := json.Marshal(presenter.ForProcess(process, h.serverURL))
if err != nil {
h.logger.Error(err, "Failed to render response", "ProcessGUID", processGUID)
writeUnknownErrorResponse(w)
return
}
w.Write(responseBody)
}
func (h *ProcessHandler) processGetSidecarsHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
processGUID := vars["guid"]
// TODO: Instantiate config based on bearer token
// Spike code from EMEA folks around this: https://github.com/cloudfoundry/cf-crd-explorations/blob/136417fbff507eb13c92cd67e6fed6b061071941/cfshim/handlers/app_handler.go#L78
client, err := h.buildClient(h.k8sConfig)
if err != nil {
h.logger.Error(err, "Unable to create Kubernetes client", "ProcessGUID", processGUID)
writeUnknownErrorResponse(w)
return
}
_, err = h.processRepo.FetchProcess(ctx, client, processGUID)
if err != nil {
h.LogError(w, processGUID, err)
return
}
w.Write([]byte(fmt.Sprintf(`{
"pagination": {
"total_results": 0,
"total_pages": 1,
"first": {
"href": "%[1]s/v3/processes/%[2]s/sidecars?page=1"
},
"last": {
"href": "%[1]s/v3/processes/%[2]s/sidecars?page=1"
},
"next": null,
"previous": null
},
"resources": []
}`, h.serverURL.String(), processGUID)))
}
func (h *ProcessHandler) LogError(w http.ResponseWriter, processGUID string, err error) {
switch err.(type) {
case repositories.NotFoundError:
h.logger.Info("Process not found", "ProcessGUID", processGUID)
writeNotFoundErrorResponse(w, "Process")
default:
h.logger.Error(err, "Failed to fetch process from Kubernetes", "ProcessGUID", processGUID)
writeUnknownErrorResponse(w)
}
}
func (h *ProcessHandler) RegisterRoutes(router *mux.Router) {
router.Path(ProcessGetEndpoint).Methods("GET").HandlerFunc(h.processGetHandler)
router.Path(ProcessGetSidecarsEndpoint).Methods("GET").HandlerFunc(h.processGetSidecarsHandler)
}