grafana/pkg/api/datasources.go

1053 lines
34 KiB
Go
Raw Normal View History

package api
import (
Encryption: Refactor securejsondata.SecureJsonData to stop relying on global functions (#38865) * Encryption: Add support to encrypt/decrypt sjd * Add datasources.Service as a proxy to datasources db operations * Encrypt ds.SecureJsonData before calling SQLStore * Move ds cache code into ds service * Fix tlsmanager tests * Fix pluginproxy tests * Remove some securejsondata.GetEncryptedJsonData usages * Add pluginsettings.Service as a proxy for plugin settings db operations * Add AlertNotificationService as a proxy for alert notification db operations * Remove some securejsondata.GetEncryptedJsonData usages * Remove more securejsondata.GetEncryptedJsonData usages * Fix lint errors * Minor fixes * Remove encryption global functions usages from ngalert * Fix lint errors * Minor fixes * Minor fixes * Remove securejsondata.DecryptedValue usage * Refactor the refactor * Remove securejsondata.DecryptedValue usage * Move securejsondata to migrations package * Move securejsondata to migrations package * Minor fix * Fix integration test * Fix integration tests * Undo undesired changes * Fix tests * Add context.Context into encryption methods * Fix tests * Fix tests * Fix tests * Trigger CI * Fix test * Add names to params of encryption service interface * Remove bus from CacheServiceImpl * Add logging * Add keys to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Add missing key to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Undo changes in markdown files * Fix formatting * Add context to secrets service * Rename decryptSecureJsonData to decryptSecureJsonDataFn * Name args in GetDecryptedValueFn * Add template back to NewAlertmanagerNotifier * Copy GetDecryptedValueFn to ngalert * Add logging to pluginsettings * Fix pluginsettings test Co-authored-by: Tania B <yalyna.ts@gmail.com> Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
2021-10-07 09:33:50 -05:00
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"sort"
"strconv"
2022-09-20 12:31:08 -05:00
"strings"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/api/datasource"
2015-02-05 03:37:13 -06:00
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/apimachinery/identity"
2022-09-20 12:31:08 -05:00
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/featuremgmt"
2022-09-20 12:31:08 -05:00
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web"
)
var datasourcesLogger = log.New("datasources")
var secretsPluginError datasources.ErrDatasourceSecretsPluginUserFriendly
// swagger:route GET /datasources datasources getDataSources
//
// Get all data sources.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scope: `datasources:*`.
//
// Responses:
// 200: getDataSourcesResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) GetDataSources(c *contextmodel.ReqContext) response.Response {
query := datasources.GetDataSourcesQuery{OrgID: c.SignedInUser.GetOrgID(), DataSourceLimit: hs.Cfg.DataSourceLimit}
dataSources, err := hs.DataSourcesService.GetDataSources(c.Req.Context(), &query)
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to query datasources", err)
}
filtered, err := hs.dsGuardian.New(c.SignedInUser.OrgID, c.SignedInUser).FilterDatasourcesByReadPermissions(dataSources)
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to query datasources", err)
}
result := make(dtos.DataSourceList, 0)
for _, ds := range filtered {
dsItem := dtos.DataSourceListItemDTO{
OrgId: ds.OrgID,
Id: ds.ID,
UID: ds.UID,
Name: ds.Name,
Url: ds.URL,
Type: ds.Type,
TypeName: ds.Type,
Access: ds.Access,
Database: ds.Database,
User: ds.User,
BasicAuth: ds.BasicAuth,
2015-01-09 09:36:23 -06:00
IsDefault: ds.IsDefault,
JsonData: ds.JsonData,
ReadOnly: ds.ReadOnly,
}
if plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), ds.Type); exists {
dsItem.TypeLogoUrl = plugin.Info.Logos.Small
dsItem.TypeName = plugin.Name
dsItem.Type = plugin.ID // may be from an alias
} else {
2016-03-23 09:09:48 -05:00
dsItem.TypeLogoUrl = "public/img/icn-datasource.svg"
}
result = append(result, dsItem)
}
sort.Sort(result)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, &result)
}
// swagger:route GET /datasources/{id} datasources getDataSourceByID
//
// Get a single data source by Id.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).
//
// Please refer to [updated API](#/datasources/getDataSourceByUID) instead
//
// Deprecated: true
//
// Responses:
// 200: getDataSourceResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) GetDataSourceById(c *contextmodel.ReqContext) response.Response {
id, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", nil)
}
query := datasources.GetDataSourceQuery{
ID: id,
OrgID: c.SignedInUser.GetOrgID(),
}
dataSource, err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
if errors.Is(err, datasources.ErrDataSourceIdentifierNotSet) {
return response.Error(http.StatusBadRequest, "Datasource id is missing", nil)
}
return response.Error(http.StatusInternalServerError, "Failed to query datasources", err)
}
dto := hs.convertModelToDtos(c.Req.Context(), dataSource)
// Add accesscontrol metadata
dto.AccessControl = getAccessControlMetadata(c, datasources.ScopePrefix, dto.UID)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, &dto)
}
// swagger:route DELETE /datasources/{id} datasources deleteDataSourceByID
//
// Delete an existing data source by id.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).
//
// Please refer to [updated API](#/datasources/deleteDataSourceByUID) instead
//
// Deprecated: true
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 404: notFoundError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) DeleteDataSourceById(c *contextmodel.ReqContext) response.Response {
id, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", err)
}
if id <= 0 {
return response.Error(http.StatusBadRequest, "Missing valid datasource id", nil)
}
ds, err := hs.getRawDataSourceById(c.Req.Context(), id, c.SignedInUser.GetOrgID())
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusBadRequest, "Failed to delete datasource", nil)
}
if ds.ReadOnly {
return response.Error(http.StatusForbidden, "Cannot delete read-only data source", nil)
}
cmd := &datasources.DeleteDataSourceCommand{ID: id, OrgID: c.SignedInUser.GetOrgID(), Name: ds.Name}
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
if err != nil {
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
if errors.As(err, &secretsPluginError) {
return response.Error(http.StatusInternalServerError, "Failed to delete datasource: "+err.Error(), err)
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
}
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
}
hs.Live.HandleDatasourceDelete(c.SignedInUser.GetOrgID(), ds.UID)
return response.Success("Data source deleted")
}
// swagger:route GET /datasources/uid/{uid} datasources getDataSourceByUID
//
// Get a single data source by UID.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:kLtEtcRGk` (single data source).
//
// Responses:
// 200: getDataSourceResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) GetDataSourceByUID(c *contextmodel.ReqContext) response.Response {
ds, err := hs.getRawDataSourceByUID(c.Req.Context(), web.Params(c.Req)[":uid"], c.SignedInUser.GetOrgID())
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusInternalServerError, "Failed to query datasource", err)
}
dto := hs.convertModelToDtos(c.Req.Context(), ds)
// Add accesscontrol metadata
dto.AccessControl = getAccessControlMetadata(c, datasources.ScopePrefix, dto.UID)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, &dto)
}
// swagger:route DELETE /datasources/uid/{uid} datasources deleteDataSourceByUID
//
// Delete an existing data source by UID.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:kLtEtcRGk` (single data source).
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) DeleteDataSourceByUID(c *contextmodel.ReqContext) response.Response {
uid := web.Params(c.Req)[":uid"]
if uid == "" {
return response.Error(http.StatusBadRequest, "Missing datasource uid", nil)
}
ds, err := hs.getRawDataSourceByUID(c.Req.Context(), uid, c.SignedInUser.GetOrgID())
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusBadRequest, "Failed to delete datasource", nil)
}
if ds.ReadOnly {
return response.Error(http.StatusForbidden, "Cannot delete read-only data source", nil)
}
cmd := &datasources.DeleteDataSourceCommand{UID: uid, OrgID: c.SignedInUser.GetOrgID(), Name: ds.Name}
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
if err != nil {
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
if errors.As(err, &secretsPluginError) {
return response.Error(http.StatusInternalServerError, "Failed to delete datasource: "+err.Error(), err)
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
}
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
}
hs.Live.HandleDatasourceDelete(c.SignedInUser.GetOrgID(), ds.UID)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, util.DynMap{
"message": "Data source deleted",
"id": ds.ID,
})
}
// swagger:route DELETE /datasources/name/{name} datasources deleteDataSourceByName
//
// Delete an existing data source by name.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:name:*` and `datasources:name:test_datasource` (single data source).
//
// Responses:
// 200: deleteDataSourceByNameResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) DeleteDataSourceByName(c *contextmodel.ReqContext) response.Response {
name := web.Params(c.Req)[":name"]
if name == "" {
return response.Error(http.StatusBadRequest, "Missing valid datasource name", nil)
}
getCmd := &datasources.GetDataSourceQuery{Name: name, OrgID: c.SignedInUser.GetOrgID()}
dataSource, err := hs.DataSourcesService.GetDataSource(c.Req.Context(), getCmd)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
}
if dataSource.ReadOnly {
return response.Error(http.StatusForbidden, "Cannot delete read-only data source", nil)
}
cmd := &datasources.DeleteDataSourceCommand{Name: name, OrgID: c.SignedInUser.GetOrgID()}
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
if err != nil {
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
if errors.As(err, &secretsPluginError) {
return response.Error(http.StatusInternalServerError, "Failed to delete datasource: "+err.Error(), err)
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
}
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
}
hs.Live.HandleDatasourceDelete(c.SignedInUser.GetOrgID(), dataSource.UID)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, util.DynMap{
2020-07-31 01:22:09 -05:00
"message": "Data source deleted",
"id": dataSource.ID,
2020-07-31 01:22:09 -05:00
})
}
func validateURL(cmdType string, url string) response.Response {
if _, err := datasource.ValidateURL(cmdType, url); err != nil {
datasourcesLogger.Error("Failed to validate URL", "url", url)
return response.Error(http.StatusBadRequest, "Validation error, invalid URL", err)
}
return nil
}
2022-09-20 12:31:08 -05:00
// validateJSONData prevents the user from adding a custom header with name that matches the auth proxy header name.
// This is done to prevent data source proxy from being used to circumvent auth proxy.
// For more context take a look at CVE-2022-35957
func validateJSONData(jsonData *simplejson.Json, cfg *setting.Cfg) error {
if jsonData == nil {
2022-09-20 12:31:08 -05:00
return nil
}
if cfg.AuthProxy.Enabled {
for key, value := range jsonData.MustMap() {
if strings.HasPrefix(key, datasources.CustomHeaderName) {
header := fmt.Sprint(value)
if http.CanonicalHeaderKey(header) == http.CanonicalHeaderKey(cfg.AuthProxy.HeaderName) {
datasourcesLogger.Error("Forbidden to add a data source header with a name equal to auth proxy header name", "headerName", key)
return errors.New("validation error, invalid header name specified")
}
2022-09-20 12:31:08 -05:00
}
}
}
2022-09-20 12:31:08 -05:00
return nil
}
// swagger:route POST /datasources datasources addDataSource
//
// Create a data source.
//
// By defining `password` and `basicAuthPassword` under secureJsonData property
// Grafana encrypts them securely as an encrypted blob in the database.
// The response then lists the encrypted fields under secureJsonFields.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:create`
//
// Responses:
// 200: createOrUpdateDatasourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
func (hs *HTTPServer) AddDataSource(c *contextmodel.ReqContext) response.Response {
cmd := datasources.AddDataSourceCommand{}
if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
2024-08-09 10:20:24 -05:00
userID, _ := identity.UserIdentifier(c.SignedInUser.GetID())
datasourcesLogger.Debug("Received command to add data source", "url", cmd.URL)
cmd.OrgID = c.SignedInUser.GetOrgID()
cmd.UserID = userID
if cmd.URL != "" {
if resp := validateURL(cmd.Type, cmd.URL); resp != nil {
return resp
}
}
if err := validateJSONData(cmd.JsonData, hs.Cfg); err != nil {
2022-09-20 12:31:08 -05:00
return response.Error(http.StatusBadRequest, "Failed to add datasource", err)
}
// It's forbidden to update the rules from the datasource api.
// team HTTP headers update have to be done through `updateDatasourceLBACRules`
if hs.Features != nil && hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagTeamHttpHeaders) {
if cmd.JsonData != nil {
if _, ok := cmd.JsonData.CheckGet("teamHttpHeaders"); ok {
return response.Error(http.StatusForbidden, "Cannot create datasource with team HTTP headers, need to use updateDatasourceLBACRules API", nil)
}
}
}
dataSource, err := hs.DataSourcesService.AddDataSource(c.Req.Context(), &cmd)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNameExists) || errors.Is(err, datasources.ErrDataSourceUidExists) {
return response.Error(http.StatusConflict, err.Error(), err)
}
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
if errors.As(err, &secretsPluginError) {
return response.Error(http.StatusInternalServerError, "Failed to add datasource: "+err.Error(), err)
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
}
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to add datasource", err)
}
// Clear permission cache for the user who's created the data source, so that new permissions are fetched for their next call
// Required for cases when caller wants to immediately interact with the newly created object
hs.accesscontrolService.ClearUserPermissionCache(c.SignedInUser)
ds := hs.convertModelToDtos(c.Req.Context(), dataSource)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, util.DynMap{
"message": "Datasource added",
"id": dataSource.ID,
"name": dataSource.Name,
"datasource": ds,
})
}
// swagger:route PUT /datasources/{id} datasources updateDataSourceByID
//
// Update an existing data source by its sequential ID.
//
// Similar to creating a data source, `password` and `basicAuthPassword` should be defined under
// secureJsonData in order to be stored securely as an encrypted blob in the database. Then, the
// encrypted fields are listed under secureJsonFields section in the response.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).
//
// Please refer to [updated API](#/datasources/updateDataSourceByUID) instead
//
// Deprecated: true
//
// Responses:
// 200: createOrUpdateDatasourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) UpdateDataSourceByID(c *contextmodel.ReqContext) response.Response {
cmd := datasources.UpdateDataSourceCommand{}
if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
datasourcesLogger.Debug("Received command to update data source", "url", cmd.URL)
cmd.OrgID = c.SignedInUser.GetOrgID()
var err error
if cmd.ID, err = strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64); err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", err)
}
if resp := validateURL(cmd.Type, cmd.URL); resp != nil {
return resp
}
if err := validateJSONData(cmd.JsonData, hs.Cfg); err != nil {
2022-09-20 12:31:08 -05:00
return response.Error(http.StatusBadRequest, "Failed to update datasource", err)
}
ds, err := hs.getRawDataSourceById(c.Req.Context(), cmd.ID, cmd.OrgID)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusInternalServerError, "Failed to update datasource", err)
}
return hs.updateDataSourceByID(c, ds, cmd)
}
// swagger:route PUT /datasources/uid/{uid} datasources updateDataSourceByUID
//
// Update an existing data source.
//
// Similar to creating a data source, `password` and `basicAuthPassword` should be defined under
// secureJsonData in order to be stored securely as an encrypted blob in the database. Then, the
// encrypted fields are listed under secureJsonFields section in the response.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).
//
// Responses:
// 200: createOrUpdateDatasourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) UpdateDataSourceByUID(c *contextmodel.ReqContext) response.Response {
cmd := datasources.UpdateDataSourceCommand{}
if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
datasourcesLogger.Debug("Received command to update data source", "url", cmd.URL)
cmd.OrgID = c.SignedInUser.GetOrgID()
if resp := validateURL(cmd.Type, cmd.URL); resp != nil {
return resp
}
if err := validateJSONData(cmd.JsonData, hs.Cfg); err != nil {
2022-09-20 12:31:08 -05:00
return response.Error(http.StatusBadRequest, "Failed to update datasource", err)
}
ds, err := hs.getRawDataSourceByUID(c.Req.Context(), web.Params(c.Req)[":uid"], c.SignedInUser.GetOrgID())
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusInternalServerError, "Failed to update datasource", err)
}
cmd.ID = ds.ID
return hs.updateDataSourceByID(c, ds, cmd)
}
func (hs *HTTPServer) updateDataSourceByID(c *contextmodel.ReqContext, ds *datasources.DataSource, cmd datasources.UpdateDataSourceCommand) response.Response {
if ds.ReadOnly {
return response.Error(http.StatusForbidden, "Cannot update read-only data source", nil)
}
_, err := hs.DataSourcesService.UpdateDataSource(c.Req.Context(), &cmd)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNameExists) {
return response.Error(http.StatusConflict, "Failed to update datasource: "+err.Error(), err)
}
if errors.Is(err, datasources.ErrDataSourceUpdatingOldVersion) {
return response.Error(http.StatusConflict, "Datasource has already been updated by someone else. Please reload and try again", err)
}
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
if errors.As(err, &secretsPluginError) {
return response.Error(http.StatusInternalServerError, "Failed to update datasource: "+err.Error(), err)
Secrets: add better error handling for secret plugin failures when updating datasources (#50542) * Add protobuf config and generated code, and client wrapper * wire up loading of secretsmanager plugin, using renderer plugin as a model * update kvstore provider to check if we should use the grpc plugin. return false always in OSS * add OSS remote plugin check * refactor wire gen file * log which secrets manager is being used * Fix argument types for remote checker * Turns out if err != nil, then the result is always nil. Return empty values if there is an error. * remove duplicate import * ensure atomicity by adding secret management as a step to sql operations and rolling back if necessary * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Update pkg/services/secrets/kvstore/kvstore.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * refactor RemotePluginCheck interface to just return the Plugin client directly * rename struct to something less silly * add special error handling for remote secrets management * switch to errors.as instead of type inference * remove unnecessary rollback call * just declare error once * refactor .proto file according to prior PR suggestions * re-generate protobuf files and fix compilation errors * only wrap (ergo display in the front end) errors that are user friendly from the plugin * rename error type to suggest user friendly only * rename plugin functions to be more descriptive * change delete message name * Revert "change delete message name" This reverts commit 8ca978301eea45d3cc6a22cda15b9d099c533955. * Revert "rename plugin functions to be more descriptive" This reverts commit 4355c9b9ff95443f74c0b588d1ffeabb544f1a34. * fix pointer to pointer problem * change plugin user error to just hold a string * fix sequencing problem with datasource updates * clean up some return statements * need to wrap multiple transactions with the InTransaction() func in order to keep the lock * make linter happy * revert input var name Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2022-06-16 11:26:57 -05:00
}
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to update datasource", err)
}
query := datasources.GetDataSourceQuery{
ID: cmd.ID,
OrgID: c.SignedInUser.GetOrgID(),
}
dataSource, err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
}
return response.Error(http.StatusInternalServerError, "Failed to query datasource", err)
}
datasourceDTO := hs.convertModelToDtos(c.Req.Context(), dataSource)
hs.Live.HandleDatasourceUpdate(c.SignedInUser.GetOrgID(), datasourceDTO.UID)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, util.DynMap{
"message": "Datasource updated",
"id": cmd.ID,
"name": cmd.Name,
"datasource": datasourceDTO,
})
}
func (hs *HTTPServer) getRawDataSourceById(ctx context.Context, id int64, orgID int64) (*datasources.DataSource, error) {
query := datasources.GetDataSourceQuery{
ID: id,
OrgID: orgID,
}
dataSource, err := hs.DataSourcesService.GetDataSource(ctx, &query)
if err != nil {
return nil, err
}
return dataSource, nil
}
func (hs *HTTPServer) getRawDataSourceByUID(ctx context.Context, uid string, orgID int64) (*datasources.DataSource, error) {
query := datasources.GetDataSourceQuery{
UID: uid,
OrgID: orgID,
}
dataSource, err := hs.DataSourcesService.GetDataSource(ctx, &query)
if err != nil {
return nil, err
}
return dataSource, nil
}
// swagger:route GET /datasources/name/{name} datasources getDataSourceByName
//
// Get a single data source by Name.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:name:*` and `datasources:name:test_datasource` (single data source).
//
// Responses:
// 200: getDataSourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) GetDataSourceByName(c *contextmodel.ReqContext) response.Response {
query := datasources.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgID: c.SignedInUser.GetOrgID()}
2016-03-07 14:25:26 -06:00
dataSource, err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
2016-03-07 14:25:26 -06:00
}
return response.Error(http.StatusInternalServerError, "Failed to query datasources", err)
2016-03-07 14:25:26 -06:00
}
dto := hs.convertModelToDtos(c.Req.Context(), dataSource)
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, &dto)
2016-03-08 04:51:03 -06:00
}
2016-03-07 14:25:26 -06:00
// swagger:route GET /datasources/id/{name} datasources getDataSourceIdByName
//
// Get data source Id by Name.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:name:*` and `datasources:name:test_datasource` (single data source).
//
// Responses:
// 200: getDataSourceIDResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) GetDataSourceIdByName(c *contextmodel.ReqContext) response.Response {
query := datasources.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgID: c.SignedInUser.GetOrgID()}
2016-03-10 03:31:10 -06:00
ds, err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceNotFound) {
return response.Error(http.StatusNotFound, "Data source not found", nil)
2016-03-10 03:31:10 -06:00
}
return response.Error(http.StatusInternalServerError, "Failed to query datasources", err)
2016-03-10 03:31:10 -06:00
}
dtos := dtos.AnyId{
Id: ds.ID,
2016-03-10 03:31:10 -06:00
}
2022-04-15 07:01:58 -05:00
return response.JSON(http.StatusOK, &dtos)
2016-03-10 03:31:10 -06:00
}
// swagger:route GET /datasources/{id}/resources/{datasource_proxy_route} datasources callDatasourceResourceByID
//
// Fetch data source resources by Id.
//
// Please refer to [updated API](#/datasources/callDatasourceResourceWithUID) instead
//
// Deprecated: true
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) CallDatasourceResource(c *contextmodel.ReqContext) {
datasourceID, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
if err != nil {
c.JsonApiErr(http.StatusBadRequest, "id is invalid", nil)
return
}
Caching: Refactor enterprise query caching middleware to a wire service (#65616) * define initial service and add to wire * update caching service interface * add skipQueryCache header handler and update metrics query function to use it * add caching service as a dependency to query service * working caching impl * propagate cache status to frontend in response * beginning of improvements suggested by Lean - separate caching logic from query logic. * more changes to simplify query function * Decided to revert renaming of function * Remove error status from cache request * add extra documentation * Move query caching duration metric to query package * add a little bit of documentation * wip: convert resource caching * Change return type of query service QueryData to a QueryDataResponse with Headers * update codeowners * change X-Cache value to const * use resource caching in endpoint handlers * write resource headers to response even if it's not a cache hit * fix panic caused by lack of nil check * update unit test * remove NONE header - shouldn't show up in OSS * Convert everything to use the plugin middleware * revert a few more things * clean up unused vars * start reverting resource caching, start to implement in plugin middleware * revert more, fix typo * Update caching interfaces - resource caching now has a separate cache method * continue wiring up new resource caching conventions - still in progress * add more safety to implementation * remove some unused objects * remove some code that I left in by accident * add some comments, fix codeowners, fix duplicate registration * fix source of panic in resource middleware * Update client decorator test to provide an empty response object * create tests for caching middleware * fix unit test * Update pkg/services/caching/service.go Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> * improve error message in error log * quick docs update * Remove use of mockery. Update return signature to return an explicit hit/miss bool * create unit test for empty request context * rename caching metrics to make it clear they pertain to caching * Update pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Add clarifying comments to cache skip middleware func * Add comment pointing to the resource cache update call * fix unit tests (missing dependency) * try to fix mystery syntax error * fix a panic * Caching: Introduce feature toggle to caching service refactor (#66323) * introduce new feature toggle * hide calls to new service behind a feature flag * remove licensing flag from toggle (misunderstood what it was for) * fix unit tests * rerun toggle gen --------- Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2023-04-12 11:30:33 -05:00
ds, err := hs.DataSourceCache.GetDatasource(c.Req.Context(), datasourceID, c.SignedInUser, c.SkipDSCache)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
c.JsonApiErr(403, "Access denied to datasource", err)
return
}
c.JsonApiErr(500, "Unable to load datasource meta data", err)
return
}
plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), ds.Type)
if !exists {
c.JsonApiErr(500, "Unable to find datasource plugin", err)
return
}
hs.callPluginResourceWithDataSource(c, plugin.ID, ds)
}
// swagger:route GET /datasources/uid/{uid}/resources/{datasource_proxy_route} datasources callDatasourceResourceWithUID
//
// Fetch data source resources.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
func (hs *HTTPServer) CallDatasourceResourceWithUID(c *contextmodel.ReqContext) {
dsUID := web.Params(c.Req)[":uid"]
if !util.IsValidShortUID(dsUID) {
c.JsonApiErr(http.StatusBadRequest, "UID is invalid", nil)
return
}
Caching: Refactor enterprise query caching middleware to a wire service (#65616) * define initial service and add to wire * update caching service interface * add skipQueryCache header handler and update metrics query function to use it * add caching service as a dependency to query service * working caching impl * propagate cache status to frontend in response * beginning of improvements suggested by Lean - separate caching logic from query logic. * more changes to simplify query function * Decided to revert renaming of function * Remove error status from cache request * add extra documentation * Move query caching duration metric to query package * add a little bit of documentation * wip: convert resource caching * Change return type of query service QueryData to a QueryDataResponse with Headers * update codeowners * change X-Cache value to const * use resource caching in endpoint handlers * write resource headers to response even if it's not a cache hit * fix panic caused by lack of nil check * update unit test * remove NONE header - shouldn't show up in OSS * Convert everything to use the plugin middleware * revert a few more things * clean up unused vars * start reverting resource caching, start to implement in plugin middleware * revert more, fix typo * Update caching interfaces - resource caching now has a separate cache method * continue wiring up new resource caching conventions - still in progress * add more safety to implementation * remove some unused objects * remove some code that I left in by accident * add some comments, fix codeowners, fix duplicate registration * fix source of panic in resource middleware * Update client decorator test to provide an empty response object * create tests for caching middleware * fix unit test * Update pkg/services/caching/service.go Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> * improve error message in error log * quick docs update * Remove use of mockery. Update return signature to return an explicit hit/miss bool * create unit test for empty request context * rename caching metrics to make it clear they pertain to caching * Update pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Add clarifying comments to cache skip middleware func * Add comment pointing to the resource cache update call * fix unit tests (missing dependency) * try to fix mystery syntax error * fix a panic * Caching: Introduce feature toggle to caching service refactor (#66323) * introduce new feature toggle * hide calls to new service behind a feature flag * remove licensing flag from toggle (misunderstood what it was for) * fix unit tests * rerun toggle gen --------- Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2023-04-12 11:30:33 -05:00
ds, err := hs.DataSourceCache.GetDatasourceByUID(c.Req.Context(), dsUID, c.SignedInUser, c.SkipDSCache)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
c.JsonApiErr(http.StatusForbidden, "Access denied to datasource", err)
return
}
c.JsonApiErr(http.StatusInternalServerError, "Unable to load datasource meta data", err)
return
}
plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), ds.Type)
if !exists {
c.JsonApiErr(http.StatusInternalServerError, "Unable to find datasource plugin", err)
return
}
hs.callPluginResourceWithDataSource(c, plugin.ID, ds)
}
func (hs *HTTPServer) convertModelToDtos(ctx context.Context, ds *datasources.DataSource) dtos.DataSource {
dto := dtos.DataSource{
Id: ds.ID,
UID: ds.UID,
OrgId: ds.OrgID,
Name: ds.Name,
Url: ds.URL,
Type: ds.Type,
Access: ds.Access,
Database: ds.Database,
User: ds.User,
BasicAuth: ds.BasicAuth,
BasicAuthUser: ds.BasicAuthUser,
WithCredentials: ds.WithCredentials,
IsDefault: ds.IsDefault,
JsonData: ds.JsonData,
SecureJsonFields: map[string]bool{},
Version: ds.Version,
ReadOnly: ds.ReadOnly,
APIVersion: ds.APIVersion,
}
if hs.pluginStore != nil {
if plugin, exists := hs.pluginStore.Plugin(ctx, ds.Type); exists {
dto.TypeLogoUrl = plugin.Info.Logos.Small
dto.Type = plugin.ID // may be from an alias
} else {
dto.TypeLogoUrl = "public/img/icn-datasource.svg"
}
}
Secrets: Implement basic unified secret store service (#45804) * wip: Implement kvstore for secrets * wip: Refactor kvstore for secrets * wip: Add format key function to secrets kvstore sql * wip: Add migration for secrets kvstore * Remove unused Key field from secrets kvstore * Remove secret values from debug logs * Integrate unified secrets with datasources * Fix minor issues and tests for kvstore * Create test service helper for secret store * Remove encryption tests from datasources * Move secret operations after datasources * Fix datasource proxy tests * Fix legacy data tests * Add Name to all delete data source commands * Implement decryption cache on sql secret store * Fix minor issue with cache and tests * Use secret type on secret store datasource operations * Add comments to make create and update clear * Rename itemFound variable to isFound * Improve secret deletion and cache management * Add base64 encoding to sql secret store * Move secret retrieval to decrypted values function * Refactor decrypt secure json data functions * Fix expr tests * Fix datasource tests * Fix plugin proxy tests * Fix query tests * Fix metrics api tests * Remove unused fake secrets service from query tests * Add rename function to secret store * Add check for error renaming secret * Remove bus from tests to fix merge conflicts * Add background secrets migration to datasources * Get datasource secure json fields from secrets * Move migration to secret store * Revert "Move migration to secret store" This reverts commit 7c3f872072e9aff601fb9d639127d468c03f97ef. * Add secret service to datasource service on tests * Fix datasource tests * Remove merge conflict on wire * Add ctx to data source http transport on prometheus stats collector * Add ctx to data source http transport on stats collector test
2022-04-25 11:57:45 -05:00
secrets, err := hs.DataSourcesService.DecryptedValues(ctx, ds)
if err == nil {
for k, v := range secrets {
if len(v) > 0 {
dto.SecureJsonFields[k] = true
}
}
} else {
datasourcesLogger.Debug("Failed to retrieve datasource secrets to parse secure json fields", "error", err)
}
return dto
2016-03-07 14:25:26 -06:00
}
// swagger:route GET /datasources/uid/{uid}/health datasources checkDatasourceHealthWithUID
//
// Sends a health check request to the plugin datasource identified by the UID.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) CheckDatasourceHealthWithUID(c *contextmodel.ReqContext) response.Response {
dsUID := web.Params(c.Req)[":uid"]
if !util.IsValidShortUID(dsUID) {
return response.Error(http.StatusBadRequest, "UID is invalid", nil)
}
Caching: Refactor enterprise query caching middleware to a wire service (#65616) * define initial service and add to wire * update caching service interface * add skipQueryCache header handler and update metrics query function to use it * add caching service as a dependency to query service * working caching impl * propagate cache status to frontend in response * beginning of improvements suggested by Lean - separate caching logic from query logic. * more changes to simplify query function * Decided to revert renaming of function * Remove error status from cache request * add extra documentation * Move query caching duration metric to query package * add a little bit of documentation * wip: convert resource caching * Change return type of query service QueryData to a QueryDataResponse with Headers * update codeowners * change X-Cache value to const * use resource caching in endpoint handlers * write resource headers to response even if it's not a cache hit * fix panic caused by lack of nil check * update unit test * remove NONE header - shouldn't show up in OSS * Convert everything to use the plugin middleware * revert a few more things * clean up unused vars * start reverting resource caching, start to implement in plugin middleware * revert more, fix typo * Update caching interfaces - resource caching now has a separate cache method * continue wiring up new resource caching conventions - still in progress * add more safety to implementation * remove some unused objects * remove some code that I left in by accident * add some comments, fix codeowners, fix duplicate registration * fix source of panic in resource middleware * Update client decorator test to provide an empty response object * create tests for caching middleware * fix unit test * Update pkg/services/caching/service.go Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> * improve error message in error log * quick docs update * Remove use of mockery. Update return signature to return an explicit hit/miss bool * create unit test for empty request context * rename caching metrics to make it clear they pertain to caching * Update pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Add clarifying comments to cache skip middleware func * Add comment pointing to the resource cache update call * fix unit tests (missing dependency) * try to fix mystery syntax error * fix a panic * Caching: Introduce feature toggle to caching service refactor (#66323) * introduce new feature toggle * hide calls to new service behind a feature flag * remove licensing flag from toggle (misunderstood what it was for) * fix unit tests * rerun toggle gen --------- Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2023-04-12 11:30:33 -05:00
ds, err := hs.DataSourceCache.GetDatasourceByUID(c.Req.Context(), dsUID, c.SignedInUser, c.SkipDSCache)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
return response.Error(http.StatusForbidden, "Access denied to datasource", err)
}
return response.Error(http.StatusInternalServerError, "Unable to load datasource metadata", err)
}
return hs.checkDatasourceHealth(c, ds)
}
// swagger:route GET /datasources/{id}/health datasources checkDatasourceHealthByID
//
// Sends a health check request to the plugin datasource identified by the ID.
//
// Please refer to [updated API](#/datasources/checkDatasourceHealthWithUID) instead
//
// Deprecated: true
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
func (hs *HTTPServer) CheckDatasourceHealth(c *contextmodel.ReqContext) response.Response {
datasourceID, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", nil)
}
Caching: Refactor enterprise query caching middleware to a wire service (#65616) * define initial service and add to wire * update caching service interface * add skipQueryCache header handler and update metrics query function to use it * add caching service as a dependency to query service * working caching impl * propagate cache status to frontend in response * beginning of improvements suggested by Lean - separate caching logic from query logic. * more changes to simplify query function * Decided to revert renaming of function * Remove error status from cache request * add extra documentation * Move query caching duration metric to query package * add a little bit of documentation * wip: convert resource caching * Change return type of query service QueryData to a QueryDataResponse with Headers * update codeowners * change X-Cache value to const * use resource caching in endpoint handlers * write resource headers to response even if it's not a cache hit * fix panic caused by lack of nil check * update unit test * remove NONE header - shouldn't show up in OSS * Convert everything to use the plugin middleware * revert a few more things * clean up unused vars * start reverting resource caching, start to implement in plugin middleware * revert more, fix typo * Update caching interfaces - resource caching now has a separate cache method * continue wiring up new resource caching conventions - still in progress * add more safety to implementation * remove some unused objects * remove some code that I left in by accident * add some comments, fix codeowners, fix duplicate registration * fix source of panic in resource middleware * Update client decorator test to provide an empty response object * create tests for caching middleware * fix unit test * Update pkg/services/caching/service.go Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> * improve error message in error log * quick docs update * Remove use of mockery. Update return signature to return an explicit hit/miss bool * create unit test for empty request context * rename caching metrics to make it clear they pertain to caching * Update pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com> * Add clarifying comments to cache skip middleware func * Add comment pointing to the resource cache update call * fix unit tests (missing dependency) * try to fix mystery syntax error * fix a panic * Caching: Introduce feature toggle to caching service refactor (#66323) * introduce new feature toggle * hide calls to new service behind a feature flag * remove licensing flag from toggle (misunderstood what it was for) * fix unit tests * rerun toggle gen --------- Co-authored-by: Arati R. <33031346+suntala@users.noreply.github.com> Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
2023-04-12 11:30:33 -05:00
ds, err := hs.DataSourceCache.GetDatasource(c.Req.Context(), datasourceID, c.SignedInUser, c.SkipDSCache)
if err != nil {
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
return response.Error(http.StatusForbidden, "Access denied to datasource", err)
}
return response.Error(http.StatusInternalServerError, "Unable to load datasource metadata", err)
}
return hs.checkDatasourceHealth(c, ds)
}
func (hs *HTTPServer) checkDatasourceHealth(c *contextmodel.ReqContext, ds *datasources.DataSource) response.Response {
pCtx, err := hs.pluginContextProvider.GetWithDataSource(c.Req.Context(), ds.Type, c.SignedInUser, ds)
if err != nil {
return response.ErrOrFallback(http.StatusInternalServerError, "Unable to get plugin context", err)
}
Plugins: Refactor Plugin Management (#40477) * add core plugin flow * add instrumentation * move func * remove cruft * support external backend plugins * refactor + clean up * remove comments * refactor loader * simplify core plugin path arg * cleanup loggers * move signature validator to plugins package * fix sig packaging * cleanup plugin model * remove unnecessary plugin field * add start+stop for pm * fix failures * add decommissioned state * export fields just to get things flowing * fix comments * set static routes * make image loading idempotent * merge with backend plugin manager * re-use funcs * reorder imports + remove unnecessary interface * add some TODOs + remove unused func * remove unused instrumentation func * simplify client usage * remove import alias * re-use backendplugin.Plugin interface * re order funcs * improve var name * fix log statements * refactor data model * add logic for dupe check during loading * cleanup state setting * refactor loader * cleanup manager interface * add rendering flow * refactor loading + init * add renderer support * fix renderer plugin * reformat imports * track errors * fix plugin signature inheritance * name param in interface * update func comment * fix func arg name * introduce class concept * remove func * fix external plugin check * apply changes from pm-experiment * fix core plugins * fix imports * rename interface * comment API interface * add support for testdata plugin * enable alerting + use correct core plugin contracts * slim manager API * fix param name * fix filter * support static routes * fix rendering * tidy rendering * get tests compiling * fix install+uninstall * start finder test * add finder test coverage * start loader tests * add test for core plugins * load core + bundled test * add test for nested plugin loading * add test files * clean interface + fix registering some core plugins * refactoring * reformat and create sub packages * simplify core plugin init * fix ctx cancel scenario * migrate initializer * remove Init() funcs * add test starter * new logger * flesh out initializer tests * refactoring * remove unused svc * refactor rendering flow * fixup loader tests * add enabled helper func * fix logger name * fix data fetchers * fix case where plugin dir doesn't exist * improve coverage + move dupe checking to loader * remove noisy debug logs * register core plugins automagically * add support for renderer in catalog * make private func + fix req validation * use interface * re-add check for renderer in catalog * tidy up from moving to auto reg core plugins * core plugin registrar * guards * copy over core plugins for test infra * all tests green * renames * propagate new interfaces * kill old manager * get compiling * tidy up * update naming * refactor manager test + cleanup * add more cases to finder test * migrate validator to field * more coverage * refactor dupe checking * add test for plugin class * add coverage for initializer * split out rendering * move * fixup tests * fix uss test * fix frontend settings * fix grafanads test * add check when checking sig errors * fix enabled map * fixup * allow manual setup of CM * rename to cloud-monitoring * remove TODO * add installer interface for testing * loader interface returns * tests passing * refactor + add more coverage * support 'stackdriver' * fix frontend settings loading * improve naming based on package name * small tidy * refactor test * fix renderer start * make cloud-monitoring plugin ID clearer * add plugin update test * add integration tests * don't break all if sig can't be calculated * add root URL check test * add more signature verification tests * update DTO name * update enabled plugins comment * update comments * fix linter * revert fe naming change * fix errors endpoint * reset error code field name * re-order test to help verify * assert -> require * pm check * add missing entry + re-order * re-check * dump icon log * verify manager contents first * reformat * apply PR feedback * apply style changes * fix one vs all loading err * improve log output * only start when no signature error * move log * rework plugin update check * fix test * fix multi loading from cfg.PluginSettings * improve log output #2 * add error abstraction to capture errors without registering a plugin * add debug log * add unsigned warning * e2e test attempt * fix logger * set home path * prevent panic * alternate * ugh.. fix home path * return renderer even if not started * make renderer plugin managed * add fallback renderer icon, update renderer badge + prevent changes when renderer is installed * fix icon loading * rollback renderer changes * use correct field * remove unneccessary block * remove newline * remove unused func * fix bundled plugins base + module fields * remove unused field since refactor * add authorizer abstraction * loader only returns plugins expected to run * fix multi log output
2021-11-01 04:53:33 -05:00
req := &backend.CheckHealthRequest{
PluginContext: pCtx,
Headers: map[string]string{},
}
var dsURL string
if req.PluginContext.DataSourceInstanceSettings != nil {
dsURL = req.PluginContext.DataSourceInstanceSettings.URL
}
err = hs.PluginRequestValidator.Validate(dsURL, c.Req)
if err != nil {
return response.Error(http.StatusForbidden, "Access denied", err)
}
Plugins: Refactor Plugin Management (#40477) * add core plugin flow * add instrumentation * move func * remove cruft * support external backend plugins * refactor + clean up * remove comments * refactor loader * simplify core plugin path arg * cleanup loggers * move signature validator to plugins package * fix sig packaging * cleanup plugin model * remove unnecessary plugin field * add start+stop for pm * fix failures * add decommissioned state * export fields just to get things flowing * fix comments * set static routes * make image loading idempotent * merge with backend plugin manager * re-use funcs * reorder imports + remove unnecessary interface * add some TODOs + remove unused func * remove unused instrumentation func * simplify client usage * remove import alias * re-use backendplugin.Plugin interface * re order funcs * improve var name * fix log statements * refactor data model * add logic for dupe check during loading * cleanup state setting * refactor loader * cleanup manager interface * add rendering flow * refactor loading + init * add renderer support * fix renderer plugin * reformat imports * track errors * fix plugin signature inheritance * name param in interface * update func comment * fix func arg name * introduce class concept * remove func * fix external plugin check * apply changes from pm-experiment * fix core plugins * fix imports * rename interface * comment API interface * add support for testdata plugin * enable alerting + use correct core plugin contracts * slim manager API * fix param name * fix filter * support static routes * fix rendering * tidy rendering * get tests compiling * fix install+uninstall * start finder test * add finder test coverage * start loader tests * add test for core plugins * load core + bundled test * add test for nested plugin loading * add test files * clean interface + fix registering some core plugins * refactoring * reformat and create sub packages * simplify core plugin init * fix ctx cancel scenario * migrate initializer * remove Init() funcs * add test starter * new logger * flesh out initializer tests * refactoring * remove unused svc * refactor rendering flow * fixup loader tests * add enabled helper func * fix logger name * fix data fetchers * fix case where plugin dir doesn't exist * improve coverage + move dupe checking to loader * remove noisy debug logs * register core plugins automagically * add support for renderer in catalog * make private func + fix req validation * use interface * re-add check for renderer in catalog * tidy up from moving to auto reg core plugins * core plugin registrar * guards * copy over core plugins for test infra * all tests green * renames * propagate new interfaces * kill old manager * get compiling * tidy up * update naming * refactor manager test + cleanup * add more cases to finder test * migrate validator to field * more coverage * refactor dupe checking * add test for plugin class * add coverage for initializer * split out rendering * move * fixup tests * fix uss test * fix frontend settings * fix grafanads test * add check when checking sig errors * fix enabled map * fixup * allow manual setup of CM * rename to cloud-monitoring * remove TODO * add installer interface for testing * loader interface returns * tests passing * refactor + add more coverage * support 'stackdriver' * fix frontend settings loading * improve naming based on package name * small tidy * refactor test * fix renderer start * make cloud-monitoring plugin ID clearer * add plugin update test * add integration tests * don't break all if sig can't be calculated * add root URL check test * add more signature verification tests * update DTO name * update enabled plugins comment * update comments * fix linter * revert fe naming change * fix errors endpoint * reset error code field name * re-order test to help verify * assert -> require * pm check * add missing entry + re-order * re-check * dump icon log * verify manager contents first * reformat * apply PR feedback * apply style changes * fix one vs all loading err * improve log output * only start when no signature error * move log * rework plugin update check * fix test * fix multi loading from cfg.PluginSettings * improve log output #2 * add error abstraction to capture errors without registering a plugin * add debug log * add unsigned warning * e2e test attempt * fix logger * set home path * prevent panic * alternate * ugh.. fix home path * return renderer even if not started * make renderer plugin managed * add fallback renderer icon, update renderer badge + prevent changes when renderer is installed * fix icon loading * rollback renderer changes * use correct field * remove unneccessary block * remove newline * remove unused func * fix bundled plugins base + module fields * remove unused field since refactor * add authorizer abstraction * loader only returns plugins expected to run * fix multi log output
2021-11-01 04:53:33 -05:00
resp, err := hs.pluginClient.CheckHealth(c.Req.Context(), req)
if err != nil {
return translatePluginRequestErrorToAPIError(err)
}
payload := map[string]any{
"status": resp.Status.String(),
"message": resp.Message,
}
// Unmarshal JSONDetails if it's not empty.
if len(resp.JSONDetails) > 0 {
var jsonDetails map[string]any
err = json.Unmarshal(resp.JSONDetails, &jsonDetails)
if err != nil {
return response.Error(http.StatusInternalServerError, "Failed to unmarshal detailed response from backend plugin", err)
}
payload["details"] = jsonDetails
}
if resp.Status != backend.HealthStatusOk {
return response.JSON(http.StatusBadRequest, payload)
}
return response.JSON(http.StatusOK, payload)
}
Encryption: Refactor securejsondata.SecureJsonData to stop relying on global functions (#38865) * Encryption: Add support to encrypt/decrypt sjd * Add datasources.Service as a proxy to datasources db operations * Encrypt ds.SecureJsonData before calling SQLStore * Move ds cache code into ds service * Fix tlsmanager tests * Fix pluginproxy tests * Remove some securejsondata.GetEncryptedJsonData usages * Add pluginsettings.Service as a proxy for plugin settings db operations * Add AlertNotificationService as a proxy for alert notification db operations * Remove some securejsondata.GetEncryptedJsonData usages * Remove more securejsondata.GetEncryptedJsonData usages * Fix lint errors * Minor fixes * Remove encryption global functions usages from ngalert * Fix lint errors * Minor fixes * Minor fixes * Remove securejsondata.DecryptedValue usage * Refactor the refactor * Remove securejsondata.DecryptedValue usage * Move securejsondata to migrations package * Move securejsondata to migrations package * Minor fix * Fix integration test * Fix integration tests * Undo undesired changes * Fix tests * Add context.Context into encryption methods * Fix tests * Fix tests * Fix tests * Trigger CI * Fix test * Add names to params of encryption service interface * Remove bus from CacheServiceImpl * Add logging * Add keys to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Add missing key to logger Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com> * Undo changes in markdown files * Fix formatting * Add context to secrets service * Rename decryptSecureJsonData to decryptSecureJsonDataFn * Name args in GetDecryptedValueFn * Add template back to NewAlertmanagerNotifier * Copy GetDecryptedValueFn to ngalert * Add logging to pluginsettings * Fix pluginsettings test Co-authored-by: Tania B <yalyna.ts@gmail.com> Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
2021-10-07 09:33:50 -05:00
// swagger:parameters checkDatasourceHealthByID
type CheckDatasourceHealthByIDParams struct {
// in:path
// required:true
DatasourceID string `json:"id"`
}
// swagger:parameters callDatasourceResourceByID
type CallDatasourceResourceByIDParams struct {
// in:path
// required:true
DatasourceID string `json:"id"`
}
// swagger:parameters deleteDataSourceByID
type DeleteDataSourceByIDParams struct {
// in:path
// required:true
DatasourceID string `json:"id"`
}
// swagger:parameters getDataSourceByID
type GetDataSourceByIDParams struct {
// in:path
// required:true
DatasourceID string `json:"id"`
}
// swagger:parameters checkDatasourceHealthWithUID
type CheckDatasourceHealthWithUIDParams struct {
// in:path
// required:true
DatasourceUID string `json:"uid"`
}
// swagger:parameters callDatasourceResourceWithUID
type CallDatasourceResourceWithUIDParams struct {
// in:path
// required:true
DatasourceUID string `json:"uid"`
}
// swagger:parameters deleteDataSourceByUID
type DeleteDataSourceByUIDParams struct {
// in:path
// required:true
DatasourceUID string `json:"uid"`
}
// swagger:parameters getDataSourceByUID
type GetDataSourceByUIDParams struct {
// in:path
// required:true
DatasourceUID string `json:"uid"`
}
// swagger:parameters getDataSourceByName
type GetDataSourceByNameParams struct {
// in:path
// required:true
DatasourceName string `json:"name"`
}
// swagger:parameters deleteDataSourceByName
type DeleteDataSourceByNameParams struct {
// in:path
// required:true
DatasourceName string `json:"name"`
}
// swagger:parameters getDataSourceIdByName
type GetDataSourceIdByNameParams struct {
// in:path
// required:true
DatasourceName string `json:"name"`
}
// swagger:parameters addDataSource
type AddDataSourceParams struct {
// in:body
// required:true
Body datasources.AddDataSourceCommand
}
// swagger:parameters updateDataSourceByID
type UpdateDataSourceByIDParams struct {
// in:body
// required:true
Body datasources.UpdateDataSourceCommand
// in:path
// required:true
DatasourceID string `json:"id"`
}
// swagger:parameters updateDataSourceByUID
type UpdateDataSourceByUIDParams struct {
// in:body
// required:true
Body datasources.UpdateDataSourceCommand
// in:path
// required:true
DatasourceUID string `json:"uid"`
}
// swagger:response getDataSourcesResponse
type GetDataSourcesResponse struct {
// The response message
// in: body
Body dtos.DataSourceList `json:"body"`
}
// swagger:response getDataSourceResponse
type GetDataSourceResponse struct {
// The response message
// in: body
Body dtos.DataSource `json:"body"`
}
// swagger:response createOrUpdateDatasourceResponse
type CreateOrUpdateDatasourceResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the new data source.
// required: true
// example: 65
ID int64 `json:"id"`
// Name of the new data source.
// required: true
// example: My Data source
Name string `json:"name"`
// Message Message of the deleted dashboard.
// required: true
// example: Data source added
Message string `json:"message"`
// Datasource properties
// required: true
Datasource dtos.DataSource `json:"datasource"`
} `json:"body"`
}
// swagger:response getDataSourceIDResponse
type GetDataSourceIDresponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the data source.
// required: true
// example: 65
ID int64 `json:"id"`
} `json:"body"`
}
// swagger:response deleteDataSourceByNameResponse
type DeleteDataSourceByNameResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the deleted data source.
// required: true
// example: 65
ID int64 `json:"id"`
// Message Message of the deleted dashboard.
// required: true
// example: Dashboard My Dashboard deleted
Message string `json:"message"`
} `json:"body"`
}