Skip to content
This repository was archived by the owner on Jan 15, 2024. It is now read-only.

Commit 075eeb6

Browse files
authored
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
1 parent b2e5a8c commit 075eeb6

File tree

2 files changed

+342
-0
lines changed

2 files changed

+342
-0
lines changed

cloud_plugin.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package gapi
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"io/ioutil"
8+
"net/http"
9+
)
10+
11+
type Plugin struct {
12+
ID int `json:"id"`
13+
Name string `json:"name"`
14+
Slug string `json:"slug"`
15+
Version string `json:"version"`
16+
Description string `json:"description"`
17+
}
18+
19+
type CloudPluginInstallation struct {
20+
ID int `json:"id"`
21+
InstanceID int `json:"instanceId"`
22+
InstanceURL string `json:"instanceUrl"`
23+
InstanceSlug string `json:"instanceSlug"`
24+
PluginID int `json:"pluginId"`
25+
PluginSlug string `json:"pluginSlug"`
26+
PluginName string `json:"pluginName"`
27+
Version string `json:"version"`
28+
}
29+
30+
// InstallCloudPlugin installs the specified plugin to the given stack.
31+
func (c *Client) InstallCloudPlugin(stackSlug string, pluginSlug string, pluginVersion string) (*CloudPluginInstallation, error) {
32+
installPluginRequest := struct {
33+
Plugin string `json:"plugin"`
34+
Version string `json:"version"`
35+
}{
36+
Plugin: pluginSlug,
37+
Version: pluginVersion,
38+
}
39+
40+
data, err := json.Marshal(installPluginRequest)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
var installation CloudPluginInstallation
46+
47+
err = c.request("POST", fmt.Sprintf("/api/instances/%s/plugins", stackSlug), nil, bytes.NewBuffer(data), &installation)
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
return &installation, nil
53+
}
54+
55+
// UninstallCloudPlugin uninstalls the specified plugin to the given stack.
56+
func (c *Client) UninstallCloudPlugin(stackSlug string, pluginSlug string) error {
57+
return c.request("DELETE", fmt.Sprintf("/api/instances/%s/plugins/%s", stackSlug, pluginSlug), nil, nil, nil)
58+
}
59+
60+
// IsCloudPluginInstalled returns a boolean if the specified plugin is installed on the stack.
61+
func (c *Client) IsCloudPluginInstalled(stackSlug string, pluginSlug string) (bool, error) {
62+
req, err := c.newRequest("GET", fmt.Sprintf("/api/instances/%s/plugins/%s", stackSlug, pluginSlug), nil, nil)
63+
if err != nil {
64+
return false, err
65+
}
66+
67+
resp, err := c.client.Do(req)
68+
if err != nil {
69+
return false, err
70+
}
71+
72+
defer resp.Body.Close()
73+
74+
if resp.StatusCode != http.StatusOK {
75+
if resp.StatusCode == http.StatusNotFound {
76+
return false, nil
77+
}
78+
bodyContents, err := ioutil.ReadAll(resp.Body)
79+
if err != nil {
80+
return false, err
81+
}
82+
83+
return false, fmt.Errorf("status: %d, body: %v", resp.StatusCode, string(bodyContents))
84+
}
85+
86+
return true, nil
87+
}
88+
89+
// GetCloudPluginInstallation returns the cloud plugin installation details for the specified plugin.
90+
func (c *Client) GetCloudPluginInstallation(stackSlug string, pluginSlug string) (*CloudPluginInstallation, error) {
91+
var installation CloudPluginInstallation
92+
93+
err := c.request("GET", fmt.Sprintf("/api/instances/%s/plugins/%s", stackSlug, pluginSlug), nil, nil, &installation)
94+
if err != nil {
95+
return nil, err
96+
}
97+
98+
return &installation, nil
99+
}
100+
101+
// PluginBySlug returns the plugin with the given slug.
102+
// An error will be returned given an unknown slug.
103+
func (c *Client) PluginBySlug(slug string) (*Plugin, error) {
104+
p := Plugin{}
105+
106+
err := c.request("GET", fmt.Sprintf("/api/plugins/%s", slug), nil, nil, &p)
107+
if err != nil {
108+
return nil, err
109+
}
110+
111+
return &p, nil
112+
}
113+
114+
// PluginByID returns the plugin with the given id.
115+
// An error will be returned given an unknown ID.
116+
func (c *Client) PluginByID(pluginID int64) (*Plugin, error) {
117+
p := Plugin{}
118+
119+
err := c.request("GET", fmt.Sprintf("/api/plugins/%d", pluginID), nil, nil, p)
120+
if err != nil {
121+
return nil, err
122+
}
123+
124+
return &p, nil
125+
}

