From cded877976e25932c37085c99836293f1947d586 Mon Sep 17 00:00:00 2001 From: Spencer Amann Date: Tue, 9 Apr 2024 19:06:54 +0000 Subject: [PATCH] adds a new subscription endpoint to save to cache --- frontend/cache.go | 24 ++++++++++-- frontend/frontend.go | 32 ++++++++++++++++ internal/api/subscription/register.go | 29 ++++++++++++++ internal/api/subscription/subscription.go | 46 +++++++++++++++++++++++ 4 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 internal/api/subscription/register.go create mode 100644 internal/api/subscription/subscription.go diff --git a/frontend/cache.go b/frontend/cache.go index 21c4ccf97..6fdb75383 100644 --- a/frontend/cache.go +++ b/frontend/cache.go @@ -3,16 +3,21 @@ package main // Copyright (c) Microsoft Corporation. // Licensed under the Apache License 2.0. -import "github.com/Azure/ARO-HCP/internal/api" +import ( + "github.com/Azure/ARO-HCP/internal/api" + "github.com/Azure/ARO-HCP/internal/api/subscription" +) type cache struct { - cluster map[string]*api.HCPOpenShiftCluster + cluster map[string]*api.HCPOpenShiftCluster + subscription map[string]*subscription.Subscription } // NewCache returns a new cache. func NewCache() *cache { return &cache{ - cluster: make(map[string]*api.HCPOpenShiftCluster), + cluster: make(map[string]*api.HCPOpenShiftCluster), + subscription: make(map[string]*subscription.Subscription), } } @@ -28,3 +33,16 @@ func (c *cache) SetCluster(id string, cluster *api.HCPOpenShiftCluster) { func (c *cache) DeleteCluster(id string) { delete(c.cluster, id) } + +func (c *cache) GetSubscription(id string) (*subscription.Subscription, bool) { + subscription, found := c.subscription[id] + return subscription, found +} + +func (c *cache) SetSubscription(id string, subscription *subscription.Subscription) { + c.subscription[id] = subscription +} + +func (c *cache) DeleteSubscription(id string) { + delete(c.subscription, id) +} diff --git a/frontend/frontend.go b/frontend/frontend.go index 3392a294e..ae4b048c7 100644 --- a/frontend/frontend.go +++ b/frontend/frontend.go @@ -17,6 +17,7 @@ import ( "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/api/arm" + "github.com/Azure/ARO-HCP/internal/api/subscription" ) const ( @@ -97,6 +98,7 @@ func NewFrontend(logger *slog.Logger, listener net.Listener) *Frontend { mux.Handle( MuxPattern(http.MethodPost, PatternSubscriptions, PatternResourceGroups, PatternProviders, PatternResourceName, PatternActionName), postMuxMiddleware.HandlerFunc(f.ArmResourceAction)) + mux.Handle(MuxPattern(http.MethodPut, PatternSubscriptions), postMuxMiddleware.HandlerFunc(f.ArmSubscriptionAction)) f.server.Handler = mux return f @@ -277,3 +279,33 @@ func (f *Frontend) ArmResourceAction(writer http.ResponseWriter, request *http.R writer.WriteHeader(http.StatusOK) } + +func (f *Frontend) ArmSubscriptionAction(writer http.ResponseWriter, request *http.Request) { + ctx := request.Context() + logger := ctx.Value(ContextKeyLogger).(*slog.Logger) + versionedInterface := ctx.Value(ContextKeyVersion).(api.Version) + logger.Info(fmt.Sprintf("%s: ArmSubscriptionAction", versionedInterface)) + + body := ctx.Value(ContextKeyBody).([]byte) + var subscription subscription.Subscription + err := json.Unmarshal(body, &subscription) + if err != nil { + f.logger.Error(err.Error()) + writer.WriteHeader(http.StatusBadRequest) + return + } + + subId := request.PathValue(strings.ToLower(PathSegmentSubscriptionID)) + f.cache.SetSubscription(subId, &subscription) + + resp, err := json.Marshal(subscription) + if err != nil { + f.logger.Error(err.Error()) + writer.WriteHeader(http.StatusInternalServerError) + return + } + _, err = writer.Write(resp) + if err != nil { + f.logger.Error(err.Error()) + } +} diff --git a/internal/api/subscription/register.go b/internal/api/subscription/register.go new file mode 100644 index 000000000..e51cc7a82 --- /dev/null +++ b/internal/api/subscription/register.go @@ -0,0 +1,29 @@ +package subscription + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +import ( + "github.com/Azure/ARO-HCP/internal/api" +) + +type version struct{} + +// NewHCPOpenShiftCluster implements api.Version. +func (v version) NewHCPOpenShiftCluster(*api.HCPOpenShiftCluster) api.VersionedHCPOpenShiftCluster { + panic("'System Version 2.0' is not supported for HCP Cluster objects") +} + +// UnmarshalHCPOpenShiftCluster implements api.Version. +func (v version) UnmarshalHCPOpenShiftCluster([]byte, bool, *api.HCPOpenShiftCluster) error { + panic("'System Version 2.0' is not supported for HCP Cluster objects") +} + +// String returns the api-version parameter value for this API. +func (v version) String() string { + return "2.0" +} + +func init() { + api.Register(version{}) +} diff --git a/internal/api/subscription/subscription.go b/internal/api/subscription/subscription.go new file mode 100644 index 000000000..dbec82341 --- /dev/null +++ b/internal/api/subscription/subscription.go @@ -0,0 +1,46 @@ +package subscription + +// Copyright (c) Microsoft Corporation. +// Licensed under the Apache License 2.0. + +type Subscription struct { + State RegistrationState `json:"state"` + RegsitrationDate *string `json:"registrationDate,omitempty"` + Properties *Properties `json:"properties,omitempty"` +} + +type Properties struct { + TenantId *string `json:"tenantId,omitempty"` + LocationPlacementId *string `json:"locationPlacementId,omitempty"` + QuotaId *string `json:"quotaId,omitempty"` + RegisteredFeatures *[]Feature `json:"registeredFeatures,omitempty"` + AvailabilityZones *AvailabilityZone `json:"availabilityZones,omitempty"` + SpendingLimit *string `json:"spendingLimit,omitempty"` + AccountOwner *map[string]string `json:"accountOwner,omitempty"` + ManagedByTenants *[]map[string]string `json:"managedByTenants,omitempty"` + AdditionalProperties *map[string]string `json:"additionalProperties,omitempty"` +} + +type Feature struct { + Name *string `json:"name,omitempty"` + State *string `json:"state,omitempty"` +} + +type AvailabilityZone struct { + Location *string `json:"location,omitempty"` + ZoneMappings *[]ZoneMapping `json:"zoneMppings,omitempty"` +} + +type ZoneMapping struct { + LogicalZone *string `json:"logicalZone,omitempty"` + PhysicalZone *string `json:"physicalZone,omitempty"` +} +type RegistrationState string + +const ( + Registered RegistrationState = "Registered" + Unregistered RegistrationState = "Unregistered" + Warned RegistrationState = "Warned" + Deleted RegistrationState = "Deleted" + Suspended RegistrationState = "Suspended" +)