MCPcopy
hub / github.com/opentofu/opentofu / ModulePackageLocation

Method ModulePackageLocation

internal/registry/client.go:163–257  ·  view source on GitHub ↗

ModulePackageLocation finds the package location for a specific module package version. The subdir parameter is the subdirectory path from the original module source address (e.g., from addrs.ModuleSourceRegistry.Subdir). This is passed separately because regaddr.ModulePackage represents only the p

(ctx context.Context, packageAddr regaddr.ModulePackage, version string, subdir string)

Source from the content-addressed store, hash-verified

161// to report. Refer to the documentation of those types for information on
162// how each variant should be used to actually install the package.
163func (c *Client) ModulePackageLocation(ctx context.Context, packageAddr regaddr.ModulePackage, version string, subdir string) (PackageLocation, error) {
164 ctx, span := tracing.Tracer().Start(ctx, "Find Module Location", tracing.SpanAttributes(
165 traceattrs.OpenTofuModuleSource(packageAddr.String()),
166 traceattrs.OpenTofuModuleVersion(version),
167 ))
168 defer span.End()
169
170 host := packageAddr.Host
171 baseURL, err := c.discoverBaseURL(ctx, host)
172 if err != nil {
173 return nil, err
174 }
175
176 // Historical note: an older version of this client code accepted "version"
177 // being empty and constructed a different form of URL where the version
178 // component was completely omitted, but the documentation for the registry
179 // protocol doesn't define the meaning of a URL scheme like that and in
180 // practice the callers of the client always populate the version, so we
181 // don't support omitting that anymore: a version string is now always expected.
182 metadataURL := modulePackageEndpointURL(baseURL, packageAddr, version, "download")
183 log.Printf("[DEBUG] looking up module location from %q", metadataURL)
184
185 req, err := retryablehttp.NewRequestWithContext(ctx, "GET", metadataURL.String(), nil)
186 if err != nil {
187 return nil, err
188 }
189
190 req = req.WithContext(ctx)
191
192 c.addRequestCreds(ctx, host, req.Request)
193 req.Header.Set(xTerraformVersion, tfVersion)
194
195 resp, err := c.client.Do(req)
196 if err != nil {
197 return nil, err
198 }
199 defer resp.Body.Close()
200
201 body, err := io.ReadAll(resp.Body)
202 if err != nil {
203 return nil, fmt.Errorf("error reading response body from registry: %w", err)
204 }
205
206 switch resp.StatusCode {
207 case http.StatusOK:
208 var v response.ModuleLocationRegistryResp
209 if err := json.Unmarshal(body, &v); err != nil {
210 return nil, fmt.Errorf("module %q version %q failed to deserialize response body %s: %w",
211 packageAddr, version, body, err)
212 }
213
214 if v.UseRegistryCredentials == nil {
215 // The registry has not opted in to "direct" installation, so we
216 // assume that it wants the old-style "indirect" behavior where
217 // the registry is essentially just a lookup table for
218 // go-getter-style source addresses, in which case the registry
219 // isn't involved in the final download step at all.
220

Calls 15

discoverBaseURLMethod · 0.95
addRequestCredsMethod · 0.95
TracerFunction · 0.92
SpanAttributesFunction · 0.92
OpenTofuModuleSourceFunction · 0.92
OpenTofuModuleVersionFunction · 0.92
modulePackageEndpointURLFunction · 0.85
PrintfMethod · 0.80
StartMethod · 0.65
StringMethod · 0.65