// PackageMeta retrieves metadata for the requested provider package
// from the object's underlying HTTP mirror service.
PackageMeta retrieves metadata for the requested provider package
from the object's underlying HTTP mirror service.
// PackageMeta retrieves metadata for the requested provider package // from the object ' s underlying HTTP mirror service .
func (s *HTTPMirrorSource) PackageMeta(ctx context.Context, provider addrs.Provider, version Version, target Platform) (PackageMeta, error) {
	log.Printf("[DEBUG] Finding package URL for %s v%s on %s via network mirror %s", provider.String(), version.String(), target.String(), s.baseURL.String())
	endpointPath := path.Join(
		provider.Hostname.String(),
		provider.Namespace,
		provider.Type,
		version.String()+".json",
	)
	statusCode, body, finalURL, err := s.get(ctx, endpointPath)
	defer func() {
		if body != nil {
			body.Close()
		}
	}()
	if err != nil {
		return PackageMeta{}, s.errQueryFailed(provider, err)
	}
	switch statusCode {
	case http.StatusOK:
	case http.StatusNotFound:
		return PackageMeta{}, s.errQueryFailed(provider, fmt.Errorf("provider mirror does not have archive index for previously-reported %s version %s", provider, version))
	case http.StatusUnauthorized, http.StatusForbidden:
		return PackageMeta{}, s.errUnauthorized(finalURL)
	default:
		return PackageMeta{}, s.errQueryFailed(provider, fmt.Errorf("server returned unsuccessful status %d", statusCode))
	}
	type ResponseArchiveMeta struct {
		RelativeURL string `json:"url"`
		Hashes      []string
	}
	type ResponseBody struct {
		Archives map[string]*ResponseArchiveMeta `json:"archives"`
	}
	var bodyContent ResponseBody
	dec := json.NewDecoder(body)
	if err := dec.Decode(&bodyContent); err != nil {
		return PackageMeta{}, s.errQueryFailed(provider, fmt.Errorf("invalid response content from mirror server: %s", err))
	}
	archiveMeta, ok := bodyContent.Archives[target.String()]
	if !ok {
		return PackageMeta{}, ErrPlatformNotSupported{
			Provider:  provider,
			Version:   version,
			Platform:  target,
			MirrorURL: s.baseURL,
		}
	}
	relURL, err := url.Parse(archiveMeta.RelativeURL)
	if err != nil {
		return PackageMeta{}, s.errQueryFailed(
			provider,
			fmt.Errorf("provider mirror returned invalid URL %q: %s", archiveMeta.RelativeURL, err),
		)
	}
	absURL := finalURL.ResolveReference(relURL)
	ret := PackageMeta{
		Provider:       provider,
		Version:        version,
		TargetPlatform: target,
		Location: PackageHTTPURL(absURL.String()),
		Filename: path.Base(absURL.Path),
	}
	if len(archiveMeta.Hashes) > 0 {
		hashes := make([]Hash, 0, len(archiveMeta.Hashes))
		for _, hashStr := range archiveMeta.Hashes {
			hash, err := ParseHash(hashStr)
			if err != nil {
				return PackageMeta{}, s.errQueryFailed(
					provider,
					fmt.Errorf("provider mirror returned invalid provider hash %q: %s", hashStr, err),
				)
			}
			hashes = append(hashes, hash)
		}
		ret.Authentication = NewPackageHashAuthentication(target, hashes)
	}
	return ret, nil
}
func ( s * HTTPMirrorSource ) PackageMeta ( ctx context . Context , provider addrs . Provider , version Version , target Platform ) ( PackageMeta , error ) { log . Printf ( " " , provider . String ( ) , version . String ( ) , target . String ( ) , s . baseURL . String ( ) ) endpointPath := path . Join ( provider . Hostname . String ( ) , provider . Namespace , provider . Type , version . String ( ) + " " , ) statusCode , body , finalURL , err := s . get ( ctx , endpointPath ) defer func ( ) { if body != nil { body . Close ( ) } } ( ) if err != nil { return PackageMeta { } , s . errQueryFailed ( provider , err ) } switch statusCode { case http . StatusOK : case http . StatusNotFound : return PackageMeta { } , s . errQueryFailed ( provider , fmt . Errorf ( " " , provider , version ) ) case http . StatusUnauthorized , http . StatusForbidden : return PackageMeta { } , s . errUnauthorized ( finalURL ) default : return PackageMeta { } , s . errQueryFailed ( provider , fmt . Errorf ( " " , statusCode ) ) } type ResponseArchiveMeta struct { RelativeURL string `json:"url"` Hashes [ ] string } type ResponseBody struct { Archives map [ string ] * ResponseArchiveMeta `json:"archives"` } var bodyContent ResponseBody dec := json . NewDecoder ( body ) if err := dec . Decode ( & bodyContent ) ; err != nil { return PackageMeta { } , s . errQueryFailed ( provider , fmt . Errorf ( " " , err ) ) } archiveMeta , ok := bodyContent . Archives [ target . String ( ) ] if ! ok { return PackageMeta { } , ErrPlatformNotSupported { Provider : provider , Version : version , Platform : target , MirrorURL : s . baseURL , } } relURL , err := url . Parse ( archiveMeta . RelativeURL ) if err != nil { return PackageMeta { } , s . errQueryFailed ( provider , fmt . Errorf ( " " , archiveMeta . RelativeURL , err ) , ) } absURL := finalURL . ResolveReference ( relURL ) ret := PackageMeta { Provider : provider , Version : version , TargetPlatform : target , Location : PackageHTTPURL ( absURL . String ( ) ) , Filename : path . Base ( absURL . Path ) , } if len ( archiveMeta . Hashes ) > 0 { hashes := make ( [ ] Hash , 0 , len ( archiveMeta . Hashes ) ) for _ , hashStr := range archiveMeta . Hashes { hash , err := ParseHash ( hashStr ) if err != nil { return PackageMeta { } , s . errQueryFailed ( provider , fmt . Errorf ( " " , hashStr , err ) , ) } hashes = append ( hashes , hash ) } ret . Authentication = NewPackageHashAuthentication ( target , hashes ) } return ret , nil }
PackageMeta retrieves metadata for the requested provider package
from the object's underlying HTTP mirror service.
PackageMeta retrieves metadata for the requested provider package from the object ' s underlying HTTP mirror service .
// Great! // A 404 Not Found for a version we previously saw in index.json is // a protocol error, so we'll report this as "query failed. // If we got here then the response had status OK and so our body // will be non-nil and should contain some JSON for us to parse. // A network mirror might not provide any hashes at all, in which case // the package has no source-defined authentication whatsoever.