Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add NetRC support to the provider installer #35843

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: add NetRC support to the provider installer
aaklilu committed Nov 19, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 6a0e1cbbaa63ee00e00bc797cc193ca00067622a
56 changes: 21 additions & 35 deletions internal/providercache/package_install.go
Original file line number Diff line number Diff line change
@@ -6,8 +6,7 @@ package providercache
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"

@@ -26,54 +25,41 @@ import (
var unzip = getter.ZipDecompressor{}

func installFromHTTPURL(ctx context.Context, meta getproviders.PackageMeta, targetDir string, allowedHashes []getproviders.Hash) (*getproviders.PackageAuthenticationResult, error) {
url := meta.Location.String()
urlStr := meta.Location.String()

// When we're installing from an HTTP URL we expect the URL to refer to
// a zip file. We'll fetch that into a temporary file here and then
// delegate to installFromLocalArchive below to actually extract it.
// (We're not using go-getter here because its HTTP getter has a bunch
// of extraneous functionality we don't need or want, like indirection
// through X-Terraform-Get header, attempting partial fetches for
// files that already exist, etc.)
httpGetter := getter.HttpGetter{
Client: httpclient.New(),
Netrc: true,
XTerraformGetDisabled: true,
}

httpClient := httpclient.New()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
urlObj, err := url.Parse(urlStr)
if err != nil {
// We don't expect to get non-HTTP locations here because we're
// using the registry source, so this seems like a bug in the
// registry source.
return nil, fmt.Errorf("invalid provider download request: %s", err)
}
resp, err := httpClient.Do(req)
if err != nil {
if ctx.Err() == context.Canceled {
// "context canceled" is not a user-friendly error message,
// so we'll return a more appropriate one here.
return nil, fmt.Errorf("provider download was interrupted")
}
return nil, fmt.Errorf("%s: %w", getproviders.HostFromRequest(req), err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unsuccessful request to %s: %s", url, resp.Status)
}

f, err := ioutil.TempFile("", "terraform-provider")
f, err := os.CreateTemp("", "terraform-provider")
if err != nil {
return nil, fmt.Errorf("failed to open temporary file to download from %s: %w", url, err)
return nil, fmt.Errorf("failed to open temporary file to download from %s: %w", urlStr, err)
}
defer f.Close()
defer os.Remove(f.Name())

// We'll borrow go-getter's "cancelable copy" implementation here so that
// the download can potentially be interrupted partway through.
n, err := getter.Copy(ctx, f, resp.Body)
if err == nil && n < resp.ContentLength {
err = fmt.Errorf("incorrect response size: expected %d bytes, but got %d bytes", resp.ContentLength, n)
}
archiveFilename := f.Name()
err = httpGetter.GetFile(archiveFilename, urlObj)
if err != nil {
return nil, err
if ctx.Err() == context.Canceled {
// "context canceled" is not a user-friendly error message,
// so we'll return a more appropriate one here.
return nil, fmt.Errorf("provider download was interrupted")
}
return nil, fmt.Errorf("%s: %w", urlObj.Host, err)
}

archiveFilename := f.Name()
localLocation := getproviders.PackageLocalArchive(archiveFilename)

var authResult *getproviders.PackageAuthenticationResult