{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://www.getambassador.io/schemas/emissary/mapping.json", "title": "Emissary-Ingress Mapping", "description": "Schema for the Emissary-Ingress Mapping custom resource definition. A Mapping connects an inbound URL prefix (and optional hostname, method, or header conditions) to a backend Kubernetes service, with support for rewrites, retries, timeouts, CORS, traffic weighting, and circuit breaking.", "type": "object", "required": ["apiVersion", "kind", "metadata", "spec"], "properties": { "apiVersion": { "type": "string", "description": "API version of the Mapping resource.", "const": "getambassador.io/v3alpha1" }, "kind": { "type": "string", "description": "Resource kind.", "const": "Mapping" }, "metadata": { "$ref": "#/$defs/ObjectMeta" }, "spec": { "$ref": "#/$defs/MappingSpec" }, "status": { "$ref": "#/$defs/MappingStatus" } }, "$defs": { "MappingSpec": { "type": "object", "description": "Specification of the Mapping defining routing behavior, target service, and traffic policies.", "required": ["prefix", "service"], "properties": { "prefix": { "type": "string", "description": "URL path prefix that incoming requests must start with for this Mapping to apply.", "examples": ["/api/v1/", "/static/", "/"] }, "service": { "type": "string", "description": "Name of the Kubernetes service to forward matching requests to. Format is 'service-name' or 'service-name:port'.", "examples": ["my-service", "my-service:8080", "my-service.my-namespace:8080"] }, "hostname": { "type": "string", "description": "Hostname or glob pattern that incoming requests must match in addition to the prefix. Supports wildcards such as '*.example.com'.", "examples": ["api.example.com", "*.example.com"] }, "host": { "type": "string", "description": "Deprecated. Use hostname instead. The Host header value incoming requests must present." }, "method": { "type": "string", "description": "HTTP method that requests must use to match this Mapping.", "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] }, "headers": { "type": "object", "description": "HTTP request headers that must be present with exact values for this Mapping to match. Key is header name, value is the required value.", "additionalProperties": { "type": "string", "description": "Required header value." } }, "regex_headers": { "type": "object", "description": "HTTP request headers that must match the specified regular expression patterns. Key is header name, value is the regex pattern.", "additionalProperties": { "type": "string", "description": "Regular expression the header value must match." } }, "rewrite": { "type": "string", "description": "URL prefix to substitute for the matched prefix before forwarding to the upstream service. Set to empty string to strip the prefix entirely.", "examples": ["/", "", "/upstream/path/"] }, "timeout_ms": { "type": "integer", "description": "Overall timeout in milliseconds for requests on this Mapping. Defaults to 3000 ms.", "minimum": 0, "examples": [3000, 30000, 60000] }, "connect_timeout_ms": { "type": "integer", "description": "Timeout in milliseconds for establishing a TCP connection to the upstream service. Defaults to 3000 ms.", "minimum": 0 }, "idle_timeout_ms": { "type": "integer", "description": "Timeout in milliseconds for idle upstream connections. Once a connection is idle for this duration it will be closed.", "minimum": 0 }, "retries": { "$ref": "#/$defs/RetryPolicy" }, "cors": { "$ref": "#/$defs/CORSPolicy" }, "weight": { "type": "integer", "description": "Relative traffic weight (0-100) for distributing requests among multiple Mappings that match the same prefix. Used to implement canary and A/B deployments.", "minimum": 0, "maximum": 100 }, "shadow": { "type": "boolean", "description": "If true, traffic is mirrored to this Mapping's service but responses are discarded. Used for dark launch testing and traffic comparison." }, "tls": { "type": "string", "description": "Name of a TLSContext resource to use when originating TLS connections to the upstream service." }, "load_balancer": { "$ref": "#/$defs/LoadBalancer" }, "circuit_breakers": { "type": "array", "description": "Circuit breaker settings to prevent cascading failures when the upstream service is under stress.", "items": { "$ref": "#/$defs/CircuitBreaker" } }, "add_request_headers": { "type": "object", "description": "HTTP headers to add to all forwarded requests. Key is header name, value is the header value to set.", "additionalProperties": { "type": "string", "description": "Header value to set." } }, "remove_request_headers": { "type": "array", "description": "Names of HTTP request headers to remove before forwarding to the upstream service.", "items": { "type": "string", "description": "HTTP header name." } }, "add_response_headers": { "type": "object", "description": "HTTP headers to add to all responses returned to clients. Key is header name, value is the header value to set.", "additionalProperties": { "type": "string", "description": "Header value to set." } }, "grpc": { "type": "boolean", "description": "If true, configures routing for a gRPC upstream service, enabling HTTP/2 and gRPC-specific protocol handling." }, "prefix_regex": { "type": "boolean", "description": "If true, the prefix field is treated as a regular expression rather than a literal path prefix." }, "bypass_auth": { "type": "boolean", "description": "If true, bypass the external AuthService for requests matching this Mapping." }, "host_rewrite": { "type": "string", "description": "Value to rewrite the Host header to before forwarding requests to the upstream service." }, "auto_host_rewrite": { "type": "boolean", "description": "If true, automatically rewrite the Host header to the upstream service's hostname." }, "case_sensitive": { "type": "boolean", "description": "If true (default), URL prefix matching is case-sensitive.", "default": true } } }, "MappingStatus": { "type": "object", "description": "Observed status of the Mapping as reported by Emissary-Ingress.", "properties": { "state": { "type": "string", "description": "High-level state of the Mapping configuration.", "enum": ["Ok", "Warning", "Error"] }, "reason": { "type": "string", "description": "Human-readable explanation of the current state, especially when state is Warning or Error." }, "conditions": { "type": "array", "description": "Detailed conditions describing the Mapping's configuration state.", "items": { "$ref": "#/$defs/Condition" } } } }, "RetryPolicy": { "type": "object", "description": "Configuration for retrying failed upstream requests for this Mapping.", "properties": { "retry_on": { "type": "string", "description": "Condition under which to retry. Supports Envoy retry policy values including '5xx', 'connect-failure', 'retriable-4xx', 'reset', 'retriable-status-codes'.", "examples": ["5xx", "connect-failure", "5xx,connect-failure"] }, "num_retries": { "type": "integer", "description": "Maximum number of retry attempts before returning an error response to the client.", "minimum": 0 }, "per_try_timeout": { "type": "string", "description": "Maximum duration for each individual retry attempt as a duration string.", "examples": ["2s", "500ms", "1m"] } } }, "CORSPolicy": { "type": "object", "description": "Cross-Origin Resource Sharing (CORS) policy to apply to requests matching this Mapping.", "properties": { "origins": { "type": "string", "description": "Comma-separated list of allowed origins, or '*' to allow requests from any origin.", "examples": ["https://app.example.com", "*", "https://a.example.com,https://b.example.com"] }, "methods": { "type": "string", "description": "Comma-separated list of HTTP methods allowed in cross-origin requests.", "examples": ["GET, POST, PUT", "GET, POST, DELETE, OPTIONS"] }, "headers": { "type": "string", "description": "Comma-separated list of request headers clients are allowed to include in cross-origin requests.", "examples": ["Content-Type, Authorization", "Accept, Content-Type, X-Custom-Header"] }, "credentials": { "type": "boolean", "description": "Whether to allow credentials (cookies, HTTP authentication) in CORS requests." }, "exposed_headers": { "type": "string", "description": "Comma-separated list of response headers that the browser is permitted to access." }, "max_age": { "type": "string", "description": "Duration in seconds to cache CORS preflight responses.", "examples": ["600", "3600"] } } }, "LoadBalancer": { "type": "object", "description": "Load balancing configuration for distributing requests across upstream service instances.", "properties": { "policy": { "type": "string", "description": "Load balancing algorithm to apply when selecting upstream instances.", "enum": ["round_robin", "ring_hash", "maglev", "least_request"], "default": "round_robin" }, "cookie": { "type": "object", "description": "Cookie-based session affinity configuration, used with ring_hash or maglev policies.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the cookie used for session affinity." }, "path": { "type": "string", "description": "Cookie Path attribute value." }, "ttl": { "type": "string", "description": "Time-to-live for the session affinity cookie as a duration string.", "examples": ["3600s", "24h"] } } }, "header": { "type": "string", "description": "HTTP request header name used as the hash key for ring_hash or maglev consistent hashing." }, "source_ip": { "type": "boolean", "description": "If true, use the client source IP address as the consistent hash key." } } }, "CircuitBreaker": { "type": "object", "description": "Circuit breaker thresholds to prevent resource exhaustion and cascading failures.", "properties": { "priority": { "type": "string", "description": "Request priority level these circuit breaker limits apply to.", "enum": ["default", "high"] }, "max_connections": { "type": "integer", "description": "Maximum number of concurrent TCP connections to the upstream cluster before circuit breaking.", "minimum": 0 }, "max_pending_requests": { "type": "integer", "description": "Maximum number of requests that can be queued waiting for a connection.", "minimum": 0 }, "max_requests": { "type": "integer", "description": "Maximum number of parallel outstanding requests to the upstream cluster.", "minimum": 0 }, "max_retries": { "type": "integer", "description": "Maximum number of parallel retry attempts to the upstream cluster.", "minimum": 0 } } }, "Condition": { "type": "object", "description": "A Kubernetes-style condition representing a point-in-time status observation.", "required": ["type", "status"], "properties": { "type": { "type": "string", "description": "Type identifier for the condition." }, "status": { "type": "string", "description": "Status of the condition.", "enum": ["True", "False", "Unknown"] }, "lastTransitionTime": { "type": "string", "format": "date-time", "description": "Timestamp when this condition last transitioned." }, "reason": { "type": "string", "description": "Short, machine-readable reason string for the condition.", "maxLength": 256 }, "message": { "type": "string", "description": "Human-readable message providing additional details about the condition.", "maxLength": 32768 } } }, "ObjectMeta": { "type": "object", "description": "Standard Kubernetes object metadata.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the resource, unique within the namespace.", "maxLength": 253, "pattern": "^[a-z0-9][a-z0-9.-]*[a-z0-9]$" }, "namespace": { "type": "string", "description": "Namespace the resource belongs to.", "maxLength": 63 }, "labels": { "type": "object", "description": "Labels for organizing and selecting the resource.", "additionalProperties": { "type": "string" } }, "annotations": { "type": "object", "description": "Non-identifying metadata attached to the resource.", "additionalProperties": { "type": "string" } } } } }, "examples": [ { "apiVersion": "getambassador.io/v3alpha1", "kind": "Mapping", "metadata": { "name": "api-mapping", "namespace": "default" }, "spec": { "hostname": "api.example.com", "prefix": "/api/v1/", "service": "api-service:8080", "timeout_ms": 10000, "retries": { "retry_on": "5xx,connect-failure", "num_retries": 3, "per_try_timeout": "2s" }, "cors": { "origins": "https://app.example.com", "methods": "GET, POST, PUT, DELETE", "headers": "Content-Type, Authorization" } } } ] }