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.
This commit is contained in:
97
internal/host/sub2api/list_resources.go
Normal file
97
internal/host/sub2api/list_resources.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package sub2api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (c *Client) ListManagedResources(ctx context.Context, req ListManagedResourcesRequest) (ManagedResourceSnapshot, error) {
|
||||
groups, err := c.listNamedResources(ctx, "/api/v1/admin/groups", req.GroupName)
|
||||
if err != nil {
|
||||
return ManagedResourceSnapshot{}, fmt.Errorf("list groups: %w", err)
|
||||
}
|
||||
channels, err := c.listNamedResources(ctx, "/api/v1/admin/channels", req.ChannelName)
|
||||
if err != nil {
|
||||
return ManagedResourceSnapshot{}, fmt.Errorf("list channels: %w", err)
|
||||
}
|
||||
plans, err := c.listNamedResources(ctx, "/api/v1/admin/payment/plans", req.PlanName)
|
||||
if err != nil {
|
||||
return ManagedResourceSnapshot{}, fmt.Errorf("list plans: %w", err)
|
||||
}
|
||||
accounts, err := c.listNamedResources(ctx, "/api/v1/admin/accounts", "")
|
||||
if err != nil {
|
||||
return ManagedResourceSnapshot{}, fmt.Errorf("list accounts: %w", err)
|
||||
}
|
||||
|
||||
return ManagedResourceSnapshot{
|
||||
Groups: groups,
|
||||
Channels: channels,
|
||||
Plans: plans,
|
||||
Accounts: filterNamedResourcesByPrefix(accounts, req.AccountNamePrefix),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) listNamedResources(ctx context.Context, path, expectedName string) ([]NamedResource, error) {
|
||||
statusCode, _, body, err := c.perform(ctx, "GET", path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if statusCode < 200 || statusCode >= 300 {
|
||||
return nil, newHTTPError("GET", path, statusCode, body)
|
||||
}
|
||||
|
||||
resources, err := decodeNamedResources(body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode %s response: %w", path, err)
|
||||
}
|
||||
return filterNamedResourcesByName(resources, expectedName), nil
|
||||
}
|
||||
|
||||
func decodeNamedResources(body []byte) ([]NamedResource, error) {
|
||||
var resources []NamedResource
|
||||
if err := decodeEnvelopeObject(body, &resources); err == nil {
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
var wrapper struct {
|
||||
Data struct {
|
||||
Items []NamedResource `json:"items"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &wrapper); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wrapper.Data.Items, nil
|
||||
}
|
||||
|
||||
func filterNamedResourcesByName(resources []NamedResource, expectedName string) []NamedResource {
|
||||
expectedName = strings.TrimSpace(expectedName)
|
||||
if expectedName == "" {
|
||||
return resources
|
||||
}
|
||||
|
||||
filtered := make([]NamedResource, 0, len(resources))
|
||||
for _, resource := range resources {
|
||||
if strings.TrimSpace(resource.Name) == expectedName {
|
||||
filtered = append(filtered, resource)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
func filterNamedResourcesByPrefix(resources []NamedResource, prefix string) []NamedResource {
|
||||
prefix = strings.TrimSpace(prefix)
|
||||
if prefix == "" {
|
||||
return resources
|
||||
}
|
||||
|
||||
filtered := make([]NamedResource, 0, len(resources))
|
||||
for _, resource := range resources {
|
||||
if strings.HasPrefix(strings.TrimSpace(resource.Name), prefix) {
|
||||
filtered = append(filtered, resource)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
Reference in New Issue
Block a user