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 }