mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-21 03:36:35 +00:00
fix: name the missing RDS engine image instead of answering ServerInternal
This commit is contained in:
@@ -52,6 +52,24 @@ const (
|
||||
// validation failure rather than launching something else.
|
||||
var ErrEngineAMINotFound = errors.New("rds: no AMI found for engine")
|
||||
|
||||
// The catalog registers every engine's system image under this prefix, so the
|
||||
// error can name the image an operator has to import.
|
||||
const engineImageNamePrefix = "spinifex-rds-"
|
||||
|
||||
// An engine image no deployment ever imported is a gap no retry closes, so the
|
||||
// failure carries a code: a bare error resolves to ServerInternal, which the
|
||||
// caller reads as a transient fault and retries.
|
||||
func engineAMINotFound(engine, version string) error {
|
||||
requested := "an engine image for " + engine
|
||||
if version != "" {
|
||||
requested = "version " + version + " for " + engine
|
||||
}
|
||||
return fmt.Errorf("%w: %w", ErrEngineAMINotFound, awserrors.Errorf(
|
||||
awserrors.ErrorInvalidParameterCombination,
|
||||
"Cannot find %s; this deployment has no %s%s system image installed",
|
||||
requested, engineImageNamePrefix, engine))
|
||||
}
|
||||
|
||||
type launchVPCProvisioner interface {
|
||||
CreateNetworkInterface(ctx context.Context, input *ec2.CreateNetworkInterfaceInput, accountID string) (*ec2.CreateNetworkInterfaceOutput, error)
|
||||
DeleteNetworkInterface(ctx context.Context, input *ec2.DeleteNetworkInterfaceInput, accountID string) (*ec2.DeleteNetworkInterfaceOutput, error)
|
||||
@@ -460,7 +478,7 @@ func resolveEngineAMI(ctx context.Context, amiSvc launchAMIResolver, engine, ver
|
||||
return "", fmt.Errorf("rds: describe %s AMI: %w", engine, err)
|
||||
}
|
||||
if out == nil {
|
||||
return "", fmt.Errorf("%w: %s %s", ErrEngineAMINotFound, engine, version)
|
||||
return "", engineAMINotFound(engine, version)
|
||||
}
|
||||
|
||||
// Several builds of one engine version can be registered; skip malformed
|
||||
@@ -485,7 +503,7 @@ func resolveEngineAMI(ctx context.Context, amiSvc launchAMIResolver, engine, ver
|
||||
}
|
||||
}
|
||||
if newestID == "" {
|
||||
return "", fmt.Errorf("%w: %s %s", ErrEngineAMINotFound, engine, version)
|
||||
return "", engineAMINotFound(engine, version)
|
||||
}
|
||||
if matches > 1 {
|
||||
slog.WarnContext(ctx, "rds: multiple AMIs match the requested engine; using newest",
|
||||
|
||||
@@ -928,5 +928,41 @@ func TestLaunchDBInstanceVMFailsWithoutAnEngineAMI(t *testing.T) {
|
||||
_, err := LaunchDBInstanceVM(t.Context(), h.deps(), testLaunchInput())
|
||||
require.ErrorIs(t, err, ErrEngineAMINotFound,
|
||||
"a missing engine image must be a named failure, never a fallback to some other AMI")
|
||||
code, _, ok := awserrors.ResolveErrorDetail(err)
|
||||
require.True(t, ok, "the launch must not swallow the code on its way out")
|
||||
assert.Equal(t, awserrors.ErrorInvalidParameterCombination, code)
|
||||
assert.Empty(t, h.enis.created)
|
||||
}
|
||||
|
||||
func TestResolveEngineAMINotFoundCarriesAClientCode(t *testing.T) {
|
||||
t.Parallel()
|
||||
h := newLaunchHarness()
|
||||
h.images.images = nil
|
||||
|
||||
_, err := resolveEngineAMI(t.Context(), h.images, "postgres", "18")
|
||||
require.ErrorIs(t, err, ErrEngineAMINotFound)
|
||||
|
||||
code, message, ok := awserrors.ResolveErrorDetail(err)
|
||||
require.True(t, ok,
|
||||
"an uncoded error reaches the caller as a retried ServerInternal, which says nothing about what is missing")
|
||||
assert.Equal(t, awserrors.ErrorInvalidParameterCombination, code)
|
||||
assert.Contains(t, message, "version 18 for postgres")
|
||||
assert.Contains(t, message, "spinifex-rds-postgres",
|
||||
"the message names the image an operator has to import")
|
||||
}
|
||||
|
||||
func TestResolveEngineAMINotFoundWithoutARequestedVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
h := newLaunchHarness()
|
||||
h.images.images = nil
|
||||
|
||||
_, err := resolveEngineAMI(t.Context(), h.images, "mariadb", "")
|
||||
require.ErrorIs(t, err, ErrEngineAMINotFound)
|
||||
|
||||
code, message, ok := awserrors.ResolveErrorDetail(err)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, awserrors.ErrorInvalidParameterCombination, code)
|
||||
assert.Contains(t, message, "an engine image for mariadb",
|
||||
"an unset version must not read back as an empty one")
|
||||
assert.Contains(t, message, "spinifex-rds-mariadb")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user