From 4a3776ecf00c4aea48bbd971fc8a42a9e13d3d6a Mon Sep 17 00:00:00 2001 From: Muhammad Hewedy Date: Fri, 21 Aug 2020 04:11:56 +0300 Subject: [PATCH] #11 implement the vagrant.GetImageURL --- vagrant/image_url.go | 105 +++++++++++++++++++++++++ vagrant/{image.go => process_image.go} | 0 vagrant/vagrant.go | 7 -- 3 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 vagrant/image_url.go rename vagrant/{image.go => process_image.go} (100%) delete mode 100644 vagrant/vagrant.go diff --git a/vagrant/image_url.go b/vagrant/image_url.go new file mode 100644 index 0000000..545b5f6 --- /dev/null +++ b/vagrant/image_url.go @@ -0,0 +1,105 @@ +package vagrant + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "strings" +) + +type vagrantResp struct { + Versions []version `json:"versions"` +} +type provider struct { + Name string `json:"name"` + URL string `json:"url"` +} +type version struct { + Version string `json:"version"` + Status string `json:"status"` + Providers []provider `json:"providers"` +} + +func GetImageURL(image string) (string, error) { + + user, imageName, imageVersion := getImageParts(image) + + req, err := http.NewRequest("GET", fmt.Sprintf("https://app.vagrantup.com/%s/boxes/%s", user, imageName), nil) + if err != nil { + return "", err + } + + req.Header.Set("Accept", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var obj vagrantResp + if err := json.Unmarshal(b, &obj); err != nil { + return "", err + } + + p, err := filterByVersion(obj, user, imageName, imageVersion) + if err != nil { + return "", err + } + + return p.URL, nil +} + +func filterByVersion(resp vagrantResp, user, imageName, imageVersion string) (provider, error) { + + if len(resp.Versions) == 0 { + return provider{}, errors.New("vagrant response contains no versions") + } + + if imageVersion == "" { + // get latest version + return getVirtualBoxProvider(resp.Versions[0].Providers) + } else { + for _, v := range resp.Versions { + if v.Version == imageVersion { + return getVirtualBoxProvider(v.Providers) + } + } + return provider{}, fmt.Errorf("vagrant image version not found, "+ + "check correct version number here: https://app.vagrantup.com/%s/boxes/%s", user, imageName) + } +} + +func getVirtualBoxProvider(providers []provider) (provider, error) { + for _, p := range providers { + if p.Name == "virtualbox" { + return p, nil + } + } + return provider{}, errors.New("VirtualBox image not found for specified version") +} + +// getImageParts syntax vagrant/USER/BOX:VERSION e.g.: vagrant/ubuntu/trusty64:20190429.0.1 +// returns USER, BOX, VERSION (ubuntu, trusty64, 20190429.0.1) +func getImageParts(image string) (user string, imageName string, imageVersion string) { + + parts := strings.Split(image, "/") + user = parts[1] + box := parts[2] + + boxParts := strings.Split(box, ":") + imageName = boxParts[0] + + if len(boxParts) > 1 { + imageVersion = boxParts[1] + } + return user, imageName, imageVersion +} diff --git a/vagrant/image.go b/vagrant/process_image.go similarity index 100% rename from vagrant/image.go rename to vagrant/process_image.go diff --git a/vagrant/vagrant.go b/vagrant/vagrant.go deleted file mode 100644 index bd42cea..0000000 --- a/vagrant/vagrant.go +++ /dev/null @@ -1,7 +0,0 @@ -package vagrant - -func GetImageURL(image string) (string, error) { - // TODO - // get json and parse it to return download URL - return "https://vagrantcloud.com/hashicorp/boxes/bionic64/versions/1.0.282/providers/virtualbox.box", nil -}