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

173 lines
5.1 KiB

package plugins
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/tests/testinfra"
)
const (
usernameAdmin = "admin"
usernameNonAdmin = "nonAdmin"
defaultPassword = "password"
)
var updateSnapshotFlag = false
func TestIntegrationPlugins(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
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
expRespPath string
}
t.Run("Install", func(t *testing.T) {
createUser(t, store, user.CreateUserCommand{Login: usernameNonAdmin, Password: defaultPassword, IsAdmin: false})
createUser(t, store, user.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, "You'll need additional permissions to perform this action. Permissions needed: plugins:install", body["message"])
status, body = makePostRequest(t, grafanaAPIURL(usernameNonAdmin, grafanaListedAddr, "plugins/grafana-plugin/uninstall"))
assert.Equal(t, 403, status)
assert.Equal(t, "You'll need additional permissions to perform this action. Permissions needed: plugins:install", 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,
expRespPath: "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 := io.ReadAll(resp.Body)
require.NoError(t, err)
expResp := expectedResp(t, tc.expRespPath)
same := assert.JSONEq(t, expResp, string(b))
if !same {
if updateSnapshotFlag {
t.Log("updating snapshot results")
var prettyJSON bytes.Buffer
if err := json.Indent(&prettyJSON, b, "", " "); err != nil {
t.FailNow()
}
updateRespSnapshot(t, tc.expRespPath, prettyJSON.String())
}
t.FailNow()
}
})
}
})
}
func createUser(t *testing.T, store *sqlstore.SQLStore, cmd user.CreateUserCommand) {
t.Helper()
store.Cfg.AutoAssignOrg = true
store.Cfg.AutoAssignOrgId = 1
quotaService := quotaimpl.ProvideService(store, store.Cfg)
orgService, err := orgimpl.ProvideService(store, store.Cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(store, orgService, store.Cfg, nil, nil, quotaService)
require.NoError(t, err)
_, err = usrSvc.CreateUserForTests(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() {
require.NoError(t, resp.Body.Close())
})
b, err := io.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 {
//nolint:GOSEC
contents, err := os.ReadFile(filepath.Join("data", filename))
if err != nil {
t.Errorf("failed to load %s: %v", filename, err)
}
return string(contents)
}
func updateRespSnapshot(t *testing.T, filename string, body string) {
err := os.WriteFile(filepath.Join("data", filename), []byte(body), 0600)
if err != nil {
t.Errorf("error writing snapshot %s: %v", filename, err)
}
}