Skip to content

Commit

Permalink
adds db calls for subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
tonytheleg committed May 22, 2024
1 parent 066bb8b commit 419b3fd
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 23 deletions.
2 changes: 1 addition & 1 deletion dev-infrastructure/configurations/svc-cluster.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ param podSubnetPrefix = '10.128.64.0/18'
param enablePrivateCluster = false
param persist = false
param disableLocalAuth = false
param deployFrontendCosmos = false
param deployFrontendCosmos = true
param deployMaestroInfra = false
param maestroNamespace = 'maestro'
param workloadIdentities = items({
Expand Down
31 changes: 31 additions & 0 deletions frontend/cluster.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"properties": {
"spec": {
"version": {
"id": "1.19.0",
"channelGroup": "stable"
},
"dns": {
"baseDomainPrefix": "xyz"
},
"network": {
"podCidr": "10.10.0.0/24",
"serviceCidr": "10.10.0.0/24",
"machineCidr": "10.10.0.0/24"
},
"console": {},
"api": {
"visibility": "public"
},
"proxy": {},
"platform": {
"managedResourceGroup": "xyz",
"subnetId": "/subscriptions/xyz/resourceGroups/xyz/providers/Microsoft.Network/virtualNetworks/xyz/subnets/xyz",
"outboundType": "loadBalancer",
"networkSecurityGroupId": "/subscriptions/xyz/resourceGroups/xyz/providers/Microsoft.Network/networkSecurityGroups/xyz",
"etcdEncryptionSetId": "/subscriptions/xyz/resourceGroups/xyz/providers/Microsoft.Compute/encryptionSets/xyz"
},
"externalAuth": {}
}
}
}
65 changes: 61 additions & 4 deletions frontend/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (

const (
clustersContainer = "Clusters"
subsContainer = "Subscriptions"
billingContainer = "Billing"
asyncContainer = "AsyncOperations"
)

// DBClient defines the needed values to perform CRUD operations against the async DB
Expand Down Expand Up @@ -75,7 +78,7 @@ func (d *DBClient) DBConnectionTest(ctx context.Context) (string, error) {
return result.DatabaseProperties.ID, nil
}

// GetCluster retreives a cluster document from async DB using resource ID
// GetClusterDoc retreives a cluster document from async DB using resource ID
func (d *DBClient) GetClusterDoc(ctx context.Context, resourceID string, partitionKey string) (*HCPOpenShiftClusterDocument, bool, error) {
container, err := d.client.NewContainer(d.config.DBName, clustersContainer)
if err != nil {
Expand Down Expand Up @@ -109,10 +112,9 @@ func (d *DBClient) GetClusterDoc(ctx context.Context, resourceID string, partiti
return doc, true, nil
}
return nil, false, nil

}

// SetCluster creates/updates a cluster document in the async DB during cluster creation/patching
// SetClusterDoc creates/updates a cluster document in the async DB during cluster creation/patching
func (d *DBClient) SetClusterDoc(ctx context.Context, doc *HCPOpenShiftClusterDocument) error {
data, err := json.Marshal(doc)
if err != nil {
Expand All @@ -132,7 +134,7 @@ func (d *DBClient) SetClusterDoc(ctx context.Context, doc *HCPOpenShiftClusterDo
return nil
}

// DeleteCluster removes a cluter document from the async DB using resource ID
// DeleteClusterDoc removes a cluter document from the async DB using resource ID
func (d *DBClient) DeleteClusterDoc(ctx context.Context, resourceID string, partitionKey string) error {
doc, found, err := d.GetClusterDoc(ctx, resourceID, partitionKey)
if !found {
Expand All @@ -153,3 +155,58 @@ func (d *DBClient) DeleteClusterDoc(ctx context.Context, resourceID string, part
}
return nil
}

// GetSubscriptionDoc retreives a subscription document from async DB using the subscription ID
func (d *DBClient) GetSubscriptionDoc(ctx context.Context, partitionKey string) (*SubscriptionDocument, bool, error) {
container, err := d.client.NewContainer(d.config.DBName, subsContainer)
if err != nil {
return nil, false, err
}

query := "SELECT * FROM c WHERE c.partitionKey = @partitionKey"
opt := azcosmos.QueryOptions{
PageSizeHint: 1,
QueryParameters: []azcosmos.QueryParameter{{Name: "@partitionKey", Value: partitionKey}},
}

pk := azcosmos.NewPartitionKeyString(partitionKey)
queryPager := container.NewQueryItemsPager(query, pk, &opt)

var doc *SubscriptionDocument
for queryPager.More() {
queryResponse, err := queryPager.NextPage(ctx)
if err != nil {
return nil, false, err
}

for _, item := range queryResponse.Items {
err = json.Unmarshal(item, &doc)
if err != nil {
return nil, false, err
}
}
}
if doc != nil {
return doc, true, nil
}
return nil, false, nil
}

// SetClusterDoc creates/updates a subscription document in the async DB during cluster creation/patching
func (d *DBClient) SetSubscriptionDoc(ctx context.Context, doc *SubscriptionDocument) error {
data, err := json.Marshal(doc)
if err != nil {
return err
}

container, err := d.client.NewContainer(d.config.DBName, subsContainer)
if err != nil {
return err
}

_, err = container.UpsertItem(ctx, azcosmos.NewPartitionKeyString(doc.PartitionKey), data, nil)
if err != nil {
return err
}
return nil
}
32 changes: 32 additions & 0 deletions frontend/document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import "github.com/Azure/ARO-HCP/internal/api/arm"

// HCPOpenShiftClusterDocument represents an HCP OpenShift cluster document.
type HCPOpenShiftClusterDocument struct {
ID string `json:"id,omitempty"`
Key string `json:"key,omitempty"`
PartitionKey string `json:"partitionKey,omitempty"`
ClusterID string `json:"clusterid,omitempty"`

// Values provided by Cosmos after doc creation
ResourceID string `json:"_rid,omitempty"`
Self string `json:"_self,omitempty"`
ETag string `json:"_etag,omitempty"`
Attachments string `json:"_attachments,omitempty"`
Timestamp int `json:"_ts,omitempty"`
}

// SubscriptionDocument represents an Azure Subscription document.
type SubscriptionDocument struct {
ID string `json:"id,omitempty"`
PartitionKey string `json:"partitionKey,omitempty"`
Subscription *arm.Subscription `json:"subscription,omitempty"`

// Values provided by Cosmos after doc creation
ResourceID string `json:"_rid,omitempty"`
Self string `json:"_self,omitempty"`
ETag string `json:"_etag,omitempty"`
Attachments string `json:"_attachments,omitempty"`
Timestamp int `json:"_ts,omitempty"`
}
55 changes: 53 additions & 2 deletions frontend/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ func NewFrontend(logger *slog.Logger, listener net.Listener, emitter metrics.Emi
mux.HandleFunc("/", f.NotFound)
mux.HandleFunc(MuxPattern(http.MethodGet, "healthz", "ready"), f.HealthzReady)
// TODO: determine where in the auth chain we should allow for this endpoint to be called by ARM
mux.HandleFunc(MuxPattern(http.MethodPut, PatternSubscriptions), f.ArmSubscriptionAction)
mux.HandleFunc(MuxPattern(http.MethodGet, PatternSubscriptions), f.ArmSubscriptionGet)
mux.HandleFunc(MuxPattern(http.MethodPut, PatternSubscriptions), f.ArmSubscriptionPut)

// Expose Prometheus metrics endpoint
mux.Handle(MuxPattern(http.MethodGet, "metrics"), promhttp.Handler())
Expand Down Expand Up @@ -411,7 +412,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) {
func (f *Frontend) ArmSubscriptionGet(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
subId := request.PathValue(PathSegmentSubscriptionID)

doc, found, err := f.dbClient.GetSubscriptionDoc(ctx, subId)
if err != nil {
f.logger.Error("failed to get document for subscription %s: %v", subId, err)
}
if !found {
f.logger.Error(fmt.Sprintf("document not found for subscription %s", subId))
}

resp, err := json.Marshal(&doc)
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())
}

writer.WriteHeader(http.StatusOK)
}

func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()

body, err := BodyFromContext(ctx)
Expand All @@ -432,6 +459,28 @@ func (f *Frontend) ArmSubscriptionAction(writer http.ResponseWriter, request *ht
subId := request.PathValue(PathSegmentSubscriptionID)
f.cache.SetSubscription(subId, &subscription)

var doc *SubscriptionDocument
doc, found, err := f.dbClient.GetSubscriptionDoc(ctx, subId)
if err != nil {
f.logger.Error("failed to fetch document for %s: %v", subId, err)
arm.WriteInternalServerError(writer)
return
}
if !found {
f.logger.Info(fmt.Sprintf("existing document not found for subscription - creating one for %s", subId))
doc = &SubscriptionDocument{
ID: uuid.New().String(),
PartitionKey: subId,
Subscription: &subscription,
}
} else {
doc.Subscription = &subscription
}
err = f.dbClient.SetSubscriptionDoc(ctx, doc)
if err != nil {
f.logger.Error("failed to create document for subscription %s: %v", subId, err)
}

resp, err := json.Marshal(subscription)
if err != nil {
f.logger.Error(err.Error())
Expand All @@ -442,6 +491,8 @@ func (f *Frontend) ArmSubscriptionAction(writer http.ResponseWriter, request *ht
if err != nil {
f.logger.Error(err.Error())
}

writer.WriteHeader(http.StatusCreated)
}

func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *http.Request) {
Expand Down
16 changes: 0 additions & 16 deletions frontend/hcpclusterdocument.go

This file was deleted.

0 comments on commit 419b3fd

Please sign in to comment.