Files
sub2api-cn-relay-manager/internal/provision/preview_service.go

92 lines
2.5 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 := 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"}
}
}