Skip to content

Commit 128c028

Browse files
authored
Making sure that plugin-manager works in disconnected env with local crane-plugins (#51)
1 parent e0c3be9 commit 128c028

File tree

5 files changed

+194
-32
lines changed

5 files changed

+194
-32
lines changed

cmd/plugin-manager/add/add.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,24 @@ func (o *Options) run(args []string) error {
171171
}
172172

173173
func downloadBinary(filepath string, filename string, url string, log *logrus.Logger) error {
174-
175-
// Get the data
176-
resp, err := http.Get(url)
177-
if err != nil {
178-
return err
174+
var binaryContents io.Reader
175+
isUrl, url := plugin.IsUrl(url)
176+
if !isUrl {
177+
srcPlugin, err := os.Open(url)
178+
if err != nil {
179+
return err
180+
}
181+
defer srcPlugin.Close()
182+
binaryContents = srcPlugin
183+
} else {
184+
// Get the data
185+
resp, err := http.Get(url)
186+
if err != nil {
187+
return err
188+
}
189+
defer resp.Body.Close()
190+
binaryContents = resp.Body
179191
}
180-
defer resp.Body.Close()
181192
// Create dir if not exists
182193
if _, err := os.Stat(filepath); os.IsNotExist(err) {
183194
err = os.MkdirAll(filepath, os.ModePerm)
@@ -187,20 +198,25 @@ func downloadBinary(filepath string, filename string, url string, log *logrus.Lo
187198
}
188199

189200
// Create the file
190-
out, err := os.OpenFile(filepath+"/"+filename, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0777)
201+
plugin, err := os.OpenFile(filepath+"/"+filename, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0777)
191202
if err != nil {
192203
return err
193204
}
194-
defer out.Close()
205+
defer plugin.Close()
195206

196207
// Write the body to filePluginDir
197-
_, err = io.Copy(out, resp.Body)
198-
if err == nil {
199-
log.Infof("plugin %s added to the path - %s", filename, filepath)
208+
_, err = io.Copy(plugin, binaryContents)
209+
if err != nil {
210+
return err
200211
}
212+
err = plugin.Sync()
213+
if err != nil {
214+
return err
215+
}
216+
log.Infof("plugin %s added to the path - %s", filename, filepath)
201217
return err
202218
}
203219

204220
func (o *Options) ManagedPluginDir() string {
205221
return fmt.Sprintf("%v/%v", o.PluginDir, plugin.MANAGED_DIR)
206-
}
222+
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.16
44

55
require (
66
github.com/ghodss/yaml v1.0.0
7+
github.com/jarcoal/httpmock v1.0.8
78
github.com/konveyor/crane-lib v0.0.4
89
github.com/mitchellh/mapstructure v1.4.1
910
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5
@@ -12,6 +13,7 @@ require (
1213
github.com/spf13/cobra v1.2.1
1314
github.com/spf13/viper v1.8.1
1415
github.com/vmware-tanzu/velero v1.6.3
16+
gotest.tools v2.2.0+incompatible
1517
k8s.io/api v0.22.2
1618
k8s.io/apimachinery v0.22.2
1719
k8s.io/cli-runtime v0.22.2

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
430430
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
431431
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
432432
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
433+
github.com/jarcoal/httpmock v1.0.8 h1:8kI16SoO6LQKgPE7PvQuV+YuD/inwHd7fOOe2zMbo4k=
434+
github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
433435
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
434436
github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8=
435437
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -1200,6 +1202,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
12001202
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
12011203
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
12021204
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
1205+
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
12031206
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
12041207
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
12051208
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=

internal/plugin/plugin_manager_helper.go

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/sirupsen/logrus"
99
"io/ioutil"
1010
"net/http"
11+
"net/url"
1112
"os"
1213
"runtime"
1314
"strings"
@@ -86,45 +87,33 @@ func BuildManifestMap(log *logrus.Logger, name string, repoName string) (map[str
8687
}
8788

8889
// takes url as input and returns index.yml for plugin repository
89-
func GetYamlFromUrl(url string) (map[string]interface{}, error) {
90-
res, err := http.Get(url)
90+
func GetYamlFromUrl(URL string) (map[string]interface{}, error) {
91+
var manifest map[string]interface{}
92+
index, err := getData(URL)
9193
if err != nil {
9294
return nil, err
9395
}
94-
95-
defer res.Body.Close()
96-
97-
body, err := ioutil.ReadAll(res.Body)
98-
96+
err = yaml.Unmarshal(index, &manifest)
9997
if err != nil {
10098
return nil, err
10199
}
102-
var manifest map[string]interface{}
103-
err = yaml.Unmarshal(body, &manifest)
104-
if err != nil {
105-
panic(err)
106-
}
107100
return manifest, nil
108101
}
109102

110103
// takes url as input and fetches the manifest of a plugin
111-
func YamlToManifest(url string) (Manifest, error) {
104+
func YamlToManifest(URL string) (Manifest, error) {
112105
plugin := Manifest{}
113-
res, err := http.Get(url)
114-
if err != nil {
115-
return plugin, err
116-
}
117106

118-
defer res.Body.Close()
119-
120-
body, err := ioutil.ReadAll(res.Body)
107+
body, err := getData(URL)
121108
if err != nil {
122109
return plugin, err
123110
}
111+
124112
err = yaml.Unmarshal(body, &plugin)
125113
if err != nil {
126114
return Manifest{}, err
127115
}
116+
128117
isPluginAvailable := FilterPluginForOsArch(&plugin)
129118
if isPluginAvailable {
130119
return plugin, nil
@@ -180,3 +169,34 @@ func LocateBinaryInPluginDir(pluginDir string, name string, files []os.FileInfo)
180169
}
181170
return paths, nil
182171
}
172+
173+
func IsUrl(URL string) (bool, string) {
174+
URL = strings.TrimPrefix(URL, "file://")
175+
u, err := url.Parse(URL)
176+
return err == nil && u.Scheme != "" && u.Host != "", URL
177+
}
178+
179+
func getData(URL string) ([]byte, error) {
180+
var index []byte
181+
var err error
182+
isUrl, URL := IsUrl(URL)
183+
if !isUrl {
184+
index, err = ioutil.ReadFile(URL)
185+
if err != nil {
186+
return nil, err
187+
}
188+
} else {
189+
res, err := http.Get(URL)
190+
if err != nil {
191+
return nil, err
192+
}
193+
194+
defer res.Body.Close()
195+
196+
index, err = ioutil.ReadAll(res.Body)
197+
if err != nil {
198+
return nil, err
199+
}
200+
}
201+
return index, nil
202+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package plugin
2+
3+
import (
4+
"github.com/ghodss/yaml"
5+
"github.com/jarcoal/httpmock"
6+
"gotest.tools/assert"
7+
"io/ioutil"
8+
"net/http"
9+
"os"
10+
"testing"
11+
)
12+
13+
func TestGetYamlFromUrlWithUrl(t *testing.T) {
14+
URL := "https://test.com/index.yml"
15+
httpmock.Activate()
16+
defer httpmock.DeactivateAndReset()
17+
index := map[string]interface{}{
18+
"foo-0.0.1": "https://test.com/foo-0.0.1.yml",
19+
}
20+
httpmock.RegisterResponder("GET", URL,
21+
func(req *http.Request) (*http.Response, error) {
22+
// Get ID from request
23+
return httpmock.NewJsonResponse(200, index)
24+
},
25+
)
26+
27+
resp, _ := GetYamlFromUrl(URL)
28+
assert.DeepEqual(t, index, resp)
29+
}
30+
31+
func TestYamlToManifestWithUrl(t *testing.T) {
32+
URL := "https://test.com/foo-0.0.1.yml"
33+
httpmock.Activate()
34+
defer httpmock.DeactivateAndReset()
35+
index := Manifest{
36+
Name: "foo",
37+
Version: "0.0.1",
38+
Description: "Description of foo plugin",
39+
ShortDescription: "Short description of foo plugin",
40+
Binaries: []Binary{
41+
{
42+
OS: "linux",
43+
Arch: "amd64",
44+
URI: "https://test.com/download/foo",
45+
},
46+
},
47+
}
48+
httpmock.RegisterResponder("GET", URL,
49+
func(req *http.Request) (*http.Response, error) {
50+
// Get ID from request
51+
return httpmock.NewJsonResponse(200, index)
52+
},
53+
)
54+
55+
resp, _ := YamlToManifest(URL)
56+
assert.DeepEqual(t, index, resp)
57+
}
58+
59+
func TestGetYamlFromUrlWithFile(t *testing.T) {
60+
index := map[string]interface{}{
61+
"foo-0.0.1": "file://tmp/foo-0.0.1.yml",
62+
}
63+
tempFile, err := ioutil.TempFile(os.TempDir(), "index.yml")
64+
if err != nil {
65+
panic(err)
66+
}
67+
defer os.Remove(tempFile.Name())
68+
69+
data, err := yaml.Marshal(&index)
70+
if err != nil {
71+
panic(err)
72+
}
73+
74+
_, err = tempFile.Write(data)
75+
if err != nil {
76+
panic(err)
77+
}
78+
79+
resp, _ := GetYamlFromUrl(tempFile.Name())
80+
assert.DeepEqual(t, index, resp)
81+
82+
resp, _ = GetYamlFromUrl("file://" + tempFile.Name())
83+
assert.DeepEqual(t, index, resp)
84+
}
85+
86+
func TestYamlToManifestWithFile(t *testing.T) {
87+
plugin := Manifest {
88+
Name: "foo",
89+
Version: "0.0.1",
90+
Description: "Description of foo plugin",
91+
ShortDescription: "Short description of foo plugin",
92+
Binaries: []Binary{
93+
{
94+
OS: "linux",
95+
Arch: "amd64",
96+
URI: "https://test.com/download/foo",
97+
},
98+
},
99+
}
100+
tempFile, err := ioutil.TempFile(os.TempDir(), "index.yml")
101+
if err != nil {
102+
panic(err)
103+
}
104+
defer os.Remove(tempFile.Name())
105+
106+
data, err := yaml.Marshal(&plugin)
107+
if err != nil {
108+
panic(err)
109+
}
110+
111+
_, err = tempFile.Write(data)
112+
if err != nil {
113+
panic(err)
114+
}
115+
116+
resp, _ := YamlToManifest(tempFile.Name())
117+
assert.DeepEqual(t, plugin, resp)
118+
119+
resp, _ = YamlToManifest("file://" + tempFile.Name())
120+
assert.DeepEqual(t, plugin, resp)
121+
}

0 commit comments

Comments
 (0)