diff --git a/spinifex/handlers/ec2/launchtemplate/service_impl.go b/spinifex/handlers/ec2/launchtemplate/service_impl.go index b7d48a850..8dab854a6 100644 --- a/spinifex/handlers/ec2/launchtemplate/service_impl.go +++ b/spinifex/handlers/ec2/launchtemplate/service_impl.go @@ -514,6 +514,13 @@ func (s *LaunchTemplateServiceImpl) DeleteLaunchTemplateVersions(ctx context.Con return nil, errors.New(awserrors.ErrorMissingParameter) } + // Naming the default version fails the whole request, so nothing is deleted. + for _, v := range input.Versions { + if n, perr := strconv.ParseInt(aws.StringValue(v), 10, 64); perr == nil && n == header.DefaultVersionNumber { + return nil, awserrors.Errorf(awserrors.ErrorInvalidParameterValue, "The default version cannot be deleted. Either specify another version as default or delete the launch template.") + } + } + out := &ec2.DeleteLaunchTemplateVersionsOutput{} for _, v := range input.Versions { @@ -524,14 +531,9 @@ func (s *LaunchTemplateServiceImpl) DeleteLaunchTemplateVersions(ctx context.Con deleteErrorItem(header, 0, awserrors.ErrorInvalidLaunchTemplateIdVersionNotFound, "invalid version number")) continue } - if n == header.DefaultVersionNumber { - out.UnsuccessfullyDeletedLaunchTemplateVersions = append(out.UnsuccessfullyDeletedLaunchTemplateVersions, - deleteErrorItem(header, n, awserrors.ErrorInvalidParameterValue, "cannot delete the default version of a launch template")) - continue - } if _, err := s.getVersion(ctx, accountID, header.LaunchTemplateId, n); err != nil { out.UnsuccessfullyDeletedLaunchTemplateVersions = append(out.UnsuccessfullyDeletedLaunchTemplateVersions, - deleteErrorItem(header, n, awserrors.ErrorInvalidLaunchTemplateIdVersionNotFound, "version does not exist")) + deleteErrorItem(header, n, launchTemplateVersionDoesNotExist, "The launch template version does not exist.")) continue } if err := s.kv.Delete(ctx, versionKey(accountID, header.LaunchTemplateId, n)); err != nil { @@ -551,6 +553,10 @@ func (s *LaunchTemplateServiceImpl) DeleteLaunchTemplateVersions(ctx context.Con return out, nil } +// launchTemplateVersionDoesNotExist is the per-version code AWS reports in a +// DeleteLaunchTemplateVersions result; it is never a request-level error. +const launchTemplateVersionDoesNotExist = "launchTemplateVersionDoesNotExist" + func deleteErrorItem(h *LaunchTemplateHeader, n int64, code, msg string) *ec2.DeleteLaunchTemplateVersionsResponseErrorItem { item := &ec2.DeleteLaunchTemplateVersionsResponseErrorItem{ LaunchTemplateId: aws.String(h.LaunchTemplateId), diff --git a/spinifex/handlers/ec2/launchtemplate/service_impl_test.go b/spinifex/handlers/ec2/launchtemplate/service_impl_test.go index 96c4a55ac..1c518a941 100644 --- a/spinifex/handlers/ec2/launchtemplate/service_impl_test.go +++ b/spinifex/handlers/ec2/launchtemplate/service_impl_test.go @@ -396,15 +396,23 @@ func TestModifyLaunchTemplate_DefaultToMissingVersion(t *testing.T) { func TestDeleteLaunchTemplateVersions_RejectDefault(t *testing.T) { svc := setupTestService(t) lt := createTemplate(t, svc, "web", "t3.micro") // default = v1 - out, err := svc.DeleteLaunchTemplateVersions(context.Background(), &ec2.DeleteLaunchTemplateVersionsInput{ - LaunchTemplateId: lt.LaunchTemplateId, - Versions: []*string{aws.String("1")}, + id := aws.StringValue(lt.LaunchTemplateId) + addVersion(t, svc, id, "a", "") // v2 + + // The default alongside a deletable version still fails the whole request. + _, err := svc.DeleteLaunchTemplateVersions(context.Background(), &ec2.DeleteLaunchTemplateVersionsInput{ + LaunchTemplateId: aws.String(id), + Versions: []*string{aws.String("2"), aws.String("1")}, }, testAccountID) + require.Error(t, err) + code, msg, ok := awserrors.ResolveErrorDetail(err) + require.True(t, ok) + assert.Equal(t, awserrors.ErrorInvalidParameterValue, code) + assert.Equal(t, "The default version cannot be deleted. Either specify another version as default or delete the launch template.", msg) + + nums, err := svc.listVersionNumbers(t.Context(), testAccountID, id) require.NoError(t, err) - assert.Empty(t, out.SuccessfullyDeletedLaunchTemplateVersions) - require.Len(t, out.UnsuccessfullyDeletedLaunchTemplateVersions, 1) - assert.Equal(t, awserrors.ErrorInvalidParameterValue, - aws.StringValue(out.UnsuccessfullyDeletedLaunchTemplateVersions[0].ResponseError.Code)) + assert.ElementsMatch(t, []int64{1, 2}, nums) } func TestDeleteLaunchTemplateVersions_SuccessAndMissing(t *testing.T) { @@ -421,7 +429,10 @@ func TestDeleteLaunchTemplateVersions_SuccessAndMissing(t *testing.T) { require.Len(t, out.SuccessfullyDeletedLaunchTemplateVersions, 1) assert.Equal(t, int64(2), aws.Int64Value(out.SuccessfullyDeletedLaunchTemplateVersions[0].VersionNumber)) require.Len(t, out.UnsuccessfullyDeletedLaunchTemplateVersions, 1) - assert.Equal(t, int64(9), aws.Int64Value(out.UnsuccessfullyDeletedLaunchTemplateVersions[0].VersionNumber)) + missing := out.UnsuccessfullyDeletedLaunchTemplateVersions[0] + assert.Equal(t, int64(9), aws.Int64Value(missing.VersionNumber)) + assert.Equal(t, "launchTemplateVersionDoesNotExist", aws.StringValue(missing.ResponseError.Code)) + assert.Equal(t, "The launch template version does not exist.", aws.StringValue(missing.ResponseError.Message)) } // --- DeleteLaunchTemplate ---