- 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.
91 lines
2.4 KiB
Go
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"}
|
|
}
|
|
}
|