package provision import ( "context" "fmt" "sub2api-cn-relay-manager/internal/host/sub2api" "sub2api-cn-relay-manager/internal/pack" ) const ( PreviewActionCreate = "create" PreviewActionReuse = "reuse" PreviewActionConflict = "conflict" ) type previewHost interface { ListManagedResources(ctx context.Context, req sub2api.ListManagedResourcesRequest) (sub2api.ManagedResourceSnapshot, error) } type PreviewRequest struct { Provider pack.ProviderManifest Mode string Keys []string } type PreviewDecision struct { Action string Suggested string ExistingID string Reason string } type PreviewReport struct { AcceptedKeys []string Names ResourceNames Decisions map[string]PreviewDecision } type PreviewService struct { host previewHost } func NewPreviewService(host previewHost) *PreviewService { return &PreviewService{host: host} } func (s *PreviewService) PreviewImport(ctx context.Context, req PreviewRequest) (PreviewReport, error) { acceptedKeys, err := normalizeKeys(req.Keys) if err != nil { return PreviewReport{}, err } if err := validateMode(req.Mode); err != nil { return PreviewReport{}, err } if s.host == nil { return PreviewReport{}, fmt.Errorf("preview host is required") } names := SuggestResourceNamesForMode(req.Provider, req.Mode) snapshot, err := s.host.ListManagedResources(ctx, sub2api.ListManagedResourcesRequest{ GroupName: names.Group, ChannelName: names.Channel, PlanName: names.Plan, AccountNamePrefix: SuggestAccountNamePrefix(req.Provider), }) if err != nil { return PreviewReport{}, fmt.Errorf("list managed resources: %w", err) } return PreviewReport{ AcceptedKeys: acceptedKeys, Names: names, Decisions: map[string]PreviewDecision{ "group": decideResource(names.Group, snapshot.Groups), "channel": decideResource(names.Channel, snapshot.Channels), "plan": decideResource(names.Plan, snapshot.Plans), }, }, nil } func decideResource(suggested string, existing []sub2api.NamedResource) PreviewDecision { switch len(existing) { case 0: return PreviewDecision{Action: PreviewActionCreate, Suggested: suggested} case 1: return PreviewDecision{Action: PreviewActionReuse, Suggested: suggested, ExistingID: existing[0].ID, Reason: "matching managed resource already exists"} default: return PreviewDecision{Action: PreviewActionConflict, Suggested: suggested, Reason: "multiple managed resources share the suggested name"} } }