Add the GCP provider: four-call surface, fire-and-forget ops, zone-qualified IDs
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
61
internal/provider/gcp/errors.go
Normal file
61
internal/provider/gcp/errors.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package gcp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"slices"
|
||||
|
||||
"google.golang.org/api/googleapi"
|
||||
|
||||
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider"
|
||||
)
|
||||
|
||||
// classify maps a GCP API error onto the provider taxonomy:
|
||||
// 404 → NotFound; 429 and quota-flavored 403s → QuotaExceeded;
|
||||
// 400/401/other 403s → Permanent; 408/5xx and anything unrecognized
|
||||
// (network errors, context cancellation) → Transient, because retrying is
|
||||
// always safer than latching Failed on an error nobody taught this
|
||||
// function to recognize.
|
||||
func classify(err error) error {
|
||||
var gerr *googleapi.Error
|
||||
if !errors.As(err, &gerr) {
|
||||
return provider.ErrTransient
|
||||
}
|
||||
switch {
|
||||
case gerr.Code == http.StatusNotFound:
|
||||
return provider.ErrNotFound
|
||||
case gerr.Code == http.StatusTooManyRequests:
|
||||
return provider.ErrQuotaExceeded
|
||||
case gerr.Code == http.StatusForbidden && hasReason(gerr, "quotaExceeded", "rateLimitExceeded"):
|
||||
return provider.ErrQuotaExceeded
|
||||
case gerr.Code == http.StatusBadRequest,
|
||||
gerr.Code == http.StatusUnauthorized,
|
||||
gerr.Code == http.StatusForbidden:
|
||||
return provider.ErrPermanent
|
||||
default:
|
||||
return provider.ErrTransient
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provider) wrapErr(op, id string, err error) error {
|
||||
return provider.Wrap(classify(err), op, p.name, id, err)
|
||||
}
|
||||
|
||||
func hasReason(gerr *googleapi.Error, reasons ...string) bool {
|
||||
for _, item := range gerr.Errors {
|
||||
if slices.Contains(reasons, item.Reason) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isAlreadyExists(err error) bool {
|
||||
var gerr *googleapi.Error
|
||||
return errors.As(err, &gerr) && gerr.Code == http.StatusConflict
|
||||
}
|
||||
|
||||
func isNotFound(err error) bool {
|
||||
var gerr *googleapi.Error
|
||||
return errors.As(err, &gerr) && gerr.Code == http.StatusNotFound
|
||||
}
|
||||
Reference in New Issue
Block a user