Commit 9d6da10e by Victor Cinaglia

snapshots: Move external snapshot creation to backend

parent d9d6a448
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
}
response, err := createExternalDashboardSnapshot(cmd)
if err != nil {
c.JsonApiErr(500, "Failed to create external snaphost", err)
return
}
cmd.OrgId = -1
cmd.UserId = -1
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),
})
}
......
......@@ -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"`
......
......@@ -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)
......
......@@ -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);
};
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment