2014-06-16 15:53:37 -04:00
|
|
|
package vagrantcloud
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2019-03-05 04:57:11 -05:00
|
|
|
"crypto/tls"
|
2014-06-16 15:53:37 -04:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
2014-06-24 15:58:45 -04:00
|
|
|
"os"
|
2014-06-16 15:53:37 -04:00
|
|
|
"strings"
|
2019-01-23 19:45:07 -05:00
|
|
|
|
2020-11-04 17:50:34 -05:00
|
|
|
"github.com/hashicorp/packer/common/net"
|
2014-06-16 15:53:37 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
type VagrantCloudClient struct {
|
|
|
|
// The http client for communicating
|
|
|
|
client *http.Client
|
|
|
|
|
|
|
|
// The base URL of the API
|
|
|
|
BaseURL string
|
|
|
|
|
|
|
|
// Access token
|
|
|
|
AccessToken string
|
|
|
|
}
|
|
|
|
|
2014-06-23 15:48:51 -04:00
|
|
|
type VagrantCloudErrors struct {
|
2020-01-10 12:21:29 -05:00
|
|
|
Errors []interface{} `json:"errors"`
|
2014-06-23 15:48:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v VagrantCloudErrors) FormatErrors() string {
|
|
|
|
errs := make([]string, 0)
|
2020-01-10 12:21:29 -05:00
|
|
|
for _, err := range v.Errors {
|
|
|
|
switch e := err.(type) {
|
|
|
|
case string:
|
|
|
|
errs = append(errs, e)
|
|
|
|
case map[string]interface{}:
|
|
|
|
for k, v := range e {
|
|
|
|
errs = append(errs, fmt.Sprintf("%s %s", k, v))
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
errs = append(errs, fmt.Sprintf("%s", err))
|
|
|
|
}
|
2014-06-23 15:48:51 -04:00
|
|
|
}
|
|
|
|
return strings.Join(errs, ". ")
|
|
|
|
}
|
|
|
|
|
2019-03-05 04:57:11 -05:00
|
|
|
func (v VagrantCloudClient) New(baseUrl string, token string, InsecureSkipTLSVerify bool) (*VagrantCloudClient, error) {
|
2014-06-16 15:53:37 -04:00
|
|
|
c := &VagrantCloudClient{
|
2020-11-04 17:50:34 -05:00
|
|
|
client: net.HttpClientWithEnvironmentProxy(),
|
2014-06-16 15:53:37 -04:00
|
|
|
BaseURL: baseUrl,
|
|
|
|
AccessToken: token,
|
|
|
|
}
|
2018-10-24 09:08:08 -04:00
|
|
|
|
2019-03-05 04:57:11 -05:00
|
|
|
if InsecureSkipTLSVerify {
|
|
|
|
transport := c.client.Transport.(*http.Transport)
|
|
|
|
transport.TLSClientConfig = &tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-24 09:08:08 -04:00
|
|
|
return c, c.ValidateAuthentication()
|
2014-06-16 15:53:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func decodeBody(resp *http.Response, out interface{}) error {
|
|
|
|
defer resp.Body.Close()
|
|
|
|
dec := json.NewDecoder(resp.Body)
|
|
|
|
return dec.Decode(out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// encodeBody is used to encode a request body
|
|
|
|
func encodeBody(obj interface{}) (io.Reader, error) {
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
enc := json.NewEncoder(buf)
|
|
|
|
if err := enc.Encode(obj); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return buf, nil
|
|
|
|
}
|
|
|
|
|
2018-10-24 09:08:08 -04:00
|
|
|
func (v *VagrantCloudClient) ValidateAuthentication() error {
|
|
|
|
resp, err := v.Get("authenticate")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != 200 {
|
2018-10-25 04:25:37 -04:00
|
|
|
return fmt.Errorf(resp.Status)
|
2018-10-24 09:08:08 -04:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *VagrantCloudClient) Get(path string) (*http.Response, error) {
|
2018-10-24 09:39:09 -04:00
|
|
|
reqUrl := fmt.Sprintf("%s/%s", v.BaseURL, path)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
2018-10-24 09:39:09 -04:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API GET: %s", reqUrl)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
2018-10-25 04:28:12 -04:00
|
|
|
req, err := v.newRequest("GET", reqUrl, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-06-20 11:20:27 -04:00
|
|
|
resp, err := v.client.Do(req)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
2014-12-16 01:11:36 -05:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Response: \n\n%+v", resp)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
2014-06-20 11:20:27 -04:00
|
|
|
return resp, err
|
2014-06-16 15:53:37 -04:00
|
|
|
}
|
|
|
|
|
2018-10-24 09:08:08 -04:00
|
|
|
func (v *VagrantCloudClient) Delete(path string) (*http.Response, error) {
|
2018-10-24 09:39:09 -04:00
|
|
|
reqUrl := fmt.Sprintf("%s/%s", v.BaseURL, path)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
|
|
|
// Scrub API key for logs
|
|
|
|
scrubbedUrl := strings.Replace(reqUrl, v.AccessToken, "ACCESS_TOKEN", -1)
|
2014-06-20 11:20:27 -04:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API DELETE: %s", scrubbedUrl)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
2019-09-12 06:37:46 -04:00
|
|
|
req, err := v.newRequest("DELETE", reqUrl, nil)
|
2018-10-25 04:28:12 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-06-16 15:53:37 -04:00
|
|
|
resp, err := v.client.Do(req)
|
|
|
|
|
2014-12-16 01:11:36 -05:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Response: \n\n%+v", resp)
|
2014-06-16 15:53:37 -04:00
|
|
|
|
|
|
|
return resp, err
|
|
|
|
}
|
|
|
|
|
2018-10-24 09:08:08 -04:00
|
|
|
func (v *VagrantCloudClient) Upload(path string, url string) (*http.Response, error) {
|
2014-06-24 15:58:45 -04:00
|
|
|
file, err := os.Open(path)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error opening file for upload: %s", err)
|
|
|
|
}
|
|
|
|
|
2017-06-12 18:01:19 -04:00
|
|
|
fi, err := file.Stat()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error stating file for upload: %s", err)
|
|
|
|
}
|
|
|
|
|
2014-06-24 15:58:45 -04:00
|
|
|
defer file.Close()
|
|
|
|
|
2018-10-24 09:39:09 -04:00
|
|
|
request, err := v.newRequest("PUT", url, file)
|
2014-06-24 15:58:45 -04:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error preparing upload request: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Upload: %s %s", path, url)
|
|
|
|
|
2017-06-12 18:01:19 -04:00
|
|
|
request.ContentLength = fi.Size()
|
2014-06-24 15:58:45 -04:00
|
|
|
resp, err := v.client.Do(request)
|
|
|
|
|
2014-12-16 01:11:36 -05:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud Upload Response: \n\n%+v", resp)
|
2014-06-24 15:58:45 -04:00
|
|
|
|
|
|
|
return resp, err
|
|
|
|
}
|
|
|
|
|
2020-11-05 20:01:55 -05:00
|
|
|
func (v *VagrantCloudClient) DirectUpload(path string, url string) (*http.Response, error) {
|
|
|
|
file, err := os.Open(path)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error opening file for upload: %s", err)
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
fi, err := file.Stat()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error stating file for upload: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
request, err := http.NewRequest("PUT", url, file)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error preparing upload request: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Direct Upload: %s %s", path, url)
|
|
|
|
|
|
|
|
request.ContentLength = fi.Size()
|
|
|
|
resp, err := v.client.Do(request)
|
|
|
|
|
|
|
|
log.Printf("Post-Processor Vagrant Cloud Direct Upload Response: \n\n%+v", resp)
|
|
|
|
|
|
|
|
return resp, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *VagrantCloudClient) Callback(url string) (*http.Response, error) {
|
|
|
|
request, err := v.newRequest("PUT", url, nil)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error preparing callback request: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Direct Upload Callback: %s", url)
|
|
|
|
|
|
|
|
resp, err := v.client.Do(request)
|
|
|
|
|
|
|
|
log.Printf("Post-Processor Vagrant Cloud Direct Upload Callback Response: \n\n%+v", resp)
|
|
|
|
|
|
|
|
return resp, err
|
|
|
|
}
|
|
|
|
|
2018-10-24 09:08:08 -04:00
|
|
|
func (v *VagrantCloudClient) Post(path string, body interface{}) (*http.Response, error) {
|
2018-10-24 09:39:09 -04:00
|
|
|
reqUrl := fmt.Sprintf("%s/%s", v.BaseURL, path)
|
2014-06-23 15:48:51 -04:00
|
|
|
|
2014-06-20 11:20:27 -04:00
|
|
|
encBody, err := encodeBody(body)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("Error encoding body for request: %s", err)
|
|
|
|
}
|
2014-06-16 15:53:37 -04:00
|
|
|
|
2018-10-24 09:39:09 -04:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API POST: %s. \n\n Body: %s", reqUrl, encBody)
|
2014-06-20 11:20:27 -04:00
|
|
|
|
2018-10-25 04:28:12 -04:00
|
|
|
req, err := v.newRequest("POST", reqUrl, encBody)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-06-20 11:20:27 -04:00
|
|
|
|
|
|
|
resp, err := v.client.Do(req)
|
|
|
|
|
2014-12-16 01:11:36 -05:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Response: \n\n%+v", resp)
|
2014-06-20 11:20:27 -04:00
|
|
|
|
|
|
|
return resp, err
|
2014-06-16 15:53:37 -04:00
|
|
|
}
|
2014-06-24 15:58:45 -04:00
|
|
|
|
2018-10-24 09:08:08 -04:00
|
|
|
func (v *VagrantCloudClient) Put(path string) (*http.Response, error) {
|
2018-10-24 09:39:09 -04:00
|
|
|
reqUrl := fmt.Sprintf("%s/%s", v.BaseURL, path)
|
2014-06-24 15:58:45 -04:00
|
|
|
|
2018-10-24 09:39:09 -04:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API PUT: %s", reqUrl)
|
2014-06-24 15:58:45 -04:00
|
|
|
|
2018-10-25 04:28:12 -04:00
|
|
|
req, err := v.newRequest("PUT", reqUrl, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-06-24 15:58:45 -04:00
|
|
|
|
|
|
|
resp, err := v.client.Do(req)
|
|
|
|
|
2014-12-16 01:11:36 -05:00
|
|
|
log.Printf("Post-Processor Vagrant Cloud API Response: \n\n%+v", resp)
|
2014-06-24 15:58:45 -04:00
|
|
|
|
|
|
|
return resp, err
|
|
|
|
}
|
2018-10-24 09:39:09 -04:00
|
|
|
|
|
|
|
func (v *VagrantCloudClient) newRequest(method, url string, body io.Reader) (*http.Request, error) {
|
|
|
|
req, err := http.NewRequest(method, url, body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
req.Header.Add("Content-Type", "application/json")
|
2019-09-12 06:37:46 -04:00
|
|
|
if len(v.AccessToken) > 0 {
|
|
|
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", v.AccessToken))
|
|
|
|
}
|
2018-10-24 09:39:09 -04:00
|
|
|
return req, err
|
|
|
|
}
|