cloud_plugin_test.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package gapi
2+
3+
import (
4+
"testing"
5+
)
6+
7+
const (
8+
installPluginJSON = `
9+
{
10+
"id": 123,
11+
"instanceId": 2,
12+
"instanceUrl": "mystack.grafana.net",
13+
"instanceSlug": "mystack",
14+
"pluginId": 3,
15+
"pluginSlug": "some-plugin",
16+
"pluginName": "Some Plugin",
17+
"version": "1.2.3",
18+
"latestVersion": "1.2.3",
19+
"createdAt": "2021-12-22T14:02:46.000Z",
20+
"updatedAt": null
21+
}`
22+
uninstallPluginJSON = `
23+
{
24+
"id": 123,
25+
"instanceId": 2,
26+
"instanceUrl": "mystack.grafana.net",
27+
"instanceSlug": "mystack",
28+
"pluginId": 3,
29+
"pluginSlug": "some-plugin",
30+
"pluginName": "Some Plugin",
31+
"version": "1.2.3",
32+
"latestVersion": "1.2.3",
33+
"createdAt": "2021-12-22T14:02:46.000Z",
34+
"updatedAt": null
35+
}`
36+
getPluginJSON = `
37+
{
38+
"id": 34,
39+
"name": "Some Plugin",
40+
"slug": "some-plugin",
41+
"version": "1.2.3",
42+
"description": "Some Plugin for adding functionality"
43+
}`
44+
)
45+
46+
func TestInstallCloudPlugin(t *testing.T) {
47+
server, client := gapiTestTools(t, 200, installPluginJSON)
48+
defer server.Close()
49+
50+
installation, err := client.InstallCloudPlugin("some-stack", "some-plugin", "1.2.3")
51+
if err != nil {
52+
t.Error(err)
53+
}
54+
55+
expectedInstallation := CloudPluginInstallation{}
56+
err = UnmarshalJSONToStruct(installPluginJSON, &expectedInstallation)
57+
if err != nil {
58+
t.Fatal(err)
59+
}
60+
61+
if *installation != expectedInstallation {
62+
t.Errorf("Unexpected installation - Actual: %v, Expected: %v", installation, expectedInstallation)
63+
}
64+
65+
for _, code := range []int{401, 403, 404, 412} {
66+
server.code = code
67+
68+
installation, err = client.InstallCloudPlugin("some-stack", "some-plugin", "1.2.3")
69+
if err == nil {
70+
t.Errorf("%d not detected", code)
71+
}
72+
if installation != nil {
73+
t.Errorf("Expected empty installation, got %v", installation)
74+
}
75+
}
76+
}
77+
78+
func TestUninstallCloudPlugin(t *testing.T) {
79+
server, client := gapiTestTools(t, 200, uninstallPluginJSON)
80+
defer server.Close()
81+
82+
err := client.UninstallCloudPlugin("some-stack", "some-plugin")
83+
if err != nil {
84+
t.Error(err)
85+
}
86+
87+
for _, code := range []int{401, 403, 404, 412} {
88+
server.code = code
89+
90+
err = client.UninstallCloudPlugin("some-stack", "some-plugin")
91+
if err == nil {
92+
t.Errorf("%d not detected", code)
93+
}
94+
}
95+
}
96+
97+
func TestIsCloudPluginInstalled(t *testing.T) {
98+
server, client := gapiTestTools(t, 200, getPluginJSON)
99+
100+
ok, err := client.IsCloudPluginInstalled("some-stack", "some-plugin")
101+
if err != nil {
102+
t.Error(err)
103+
}
104+
105+
if !ok {
106+
t.Errorf("Expected plugin installation - Expected true, got false")
107+
}
108+
109+
server.code = 404
110+
ok, err = client.IsCloudPluginInstalled("some-stack", "some-plugin")
111+
if err != nil {
112+
t.Error(err)
113+
}
114+
115+
if ok {
116+
t.Errorf("Unexpected plugin installation - Expected false, got true")
117+
}
118+
119+
for _, code := range []int{401, 403, 412} {
120+
server.code = code
121+
122+
_, err := client.IsCloudPluginInstalled("some-stack", "some-plugin")
123+
if err == nil {
124+
t.Errorf("%d not detected", code)
125+
}
126+
}
127+
}
128+
129+
func TestGetCloudPluginInstallation(t *testing.T) {
130+
server, client := gapiTestTools(t, 200, installPluginJSON)
131+
defer server.Close()
132+
133+
installation, err := client.GetCloudPluginInstallation("some-stack", "some-plugin")
134+
if err != nil {
135+
t.Error(err)
136+
}
137+
138+
expectedInstallation := CloudPluginInstallation{}
139+
err = UnmarshalJSONToStruct(installPluginJSON, &expectedInstallation)
140+
if err != nil {
141+
t.Fatal(err)
142+
}
143+
144+
if *installation != expectedInstallation {
145+
t.Errorf("Unexpected installation - Actual: %v, Expected: %v", installation, expectedInstallation)
146+
}
147+
148+
for _, code := range []int{401, 403, 404, 412} {
149+
server.code = code
150+
151+
installation, err = client.GetCloudPluginInstallation("some-stack", "some-plugin")
152+
if err == nil {
153+
t.Errorf("%d not detected", code)
154+
}
155+
if installation != nil {
156+
t.Errorf("Expected empty installation, got %v", installation)
157+
}
158+
}
159+
}
160+
161+
func TestPlugin(t *testing.T) {
162+
server, client := gapiTestTools(t, 200, getPluginJSON)
163+
defer server.Close()
164+
165+
plugin, err := client.PluginBySlug("some-plugin")
166+
if err != nil {
167+
t.Error(err)
168+
}
169+
170+
expectedPlugin := Plugin{}
171+
err = UnmarshalJSONToStruct(getPluginJSON, &expectedPlugin)
172+
if err != nil {
173+
t.Fatal(err)
174+
}
175+
176+
if *plugin != expectedPlugin {
177+
t.Errorf("Unexpected plugin - Actual: %v, Expected: %v", plugin, expectedPlugin)
178+
}
179+
180+
for _, code := range []int{404} {
181+
server.code = code
182+
183+
_, err = client.PluginBySlug("some-plugin")
184+
if err == nil {
185+
t.Errorf("%d not detected", code)
186+
}
187+
}
188+
}
189+
190+
func TestPluginByID(t *testing.T) {
191+
server, client := gapiTestTools(t, 200, getPluginJSON)
192+
defer server.Close()
193+
194+
plugin, err := client.PluginBySlug("some-plugin")
195+
if err != nil {
196+
t.Error(err)
197+
}
198+
199+
expectedPlugin := Plugin{}
200+
err = UnmarshalJSONToStruct(getPluginJSON, &expectedPlugin)
201+
if err != nil {
202+
t.Fatal(err)
203+
}
204+
205+
if *plugin != expectedPlugin {
206+
t.Errorf("Unexpected plugin - Actual: %v, Expected: %v", plugin, expectedPlugin)
207+
}
208+
209+
for _, code := range []int{404} {
210+
server.code = code
211+
212+
_, err = client.PluginByID(123)
213+
if err == nil {
214+
t.Errorf("%d not detected", code)
215+
}
216+
}
217+
}

0 commit comments

Comments
 (0)