Skip to content

Commit

Permalink
improved health check for azure blob
Browse files Browse the repository at this point in the history
  • Loading branch information
yesoreyeram committed Mar 15, 2024
1 parent 0b7a019 commit 3bea7b5
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/hungry-owls-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'grafana-infinity-datasource': minor
---

Improved health check for azure blob storage connections
15 changes: 10 additions & 5 deletions pkg/infinity/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ func NewClient(ctx context.Context, settings models.InfinitySettings) (client *C
httpClient := getBaseHTTPClient(ctx, settings)
if httpClient == nil {
span.RecordError(errors.New("invalid http client"))
return nil, errors.New("invalid http client")
backend.Logger.Error("invalid http client", "datasource uid", settings.UID, "datasource name", settings.Name)
return client, errors.New("invalid http client")
}
httpClient = ApplyDigestAuth(ctx, httpClient, settings)
httpClient = ApplyOAuthClientCredentials(ctx, httpClient, settings)
Expand All @@ -108,7 +109,8 @@ func NewClient(ctx context.Context, settings models.InfinitySettings) (client *C

httpClient, err = ApplySecureSocksProxyConfiguration(httpClient, settings)
if err != nil {
return nil, err
backend.Logger.Error("error applying secure socks proxy", "datasource uid", settings.UID, "datasource name", settings.Name)
return client, err
}

client = &Client{
Expand All @@ -121,7 +123,8 @@ func NewClient(ctx context.Context, settings models.InfinitySettings) (client *C
if err != nil {
span.RecordError(err)
span.SetStatus(500, err.Error())
return nil, fmt.Errorf("invalid azure blob credentials. %s", err)
backend.Logger.Error("invalid azure blob credentials", "datasource uid", settings.UID, "datasource name", settings.Name)
return client, errors.New("invalid azure blob credentials")
}
clientUrl := "https://%s.blob.core.windows.net/"
if settings.AzureBlobAccountUrl != "" {
Expand All @@ -134,12 +137,14 @@ func NewClient(ctx context.Context, settings models.InfinitySettings) (client *C
if err != nil {
span.RecordError(err)
span.SetStatus(500, err.Error())
return nil, fmt.Errorf("invalid azure blob client. %s", err)
backend.Logger.Error("error creating azure blob client", "datasource uid", settings.UID, "datasource name", settings.Name)
return client, fmt.Errorf("error creating azure blob client. %s", err)
}
if azClient == nil {
span.RecordError(errors.New("invalid/empty azure blob client"))
span.SetStatus(500, "invalid/empty azure blob client")
return nil, errors.New("invalid/empty azure blob client")
backend.Logger.Error("invalid/empty azure blob client", "datasource uid", settings.UID, "datasource name", settings.Name)
return client, errors.New("invalid/empty azure blob client")
}
client.AzureBlobClient = azClient
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/models/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ const (
)

type InfinitySettings struct {
UID string
Name string
IsMock bool
AuthenticationMethod string
OAuth2Settings OAuth2Settings
Expand Down Expand Up @@ -120,6 +122,12 @@ func (s *InfinitySettings) Validate() error {
return errors.New("invalid or empty bearer token detected")
}
if s.AuthenticationMethod == AuthenticationMethodAzureBlob {
if strings.TrimSpace(s.AzureBlobAccountName) == "" {
return errors.New("invalid/empty azure blob account name")
}
if strings.TrimSpace(s.AzureBlobAccountKey) == "" {
return errors.New("invalid/empty azure blob key")
}
return nil
}
if s.AuthenticationMethod != AuthenticationMethodNone && len(s.AllowedHosts) < 1 {
Expand Down Expand Up @@ -176,6 +184,8 @@ type InfinitySettingsJson struct {
}

func LoadSettings(ctx context.Context, config backend.DataSourceInstanceSettings) (settings InfinitySettings, err error) {
settings.UID = config.UID
settings.Name = config.Name
settings.URL = config.URL
if config.URL == "__IGNORE_URL__" {
settings.URL = ""
Expand Down
15 changes: 14 additions & 1 deletion pkg/pluginhost/handler_checkhealth.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ func (ds *PluginHost) CheckHealth(ctx context.Context, req *backend.CheckHealthR
func CheckHealth(ctx context.Context, ds *PluginHost, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
logger := backend.Logger.FromContext(ctx)
client, err := getInstance(ctx, ds.im, req.PluginContext)
if err != nil || client == nil || client.client == nil {
if err != nil {
return &backend.CheckHealthResult{
Status: backend.HealthStatusError,
Message: fmt.Sprintf("error loading datasource settings. %s", err.Error()),
}, nil
}
if client == nil || client.client == nil {
return &backend.CheckHealthResult{
Status: backend.HealthStatusError,
Message: "failed to get plugin instance",
Expand All @@ -47,6 +53,9 @@ func CheckHealth(ctx context.Context, ds *PluginHost, req *backend.CheckHealthRe
Message: fmt.Sprintf("invalid settings. %s", err.Error()),
}, nil
}
if client.client.Settings.AuthenticationMethod == models.AuthenticationMethodAzureBlob {
return checkHealthAzureBlobStorage(ctx, client)
}
if client.client.Settings.CustomHealthCheckEnabled && client.client.Settings.CustomHealthCheckUrl != "" {
_, statusCode, _, err := client.client.GetResults(ctx, models.Query{
Type: models.QueryTypeUQL,
Expand Down Expand Up @@ -80,3 +89,7 @@ func CheckHealth(ctx context.Context, ds *PluginHost, req *backend.CheckHealthRe
Message: "OK",
}, nil
}

func healthCheckError(msg string) (*backend.CheckHealthResult, error) {
return &backend.CheckHealthResult{Status: backend.HealthStatusError, Message: msg}, nil
}
38 changes: 38 additions & 0 deletions pkg/pluginhost/handler_checkhealth_azblog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package pluginhost

import (
"context"
"strings"

"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)

func checkHealthAzureBlobStorage(ctx context.Context, client *instanceSettings) (*backend.CheckHealthResult, error) {
if client == nil {
return healthCheckError("invalid client")
}
if client.client == nil {
return healthCheckError("invalid infinity client")
}
if client.client.AzureBlobClient == nil {
return healthCheckError("invalid azure blob client")
}
blobServiceClient := client.client.AzureBlobClient.ServiceClient()
if blobServiceClient == nil {
return healthCheckError("invalid azure blob service client. check storage account name and key")
}
if _, err := blobServiceClient.GetAccountInfo(ctx, &service.GetAccountInfoOptions{}); err != nil {
if strings.Contains(err.Error(), "no such host") {
return healthCheckError("error connecting to blob storage. invalid blog storage name")
}
if strings.Contains(err.Error(), "RESPONSE 403") {
return healthCheckError("error connecting to blob storage. http 403. check blob storage key")
}
if strings.Contains(err.Error(), "RESPONSE 500") {
return healthCheckError("error connecting to blob storage. http 500")
}
return healthCheckError("error connecting to blob storage. check grafana logs for more details")
}
return &backend.CheckHealthResult{Status: backend.HealthStatusOk, Message: "OK"}, nil
}
3 changes: 3 additions & 0 deletions src/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ export class Datasource extends DataSourceWithBackend<InfinityQuery, InfinityOpt
reportHealthCheck(o, this.instanceSettings, this.meta);
switch (o?.message) {
case 'OK':
if (this.instanceSettings?.jsonData?.auth_method === 'azureBlob' || this.instanceSettings?.jsonData?.auth_method === 'aws') {
return Promise.resolve({ status: 'success', message: 'OK. Settings saved' });
}
if (!(this.instanceSettings?.jsonData?.customHealthCheckEnabled && this.instanceSettings?.jsonData?.customHealthCheckUrl) && this.instanceSettings?.jsonData?.auth_method) {
const healthCheckMessage = [
'Success',
Expand Down

0 comments on commit 3bea7b5

Please sign in to comment.