The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/tests/api/plugins/api_plugins_test.go

135 lines
3.8 KiB

package plugins
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"testing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
usernameAdmin = "admin"
usernameNonAdmin = "nonAdmin"
defaultPassword = "password"
)
func TestPlugins(t *testing.T) {
dir, cfgPath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
PluginAdminEnabled: true,
})
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, cfgPath)
type testCase struct {
desc string
url string
expStatus int
expResp string
}
t.Run("Install", func(t *testing.T) {
store.Bus = bus.GetBus()
createUser(t, store, models.CreateUserCommand{Login: usernameNonAdmin, Password: defaultPassword, IsAdmin: false})
createUser(t, store, models.CreateUserCommand{Login: usernameAdmin, Password: defaultPassword, IsAdmin: true})
t.Run("Request is forbidden if not from an admin", func(t *testing.T) {
status, body := makePostRequest(t, grafanaAPIURL(usernameNonAdmin, grafanaListedAddr, "plugins/grafana-plugin/install"))
assert.Equal(t, 403, status)
assert.Equal(t, "Permission denied", body["message"])
status, body = makePostRequest(t, grafanaAPIURL(usernameNonAdmin, grafanaListedAddr, "plugins/grafana-plugin/uninstall"))
assert.Equal(t, 403, status)
assert.Equal(t, "Permission denied", body["message"])
})
t.Run("Request is not forbidden if from an admin", func(t *testing.T) {
statusCode, body := makePostRequest(t, grafanaAPIURL(usernameAdmin, grafanaListedAddr, "plugins/test/install"))
assert.Equal(t, 404, statusCode)
assert.Equal(t, "Plugin not found", body["message"])
statusCode, body = makePostRequest(t, grafanaAPIURL(usernameAdmin, grafanaListedAddr, "plugins/test/uninstall"))
assert.Equal(t, 404, statusCode)
assert.Equal(t, "Plugin not installed", body["message"])
})
})
t.Run("List", func(t *testing.T) {
testCases := []testCase{
{
desc: "should return all loaded core and bundled plugins",
url: "http://%s/api/plugins",
expStatus: http.StatusOK,
expResp: expectedResp(t, "expectedListResp.json"),
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
url := fmt.Sprintf(tc.url, grafanaListedAddr)
// nolint:gosec
resp, err := http.Get(url)
t.Cleanup(func() {
require.NoError(t, resp.Body.Close())
})
require.NoError(t, err)
require.Equal(t, tc.expStatus, resp.StatusCode)
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.JSONEq(t, tc.expResp, string(b))
})
}
})
}
func createUser(t *testing.T, store *sqlstore.SQLStore, cmd models.CreateUserCommand) {
t.Helper()
_, err := store.CreateUser(context.Background(), cmd)
require.NoError(t, err)
}
func makePostRequest(t *testing.T, URL string) (int, map[string]interface{}) {
t.Helper()
// nolint:gosec
resp, err := http.Post(URL, "application/json", bytes.NewBufferString(""))
require.NoError(t, err)
t.Cleanup(func() {
_ = resp.Body.Close()
fmt.Printf("Failed to close response body err: %s", err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
var body = make(map[string]interface{})
err = json.Unmarshal(b, &body)
require.NoError(t, err)
return resp.StatusCode, body
}
func grafanaAPIURL(username string, grafanaListedAddr string, path string) string {
return fmt.Sprintf("http://%s:%s@%s/api/%s", username, defaultPassword, grafanaListedAddr, path)
}
func expectedResp(t *testing.T, filename string) string {
contents, err := ioutil.ReadFile(fmt.Sprintf("data/%s", filename))
if err != nil {
t.Errorf("failed to load %s: %v", filename, err)
}
return string(contents)
}