This repository has been archived by the owner on Jan 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add functionality to manage plugins (#68)
* Add functionality to manage plugins * Prefix plugin management with cloud * Use stack slug instead of ID * return ID of the installation * Return CloudInstallation
- Loading branch information
1 parent
b2e5a8c
commit 075eeb6
Showing
2 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package gapi | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
) | ||
|
||
type Plugin struct { | ||
ID int `json:"id"` | ||
Name string `json:"name"` | ||
Slug string `json:"slug"` | ||
Version string `json:"version"` | ||
Description string `json:"description"` | ||
} | ||
|
||
type CloudPluginInstallation struct { | ||
ID int `json:"id"` | ||
InstanceID int `json:"instanceId"` | ||
InstanceURL string `json:"instanceUrl"` | ||
InstanceSlug string `json:"instanceSlug"` | ||
PluginID int `json:"pluginId"` | ||
PluginSlug string `json:"pluginSlug"` | ||
PluginName string `json:"pluginName"` | ||
Version string `json:"version"` | ||
} | ||
|
||
// InstallCloudPlugin installs the specified plugin to the given stack. | ||
func (c *Client) InstallCloudPlugin(stackSlug string, pluginSlug string, pluginVersion string) (*CloudPluginInstallation, error) { | ||
installPluginRequest := struct { | ||
Plugin string `json:"plugin"` | ||
Version string `json:"version"` | ||
}{ | ||
Plugin: pluginSlug, | ||
Version: pluginVersion, | ||
} | ||
|
||
data, err := json.Marshal(installPluginRequest) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var installation CloudPluginInstallation | ||
|
||
err = c.request("POST", fmt.Sprintf("/api/instances/%s/plugins", stackSlug), nil, bytes.NewBuffer(data), &installation) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &installation, nil | ||
} | ||
|
||
// UninstallCloudPlugin uninstalls the specified plugin to the given stack. | ||
func (c *Client) UninstallCloudPlugin(stackSlug string, pluginSlug string) error { | ||
return c.request("DELETE", fmt.Sprintf("/api/instances/%s/plugins/%s", stackSlug, pluginSlug), nil, nil, nil) | ||
} | ||
|
||
// IsCloudPluginInstalled returns a boolean if the specified plugin is installed on the stack. | ||
func (c *Client) IsCloudPluginInstalled(stackSlug string, pluginSlug string) (bool, error) { | ||
req, err := c.newRequest("GET", fmt.Sprintf("/api/instances/%s/plugins/%s", stackSlug, pluginSlug), nil, nil) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
resp, err := c.client.Do(req) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
if resp.StatusCode == http.StatusNotFound { | ||
return false, nil | ||
} | ||
bodyContents, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
return false, fmt.Errorf("status: %d, body: %v", resp.StatusCode, string(bodyContents)) | ||
} | ||
|
||
return true, nil | ||
} | ||
|
||
// GetCloudPluginInstallation returns the cloud plugin installation details for the specified plugin. | ||
func (c *Client) GetCloudPluginInstallation(stackSlug string, pluginSlug string) (*CloudPluginInstallation, error) { | ||
var installation CloudPluginInstallation | ||
|
||
err := c.request("GET", fmt.Sprintf("/api/instances/%s/plugins/%s", stackSlug, pluginSlug), nil, nil, &installation) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &installation, nil | ||
} | ||
|
||
// PluginBySlug returns the plugin with the given slug. | ||
// An error will be returned given an unknown slug. | ||
func (c *Client) PluginBySlug(slug string) (*Plugin, error) { | ||
p := Plugin{} | ||
|
||
err := c.request("GET", fmt.Sprintf("/api/plugins/%s", slug), nil, nil, &p) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &p, nil | ||
} | ||
|
||
// PluginByID returns the plugin with the given id. | ||
// An error will be returned given an unknown ID. | ||
func (c *Client) PluginByID(pluginID int64) (*Plugin, error) { | ||
p := Plugin{} | ||
|
||
err := c.request("GET", fmt.Sprintf("/api/plugins/%d", pluginID), nil, nil, p) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &p, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
package gapi | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
const ( | ||
installPluginJSON = ` | ||
{ | ||
"id": 123, | ||
"instanceId": 2, | ||
"instanceUrl": "mystack.grafana.net", | ||
"instanceSlug": "mystack", | ||
"pluginId": 3, | ||
"pluginSlug": "some-plugin", | ||
"pluginName": "Some Plugin", | ||
"version": "1.2.3", | ||
"latestVersion": "1.2.3", | ||
"createdAt": "2021-12-22T14:02:46.000Z", | ||
"updatedAt": null | ||
}` | ||
uninstallPluginJSON = ` | ||
{ | ||
"id": 123, | ||
"instanceId": 2, | ||
"instanceUrl": "mystack.grafana.net", | ||
"instanceSlug": "mystack", | ||
"pluginId": 3, | ||
"pluginSlug": "some-plugin", | ||
"pluginName": "Some Plugin", | ||
"version": "1.2.3", | ||
"latestVersion": "1.2.3", | ||
"createdAt": "2021-12-22T14:02:46.000Z", | ||
"updatedAt": null | ||
}` | ||
getPluginJSON = ` | ||
{ | ||
"id": 34, | ||
"name": "Some Plugin", | ||
"slug": "some-plugin", | ||
"version": "1.2.3", | ||
"description": "Some Plugin for adding functionality" | ||
}` | ||
) | ||
|
||
func TestInstallCloudPlugin(t *testing.T) { | ||
server, client := gapiTestTools(t, 200, installPluginJSON) | ||
defer server.Close() | ||
|
||
installation, err := client.InstallCloudPlugin("some-stack", "some-plugin", "1.2.3") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
expectedInstallation := CloudPluginInstallation{} | ||
err = UnmarshalJSONToStruct(installPluginJSON, &expectedInstallation) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if *installation != expectedInstallation { | ||
t.Errorf("Unexpected installation - Actual: %v, Expected: %v", installation, expectedInstallation) | ||
} | ||
|
||
for _, code := range []int{401, 403, 404, 412} { | ||
server.code = code | ||
|
||
installation, err = client.InstallCloudPlugin("some-stack", "some-plugin", "1.2.3") | ||
if err == nil { | ||
t.Errorf("%d not detected", code) | ||
} | ||
if installation != nil { | ||
t.Errorf("Expected empty installation, got %v", installation) | ||
} | ||
} | ||
} | ||
|
||
func TestUninstallCloudPlugin(t *testing.T) { | ||
server, client := gapiTestTools(t, 200, uninstallPluginJSON) | ||
defer server.Close() | ||
|
||
err := client.UninstallCloudPlugin("some-stack", "some-plugin") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
for _, code := range []int{401, 403, 404, 412} { | ||
server.code = code | ||
|
||
err = client.UninstallCloudPlugin("some-stack", "some-plugin") | ||
if err == nil { | ||
t.Errorf("%d not detected", code) | ||
} | ||
} | ||
} | ||
|
||
func TestIsCloudPluginInstalled(t *testing.T) { | ||
server, client := gapiTestTools(t, 200, getPluginJSON) | ||
|
||
ok, err := client.IsCloudPluginInstalled("some-stack", "some-plugin") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
if !ok { | ||
t.Errorf("Expected plugin installation - Expected true, got false") | ||
} | ||
|
||
server.code = 404 | ||
ok, err = client.IsCloudPluginInstalled("some-stack", "some-plugin") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
if ok { | ||
t.Errorf("Unexpected plugin installation - Expected false, got true") | ||
} | ||
|
||
for _, code := range []int{401, 403, 412} { | ||
server.code = code | ||
|
||
_, err := client.IsCloudPluginInstalled("some-stack", "some-plugin") | ||
if err == nil { | ||
t.Errorf("%d not detected", code) | ||
} | ||
} | ||
} | ||
|
||
func TestGetCloudPluginInstallation(t *testing.T) { | ||
server, client := gapiTestTools(t, 200, installPluginJSON) | ||
defer server.Close() | ||
|
||
installation, err := client.GetCloudPluginInstallation("some-stack", "some-plugin") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
expectedInstallation := CloudPluginInstallation{} | ||
err = UnmarshalJSONToStruct(installPluginJSON, &expectedInstallation) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if *installation != expectedInstallation { | ||
t.Errorf("Unexpected installation - Actual: %v, Expected: %v", installation, expectedInstallation) | ||
} | ||
|
||
for _, code := range []int{401, 403, 404, 412} { | ||
server.code = code | ||
|
||
installation, err = client.GetCloudPluginInstallation("some-stack", "some-plugin") | ||
if err == nil { | ||
t.Errorf("%d not detected", code) | ||
} | ||
if installation != nil { | ||
t.Errorf("Expected empty installation, got %v", installation) | ||
} | ||
} | ||
} | ||
|
||
func TestPlugin(t *testing.T) { | ||
server, client := gapiTestTools(t, 200, getPluginJSON) | ||
defer server.Close() | ||
|
||
plugin, err := client.PluginBySlug("some-plugin") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
expectedPlugin := Plugin{} | ||
err = UnmarshalJSONToStruct(getPluginJSON, &expectedPlugin) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if *plugin != expectedPlugin { | ||
t.Errorf("Unexpected plugin - Actual: %v, Expected: %v", plugin, expectedPlugin) | ||
} | ||
|
||
for _, code := range []int{404} { | ||
server.code = code | ||
|
||
_, err = client.PluginBySlug("some-plugin") | ||
if err == nil { | ||
t.Errorf("%d not detected", code) | ||
} | ||
} | ||
} | ||
|
||
func TestPluginByID(t *testing.T) { | ||
server, client := gapiTestTools(t, 200, getPluginJSON) | ||
defer server.Close() | ||
|
||
plugin, err := client.PluginBySlug("some-plugin") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
expectedPlugin := Plugin{} | ||
err = UnmarshalJSONToStruct(getPluginJSON, &expectedPlugin) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if *plugin != expectedPlugin { | ||
t.Errorf("Unexpected plugin - Actual: %v, Expected: %v", plugin, expectedPlugin) | ||
} | ||
|
||
for _, code := range []int{404} { | ||
server.code = code | ||
|
||
_, err = client.PluginByID(123) | ||
if err == nil { | ||
t.Errorf("%d not detected", code) | ||
} | ||
} | ||
} |