2020-12-09 15:31:34 +00:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
2021-06-04 11:49:31 +00:00
|
|
|
error2 "github.com/cloudskiff/driftctl/pkg/terraform/error"
|
2020-12-09 15:31:34 +00:00
|
|
|
"github.com/hashicorp/go-getter"
|
2021-02-09 18:43:39 +00:00
|
|
|
"github.com/pkg/errors"
|
2020-12-09 15:31:34 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ProviderDownloaderInterface interface {
|
|
|
|
Download(url, path string) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type ProviderDownloader struct {
|
|
|
|
httpclient *http.Client
|
|
|
|
unzip getter.ZipDecompressor
|
|
|
|
context context.Context
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewProviderDownloader() *ProviderDownloader {
|
|
|
|
return &ProviderDownloader{
|
|
|
|
httpclient: http.DefaultClient,
|
|
|
|
unzip: getter.ZipDecompressor{},
|
|
|
|
context: context.Background(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *ProviderDownloader) Download(url, path string) error {
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
"url": url,
|
|
|
|
"path": path,
|
|
|
|
}).Debug("Downloading provider")
|
|
|
|
|
|
|
|
req, err := http.NewRequestWithContext(p.context, "GET", url, nil)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
resp, err := p.httpclient.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
2021-06-04 11:49:31 +00:00
|
|
|
if resp.StatusCode == http.StatusForbidden {
|
|
|
|
return error2.ProviderNotFoundError{}
|
|
|
|
}
|
2020-12-09 15:31:34 +00:00
|
|
|
if resp.StatusCode != http.StatusOK {
|
2021-02-10 13:37:59 +00:00
|
|
|
return errors.Errorf("unsuccessful request to %s: %s", url, resp.Status)
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
f, err := ioutil.TempFile("", "terraform-provider")
|
|
|
|
if err != nil {
|
2021-02-10 13:37:59 +00:00
|
|
|
return errors.Errorf("failed to open temporary file to download from %s", url)
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
defer os.Remove(f.Name())
|
|
|
|
n, err := getter.Copy(p.context, f, resp.Body)
|
|
|
|
if err == nil && n < resp.ContentLength {
|
2021-02-10 13:37:59 +00:00
|
|
|
err = errors.Errorf(
|
|
|
|
"incorrect response size: expected %d bytes, but got %d bytes",
|
|
|
|
resp.ContentLength,
|
|
|
|
n,
|
2021-02-09 18:43:39 +00:00
|
|
|
)
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
"src": f.Name(),
|
|
|
|
"dst": path,
|
|
|
|
}).Debug("Decompressing archive")
|
|
|
|
err = p.unzip.Decompress(path, f.Name(), true, 0)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|