github.com/opentofu/opentofu@v1.7.1/internal/getproviders/errors.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package getproviders
     7  
     8  import (
     9  	"fmt"
    10  	"net/url"
    11  
    12  	svchost "github.com/hashicorp/terraform-svchost"
    13  
    14  	"github.com/opentofu/opentofu/internal/addrs"
    15  )
    16  
    17  // ErrHostNoProviders is an error type used to indicate that a hostname given
    18  // in a provider address does not support the provider registry protocol.
    19  type ErrHostNoProviders struct {
    20  	Hostname svchost.Hostname
    21  
    22  	// HasOtherVersionis set to true if the discovery process detected
    23  	// declarations of services named "providers" whose version numbers did not
    24  	// match any version supported by the current version of OpenTofu.
    25  	//
    26  	// If this is set, it's helpful to hint to the user in an error message
    27  	// that the provider host may be expecting an older or a newer version
    28  	// of OpenTofu, rather than that it isn't a provider registry host at all.
    29  	HasOtherVersion bool
    30  }
    31  
    32  func (err ErrHostNoProviders) Error() string {
    33  	switch {
    34  	case err.HasOtherVersion:
    35  		return fmt.Sprintf("host %s does not support the provider registry protocol required by this OpenTofu version, but may be compatible with a different OpenTofu version", err.Hostname.ForDisplay())
    36  	default:
    37  		return fmt.Sprintf("host %s does not offer a OpenTofu provider registry", err.Hostname.ForDisplay())
    38  	}
    39  }
    40  
    41  // ErrHostUnreachable is an error type used to indicate that a hostname
    42  // given in a provider address did not resolve in DNS, did not respond to an
    43  // HTTPS request for service discovery, or otherwise failed to correctly speak
    44  // the service discovery protocol.
    45  type ErrHostUnreachable struct {
    46  	Hostname svchost.Hostname
    47  	Wrapped  error
    48  }
    49  
    50  func (err ErrHostUnreachable) Error() string {
    51  	return fmt.Sprintf("could not connect to %s: %s", err.Hostname.ForDisplay(), err.Wrapped.Error())
    52  }
    53  
    54  // Unwrap returns the underlying error that occurred when trying to reach the
    55  // indicated host.
    56  func (err ErrHostUnreachable) Unwrap() error {
    57  	return err.Wrapped
    58  }
    59  
    60  // ErrUnauthorized is an error type used to indicate that a hostname
    61  // given in a provider address returned a "401 Unauthorized" or "403 Forbidden"
    62  // error response when we tried to access it.
    63  type ErrUnauthorized struct {
    64  	Hostname svchost.Hostname
    65  
    66  	// HaveCredentials is true when the request that failed included some
    67  	// credentials, and thus it seems that those credentials were invalid.
    68  	// Conversely, HaveCredentials is false if the request did not include
    69  	// credentials at all, in which case it seems that credentials must be
    70  	// provided.
    71  	HaveCredentials bool
    72  }
    73  
    74  func (err ErrUnauthorized) Error() string {
    75  	switch {
    76  	case err.HaveCredentials:
    77  		return fmt.Sprintf("host %s rejected the given authentication credentials", err.Hostname)
    78  	default:
    79  		return fmt.Sprintf("host %s requires authentication credentials", err.Hostname)
    80  	}
    81  }
    82  
    83  // ErrProviderNotFound is an error type used to indicate that requested provider
    84  // was not found in the source(s) included in the Description field. This can be
    85  // used to produce user-friendly error messages.
    86  type ErrProviderNotFound struct {
    87  	Provider addrs.Provider
    88  	Sources  []string
    89  }
    90  
    91  func (err ErrProviderNotFound) Error() string {
    92  	return fmt.Sprintf(
    93  		"provider %s was not found in any of the search locations",
    94  		err.Provider,
    95  	)
    96  }
    97  
    98  // ErrRegistryProviderNotKnown is an error type used to indicate that the hostname
    99  // given in a provider address does appear to be a provider registry but that
   100  // registry does not know about the given provider namespace or type.
   101  //
   102  // A caller serving requests from an end-user should recognize this error type
   103  // and use it to produce user-friendly hints for common errors such as failing
   104  // to specify an explicit source for a provider not in the default namespace
   105  // (one not under registry.opentofu.org/hashicorp/). The default error message
   106  // for this type is a direct description of the problem with no such hints,
   107  // because we expect that the caller will have better context to decide what
   108  // hints are appropriate, e.g. by looking at the configuration given by the
   109  // user.
   110  type ErrRegistryProviderNotKnown struct {
   111  	Provider addrs.Provider
   112  }
   113  
   114  func (err ErrRegistryProviderNotKnown) Error() string {
   115  	return fmt.Sprintf(
   116  		"provider registry %s does not have a provider named %s",
   117  		err.Provider.Hostname.ForDisplay(),
   118  		err.Provider,
   119  	)
   120  }
   121  
   122  // ErrPlatformNotSupported is an error type used to indicate that a particular
   123  // version of a provider isn't available for a particular target platform.
   124  //
   125  // This is returned when DownloadLocation encounters a 404 Not Found response
   126  // from the underlying registry, because it presumes that a caller will only
   127  // ask for the DownloadLocation for a version it already found the existence
   128  // of via AvailableVersions.
   129  type ErrPlatformNotSupported struct {
   130  	Provider addrs.Provider
   131  	Version  Version
   132  	Platform Platform
   133  
   134  	// MirrorURL, if non-nil, is the base URL of the mirror that serviced
   135  	// the request in place of the provider's origin registry. MirrorURL
   136  	// is nil for a direct query.
   137  	MirrorURL *url.URL
   138  }
   139  
   140  func (err ErrPlatformNotSupported) Error() string {
   141  	if err.MirrorURL != nil {
   142  		return fmt.Sprintf(
   143  			"provider mirror %s does not have a package of %s %s for %s",
   144  			err.MirrorURL.String(),
   145  			err.Provider,
   146  			err.Version,
   147  			err.Platform,
   148  		)
   149  	}
   150  	return fmt.Sprintf(
   151  		"provider %s %s is not available for %s",
   152  		err.Provider,
   153  		err.Version,
   154  		err.Platform,
   155  	)
   156  }
   157  
   158  // ErrProtocolNotSupported is an error type used to indicate that a particular
   159  // version of a provider is not supported by the current version of OpenTofu.
   160  //
   161  // Specfically, this is returned when the version's plugin protocol is not supported.
   162  //
   163  // When available, the error will include a suggested version that can be displayed to
   164  // the user. Otherwise it will return UnspecifiedVersion
   165  type ErrProtocolNotSupported struct {
   166  	Provider   addrs.Provider
   167  	Version    Version
   168  	Suggestion Version
   169  }
   170  
   171  func (err ErrProtocolNotSupported) Error() string {
   172  	return fmt.Sprintf(
   173  		"provider %s %s is not supported by this version of OpenTofu",
   174  		err.Provider,
   175  		err.Version,
   176  	)
   177  }
   178  
   179  // ErrQueryFailed is an error type used to indicate that the hostname given
   180  // in a provider address does appear to be a provider registry but that when
   181  // we queried it for metadata for the given provider the server returned an
   182  // unexpected error.
   183  //
   184  // This is used for any error responses other than "Not Found", which would
   185  // indicate the absense of a provider and is thus reported using
   186  // ErrProviderNotKnown instead.
   187  type ErrQueryFailed struct {
   188  	Provider addrs.Provider
   189  	Wrapped  error
   190  
   191  	// MirrorURL, if non-nil, is the base URL of the mirror that serviced
   192  	// the request in place of the provider's origin registry. MirrorURL
   193  	// is nil for a direct query.
   194  	MirrorURL *url.URL
   195  }
   196  
   197  func (err ErrQueryFailed) Error() string {
   198  	if err.MirrorURL != nil {
   199  		return fmt.Sprintf(
   200  			"failed to query provider mirror %s for %s: %s",
   201  			err.MirrorURL.String(),
   202  			err.Provider.String(),
   203  			err.Wrapped.Error(),
   204  		)
   205  	}
   206  	return fmt.Sprintf(
   207  		"could not query provider registry for %s: %s",
   208  		err.Provider.String(),
   209  		err.Wrapped.Error(),
   210  	)
   211  }
   212  
   213  // Unwrap returns the underlying error that occurred when trying to reach the
   214  // indicated host.
   215  func (err ErrQueryFailed) Unwrap() error {
   216  	return err.Wrapped
   217  }
   218  
   219  // ErrRequestCanceled is an error type used to indicate that an operation
   220  // failed due to being cancelled via the given context.Context object.
   221  //
   222  // This error type doesn't include information about what was cancelled,
   223  // because the expected treatment of this error type is to quickly abort and
   224  // exit with minimal ceremony.
   225  type ErrRequestCanceled struct {
   226  }
   227  
   228  func (err ErrRequestCanceled) Error() string {
   229  	return "request canceled"
   230  }
   231  
   232  // ErrIsNotExist returns true if and only if the given error is one of the
   233  // errors from this package that represents an affirmative response that a
   234  // requested object does not exist.
   235  //
   236  // This is as opposed to errors indicating that the source is unavailable
   237  // or misconfigured in some way, where we therefore cannot say for certain
   238  // whether the requested object exists.
   239  //
   240  // If a caller needs to take a special action based on something not existing,
   241  // such as falling back on some other source, use this function rather than
   242  // direct type assertions so that the set of possible "not exist" errors can
   243  // grow in future.
   244  func ErrIsNotExist(err error) bool {
   245  	switch err.(type) {
   246  	case ErrProviderNotFound, ErrRegistryProviderNotKnown, ErrPlatformNotSupported:
   247  		return true
   248  	default:
   249  		return false
   250  	}
   251  }