oncall-engine/grafana-plugin/pkg/plugin/resources.go
Dominik Broj 06d19bf6e9
New OnCall plugin initialization process (#4657)
# What this PR does

New OnCall plugin initialization process

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.

---------

Co-authored-by: Michael Derynck <michael.derynck@grafana.com>
Co-authored-by: Matias Bordese <mbordese@gmail.com>
2024-08-16 16:43:52 +00:00

137 lines
3.8 KiB
Go

package plugin
import (
"bytes"
"encoding/json"
"net/http"
"sort"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
)
type OnCallSync struct {
Users []OnCallUser `json:"users"`
Teams []OnCallTeam `json:"teams"`
TeamMembers map[int][]int `json:"team_members"`
Settings OnCallPluginSettings `json:"settings"`
}
func (a *OnCallSync) Equal(b *OnCallSync) bool {
if len(a.Users) != len(b.Users) || len(a.Teams) != len(b.Teams) || len(a.TeamMembers) != len(b.TeamMembers) {
return false
}
for i := range a.Users {
if !a.Users[i].Equal(&b.Users[i]) {
return false
}
}
for i := range a.Teams {
if !a.Teams[i].Equal(&b.Teams[i]) {
return false
}
}
for key, teamMembersA := range a.TeamMembers {
if teamMembersB, exists := b.TeamMembers[key]; !exists {
if len(teamMembersA) != len(teamMembersB) {
return false
}
sort.Slice(teamMembersA, func(i, j int) bool {
return teamMembersA[i] < teamMembersA[j]
})
sort.Slice(teamMembersB, func(i, j int) bool {
return teamMembersB[i] < teamMembersB[j]
})
for i := range teamMembersA {
if teamMembersA[i] != teamMembersB[i] {
return false
}
}
}
}
if !a.Settings.Equal(&b.Settings) {
return false
}
return true
}
type responseWriter struct {
http.ResponseWriter
statusCode int
body bytes.Buffer
}
func (rw *responseWriter) WriteHeader(statusCode int) {
rw.statusCode = statusCode
rw.ResponseWriter.WriteHeader(statusCode)
}
func (rw *responseWriter) Write(b []byte) (int, error) {
if rw.statusCode == 0 {
rw.WriteHeader(http.StatusOK)
}
n, err := rw.body.Write(b)
if err != nil {
return n, err
}
return rw.ResponseWriter.Write(b)
}
func afterRequest(handler http.Handler, afterFunc func(*responseWriter, *http.Request)) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
wrappedWriter := &responseWriter{ResponseWriter: w}
handler.ServeHTTP(wrappedWriter, r)
afterFunc(wrappedWriter, r)
})
}
func (a *App) handleInternalApi(w http.ResponseWriter, req *http.Request) {
a.ProxyRequestToOnCall(w, req, "api/internal/v1/")
}
func (a *App) handleLegacyInstall(w *responseWriter, req *http.Request) {
var provisioningData OnCallProvisioningJSONData
err := json.Unmarshal(w.body.Bytes(), &provisioningData)
if err != nil {
log.DefaultLogger.Error("Error unmarshalling OnCallProvisioningJSONData", "error", err)
return
}
onCallPluginSettings, err := a.OnCallSettingsFromContext(req.Context())
if err != nil {
log.DefaultLogger.Error("Error getting settings from context", "error", err)
return
}
if provisioningData.Error != "" {
log.DefaultLogger.Error("Error installing OnCall", "error", provisioningData.Error)
return
}
onCallPluginSettings.License = provisioningData.License
onCallPluginSettings.OrgID = provisioningData.OrgId
onCallPluginSettings.StackID = provisioningData.StackId
onCallPluginSettings.OnCallToken = provisioningData.OnCallToken
err = a.SaveOnCallSettings(onCallPluginSettings)
if err != nil {
log.DefaultLogger.Error("Error saving settings", "error", err)
return
}
}
// registerRoutes takes a *http.ServeMux and registers some HTTP handlers.
func (a *App) registerRoutes(mux *http.ServeMux) {
mux.HandleFunc("/plugin/install", a.handleInstall)
mux.HandleFunc("/plugin/status", a.handleStatus)
mux.HandleFunc("/plugin/sync", a.handleSync)
mux.Handle("/plugin/self-hosted/install", afterRequest(http.HandlerFunc(a.handleInternalApi), a.handleLegacyInstall))
// Disable debug endpoints
//mux.HandleFunc("/debug/user", a.handleDebugUser)
//mux.HandleFunc("/debug/sync", a.handleDebugSync)
//mux.HandleFunc("/debug/settings", a.handleDebugSettings)
//mux.HandleFunc("/debug/permissions", a.handleDebugPermissions)
//mux.HandleFunc("/debug/stats", a.handleDebugStats)
mux.HandleFunc("/", a.handleInternalApi)
}