From 0e940b83391570ddcd6eaafe668a311b5518de88 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Mon, 2 Nov 2020 13:49:18 -0700 Subject: [PATCH] registry: Add support for the options endpoint This is the endpoint for listing subscription options for DOCR. --- registry.go | 45 ++++++++++++++++++++- registry_test.go | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/registry.go b/registry.go index 2e31184d..19f805ac 100644 --- a/registry.go +++ b/registry.go @@ -32,6 +32,7 @@ type RegistryService interface { GetGarbageCollection(context.Context, string) (*GarbageCollection, *Response, error) ListGarbageCollections(context.Context, string, *ListOptions) ([]*GarbageCollection, *Response, error) UpdateGarbageCollection(context.Context, string, string, *UpdateGarbageCollectionRequest) (*GarbageCollection, *Response, error) + GetOptions(context.Context) (*RegistryOptions, *Response, error) } var _ RegistryService = &RegistryServiceOp{} @@ -121,6 +122,30 @@ type UpdateGarbageCollectionRequest struct { Cancel bool `json:"cancel"` } +// RegistryOptions are options for users when creating or updating a registry. +type RegistryOptions struct { + SubscriptionTiers []*RegistrySubscriptionTier `json:"subscription_tiers,omitempty"` +} + +type registryOptionsRoot struct { + Options *RegistryOptions `json:"options"` +} + +// RegistrySubscriptionTier is a subscription tier for container registry. +type RegistrySubscriptionTier struct { + Name string `json:"name"` + Slug string `json:"slug"` + IncludedRepositories uint64 `json:"included_repositories"` + IncludedStorageBytes uint64 `json:"included_storage_bytes"` + AllowStorageOverage bool `json:"allow_storage_overage"` + IncludedBandwidthBytes uint64 `json:"included_bandwidth_bytes"` + MonthlyPriceInCents uint64 `json:"monthly_price_in_cents"` + Eligible bool `json:"eligible,omitempty"` + // EligibilityReaons is included when Eligible is false, and indicates the + // reasons why this tier is not availble to the user. + EligibilityReasons []string `json:"eligibility_reasons,omitempty"` +} + // Get retrieves the details of a Registry. func (svc *RegistryServiceOp) Get(ctx context.Context) (*Registry, *Response, error) { req, err := svc.client.NewRequest(ctx, http.MethodGet, registryPath, nil) @@ -321,7 +346,7 @@ func (svc *RegistryServiceOp) GetGarbageCollection(ctx context.Context, registry return root.GarbageCollection, resp, nil } -// ListGarbageCollection retrieves all garbage collections (active and +// ListGarbageCollections retrieves all garbage collections (active and // inactive) for the specified registry. func (svc *RegistryServiceOp) ListGarbageCollections(ctx context.Context, registry string, opts *ListOptions) ([]*GarbageCollection, *Response, error) { path := fmt.Sprintf("%s/%s/garbage-collections", registryPath, registry) @@ -371,3 +396,21 @@ func (svc *RegistryServiceOp) UpdateGarbageCollection(ctx context.Context, regis return root.GarbageCollection, resp, nil } + +// GetOptions returns options the user can use when creating or updating a +// registry. +func (svc *RegistryServiceOp) GetOptions(ctx context.Context) (*RegistryOptions, *Response, error) { + path := fmt.Sprintf("%s/options", registryPath) + req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(registryOptionsRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Options, resp, nil +} diff --git a/registry_test.go b/registry_test.go index fed74405..0f4ebca4 100644 --- a/registry_test.go +++ b/registry_test.go @@ -494,3 +494,103 @@ func TestGarbageCollection_Update(t *testing.T) { require.NoError(t, err) require.Equal(t, want, got) } + +func TestRegistry_GetOptions(t *testing.T) { + responseJSON := ` +{ + "options": { + "subscription_tiers": [ + { + "name": "Starter", + "slug": "starter", + "included_repositories": 1, + "included_storage_bytes": 524288000, + "allow_storage_overage": false, + "included_bandwidth_bytes": 524288000, + "monthly_price_in_cents": 0, + "eligible": false, + "eligibility_reasons": [ + "OverStorageLimit", + "OverRepositoryLimit" + ] + }, + { + "name": "Basic", + "slug": "basic", + "included_repositories": 5, + "included_storage_bytes": 5368709120, + "allow_storage_overage": true, + "included_bandwidth_bytes": 5368709120, + "monthly_price_in_cents": 500, + "eligible": false, + "eligibility_reasons": [ + "OverRepositoryLimit" + ] + }, + { + "name": "Professional", + "slug": "professional", + "included_repositories": 0, + "included_storage_bytes": 107374182400, + "allow_storage_overage": true, + "included_bandwidth_bytes": 107374182400, + "monthly_price_in_cents": 2000, + "eligible": true + } + ] + } +}` + want := &RegistryOptions{ + SubscriptionTiers: []*RegistrySubscriptionTier{ + { + Name: "Starter", + Slug: "starter", + IncludedRepositories: 1, + IncludedStorageBytes: 524288000, + AllowStorageOverage: false, + IncludedBandwidthBytes: 524288000, + MonthlyPriceInCents: 0, + Eligible: false, + EligibilityReasons: []string{ + "OverStorageLimit", + "OverRepositoryLimit", + }, + }, + { + Name: "Basic", + Slug: "basic", + IncludedRepositories: 5, + IncludedStorageBytes: 5368709120, + AllowStorageOverage: true, + IncludedBandwidthBytes: 5368709120, + MonthlyPriceInCents: 500, + Eligible: false, + EligibilityReasons: []string{ + "OverRepositoryLimit", + }, + }, + { + Name: "Professional", + Slug: "professional", + IncludedRepositories: 0, + IncludedStorageBytes: 107374182400, + AllowStorageOverage: true, + IncludedBandwidthBytes: 107374182400, + MonthlyPriceInCents: 2000, + Eligible: true, + }, + }, + } + + setup() + defer teardown() + + mux.HandleFunc("/v2/registry/options", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, responseJSON) + }) + + got, _, err := client.Registry.GetOptions(ctx) + require.NoError(t, err) + require.Equal(t, want, got) +}