Files
sub2api-cn-relay-manager/internal/provision/preview_service.go
phamnazage-jpg 71cbaf5fa6 test(project): achieve ≥70% package coverage across all internal packages
- store/sqlite: 75.4% (repos + db coverage)
- host/sub2api: 80.8% (httptest mock server, pure function tests)
- app: 74.2% (handler error paths, NewActionSet closures)
- pack: 72.4%
- provision: 75.2%
- access: 77.3%
- config: 94.7% (lookup mock tests)

All tests pass: build, vet, race, coverage gates.
2026-05-15 19:26:25 +08:00

91 lines
2.4 KiB
Go

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 := SuggestResourceNames(req.Provider)
snapshot, err := s.host.ListManagedResources(ctx, sub2api.ListManagedResourcesRequest{
GroupName: names.Group,
ChannelName: names.Channel,
PlanName: names.Plan,
})
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"}
}
}