frontend

package
v0.0.0-...-2fcb30d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 24, 2025 License: Apache-2.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ProgramName = "ARO HCP Frontend"

	// APIVersionKey is the request parameter name for the API version.
	APIVersionKey = "api-version"

	// Wildcard path segment names for request multiplexing, must be lowercase as we lowercase the request URL pattern when registering handlers
	PathSegmentActionName        = "actionname"
	PathSegmentDeploymentName    = "deploymentname"
	PathSegmentLocation          = "location"
	PathSegmentNodePoolName      = "nodepoolname"
	PathSegmentOperationID       = "operationid"
	PathSegmentResourceGroupName = "resourcegroupname"
	PathSegmentResourceName      = "resourcename"
	PathSegmentSubscriptionID    = "subscriptionid"
)
View Source
const (
	UnregisteredSubscriptionStateMessage = "Request is not allowed in unregistered subscription '%s'."
	InvalidSubscriptionStateMessage      = "Request is not allowed in subscription in state '%s'."
	SubscriptionMissingMessage           = "The request is missing required parameter '%s'."
)
View Source
const (
	WildcardActionName        = "{" + PathSegmentActionName + "}"
	WildcardDeploymentName    = "{" + PathSegmentDeploymentName + "}"
	WildcardLocation          = "{" + PathSegmentLocation + "}"
	WildcardNodePoolName      = "{" + PathSegmentNodePoolName + "}"
	WildcardOperationID       = "{" + PathSegmentOperationID + "}"
	WildcardResourceGroupName = "{" + PathSegmentResourceGroupName + "}"
	WildcardResourceName      = "{" + PathSegmentResourceName + "}"
	WildcardSubscriptionID    = "{" + PathSegmentSubscriptionID + "}"

	PatternSubscriptions    = "subscriptions/" + WildcardSubscriptionID
	PatternLocations        = "locations/" + WildcardLocation
	PatternProviders        = "providers/" + api.ProviderNamespace
	PatternClusters         = api.ClusterResourceTypeName + "/" + WildcardResourceName
	PatternNodePools        = api.NodePoolResourceTypeName + "/" + WildcardNodePoolName
	PatternDeployments      = "deployments/" + WildcardDeploymentName
	PatternResourceGroups   = "resourcegroups/" + WildcardResourceGroupName
	PatternOperationResults = api.OperationResultResourceTypeName + "/" + WildcardOperationID
	PatternOperationsStatus = api.OperationStatusResourceTypeName + "/" + WildcardOperationID
)

Variables

This section is empty.

Functions

func BodyFromContext

func BodyFromContext(ctx context.Context) ([]byte, error)

func ContextWithBody

func ContextWithBody(ctx context.Context, body []byte) context.Context

func ContextWithCorrelationData

func ContextWithCorrelationData(ctx context.Context, correlationData *arm.CorrelationData) context.Context

func ContextWithDBClient

func ContextWithDBClient(ctx context.Context, dbClient database.DBClient) context.Context

func ContextWithLogger

func ContextWithLogger(ctx context.Context, logger *slog.Logger) context.Context

func ContextWithOriginalPath

func ContextWithOriginalPath(ctx context.Context, originalPath string) context.Context

func ContextWithResourceID

func ContextWithResourceID(ctx context.Context, resourceID *azcorearm.ResourceID) context.Context

func ContextWithSystemData

func ContextWithSystemData(ctx context.Context, systemData *arm.SystemData) context.Context

func ContextWithVersion

func ContextWithVersion(ctx context.Context, version api.Version) context.Context

func ConvertCStoHCPOpenShiftCluster

func ConvertCStoHCPOpenShiftCluster(resourceID *azcorearm.ResourceID, cluster *cmv1.Cluster) *api.HCPOpenShiftCluster

ConvertCStoHCPOpenShiftCluster converts a CS Cluster object into HCPOpenShiftCluster object

func ConvertCStoNodePool

func ConvertCStoNodePool(resourceID *azcorearm.ResourceID, np *cmv1.NodePool) *api.HCPOpenShiftClusterNodePool

ConvertCStoNodePool converts a CS Node Pool object into HCPOpenShiftClusterNodePool object

func CorrelationDataFromContext

func CorrelationDataFromContext(ctx context.Context) (*arm.CorrelationData, error)

