snapshots: Move external snapshot creation to backend

This commit is contained in:
Victor Cinaglia 2018-12-10 16:36:32 -05:00
parent d9d6a4481f
commit 9d6da10e82
No known key found for this signature in database
GPG Key ID: 2D68FAE898258503
4 changed files with 103 additions and 56 deletions

View File

@ -1,10 +1,15 @@
package api
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/metrics"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/guardian"
@ -12,6 +17,11 @@ import (
"github.com/grafana/grafana/pkg/util"
)
var client = &http.Client{
Timeout: time.Second * 5,
Transport: &http.Transport{Proxy: http.ProxyFromEnvironment},
}
func GetSharingOptions(c *m.ReqContext) {
c.JSON(200, util.DynMap{
"externalSnapshotURL": setting.ExternalSnapshotUrl,
@ -20,26 +30,82 @@ func GetSharingOptions(c *m.ReqContext) {
})
}
type CreateExternalSnapshotResponse struct {
Key string `json:"key"`
DeleteKey string `json:"deleteKey"`
Url string `json:"url"`
DeleteUrl string `json:"deleteUrl"`
}
func createExternalDashboardSnapshot(cmd m.CreateDashboardSnapshotCommand) (*CreateExternalSnapshotResponse, error) {
var createSnapshotResponse CreateExternalSnapshotResponse
message := map[string]interface{}{
"name": cmd.Name,
"expires": cmd.Expires,
"dashboard": cmd.Dashboard,
}
messageBytes, err := simplejson.NewFromAny(message).Encode()
if err != nil {
return nil, err
}
response, err := client.Post(setting.ExternalSnapshotUrl+"/api/snapshots", "application/json", bytes.NewBuffer(messageBytes))
if response != nil {
defer response.Body.Close()
}
if err != nil {
return nil, err
}
if response.StatusCode != 200 {
return nil, fmt.Errorf("Create external snapshot response status code %d", response.StatusCode)
}
if err := json.NewDecoder(response.Body).Decode(&createSnapshotResponse); err != nil {
return nil, err
}
return &createSnapshotResponse, nil
}
// POST /api/snapshots
func CreateDashboardSnapshot(c *m.ReqContext, cmd m.CreateDashboardSnapshotCommand) {
if cmd.Name == "" {
cmd.Name = "Unnamed snapshot"
}
var url string
cmd.ExternalUrl = ""
cmd.OrgId = c.OrgId
cmd.UserId = c.UserId
if cmd.External {
// external snapshot ref requires key and delete key
if cmd.Key == "" || cmd.DeleteKey == "" {
c.JsonApiErr(400, "Missing key and delete key for external snapshot", nil)
if !setting.ExternalEnabled {
c.JsonApiErr(403, "External dashboard creation is disabled", nil)
return
}
cmd.OrgId = -1
cmd.UserId = -1
response, err := createExternalDashboardSnapshot(cmd)
if err != nil {
c.JsonApiErr(500, "Failed to create external snaphost", err)
return
}
url = response.Url
cmd.Key = response.Key
cmd.DeleteKey = response.DeleteKey
cmd.ExternalUrl = response.Url
cmd.ExternalDeleteUrl = response.DeleteUrl
cmd.Dashboard = simplejson.New()
metrics.M_Api_Dashboard_Snapshot_External.Inc()
} else {
cmd.Key = util.GetRandomString(32)
cmd.DeleteKey = util.GetRandomString(32)
cmd.OrgId = c.OrgId
cmd.UserId = c.UserId
url = setting.ToAbsUrl("dashboard/snapshot/" + cmd.Key)
metrics.M_Api_Dashboard_Snapshot_Create.Inc()
}
@ -51,7 +117,7 @@ func CreateDashboardSnapshot(c *m.ReqContext, cmd m.CreateDashboardSnapshotComma
c.JSON(200, util.DynMap{
"key": cmd.Key,
"deleteKey": cmd.DeleteKey,
"url": setting.ToAbsUrl("dashboard/snapshot/" + cmd.Key),
"url": url,
"deleteUrl": setting.ToAbsUrl("api/snapshots-delete/" + cmd.DeleteKey),
})
}

View File

@ -8,14 +8,15 @@ import (
// DashboardSnapshot model
type DashboardSnapshot struct {
Id int64
Name string
Key string
DeleteKey string
OrgId int64
UserId int64
External bool
ExternalUrl string
Id int64
Name string
Key string
DeleteKey string
OrgId int64
UserId int64
External bool
ExternalUrl string
ExternalDeleteUrl string
Expires time.Time
Created time.Time
@ -48,7 +49,10 @@ type CreateDashboardSnapshotCommand struct {
Expires int64 `json:"expires"`
// these are passed when storing an external snapshot ref
External bool `json:"external"`
External bool `json:"external"`
ExternalUrl string `json:"-"`
ExternalDeleteUrl string `json:"-"`
Key string `json:"key"`
DeleteKey string `json:"deleteKey"`

View File

@ -47,16 +47,18 @@ func CreateDashboardSnapshot(cmd *m.CreateDashboardSnapshotCommand) error {
}
snapshot := &m.DashboardSnapshot{
Name: cmd.Name,
Key: cmd.Key,
DeleteKey: cmd.DeleteKey,
OrgId: cmd.OrgId,
UserId: cmd.UserId,
External: cmd.External,
Dashboard: cmd.Dashboard,
Expires: expires,
Created: time.Now(),
Updated: time.Now(),
Name: cmd.Name,
Key: cmd.Key,
DeleteKey: cmd.DeleteKey,
OrgId: cmd.OrgId,
UserId: cmd.UserId,
External: cmd.External,
ExternalUrl: cmd.ExternalUrl,
ExternalDeleteUrl: cmd.ExternalDeleteUrl,
Dashboard: cmd.Dashboard,
Expires: expires,
Created: time.Now(),
Updated: time.Now(),
}
_, err := sess.Insert(snapshot)

View File

@ -27,7 +27,6 @@ export class ShareSnapshotCtrl {
$scope.init = () => {
backendSrv.get('/api/snapshot/shared-options').then(options => {
$scope.externalUrl = options['externalSnapshotURL'];
$scope.sharingButtonText = options['externalSnapshotName'];
$scope.externalEnabled = options['externalEnabled'];
});
@ -61,30 +60,14 @@ export class ShareSnapshotCtrl {
dashboard: dash,
name: dash.title,
expires: $scope.snapshot.expires,
external: external,
};
const postUrl = external ? $scope.externalUrl + $scope.apiUrl : $scope.apiUrl;
backendSrv.post(postUrl, cmdData).then(
backendSrv.post($scope.apiUrl, cmdData).then(
results => {
$scope.loading = false;
if (external) {
$scope.deleteUrl = results.deleteUrl;
$scope.snapshotUrl = results.url;
$scope.saveExternalSnapshotRef(cmdData, results);
} else {
const url = $location.url();
let baseUrl = $location.absUrl();
if (url !== '/') {
baseUrl = baseUrl.replace(url, '') + '/';
}
$scope.snapshotUrl = baseUrl + 'dashboard/snapshot/' + results.key;
$scope.deleteUrl = baseUrl + 'api/snapshots-delete/' + results.deleteKey;
}
$scope.deleteUrl = results.deleteUrl;
$scope.snapshotUrl = results.url;
$scope.step = 2;
},
() => {
@ -161,14 +144,6 @@ export class ShareSnapshotCtrl {
$scope.step = 3;
});
};
$scope.saveExternalSnapshotRef = (cmdData, results) => {
// save external in local instance as well
cmdData.external = true;
cmdData.key = results.key;
cmdData.deleteKey = results.deleteKey;
backendSrv.post('/api/snapshots/', cmdData);
};
}
}