oncall-engine/grafana-plugin/pkg/plugin/install.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

136 lines
3.7 KiB
Go

package plugin
import (
"bytes"
"encoding/json"
"io"
"net/url"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"net/http"
)
type OnCallInstall struct {
OnCallError `json:"onCallError,omitempty"`
}
func (a *App) handleInstall(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
locked := a.installMutex.TryLock()
if !locked {
http.Error(w, "Install is already in progress", http.StatusBadRequest)
return
}
defer a.installMutex.Unlock()
onCallPluginSettings, err := a.OnCallSettingsFromContext(req.Context())
if err != nil {
log.DefaultLogger.Error("Error getting settings from context", "error", err)
return
}
healthStatus, err := a.CheckOnCallApiHealthStatus(onCallPluginSettings)
if err != nil {
log.DefaultLogger.Error("Error checking on-call API health", "error", err)
http.Error(w, err.Error(), healthStatus)
return
}
onCallSync, err := a.GetSyncData(req.Context(), onCallPluginSettings)
if err != nil {
log.DefaultLogger.Error("Error getting sync data", "error", err)
return
}
onCallSyncJsonData, err := json.Marshal(onCallSync)
if err != nil {
log.DefaultLogger.Error("Error marshalling JSON", "error", err)
return
}
installURL, err := url.JoinPath(onCallPluginSettings.OnCallAPIURL, "api/internal/v1/plugin/v2/install")
if err != nil {
log.DefaultLogger.Error("Error joining path", "error", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
parsedInstallURL, err := url.Parse(installURL)
if err != nil {
log.DefaultLogger.Error("Error parsing path", "error", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
installReq, err := http.NewRequest("POST", parsedInstallURL.String(), bytes.NewBuffer(onCallSyncJsonData))
if err != nil {
log.DefaultLogger.Error("Error creating request", "error", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
installReq.Header.Set("Content-Type", "application/json")
res, err := a.httpClient.Do(installReq)
if err != nil {
log.DefaultLogger.Error("Error request to oncall", "error", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
errorBody, err := io.ReadAll(res.Body)
var installError = OnCallInstall{
OnCallError: OnCallError{
Code: INSTALL_ERROR_CODE,
Message: "Install failed check /status for details",
},
}
if errorBody != nil {
var tempError OnCallError
err = json.Unmarshal(errorBody, &tempError)
if err != nil {
log.DefaultLogger.Error("Error unmarshalling OnCallError", "error", err)
}
if tempError.Message == "" {
installError.OnCallError.Message = string(errorBody)
} else {
installError.OnCallError = tempError
}
}
w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(installError); err != nil {
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusBadRequest)
} else {
provisionBody, err := io.ReadAll(res.Body)
if err != nil {
log.DefaultLogger.Error("Error reading response body", "error", err)
return
}
var provisioningData OnCallProvisioningJSONData
err = json.Unmarshal(provisionBody, &provisioningData)
if err != nil {
log.DefaultLogger.Error("Error unmarshalling OnCallProvisioningJSONData", "error", err)
return
}
onCallPluginSettings.OnCallToken = provisioningData.OnCallToken
err = a.SaveOnCallSettings(onCallPluginSettings)
if err != nil {
log.DefaultLogger.Error("Error saving settings", "error", err)
return
}
w.WriteHeader(http.StatusOK)
}
}