refactor: move ecr lifecycle preview get action to domain

This commit is contained in:
joshsiv-mulga
2026-10-02 08:05:22 +10:00
parent 47d028eda4
commit 68945bbb1d
3 changed files with 53 additions and 23 deletions
@@ -97,3 +97,32 @@ func StartLifecyclePolicyPreview(ctx context.Context, policies LifecyclePolicySt
Status: aws.String(ecr.LifecyclePolicyPreviewStatusComplete),
}, nil
}
// GetLifecyclePolicyPreview evaluates synchronously and returns every expiry
// result. v1 has no asynchronous preview-job state, so its status is always
// COMPLETE when evaluation succeeds.
func GetLifecyclePolicyPreview(ctx context.Context, policies LifecyclePolicyStore, catalog ImageCatalog, accountID string, body []byte) (*ecr.GetLifecyclePolicyPreviewOutput, error) {
preview, err := EvaluateLifecyclePreview(ctx, policies, catalog, accountID, body)
if err != nil {
return nil, err
}
results := make([]*ecr.LifecyclePolicyPreviewResult, 0, len(preview.Expiries))
for _, expiry := range preview.Expiries {
results = append(results, &ecr.LifecyclePolicyPreviewResult{
Action: &ecr.LifecyclePolicyRuleAction{Type: aws.String(ecr.ImageActionTypeExpire)},
AppliedRulePriority: aws.Int64(int64(expiry.RulePriority)),
ImageDigest: aws.String(expiry.Digest),
ImagePushedAt: aws.Time(expiry.PushedAt),
ImageTags: aws.StringSlice(expiry.Tags),
})
}
return &ecr.GetLifecyclePolicyPreviewOutput{
RegistryId: aws.String(accountID),
RepositoryName: aws.String(preview.RepositoryName),
LifecyclePolicyText: aws.String(preview.LifecyclePolicyText),
Status: aws.String(ecr.LifecyclePolicyPreviewStatusComplete),
PreviewResults: results,
Summary: &ecr.LifecyclePolicyPreviewSummary{ExpiringImageTotalCount: aws.Int64(int64(len(preview.Expiries)))},
}, nil
}
@@ -41,6 +41,25 @@ func TestStartLifecyclePolicyPreview_EvaluatesOverride(t *testing.T) {
assert.Equal(t, ecr.LifecyclePolicyPreviewStatusComplete, *out.Status)
}
func TestGetLifecyclePolicyPreview_ProjectsExpiryResults(t *testing.T) {
catalog := fakeImageCatalog{records: []ecrregistry.ImageRecord{
{Digest: "sha256:older", Tags: []string{"v1"}, PushedAt: time.Now().Add(-time.Hour)},
{Digest: "sha256:newer", Tags: []string{"v2"}, PushedAt: time.Now()},
}}
encodedPolicy, err := json.Marshal(lifecyclePreviewPolicy)
require.NoError(t, err)
body := []byte(`{"repositoryName":"team/app","lifecyclePolicyText":` + string(encodedPolicy) + `}`)
out, err := GetLifecyclePolicyPreview(context.Background(), fakeLifecyclePolicyStore{}, catalog, "123456789012", body)
require.NoError(t, err)
assert.Equal(t, ecr.LifecyclePolicyPreviewStatusComplete, *out.Status)
require.Len(t, out.PreviewResults, 1)
assert.Equal(t, "sha256:older", *out.PreviewResults[0].ImageDigest)
assert.Equal(t, int64(7), *out.PreviewResults[0].AppliedRulePriority)
require.NotNil(t, out.Summary)
assert.Equal(t, int64(1), *out.Summary.ExpiringImageTotalCount)
}
func TestEvaluateLifecyclePreview_MapsPolicyAndRepositoryFailures(t *testing.T) {
cases := []struct {
name string
+5 -23
View File
@@ -4,8 +4,6 @@ import (
"io"
"net/http"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecr"
handlers_ecr "github.com/mulgadc/spinifex/spinifex/domains/ecr"
awsapi "github.com/mulgadc/spinifex/spinifex/domains/ecr/awsapi"
)
@@ -30,7 +28,9 @@ func (gw *GatewayConfig) handleStartLifecyclePolicyPreview(w http.ResponseWriter
return nil
}
// handleGetLifecyclePolicyPreview returns the evaluated expiry set.
// handleGetLifecyclePolicyPreview adapts the authenticated HTTP request to the
// ECR action. Lifecycle evaluation and AWS response projection live in the
// ECR adapter; gateway supplies the policy store and image catalog.
func (gw *GatewayConfig) handleGetLifecyclePolicyPreview(w http.ResponseWriter, r *http.Request) error {
accountID, err := gw.ecrImageAccount(r)
if err != nil {
@@ -40,28 +40,10 @@ func (gw *GatewayConfig) handleGetLifecyclePolicyPreview(w http.ResponseWriter,
if err != nil {
return awsapi.MalformedBodyError()
}
preview, err := awsapi.EvaluateLifecyclePreview(r.Context(), handlers_ecr.NewNATSMetaStore(gw.NATSConn), gw.ECRRegistry, accountID, body)
output, err := awsapi.GetLifecyclePolicyPreview(r.Context(), handlers_ecr.NewNATSMetaStore(gw.NATSConn), gw.ECRRegistry, accountID, body)
if err != nil {
return err
}
results := make([]*ecr.LifecyclePolicyPreviewResult, 0, len(preview.Expiries))
for _, e := range preview.Expiries {
results = append(results, &ecr.LifecyclePolicyPreviewResult{
Action: &ecr.LifecyclePolicyRuleAction{Type: aws.String(ecr.ImageActionTypeExpire)},
AppliedRulePriority: aws.Int64(int64(e.RulePriority)),
ImageDigest: aws.String(e.Digest),
ImagePushedAt: aws.Time(e.PushedAt),
ImageTags: aws.StringSlice(e.Tags),
})
}
awsapi.WriteJSONResponse(w, &ecr.GetLifecyclePolicyPreviewOutput{
RegistryId: aws.String(accountID),
RepositoryName: aws.String(preview.RepositoryName),
LifecyclePolicyText: aws.String(preview.LifecyclePolicyText),
Status: aws.String(ecr.LifecyclePolicyPreviewStatusComplete),
PreviewResults: results,
Summary: &ecr.LifecyclePolicyPreviewSummary{ExpiringImageTotalCount: aws.Int64(int64(len(preview.Expiries)))},
})
awsapi.WriteJSONResponse(w, output)
return nil
}