func DBClientFromContext

func DBClientFromContext(ctx context.Context) (database.DBClient, error)

func LoggerFromContext

func LoggerFromContext(ctx context.Context) *slog.Logger

func MiddlewareBody

func MiddlewareBody(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareLockSubscription

func MiddlewareLockSubscription(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareLogging

func MiddlewareLogging(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareLoggingPostMux

func MiddlewareLoggingPostMux(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareLowercase

func MiddlewareLowercase(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

This middleware helps comply with Azure OpenAPI Specifications Guidelines around case sensitivity for resource IDs. Specifically:

OAPI012: Resource IDs must not be case sensitive

Any entity name in the URL or resource ID (resource group names, resource
names, resource provider names) must be treated case insensitively. RPs
should also persist the casing provided by the user for tags, resource
names, etc... and use that same casing in responses.

Example:

The following two resource IDs are both valid and point to the same
resource. Casing must be ignored.

/subscriptions/45cefb9a-1824-4c35-ab4b-05c78763c03e/resourceGroups/myResourceGroup/
providers/Microsoft.KeyVault/vaults/sample-vault?api-version=2019-09-01

/SUBSCRIPTIONS/45CEFB9A-1824-4C35-AB4B-05C78763C03E/RESOURCEGROUPS/myresourceGROUP/
PROVIDERS/MICROSOFT.keyvault/VAULTS/SAMPLE-VAULT?API-VERSION=2019-09-01

The frontend uses ServeMux from Go's standard library (net/http), which matches literal (that is, non-wildcarded) path segments case-sensitively. For instance, in a resource ID, "subscriptions" and "resourcegroups" are literal path segments and therefore are matched case-sensitvely.

So this middleware saves the original path casing in the request context, and then normalizes the casing for ServeMux by lowercasing it. At the same time, when registering URL patterns with ServeMux in routes.go, we use the helper function MuxPattern which also lowercases the path segments passed to it to ensure their normalized casing agrees with this middleware.

When the resource ID, or parts of it, needs to be used in an HTTP response (such as an error message), be sure to retrieve the original path from the request context. Do not use the normalized request path nor path values in the request (via PathValue). If necessary, you can parse the original path into a resource ID using ParseResourceID from the azcore/arm package.

func MiddlewarePanic

func MiddlewarePanic(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareResourceID

func MiddlewareResourceID(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareSystemData

func MiddlewareSystemData(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareValidateAPIVersion

func MiddlewareValidateAPIVersion(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareValidateStatic

func MiddlewareValidateStatic(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func MiddlewareValidateSubscriptionState

func MiddlewareValidateSubscriptionState(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

MiddlewareValidateSubscriptionState validates the state of the subscription as outlined by https://github.com/cloud-and-ai-microsoft/resource-provider-contract/blob/master/v1.0/subscription-lifecycle-api-reference.md

func MuxPattern

func MuxPattern(method string, segments ...string) string

MuxPattern forms a URL pattern suitable for passing to http.ServeMux. Literal path segments must be lowercase because MiddlewareLowercase converts the request URL to lowercase before multiplexing.

func OriginalPathFromContext

func OriginalPathFromContext(ctx context.Context) (string, error)

func ResourceIDFromContext

func ResourceIDFromContext(ctx context.Context) (*azcorearm.ResourceID, error)

func SystemDataFromContext

func SystemDataFromContext(ctx context.Context) (*arm.SystemData, error)

func VersionFromContext

func VersionFromContext(ctx context.Context) (api.Version, error)

Types

type ContextError

type ContextError struct {
	// contains filtered or unexported fields
}

func (*ContextError) Error

func (c *ContextError) Error() string

type Emitter

type Emitter interface {
	AddCounter(metricName string, value float64, labels map[string]string)
	EmitGauge(metricName string, value float64, labels map[string]string)
}

Emitter emits different types of metrics

type Frontend

type Frontend struct {
	// contains filtered or unexported fields
}

func NewFrontend

func NewFrontend(logger *slog.Logger, listener net.Listener, metricsListener net.Listener, emitter Emitter, dbClient database.DBClient, location string, csClient ocm.ClusterServiceClientSpec) *Frontend

func (*Frontend) AddAsyncOperationHeader

func (f *Frontend) AddAsyncOperationHeader(writer http.ResponseWriter, request *http.Request, doc *database.OperationDocument)

AddAsyncOperationHeader adds an "Azure-AsyncOperation" header to the ResponseWriter with a URL of the operation status endpoint for the given OperationDocument.

func (*Frontend) AddLocationHeader

func (f *Frontend) AddLocationHeader(writer http.ResponseWriter, request *http.Request, doc *database.OperationDocument)

AddLocationHeader adds a "Location" header to the ResponseWriter with a URL of the operation result endpoint for the given OperationDocument.

func (*Frontend) ArmDeploymentPreflight

func (f *Frontend) ArmDeploymentPreflight(writer http.ResponseWriter, request *http.Request)

func (*Frontend) ArmResourceAction

func (f *Frontend) ArmResourceAction(writer http.ResponseWriter, request *http.Request)

func (*Frontend) ArmResourceCreateOrUpdate

func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request *http.Request)

func (*Frontend) ArmResourceDelete

func (f *Frontend) ArmResourceDelete(writer http.ResponseWriter, request *http.Request)

ArmResourceDelete implements the deletion API contract for ARM * 200 if a deletion is successful * 202 if an asynchronous delete is initiated * 204 if a well-formed request attempts to delete a nonexistent resource

func (*Frontend) ArmResourceList

func (f *Frontend) ArmResourceList(writer http.ResponseWriter, request *http.Request)

func (*Frontend) ArmResourceRead

func (f *Frontend) ArmResourceRead(writer http.ResponseWriter, request *http.Request)

ArmResourceRead implements the GET single resource API contract for ARM * 200 If the resource exists * 404 If the resource does not exist

func (*Frontend) ArmSubscriptionGet

func (f *Frontend) ArmSubscriptionGet(writer http.ResponseWriter, request *http.Request)

func (*Frontend) ArmSubscriptionPut

func (f *Frontend) ArmSubscriptionPut(writer http.ResponseWriter, request *http.Request)

func (*Frontend) BuildCSCluster

func (f *Frontend) BuildCSCluster(resourceID *azcorearm.ResourceID, requestHeader http.Header, hcpCluster *api.HCPOpenShiftCluster, updating bool) (*cmv1.Cluster, error)

BuildCSCluster creates a CS Cluster object from an HCPOpenShiftCluster object

func (*Frontend) BuildCSNodePool

func (f *Frontend) BuildCSNodePool(ctx context.Context, nodePool *api.HCPOpenShiftClusterNodePool, updating bool) (*cmv1.NodePool, error)

BuildCSNodePool creates a CS Node Pool object from an HCPOpenShiftClusterNodePool object

func (*Frontend) CancelActiveOperation

func (f *Frontend) CancelActiveOperation(ctx context.Context, resourceDoc *database.ResourceDocument) error

CancelActiveOperation marks the status of any active operation on the resource as canceled.

func (*Frontend) CheckForProvisioningStateConflict

func (f *Frontend) CheckForProvisioningStateConflict(ctx context.Context, operationRequest database.OperationRequest, doc *database.ResourceDocument) *arm.CloudError

CheckForProvisioningStateConflict returns a "409 Conflict" error response if the provisioning state of the resource is non-terminal, or any of its parent resources within the same provider namespace are in a "Deleting" state.

func (*Frontend) CheckReady

func (f *Frontend) CheckReady(ctx context.Context) bool

func (*Frontend) CreateOrUpdateNodePool

func (f *Frontend) CreateOrUpdateNodePool(writer http.ResponseWriter, request *http.Request)

func (*Frontend) DeleteAllResources

func (f *Frontend) DeleteAllResources(ctx context.Context, subscriptionID string) *arm.CloudError

func (*Frontend) DeleteResource

func (f *Frontend) DeleteResource(ctx context.Context, resourceDoc *database.ResourceDocument) (string, *arm.CloudError)

func (*Frontend) ExposeOperation

func (f *Frontend) ExposeOperation(writer http.ResponseWriter, request *http.Request, operationID string) error

ExposeOperation fully initiates a new asynchronous operation by enriching the operation database item and adding the necessary response headers.

func (*Frontend) Healthz

func (f *Frontend) Healthz(writer http.ResponseWriter, request *http.Request)

func (*Frontend) Join

func (f *Frontend) Join()

func (*Frontend) MarshalResource

func (f *Frontend) MarshalResource(ctx context.Context, resourceID *azcorearm.ResourceID, versionedInterface api.Version) ([]byte, *arm.CloudError)

func (*Frontend) NotFound

func (f *Frontend) NotFound(writer http.ResponseWriter, request *http.Request)

func (*Frontend) OperationIsVisible

func (f *Frontend) OperationIsVisible(request *http.Request, doc *database.OperationDocument) bool

OperationIsVisible returns true if the request is being called from the same tenant and subscription that the operation originated in.

func (*Frontend) OperationResult

func (f *Frontend) OperationResult(writer http.ResponseWriter, request *http.Request)

func (*Frontend) OperationStatus

func (f *Frontend) OperationStatus(writer http.ResponseWriter, request *http.Request)

func (*Frontend) Run

func (f *Frontend) Run(ctx context.Context, stop <-chan struct{})

type LoggingReadCloser

type LoggingReadCloser struct {
	io.ReadCloser
	// contains filtered or unexported fields
}

func (*LoggingReadCloser) Read

func (rc *LoggingReadCloser) Read(b []byte) (int, error)

type LoggingResponseWriter

type LoggingResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

func (*LoggingResponseWriter) Write

func (w *LoggingResponseWriter) Write(b []byte) (int, error)

func (*LoggingResponseWriter) WriteHeader

func (w *LoggingResponseWriter) WriteHeader(statusCode int)

type MetricsMiddleware

type MetricsMiddleware struct {
	Emitter
	// contains filtered or unexported fields
}

func (MetricsMiddleware) Metrics

func (mm MetricsMiddleware) Metrics() MiddlewareFunc

Metrics middleware to capture response time and status code

type Middleware

type Middleware struct {
	// contains filtered or unexported fields
}

Middleware is a list of middleware functions to execute before invoking an http.Handler.

func NewMiddleware

func NewMiddleware(functions ...MiddlewareFunc) *Middleware

NewMiddleware allocates and returns a new Middleware.

func (*Middleware) Handler

func (m *Middleware) Handler(handler http.Handler) http.Handler

Handler returns an http.Handler that invokes the list of middleware functions before invoking the given HTTP handler. Pass the returned http.Handler to http.ServeMux.Handle to add middleware functions that execute after pattern-based multiplexing occurs and values for path wildcards are available via http.Request.PathValue.

func (*Middleware) HandlerFunc

func (m *Middleware) HandlerFunc(handler func(http.ResponseWriter, *http.Request)) http.Handler

HandlerFunc returns an http.Handler that invokes the list of middleware functions before invoking the given HTTP handler function. Pass the returned http.Handler to http.ServeMux.Handle to add middleware functions that execute after pattern-based multiplexing occurs and values for path wildcards are available via http.Request.PathValue.

type MiddlewareFunc

type MiddlewareFunc func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

MiddlewareFunc specifies the call signature for middleware functions. At some point during normal execution, the middleware function must call the "next" handler function to invoke the next layer of request handling.

type MiddlewareMux

type MiddlewareMux struct {
	http.ServeMux
	// contains filtered or unexported fields
}

MiddlewareMux is an http.ServeMux with middleware functions that execute before pattern-based multiplexing occurs.

func NewMiddlewareMux

func NewMiddlewareMux(functions ...MiddlewareFunc) *MiddlewareMux

NewMiddlewareMux allocates and returns a new MiddlewareMux.

func (*MiddlewareMux) ServeHTTP

func (mux *MiddlewareMux) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP dispatches the request to each middleware function, and then to the handler whose pattern most closely matches the request URL.

type PrometheusEmitter

type PrometheusEmitter struct {
	// contains filtered or unexported fields
}

func NewPrometheusEmitter

func NewPrometheusEmitter(r prometheus.Registerer) *PrometheusEmitter

func (*PrometheusEmitter) AddCounter

func (pe *PrometheusEmitter) AddCounter(name string, value float64, labels map[string]string)

func (*PrometheusEmitter) EmitGauge

func (pe *PrometheusEmitter) EmitGauge(name string, value float64, labels map[string]string)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL