frontend

package
v0.0.0-...-54aa2bd Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2026 License: Apache-2.0 Imports: 56 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.
	PathSegmentDeploymentName    = "deploymentname"
	PathSegmentLocation          = "location"
	PathSegmentNodePoolName      = "nodepoolname"
	PathSegmentExternalAuthName  = "externalauthname"
	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 (
	WildcardDeploymentName    = "{" + PathSegmentDeploymentName + "}"
	WildcardLocation          = "{" + PathSegmentLocation + "}"
	WildcardNodePoolName      = "{" + PathSegmentNodePoolName + "}"
	WildcardExternalAuthName  = "{" + PathSegmentExternalAuthName + "}"
	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
	PatternVersions          = api.VersionResourceTypeName + "/" + WildcardResourceName
	PatternExternalAuth      = api.ExternalAuthResourceTypeName + "/" + WildcardExternalAuthName
	PatternDeployments       = "deployments/" + WildcardDeploymentName
	PatternResourceGroups    = "resourcegroups/" + WildcardResourceGroupName
	PatternOperationResults  = api.OperationResultResourceTypeName + "/" + WildcardOperationID
	PatternOperationStatuses = api.OperationStatusResourceTypeName + "/" + WildcardOperationID

	ActionRequestAdminCredential = "requestadmincredential"
	ActionRevokeCredentials      = "revokecredentials"
)

Variables

This section is empty.

Functions

func AddAsyncOperationHeader

func AddAsyncOperationHeader(writer http.ResponseWriter, request *http.Request, operationID *azcorearm.ResourceID)

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

func AddLocationHeader

func AddLocationHeader(writer http.ResponseWriter, request *http.Request, operationID *azcorearm.ResourceID)

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

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 ContextWithOriginalPath

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

func ContextWithPattern

func ContextWithPattern(ctx context.Context, pattern *string) 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 CorrelationDataFromContext

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

func MiddlewareBody

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

MiddlewareBody ensures that the request's body doesn't exceed the maximum size of 4MB.

func MiddlewareCorrelationData

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

MiddlewareCorrelationData reads the correlation data from the incoming request, extends the contextual logger with correlation attributes and adds the necessary X-ms-* headers to the HTTP response.

func MiddlewareLogging

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

MiddlewareLogging logs the HTTP request and response.

func MiddlewareLoggingPostMux

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

MiddlewareLoggingPostMux extends the contextual logger with additional attributes after the request has been matched by the ServeMux.

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 MiddlewareReferer

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

MiddlewareReferer ensures a Referer header is present in the request. This header is always added by ARM but is often forgotten in testing environments. If missing, derive a Referer from the http.Request.

Referer headers are used in a few places: - The "nextLink" field in a paginated response body - "Location" and "Azure-AsyncOperation" response headers

func MiddlewareResourceID

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

This middleware only applies to endpoints whose path form a valid Azure resource ID. It should follow the MiddlewareLowercase function.

func MiddlewareSystemData

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

func MiddlewareTracing

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

MiddlewareTracing starts an OpenTelemetry span wrapping all incoming HTTP requests. Other middlewares or actual request handlers can extend its metadata or create their own associated spans. The middleware expects that the trace provider is initialized and configured in advance.

func MigrateCosmosOrDie

func MigrateCosmosOrDie(ctx context.Context, cosmosClient database.DBClient)

MigrateCosmosOrDie if migration fails, we panic and exit the process. This makes it very detectable.

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 PatternFromContext

func PatternFromContext(ctx context.Context) *string

func RequestIDPropagator

func RequestIDPropagator(next http.RoundTripper) http.RoundTripper

RequestIDPropagator returns an http.RoundTripper interface which reads the request ID from the request's context and propagates it to the Clusters Service API via the "X-Request-ID" header.

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 Frontend

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

func NewFrontend

func NewFrontend(
	logger logr.Logger,
	listener net.Listener,
	metricsListener net.Listener,
	registry *prometheus.Registry,
	dbClient database.DBClient,
	csClient ocm.ClusterServiceClientSpec,
	auditClient audit.Client,
	azureLocation string,
	clusterServiceProvisionShard string,
	clusterServiceNoopProvision bool,
	clusterServiceNoopDeprovision bool,
	exitOnPanic bool,
) *Frontend

func NewTestFrontend

func NewTestFrontend(t *testing.T) *Frontend

func (*Frontend) ArmDeploymentPreflight

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

func (*Frontend) ArmResourceActionRequestAdminCredential

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

func (*Frontend) ArmResourceActionRevokeCredentials

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

func (*Frontend) ArmResourceListClusters

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

func (*Frontend) ArmResourceListExternalAuths

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

func (*Frontend) ArmResourceListNodePools

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

func (*Frontend) ArmResourceListVersion

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

func (*Frontend) ArmSubscriptionGet

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

func (*Frontend) ArmSubscriptionPut

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

func (*Frontend) CancelActiveOperations

func (f *Frontend) CancelActiveOperations(ctx context.Context, transaction database.DBTransaction, opts *database.DBClientListActiveOperationDocsOptions) error

CancelActiveOperations queries for operation documents with a non-terminal status using the filters specified in opts. For every document returned in the query result, CancelActiveOperations adds patch operations to the given DBTransaction to mark the document as canceled.

func (*Frontend) CreateOrUpdateExternalAuth

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

func (*Frontend) CreateOrUpdateHCPCluster

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

CreateOrUpdateHCPCluster handles both PUT and PATCH requests from clients to ARM. The semantics of these verbs are: When no resource by this identifier exists:

  • PUT: create the resource, overlaying client-specified fields on a default resource struct, which only has API-specified non-zero default values
  • PATCH: error

When a resource by this identifier already exists:

  • PUT: replace the resource, overlaying client-specified fields on a default resource struct, which only has API-specified non-zero default values (and NOT taking into account the existing content of the resource in storage)
  • PATCH: update the resource, overlaying client-specified fields onto the existing resource

This means all required properties must be specified in the request body for PUT, whether creating or updating a resource.

See these documents for a description of required semantics from ARM Resource Providers:

PUT: The Put operation creates or replaces a resource. Resource types can be nested and, if so, must follow the Resource API guidelines. ARM does not distinguish between creation and replacement requests. The resource provider should consult its datastore if a distinction is necessary. A Put should always be allowed to overwrite an existing resource. An exception to this rule is when `x-ms-mutability ['create', 'read']` is applied to a property. For such properties, the value submitted during the create operation must be retained. Eg: The location property defined for tracked resources. ref: https://github.com/cloud-and-ai-microsoft/resource-provider-contract/blob/master/v1.0/put-resource.md#put-resource

PATCH A Patch operation updates a resource and it is strongly recommended that service teams implement it. ARM requires RPs to support Patch for updating tags for a tracked resource. ref: https://github.com/cloud-and-ai-microsoft/resource-provider-contract/blob/master/v1.0/patch-resource.md#patch-resource

func (*Frontend) CreateOrUpdateNodePool

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

func (*Frontend) DeleteAllResourcesInSubscription

func (f *Frontend) DeleteAllResourcesInSubscription(ctx context.Context, subscriptionID string) error

func (*Frontend) DeleteCluster

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

DeleteCluster 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) DeleteExternalAuth

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

DeleteExternalAuth 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) DeleteNodePool

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

DeleteNodePool 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) GetExternalAuth

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

func (*Frontend) GetHCPCluster

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

GetHCPCluster implements the GET single resource API contract for HCP Clusters * 200 If the resource exists * 404 If the resource does not exist

func (*Frontend) GetNodePool

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

func (*Frontend) GetOpenshiftVersions

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

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

func (*Frontend) Healthz

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

func (*Frontend) Location

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

func (*Frontend) NotFound

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

func (*Frontend) OperationIsVisible

func (f *Frontend) OperationIsVisible(request *http.Request, operation *api.Operation) 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) error

func (*Frontend) OperationStatus

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

func (*Frontend) Run

func (f *Frontend) Run(ctx context.Context) error

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 {
	// 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 SubscriptionStateGetter

type SubscriptionStateGetter interface {
	GetSubscriptionState(string) string
}

Jump to

Keyboard shortcuts

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