From b2e5a8cf078abbaf2780f9c72017afa1906ff37f Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Wed, 9 Mar 2022 18:15:44 -0500 Subject: [PATCH] Allow creating Grafana API keys from Cloud (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow creating Grafana API keys from Cloud Also add a function to create a temporary client. This will be used by Terraform. See https://github.com/grafana/terraform-provider-grafana/pull/416 * Apply suggestions from code review Co-authored-by: Leandro López Co-authored-by: Leandro López --- cloud_grafana_api_key.go | 57 ++++++++++++++++++++++++++++ stacks.go => cloud_stack.go | 0 stack_test.go => cloud_stack_test.go | 0 3 files changed, 57 insertions(+) create mode 100644 cloud_grafana_api_key.go rename stacks.go => cloud_stack.go (100%) rename stack_test.go => cloud_stack_test.go (100%) diff --git a/cloud_grafana_api_key.go b/cloud_grafana_api_key.go new file mode 100644 index 00000000..11d788c5 --- /dev/null +++ b/cloud_grafana_api_key.go @@ -0,0 +1,57 @@ +package gapi + +import ( + "bytes" + "encoding/json" + "fmt" + "time" +) + +// This function creates a API key inside the Grafana instance running in stack `stack`. It's used in order +// to provision API keys inside Grafana while just having access to a Grafana Cloud API key. +// +// See https://grafana.com/docs/grafana-cloud/api/#create-grafana-api-keys for more information. +func (c *Client) CreateGrafanaAPIKeyFromCloud(stack string, input *CreateAPIKeyRequest) (*CreateAPIKeyResponse, error) { + data, err := json.Marshal(input) + if err != nil { + return nil, err + } + + resp := &CreateAPIKeyResponse{} + err = c.request("POST", fmt.Sprintf("/api/instances/%s/api/auth/keys", stack), nil, bytes.NewBuffer(data), resp) + return resp, err +} + +// The Grafana Cloud API is disconnected from the Grafana API on the stacks unfortunately. That's why we can't use +// the Grafana Cloud API key to fully manage API keys on the Grafana API. The only thing we can do is to create +// a temporary Admin key, and create a Grafana API client with that. +func (c *Client) CreateTemporaryStackGrafanaClient(stackSlug, tempKeyPrefix string, tempKeyDuration time.Duration) (tempClient *Client, cleanup func() error, err error) { + stack, err := c.StackBySlug(stackSlug) + if err != nil { + return nil, nil, err + } + + name := fmt.Sprintf("%s-%d", tempKeyPrefix, time.Now().UnixNano()) + req := &CreateAPIKeyRequest{ + Name: name, + Role: "Admin", + SecondsToLive: int64(tempKeyDuration.Seconds()), + } + + apiKey, err := c.CreateGrafanaAPIKeyFromCloud(stackSlug, req) + if err != nil { + return nil, nil, err + } + + client, err := New(stack.URL, Config{APIKey: apiKey.Key}) + if err != nil { + return nil, nil, err + } + + cleanup = func() error { + _, err = client.DeleteAPIKey(apiKey.ID) + return err + } + + return client, cleanup, nil +} diff --git a/stacks.go b/cloud_stack.go similarity index 100% rename from stacks.go rename to cloud_stack.go diff --git a/stack_test.go b/cloud_stack_test.go similarity index 100% rename from stack_test.go rename to cloud_stack_test.go