diff --git a/.claude/rules/01-coding-conventions.md b/.claude/rules/01-coding-conventions.md new file mode 100644 index 0000000..82b37b7 --- /dev/null +++ b/.claude/rules/01-coding-conventions.md @@ -0,0 +1,30 @@ +# 编码规范 + +## 命名约定 + +| 类型 | 格式 | 示例 | +|------|------|------| +| 文件 | 蛇形命名 | `agentic_version_create.go` | +| 结构体 | PascalCase | `AgenticVersionCreateRequest` | +| 方法 | CamelCase,动词开头 | `CreateVersion` | +| 常量 | 驼峰或全大写下划线 | `DefaultEnvPre` | + +## 包导入顺序 + +```go +import ( + // 标准库 + "context" + "fmt" + "time" + + // 第三方库 + "github.com/gin-gonic/gin" + "go.uber.org/zap" + "go.mongodb.org/mongo-driver/bson" + + // 项目内部包 + "code.alipay.com/paas-core/kox/pkg/model" + "code.alipay.com/paas-core/kox/pkg/logging" +) +``` diff --git a/.claude/rules/02-testing.md b/.claude/rules/02-testing.md new file mode 100644 index 0000000..4f88cb6 --- /dev/null +++ b/.claude/rules/02-testing.md @@ -0,0 +1,68 @@ +# 测试规范 +- 单元测试覆盖 Reconcile 各分支 +- 使用 envtest 模拟 API Server +- 集成测试验证端到端流程 +- 测试执行命令 `go test -v`,仅执行改动的测试文件 + +## 单元测试模板 + +```go +func TestFunctionName(t *testing.T) { + type args struct { + param string + } + + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "success case", + args: args{param: "value"}, + want: "expected", + wantErr: false, + }, + { + name: "error case", + args: args{param: ""}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Function(tt.args.param) + if (err != nil) != tt.wantErr { + t.Errorf("Function() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("Function() = %v, want %v", got, tt.want) + } + }) + } +} +``` + +## 集成测试模板 + +### 使用 "github.com/onsi/ginkgo" 和 "github.com/onsi/gomega" 框架 + +```go +It("namespace created", func() { + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespaceUT, + }, + } + + Expect(c.Create(context.TODO(), ns)).Should(Succeed()) +}) +``` + +## 测试文件位置 + +- 单元测试文件与源文件同目录 +- 命名:`xxx_test.go` diff --git a/.claude/rules/03-code-review.md b/.claude/rules/03-code-review.md new file mode 100644 index 0000000..da41d03 --- /dev/null +++ b/.claude/rules/03-code-review.md @@ -0,0 +1,18 @@ +# 代码审查清单 + +## 检查项 + +- [ ] 错误处理是否完善? +- [ ] 日志是否包含足够的上下文? +- [ ] 参数校验是否完整? +- [ ] 测试是否覆盖了主要路径? +- [ ] 是否有未使用的导入或变量? + +## 不要做的事 + +- **不要** 忽略 error 检查(使用 `_` 丢弃) + +## 必须做的事 + +- **必须** 提交前执行 `go build -o bin/manager kusionstack.io/rollout/cmd/rollout` +- **必须** 提交前执行 `make lint` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..84cf8dc --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,210 @@ +# CLAUDE.md - Rollout 开发上下文 + +## 快速参考 + +| 主题 | 规则文件 | +|------|------------------------------------------| +| 编码规范 | `.claude/rules/01-coding-conventions.md` | +| 测试规范 | `.claude/rules/02-testing.md` | +| 代码审查 | `.claude/rules/03-code-review.md` | + +--- + +## Claude 开发工作流 (SDD) + +使用 Specification-Driven Development (SDD) 方式与 Claude 协作开发,确保开发过程有序可控。 + +**⚠️ 绝对禁止:在任何阶段未完成时进入下一阶段。Claude 必须等待用户明确确认后才能继续。** + +**推荐技能:** + +```bash +/superpowers:brainstorming # 需求讨论和设计 +/superpowers:writing-plans # 编写设计文档 +/superpowers:using-git-worktrees # 创建隔离工作区 +/superpowers:test-driven-development # TDD开发 +/superpowers:requesting-code-review # 代码审查 +/skill create-dima-issue # 创建 DIMA 工单 +/skill gitpr # 创建 PR +``` + +--- + +### Phase 1: 需求澄清 (Requirement Clarification) + +**触发条件**:用户提出任何需求、想法或问题时 + +**Claude 必须执行:** +1. 使用 `/superpowers:brainstorming` skill 启动头脑风暴 +2. 通过提问充分理解需求,一次只问一个问题 +3. 明确功能目标、验收标准、影响范围 + +**完成标准**: +- [ ] 需求已充分澄清 +- [ ] 验收标准已定义 +- [ ] 用户确认需求理解正确 + +**阶段输出**:需求澄清总结(文字描述即可) + +**用户确认话术**:"需求澄清完毕,请确认我的理解是否正确:[总结]。确认无误后,我将进入 Dima Issue 创建阶段。" + +**⚠️ 禁止**:未完成需求澄清前进入 Dima 创建阶段 + +--- + +### Phase 2: Dima Issue 关联 (Issue Tracking) + +**触发条件**:需求澄清完成且用户确认后 + +**Claude 必须执行:** +1. 询问用户是否已有 Dima Issue +2. 如无,调用 `/skill create-dima-issue` 创建 +3. 记录 Dima ID,后续所有工作必须关联此 ID + +**完成标准**: +- [ ] Dima Issue 已存在或已创建 +- [ ] Dima ID 已记录 + +**阶段输出**:Dima Issue 链接/ID + +**用户确认话术**:"Dima Issue 已关联:[DIMA-XXXX]。确认后,我将进入方案设计阶段。" + +**⚠️ 禁止**:无 Dima Issue 关联时进入设计阶段 + +--- + +### Phase 3: 方案设计 (Design) + +**触发条件**:Dima Issue 关联完成后 + +**Claude 必须执行:** +1. 输出设计文档到 `docs/plans/YYYY-MM-DD-.md`,包含: + - 背景和目标 + - 技术方案(含接口设计、数据模型变更) + - 影响分析 + - 风险和对策 +2. 使用 `/superpowers:writing-plans` skill 辅助生成规范的计划文档 + +**完成标准**: +- [ ] 设计文档已创建并写入文件 +- [ ] 技术方案已详细描述 +- [ ] 用户已审阅设计文档 + +**阶段输出**:`docs/plans/YYYY-MM-DD-.md` + +**用户确认话术**:"设计方案已输出到 [文件路径],请审阅。确认无误后,我将进入开发阶段。" + +**⚠️ 禁止**:设计文档未经用户确认前编写任何业务代码 + +--- + +### Phase 4: 开发实现 (Implementation) + +**触发条件**:设计方案经用户确认后 + +**4.1 环境准备** +- 询问用户是否需要创建隔离工作区以及独立分支 +- 若需要,使用 `/superpowers:using-git-worktrees` 创建隔离工作区 +- 切换到独立分支 + +**4.2 TDD 开发流程** + +**Step 1: Red - 编写失败的测试** +- 先编写测试用例(覆盖正常路径、边界条件、错误处理) +- 运行测试确保失败(验证测试有效性) +- **检查点**:测试文件已创建,测试失败符合预期 + +**Step 2: Green - 最小化实现** +- 编写刚好让测试通过的最小代码 +- 运行测试确保通过 +- **检查点**:所有测试通过 + +**Step 3: Refactor - 重构优化** +- 优化代码质量 +- 确保测试仍然通过 +- 运行 `make lint` 确保规范 +- 运行 `go build -o bin/manager kusionstack.io/rollout/cmd/rollout` 确保编译通过 +- 运行 `go test` 确保测试通过 +- **检查点**:确保编译测试全部通过 + +**完成标准**: +- [ ] 单元测试已编写并通过 +- [ ] 实现代码已完成 +- [ ] 编译测试全部通过 + +**阶段输出**:实现代码 + 测试代码 + +--- + +### Phase 5: 代码审查与提交 (Review & Commit) + +**触发条件**:开发实现完成后 + +**Claude 必须执行:** +1. 使用 `/superpowers:requesting-code-review` 进行自我审查 +2. 使用 `/skill gitpr` 创建 PR +3. PR 描述中必须包含:`Relates to: DIMA-XXXX` + +**PR 格式要求:** +``` +[DIMA-XXXX] (): + +- 变更点 1 +- 变更点 2 + +Relates to: DIMA-XXXX +``` + +**完成标准**: +- [ ] 代码审查完成 +- [ ] PR 已创建并关联 Dima Issue + +**阶段输出**:PR 链接 + +--- + +### 阶段转换检查清单 + +**每个阶段转换前,Claude 必须:** + +1. **明确询问用户**:"[当前阶段] 已完成,是否进入 [下一阶段]?" +2. **等待用户明确回复** "是/确认/可以" 后才能继续 +3. **不允许假设用户同意** + +**阶段依赖关系:** +``` +需求澄清 → Dima关联 → 方案设计 → 开发实现 → 代码审查 + ↑ ↑ ↑ ↑ ↑ +必须等待 必须等待 必须等待 必须等待 必须等待 +用户确认 用户确认 用户确认 用户确认 用户确认 +``` + +--- + +### Rule: 严格禁止的行为 + +| 禁止行为 | 违反后果 | +|---------|---------| +| 跳过用户确认进入下一阶段 | 可能导致方向错误,需回滚重做 | +| Planning 完成前编写业务代码 | 违反 SDD 原则 | +| 无 Dima Issue 关联进行开发 | 无法追溯需求来源 | +| 一次提交超过 500 行代码(不含测试) | 难以 Review,容易引入 Bug | +| 修改与当前功能无关的代码 | 引入不可控变更 | +| 跳过测试直接提交 | 质量无法保证 | +| 假设用户同意而非明确确认 | 可能误解需求 | + +--- + +### 工作流程总结 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 强制用户确认点 │ +├─────────────────────────────────────────────────────────────────┤ +│ 1. 需求澄清 → [等待用户确认: 理解是否正确?] → Dima关联 │ +│ 2. Dima关联 → [等待用户确认: Issue是否创建?] → 方案设计 │ +│ 3. 方案设计 → [等待用户确认: 设计文档是否可接受?] → 开发实现 │ +│ 4. 开发实现 → [TDD循环: Red→Green→Refactor] → 代码审查 │ +│ 5. 代码审查 → [等待用户确认: 是否创建PR?] → 完成 │ +└─────────────────────────────────────────────────────────────────┘ +``` diff --git a/apis/rollout/v1alpha1/validation/rollout.go b/apis/rollout/v1alpha1/validation/rollout.go index 3d19422..09efb19 100644 --- a/apis/rollout/v1alpha1/validation/rollout.go +++ b/apis/rollout/v1alpha1/validation/rollout.go @@ -42,8 +42,44 @@ func ValidateRolloutSpec(spec *rolloutv1alpha1.RolloutSpec, fldPath *field.Path, allErrs = append(allErrs, field.NotSupported(fldPath.Child("triggerPolicy"), spec.TriggerPolicy, []string{string(rolloutv1alpha1.AutoTriggerPolicy), string(rolloutv1alpha1.ManualTriggerPolicy)})) } - if len(spec.StrategyRef) == 0 { - allErrs = append(allErrs, field.Required(fldPath.Child("strategyRef"), "must specify a strategy")) + // Validate strategy mutual exclusion: StrategyRef vs inline strategies (CanaryStrategy and BatchStrategy) + hasStrategyRef := len(spec.StrategyRef) > 0 + hasCanary := spec.CanaryStrategy != nil + hasBatch := spec.BatchStrategy != nil + + // StrategyRef is mutually exclusive with inline strategies + if hasStrategyRef && hasBatch { + allErrs = append(allErrs, field.Invalid( + fldPath, + spec.StrategyRef, + "strategyRef is mutually exclusive with batchStrategy", + )) + } + + if hasCanary && !hasBatch { + allErrs = append(allErrs, field.Invalid( + fldPath, + spec.StrategyRef, + "batchStrategy is required when canaryStrategy is set", + )) + } + + // Must specify at least one strategy + if !hasStrategyRef && !hasBatch { + allErrs = append(allErrs, field.Required( + fldPath.Child("strategyRef"), + "must specify either strategyRef, or batchStrategy", + )) + } + + // Validate CanaryStrategy if present + if hasCanary { + allErrs = append(allErrs, ValidateRolloutRunCanaryStrategy(spec.CanaryStrategy, fldPath.Child("canaryStrategy"))...) + } + + // Validate BatchStrategy if present + if hasBatch { + allErrs = append(allErrs, ValidateRolloutRunBatchStrategy(spec.BatchStrategy, fldPath.Child("batchStrategy"))...) } allErrs = append(allErrs, ValidateWorkloadRef(&spec.WorkloadRef, fldPath.Child("workloadRef"), isSupportedGVK)...) diff --git a/apis/rollout/v1alpha1/validation/rollout_test.go b/apis/rollout/v1alpha1/validation/rollout_test.go index 5e97f46..9cee580 100644 --- a/apis/rollout/v1alpha1/validation/rollout_test.go +++ b/apis/rollout/v1alpha1/validation/rollout_test.go @@ -21,6 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/intstr" rolloutv1alpha1 "kusionstack.io/kube-api/rollout/v1alpha1" ) @@ -121,3 +122,307 @@ func TestValidateRollout(t *testing.T) { }) } } + +// Tests for inline batch strategy validation +func TestValidateRollout_InlineBatchStrategy(t *testing.T) { + tests := []struct { + name string + obj *rolloutv1alpha1.Rollout + isSupportedGVK SupportedGVKFunc + wantErr bool + errMsg string + }{ + { + name: "valid inline batch strategy", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: false, + }, + { + name: "batch strategy with multiple batches", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Breakpoint: true, + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test", + }, + Replicas: intstr.FromString("100%"), + }, + }, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: false, + }, + { + name: "batch strategy with multiple targets in one batch", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", + Name: "test-2", + }, + Replicas: intstr.FromString("30%"), + }, + }, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: false, + }, + { + name: "empty batch strategy - no batches", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{}, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: true, + errMsg: "must specify at least one batch", + }, + { + name: "batch with empty targets", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{}, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: true, + errMsg: "must specify at least one target", + }, + { + name: "target missing name", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: true, + errMsg: "name is required", + }, + { + name: "target with invalid replicas", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test", + }, + Replicas: intstr.FromString("-1"), + }, + }, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ValidateRollout(tt.obj, tt.isSupportedGVK) + hasErr := got.ToAggregate() != nil + if tt.wantErr != hasErr { + t.Errorf("ValidateRollout() error = %v, wantErr %v", got.ToAggregate(), tt.wantErr) + return + } + if tt.wantErr && tt.errMsg != "" { + errStr := got.ToAggregate().Error() + if !containsString(errStr, tt.errMsg) { + t.Errorf("ValidateRollout() error message = %q, should contain %q", errStr, tt.errMsg) + } + } + }) + } +} + +// Tests for StrategyRef and inline strategy mutual exclusion +func TestValidateRollout_StrategyMutualExclusion(t *testing.T) { + tests := []struct { + name string + obj *rolloutv1alpha1.Rollout + isSupportedGVK SupportedGVKFunc + wantErr bool + errMsg string + }{ + { + name: "StrategyRef is mutually exclusive with BatchStrategy", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + StrategyRef: "strategy-a", + WorkloadRef: validWorkloadRef, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + }, + }, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: true, + errMsg: "strategyRef is mutually exclusive with batchStrategy", + }, + { + name: "neither StrategyRef nor BatchStrategy specified", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: validMetadata, + Spec: rolloutv1alpha1.RolloutSpec{ + TriggerPolicy: "Auto", + WorkloadRef: validWorkloadRef, + }, + }, + isSupportedGVK: supportAllGVK, + wantErr: true, + errMsg: "must specify either strategyRef, or batchStrategy", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ValidateRollout(tt.obj, tt.isSupportedGVK) + hasErr := got.ToAggregate() != nil + if tt.wantErr != hasErr { + t.Errorf("ValidateRollout() error = %v, wantErr %v", got.ToAggregate(), tt.wantErr) + return + } + if tt.wantErr && tt.errMsg != "" { + errStr := got.ToAggregate().Error() + if !containsString(errStr, tt.errMsg) { + t.Errorf("ValidateRollout() error message = %q, should contain %q", errStr, tt.errMsg) + } + } + }) + } +} + +// Helper function +func containsString(s, substr string) bool { + return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsStringSub(s, substr)) +} + +func containsStringSub(s, substr string) bool { + for i := 0; i <= len(s)-len(substr); i++ { + if s[i:i+len(substr)] == substr { + return true + } + } + return false +} diff --git a/config/crd/bases/rollout.kusionstack.io_rolloutruns.yaml b/config/crd/bases/rollout.kusionstack.io_rolloutruns.yaml index b580d4e..f6ddbe0 100644 --- a/config/crd/bases/rollout.kusionstack.io_rolloutruns.yaml +++ b/config/crd/bases/rollout.kusionstack.io_rolloutruns.yaml @@ -11,4961 +11,4946 @@ spec: listKind: RolloutRunList plural: rolloutruns shortNames: - - ror + - ror singular: rolloutrun scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .metadata.ownerReferences[0].name - name: OWNER - type: string - - jsonPath: .status.phase - name: Phase - type: string - - jsonPath: .status.canaryStatus.state - name: Canary State - type: string - - jsonPath: .status.batchStatus.currentBatchIndex - name: Batch Index - type: string - - jsonPath: .status.batchStatus.currentBatchState - name: Batch State - type: string - - jsonPath: .status.error.code - name: Error - type: string - - format: date-time - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - properties: - batch: - description: Batch Strategy - properties: - batches: - description: Batches define the order of phases to execute release in batch release - items: - properties: - breakpoint: - description: If set to true, the rollout will be paused before the step starts. - type: boolean + - additionalPrinterColumns: + - jsonPath: .metadata.ownerReferences[0].name + name: OWNER + type: string + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .status.canaryStatus.state + name: Canary State + type: string + - jsonPath: .status.batchStatus.currentBatchIndex + name: Batch Index + type: string + - jsonPath: .status.batchStatus.currentBatchState + name: Batch State + type: string + - jsonPath: .status.error.code + name: Error + type: string + - format: date-time + jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + batch: + description: Batch Strategy + properties: + batches: + description: Batches define the order of phases to execute release in batch release + items: properties: - additionalProperties: - type: string - description: Properties contains additional information for step - type: object - targets: - description: desired target replicas - items: - properties: - cluster: - description: Cluster indicates the name of cluster - type: string - name: - description: Name is the resource name - type: string - replicaSlidingWindow: - anyOf: - - type: integer - - type: string - description: |- - ReplicaSlidingWindow used to control the number of pods that are allowed to be upgraded in - a sliding window for progressive rollout smoothly. - x-kubernetes-int-or-string: true - replicas: - anyOf: - - type: integer - - type: string - description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded - x-kubernetes-int-or-string: true - required: - - name - - replicas - type: object - type: array - traffic: - description: traffic strategy + breakpoint: + description: If set to true, the rollout will be paused before the step starts. + type: boolean properties: - http: + additionalProperties: + type: string + description: Properties contains additional information for step + type: object + targets: + description: desired target replicas + items: properties: - filters: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + replicaSlidingWindow: + anyOf: + - type: integer + - type: string description: |- - Filters define the filters that are applied to requests that match - this rule. - - - The effects of ordering of multiple behaviors are currently unspecified. - This can change in the future based on feedback during the alpha stage. - - - Conformance-levels at this level are defined based on the type of filter: - - - - ALL core filters MUST be supported by all implementations. - - Implementers are encouraged to support extended filters. - - Implementation-specific custom filters have no API guarantees across - implementations. - - - Specifying the same filter multiple times is not supported unless explicitly - indicated in the filter. - - - All filters are expected to be compatible with each other except for the - URLRewrite and RequestRedirect filters, which may not be combined. If an - implementation can not support other combinations of filters, they must clearly - document that limitation. In cases where incompatible or unsupported - filters are specified and cause the `Accepted` condition to be set to status - `False`, implementations may use the `IncompatibleFilters` reason to specify - this configuration error. - - - Support: Core - items: + ReplicaSlidingWindow used to control the number of pods that are allowed to be upgraded in + a sliding window for progressive rollout smoothly. + x-kubernetes-int-or-string: true + replicas: + anyOf: + - type: integer + - type: string + description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded + x-kubernetes-int-or-string: true + required: + - name + - replicas + type: object + type: array + traffic: + description: traffic strategy + properties: + http: + properties: + filters: description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. - properties: - extensionRef: - description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - - This filter can be used multiple times within the same rule. - - - Support: Implementation-specific - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - - Support: Core - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource properties: - name: + group: + default: "" description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 + description: Name is the name of the referent. + maxLength: 253 minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer required: - - name - - value + - name type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - requestMirror: - description: |- - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - - Support: Extended - - - - properties: - backendRef: + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: description: |- - BackendRef references a resource where mirrored requests are sent. - - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - - Support: Extended for Kubernetes Service - - - Support: Implementation-specific for any other resource + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. properties: - group: - default: "" + name: description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - kind: - default: Service + type: + default: Exact description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - - Defaults to "Service" when not specified. - - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - - Support: Core (Services with a type other than ExternalName) - - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: name: - description: Name is the name of the referent. - maxLength: 253 + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - namespace: + type: + default: Exact description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - Support: Core - maxLength: 63 + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: - - name - type: object - fraction: - description: |- - Fraction represents the fraction of requests that should be - mirrored to BackendRef. - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - properties: - denominator: - default: 100 - format: int32 - minimum: 1 - type: integer - numerator: - format: int32 - minimum: 0 - type: integer required: - - numerator + - name + - value type: object - percent: - description: |- - Percent represents the percentage of requests that should be - mirrored to BackendRef. Its minimum value is 0 (indicating 0% of - requests) and its maximum value is 100 (indicating 100% of requests). - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - format: int32 - maximum: 100 - minimum: 0 - type: integer - required: - - backendRef - type: object - requestRedirect: + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + stableTraffic: + description: StableTraffic indicate the base traffic rule + properties: + filters: description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + Support: Core - properties: - hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 - type: string - type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch - type: string - required: - - type - type: object - port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - - If no port is specified, the redirect port MUST be derived using the - following rules: - - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Extended - enum: - - http - - https - type: string - statusCode: - default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Core - enum: - - 301 - - 302 - type: integer - type: object - responseHeaderModifier: - description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - - Support: Extended - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific properties: - name: + group: description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 + name: + description: Name is the name of the referent. + maxLength: 253 minLength: 1 type: string required: - - name - - value + - group + - kind + - name type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core properties: - name: + add: description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string - required: - - name - - value + path: + description: |- + Path defines a path rewrite. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - type: - description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - RequestHeaderModifier - - ResponseHeaderModifier - - RequestMirror - - RequestRedirect - - URLRewrite - - ExtensionRef - type: string - urlRewrite: + required: + - type + type: object + maxItems: 16 + type: array + matches: description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - - Support: Extended - properties: - hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - - Support: Extended - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines a path rewrite. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 - type: string - type: + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch - type: string - required: - - type - type: object - type: object - required: - - type - type: object - maxItems: 16 - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming - HTTP requests. Each match is independent, i.e. this rule will be matched - if **any** one of the matches is satisfied. - - - For example, take the following matches configuration: - - - ``` - matches: - - path: - value: "/foo" - headers: - - name: "version" - value: "v2" - - path: - value: "/v2/foo" - ``` - - - For a request to match against this rule, a request must satisfy - EITHER of the two conditions: - - - - path prefixed with `/foo` AND contains the header `version: v2` - - path prefix of `/v2/foo` - - - See the documentation for HTTPRouteMatch on how to specify multiple - match conditions that should be ANDed together. - - - If no matches are specified, the default is a prefix - path match on "/", which has the effect of matching every - HTTP request. - - - Proxy or Load Balancer routing configuration generated from HTTPRoutes - MUST prioritize matches based on the following criteria, continuing on - ties. Across all rules specified on applicable Routes, precedence must be - given to the match having: - - - * "Exact" path match. - * "Prefix" path match with largest number of characters. - * Method match. - * Largest number of header matches. - * Largest number of query param matches. - - - Note: The precedence of RegularExpression path matches are implementation-specific. - - - If ties still exist across multiple Routes, matching precedence MUST be - determined in order of the following criteria, continuing on ties: - - - * The oldest Route based on creation timestamp. - * The Route appearing first in alphabetical order by - "{namespace}/{name}". - - - If ties still exist within an HTTPRoute, matching precedence MUST be granted - to the FIRST matching rule (in list order) with a match meeting the above - criteria. - - - When no rules matching a request have been successfully attached to the - parent a request is coming from, a HTTP 404 status code MUST be returned. - items: + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + weight: + description: Weight indicate how many percentage of traffic the canary pods should receive + format: int32 + maximum: 100 + minimum: 0 + type: integer + type: object + type: object + required: + - targets + type: object + type: array + toleration: + description: Toleration is the toleration policy of the canary strategy + properties: + initialDelaySeconds: + description: Number of seconds after the toleration check has started before the task are initiated. + format: int32 + type: integer + taskFailureThreshold: + anyOf: + - type: integer + - type: string + description: |- + FailureThreshold indicates how many failed pods can be tolerated before marking the rollout task as success + If not set, the default value is 0, which means no failed pods can be tolerated + This is a task level threshold. + x-kubernetes-int-or-string: true + workloadTotalFailureThreshold: + anyOf: + - type: integer + - type: string + description: |- + WorkloadFailureThreshold indicates how many failed pods can be tolerated in all upgraded pods of one workload. + The default value is 0, which means no failed pods can be tolerated. + This is a workload level threshold. + x-kubernetes-int-or-string: true + type: object + type: object + canary: + description: Canary defines the canary strategy + properties: + podTemplateMetadataPatch: + description: PodTemplateMetadataPatch defines a patch for workload podTemplate metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations are additional metadata that can be included. + type: object + labels: + additionalProperties: + type: string + description: Labels are additional metadata that can be included. + type: object + type: object + properties: + additionalProperties: + type: string + description: Properties contains additional information for step + type: object + targets: + description: desired target replicas + items: + properties: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + replicaSlidingWindow: + anyOf: + - type: integer + - type: string + description: |- + ReplicaSlidingWindow used to control the number of pods that are allowed to be upgraded in + a sliding window for progressive rollout smoothly. + x-kubernetes-int-or-string: true + replicas: + anyOf: + - type: integer + - type: string + description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded + x-kubernetes-int-or-string: true + required: + - name + - replicas + type: object + type: array + traffic: + description: traffic strategy + properties: + http: + properties: + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific properties: - headers: + group: description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - - name - - value + - name + - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - - name + - name x-kubernetes-list-type: map - path: - description: Path specifies a HTTP request path matcher. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match against. - maxLength: 1024 - type: string - type: object - queryParams: + remove: description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string value: - description: Value is the value of HTTP query param to be matched. - maxLength: 1024 + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 minLength: 1 type: string required: - - name - - value + - name + - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - - name + - name x-kubernetes-list-type: map type: object - maxItems: 8 - type: array - stableTraffic: - description: StableTraffic indicate the base traffic rule - properties: - filters: - description: |- - Filters define the filters that are applied to requests that match - this rule. - - - The effects of ordering of multiple behaviors are currently unspecified. - This can change in the future based on feedback during the alpha stage. - - - Conformance-levels at this level are defined based on the type of filter: - - - - ALL core filters MUST be supported by all implementations. - - Implementers are encouraged to support extended filters. - - Implementation-specific custom filters have no API guarantees across - implementations. - - - Specifying the same filter multiple times is not supported unless explicitly - indicated in the filter. - - - All filters are expected to be compatible with each other except for the - URLRewrite and RequestRedirect filters, which may not be combined. If an - implementation can not support other combinations of filters, they must clearly - document that limitation. In cases where incompatible or unsupported - filters are specified and cause the `Accepted` condition to be set to status - `False`, implementations may use the `IncompatibleFilters` reason to specify - this configuration error. - - - Support: Core - items: + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource properties: - extensionRef: + group: + default: "" description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - - This filter can be used multiple times within the same rule. - - - Support: Implementation-specific - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - - Support: Core - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - requestMirror: - description: |- - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - - Support: Extended - - - - properties: - backendRef: - description: |- - BackendRef references a resource where mirrored requests are sent. - - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - - Support: Extended for Kubernetes Service - - - Support: Implementation-specific for any other resource - properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - - Defaults to "Service" when not specified. - - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - - Support: Core (Services with a type other than ExternalName) - - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: - - name - type: object - fraction: - description: |- - Fraction represents the fraction of requests that should be - mirrored to BackendRef. - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - properties: - denominator: - default: 100 - format: int32 - minimum: 1 - type: integer - numerator: - format: int32 - minimum: 0 - type: integer - required: - - numerator - type: object - percent: - description: |- - Percent represents the percentage of requests that should be - mirrored to BackendRef. Its minimum value is 0 (indicating 0% of - requests) and its maximum value is 100 (indicating 100% of requests). - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - format: int32 - maximum: 100 - minimum: 0 - type: integer - required: - - backendRef - type: object - requestRedirect: + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + Support: Core - properties: - hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 - type: string - type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch - type: string - required: - - type - type: object - port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - - If no port is specified, the redirect port MUST be derived using the - following rules: - - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Extended - enum: - - http - - https - type: string - statusCode: - default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Core - enum: - - 301 - - 302 - type: integer - type: object - responseHeaderModifier: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - - Support: Extended - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string type: description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. - - + + Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - - RequestHeaderModifier - - ResponseHeaderModifier - - RequestMirror - - RequestRedirect - - URLRewrite - - ExtensionRef + - ReplaceFullPath + - ReplacePrefixMatch type: string - urlRewrite: - description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - - Support: Extended - properties: - hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - - Support: Extended - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines a path rewrite. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 - type: string - type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch - type: string - required: - - type - type: object - type: object required: - - type + - type type: object - maxItems: 16 - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming - HTTP requests. Each match is independent, i.e. this rule will be matched - if **any** one of the matches is satisfied. - - - For example, take the following matches configuration: - - - ``` - matches: - - path: - value: "/foo" - headers: - - name: "version" - value: "v2" - - path: - value: "/v2/foo" - ``` - - - For a request to match against this rule, a request must satisfy - EITHER of the two conditions: - - - - path prefixed with `/foo` AND contains the header `version: v2` - - path prefix of `/v2/foo` - - - See the documentation for HTTPRouteMatch on how to specify multiple - match conditions that should be ANDed together. - - - If no matches are specified, the default is a prefix - path match on "/", which has the effect of matching every - HTTP request. - - - Proxy or Load Balancer routing configuration generated from HTTPRoutes - MUST prioritize matches based on the following criteria, continuing on - ties. Across all rules specified on applicable Routes, precedence must be - given to the match having: - - - * "Exact" path match. - * "Prefix" path match with largest number of characters. - * Method match. - * Largest number of header matches. - * Largest number of query param matches. - - - Note: The precedence of RegularExpression path matches are implementation-specific. - - - If ties still exist across multiple Routes, matching precedence MUST be - determined in order of the following criteria, continuing on ties: - - - * The oldest Route based on creation timestamp. - * The Route appearing first in alphabetical order by - "{namespace}/{name}". - - - If ties still exist within an HTTPRoute, matching precedence MUST be granted - to the FIRST matching rule (in list order) with a match meeting the above - criteria. - - - When no rules matching a request have been successfully attached to the - parent a request is coming from, a HTTP 404 status code MUST be returned. - items: - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: - name - x-kubernetes-list-type: map - path: - description: Path specifies a HTTP request path matcher. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match against. - maxLength: 1024 - type: string - type: object - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - weight: - description: Weight indicate how many percentage of traffic the canary pods should receive - format: int32 - maximum: 100 - minimum: 0 - type: integer - type: object - type: object - required: - - targets - type: object - type: array - toleration: - description: Toleration is the toleration policy of the canary strategy - properties: - initialDelaySeconds: - description: Number of seconds after the toleration check has started before the task are initiated. - format: int32 - type: integer - taskFailureThreshold: - anyOf: - - type: integer - - type: string - description: |- - FailureThreshold indicates how many failed pods can be tolerated before marking the rollout task as success - If not set, the default value is 0, which means no failed pods can be tolerated - This is a task level threshold. - x-kubernetes-int-or-string: true - workloadTotalFailureThreshold: - anyOf: - - type: integer - - type: string - description: |- - WorkloadFailureThreshold indicates how many failed pods can be tolerated in all upgraded pods of one workload. - The default value is 0, which means no failed pods can be tolerated. - This is a workload level threshold. - x-kubernetes-int-or-string: true - type: object - type: object - canary: - description: Canary defines the canary strategy - properties: - podTemplateMetadataPatch: - description: PodTemplateMetadataPatch defines a patch for workload podTemplate metadata. - properties: - annotations: - additionalProperties: - type: string - description: Annotations are additional metadata that can be included. - type: object - labels: - additionalProperties: - type: string - description: Labels are additional metadata that can be included. - type: object - type: object - properties: - additionalProperties: - type: string - description: Properties contains additional information for step - type: object - targets: - description: desired target replicas - items: - properties: - cluster: - description: Cluster indicates the name of cluster - type: string - name: - description: Name is the resource name - type: string - replicaSlidingWindow: - anyOf: - - type: integer - - type: string - description: |- - ReplicaSlidingWindow used to control the number of pods that are allowed to be upgraded in - a sliding window for progressive rollout smoothly. - x-kubernetes-int-or-string: true - replicas: - anyOf: - - type: integer - - type: string - description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded - x-kubernetes-int-or-string: true - required: - - name - - replicas - type: object - type: array - traffic: - description: traffic strategy - properties: - http: - properties: - filters: - description: |- - Filters define the filters that are applied to requests that match - this rule. - - - The effects of ordering of multiple behaviors are currently unspecified. - This can change in the future based on feedback during the alpha stage. - - - Conformance-levels at this level are defined based on the type of filter: - - - - ALL core filters MUST be supported by all implementations. - - Implementers are encouraged to support extended filters. - - Implementation-specific custom filters have no API guarantees across - implementations. - - - Specifying the same filter multiple times is not supported unless explicitly - indicated in the filter. - - - All filters are expected to be compatible with each other except for the - URLRewrite and RequestRedirect filters, which may not be combined. If an - implementation can not support other combinations of filters, they must clearly - document that limitation. In cases where incompatible or unsupported - filters are specified and cause the `Accepted` condition to be set to status - `False`, implementations may use the `IncompatibleFilters` reason to specify - this configuration error. - - - Support: Core - items: - description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. - properties: - extensionRef: - description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - - This filter can be used multiple times within the same rule. - - - Support: Implementation-specific - properties: - group: - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - - Support: Core - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended properties: - name: + replaceFullPath: description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: + replacePrefixMatch: description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch type: string required: - - name - - value + - type type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - requestMirror: - description: |- - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - - Support: Extended - - - - properties: - backendRef: + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: description: |- - BackendRef references a resource where mirrored requests are sent. - - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - - Support: Extended for Kubernetes Service - - - Support: Implementation-specific for any other resource + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - - Defaults to "Service" when not specified. - - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - - Support: Core (Services with a type other than ExternalName) - - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string name: - description: Name is the name of the referent. - maxLength: 253 + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - namespace: + type: + default: Exact description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - Support: Core - maxLength: 63 + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer required: - - name - type: object - fraction: - description: |- - Fraction represents the fraction of requests that should be - mirrored to BackendRef. - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - properties: - denominator: - default: 100 - format: int32 - minimum: 1 - type: integer - numerator: - format: int32 - minimum: 0 - type: integer - required: - - numerator - type: object - percent: - description: |- - Percent represents the percentage of requests that should be - mirrored to BackendRef. Its minimum value is 0 (indicating 0% of - requests) and its maximum value is 100 (indicating 100% of requests). - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - format: int32 - maximum: 100 - minimum: 0 - type: integer - required: - - backendRef - type: object - requestRedirect: - description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - - Support: Core - properties: - hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 - type: string - type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch - type: string - required: - - type - type: object - port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - - If no port is specified, the redirect port MUST be derived using the - following rules: - - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Extended - enum: - - http - - https - type: string - statusCode: - default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Core - enum: - - 301 - - 302 - type: integer - type: object - responseHeaderModifier: - description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - - Support: Extended - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - name - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - type: - description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - RequestHeaderModifier - - ResponseHeaderModifier - - RequestMirror - - RequestRedirect - - URLRewrite - - ExtensionRef - type: string - urlRewrite: - description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - - Support: Extended - properties: - hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - - Support: Extended - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines a path rewrite. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 - type: string - type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch - type: string - required: - - type type: object - type: object - required: - - type - type: object - maxItems: 16 - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming - HTTP requests. Each match is independent, i.e. this rule will be matched - if **any** one of the matches is satisfied. - - - For example, take the following matches configuration: - - - ``` - matches: - - path: - value: "/foo" - headers: - - name: "version" - value: "v2" - - path: - value: "/v2/foo" - ``` - - - For a request to match against this rule, a request must satisfy - EITHER of the two conditions: - - - - path prefixed with `/foo` AND contains the header `version: v2` - - path prefix of `/v2/foo` - - - See the documentation for HTTPRouteMatch on how to specify multiple - match conditions that should be ANDed together. - - - If no matches are specified, the default is a prefix - path match on "/", which has the effect of matching every - HTTP request. - - - Proxy or Load Balancer routing configuration generated from HTTPRoutes - MUST prioritize matches based on the following criteria, continuing on - ties. Across all rules specified on applicable Routes, precedence must be - given to the match having: - - - * "Exact" path match. - * "Prefix" path match with largest number of characters. - * Method match. - * Largest number of header matches. - * Largest number of query param matches. - - - Note: The precedence of RegularExpression path matches are implementation-specific. - - - If ties still exist across multiple Routes, matching precedence MUST be - determined in order of the following criteria, continuing on ties: - - - * The oldest Route based on creation timestamp. - * The Route appearing first in alphabetical order by - "{namespace}/{name}". - - - If ties still exist within an HTTPRoute, matching precedence MUST be granted - to the FIRST matching rule (in list order) with a match meeting the above - criteria. - - - When no rules matching a request have been successfully attached to the - parent a request is coming from, a HTTP 404 status code MUST be returned. - items: - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - path: - description: Path specifies a HTTP request path matcher. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match against. - maxLength: 1024 - type: string - type: object - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string type: - default: Exact + default: PathPrefix description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. enum: - - Exact - - RegularExpression + - Exact + - PathPrefix + - RegularExpression type: string value: - description: Value is the value of HTTP query param to be matched. + default: / + description: Value of the HTTP path to match against. maxLength: 1024 - minLength: 1 type: string - required: - - name - - value type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - stableTraffic: - description: StableTraffic indicate the base traffic rule - properties: - filters: - description: |- - Filters define the filters that are applied to requests that match - this rule. - - - The effects of ordering of multiple behaviors are currently unspecified. - This can change in the future based on feedback during the alpha stage. - - - Conformance-levels at this level are defined based on the type of filter: - - - - ALL core filters MUST be supported by all implementations. - - Implementers are encouraged to support extended filters. - - Implementation-specific custom filters have no API guarantees across - implementations. - - - Specifying the same filter multiple times is not supported unless explicitly - indicated in the filter. - - - All filters are expected to be compatible with each other except for the - URLRewrite and RequestRedirect filters, which may not be combined. If an - implementation can not support other combinations of filters, they must clearly - document that limitation. In cases where incompatible or unsupported - filters are specified and cause the `Accepted` condition to be set to status - `False`, implementations may use the `IncompatibleFilters` reason to specify - this configuration error. - - - Support: Core - items: - description: |- - HTTPRouteFilter defines processing steps that must be completed during the - request or response lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway implementations. Some - examples include request or response modification, implementing - authentication strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type of the filter. - properties: - extensionRef: + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: description: |- - ExtensionRef is an optional, implementation-specific extension to the - "filter" behavior. For example, resource "myroutefilter" in group - "networking.example.net"). ExtensionRef MUST NOT be used for core and - extended filters. - - - This filter can be used multiple times within the same rule. - - - Support: Implementation-specific + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. properties: - group: + name: description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example "HTTPRoute" or "Service". - maxLength: 63 + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string - name: - description: Name is the name of the referent. - maxLength: 253 + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 minLength: 1 type: string required: - - group - - kind - - name + - name + - value type: object - requestHeaderModifier: - description: |- - RequestHeaderModifier defines a schema for a filter that modifies request - headers. - - - Support: Core - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + stableTraffic: + description: StableTraffic indicate the base traffic rule + properties: + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - requestMirror: - description: |- - RequestMirror defines a schema for a filter that mirrors requests. - Requests are sent to the specified destination, but responses from - that destination are ignored. - - - This filter can be used multiple times within the same rule. Note that - not all implementations will be able to support mirroring to multiple - backends. - - - Support: Extended - - - - properties: - backendRef: - description: |- - BackendRef references a resource where mirrored requests are sent. - - - Mirrored requests must be sent only to a single destination endpoint - within this BackendRef, irrespective of how many endpoints are present - within this BackendRef. - - - If the referent cannot be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure the "ResolvedRefs" - condition on the Route status is set to `status: False` and not configure - this backend in the underlying implementation. - - - If there is a cross-namespace reference to an *existing* object - that is not allowed by a ReferenceGrant, the controller must ensure the - "ResolvedRefs" condition on the Route is set to `status: False`, - with the "RefNotPermitted" reason and not configure this backend in the - underlying implementation. - - - In either error case, the Message of the `ResolvedRefs` Condition - should be used to provide more detail about the problem. - - - Support: Extended for Kubernetes Service - - - Support: Implementation-specific for any other resource - properties: - group: - default: "" - description: |- - Group is the group of the referent. For example, "gateway.networking.k8s.io". - When unspecified or empty string, core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: |- - Kind is the Kubernetes resource kind of the referent. For example - "Service". - - - Defaults to "Service" when not specified. - - - ExternalName services can refer to CNAME DNS records that may live - outside of the cluster and as such are difficult to reason about in - terms of conformance. They also may not be safe to forward to (see - CVE-2021-25740 for more information). Implementations SHOULD NOT - support ExternalName Services. - - - Support: Core (Services with a type other than ExternalName) - - - Support: Implementation-specific (Services with type ExternalName) - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: |- - Namespace is the namespace of the backend. When unspecified, the local - namespace is inferred. - - - Note that when a namespace different than the local namespace is specified, - a ReferenceGrant object is required in the referent namespace to allow that - namespace's owner to accept the reference. See the ReferenceGrant - documentation for details. - - - Support: Core - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: |- - Port specifies the destination port number to use for this resource. - Port is required when the referent is a Kubernetes Service. In this - case, the port number is the service port number, not the target port. - For other resources, destination port might be derived from the referent - resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind - name - type: object - fraction: - description: |- - Fraction represents the fraction of requests that should be - mirrored to BackendRef. - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - properties: - denominator: - default: 100 - format: int32 - minimum: 1 - type: integer - numerator: - format: int32 - minimum: 0 - type: integer - required: - - numerator - type: object - percent: - description: |- - Percent represents the percentage of requests that should be - mirrored to BackendRef. Its minimum value is 0 (indicating 0% of - requests) and its maximum value is 100 (indicating 100% of requests). - - - Only one of Fraction or Percent may be specified. If neither field - is specified, 100% of requests will be mirrored. - - - - format: int32 - maximum: 100 - minimum: 0 - type: integer - required: - - backendRef - type: object - requestRedirect: - description: |- - RequestRedirect defines a schema for a filter that responds to the - request with an HTTP redirection. - - - Support: Core - properties: - hostname: - description: |- - Hostname is the hostname to be used in the value of the `Location` - header in the response. - When empty, the hostname in the `Host` header of the request is used. - - - Support: Core - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: - description: |- - Path defines parameters used to modify the path of the incoming request. - The modified path is then used to construct the `Location` header. When - empty, the request path is used as-is. - - - Support: Extended - properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: - description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: type: string - type: - description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - ReplaceFullPath - - ReplacePrefixMatch + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: type: string - required: - - type - type: object - port: - description: |- - Port is the port to be used in the value of the `Location` - header in the response. - - - If no port is specified, the redirect port MUST be derived using the - following rules: - - - * If redirect scheme is not-empty, the redirect port MUST be the well-known - port associated with the redirect scheme. Specifically "http" to port 80 - and "https" to port 443. If the redirect scheme does not have a - well-known port, the listener port of the Gateway SHOULD be used. - * If redirect scheme is empty, the redirect port MUST be the Gateway - Listener port. - - - Implementations SHOULD NOT add the port number in the 'Location' - header in the following cases: - - - * A Location header that will use HTTP (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 80. - * A Location header that will use HTTPS (whether that is determined via - the Listener protocol or the Scheme field) _and_ use port 443. - - - Support: Extended - format: int32 - maximum: 65535 - minimum: 1 - type: integer - scheme: - description: |- - Scheme is the scheme to be used in the value of the `Location` header in - the response. When empty, the scheme of the request is used. - - - Scheme redirects can affect the port of the redirect, for more information, - refer to the documentation for the port field of this filter. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Extended - enum: - - http - - https - type: string - statusCode: - default: 302 - description: |- - StatusCode is the HTTP status code to be used in response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - - - Support: Core - enum: - - 301 - - 302 - type: integer - type: object - responseHeaderModifier: - description: |- - ResponseHeaderModifier defines a schema for a filter that modifies response - headers. - - - Support: Extended - properties: - add: - description: |- - Add adds the given header(s) (name, value) to the request - before the action. It appends to any existing values associated - with the header name. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - add: - - name: "my-header" - value: "bar,baz" - - - Output: - GET /foo HTTP/1.1 - my-header: foo,bar,baz - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended properties: - name: + replaceFullPath: description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: |- - Remove the given header(s) from the HTTP request before the action. The - value of Remove is a list of HTTP header names. Note that the header - names are case-insensitive (see - https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - - - Input: - GET /foo HTTP/1.1 - my-header1: foo - my-header2: bar - my-header3: baz - - - Config: - remove: ["my-header1", "my-header3"] - - - Output: - GET /foo HTTP/1.1 - my-header2: bar - items: - type: string - maxItems: 16 - type: array - x-kubernetes-list-type: set - set: - description: |- - Set overwrites the request with the given header (name, value) - before the action. - - - Input: - GET /foo HTTP/1.1 - my-header: foo - - - Config: - set: - - name: "my-header" - value: "bar" - - - Output: - GET /foo HTTP/1.1 - my-header: bar - items: - description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. - properties: - name: + replacePrefixMatch: description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, the first entry with - an equivalent name MUST be considered for a match. Subsequent entries - with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch type: string required: - - name - - value + - type type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - type: - description: |- - Type identifies the type of filter to apply. As with other API fields, - types are classified into three conformance levels: - - - - Core: Filter types and their corresponding configuration defined by - "Support: Core" in this package, e.g. "RequestHeaderModifier". All - implementations must support core filters. - - - - Extended: Filter types and their corresponding configuration defined by - "Support: Extended" in this package, e.g. "RequestMirror". Implementers - are encouraged to support extended filters. - - - - Implementation-specific: Filters that are defined and supported by - specific vendors. - In the future, filters showing convergence in behavior across multiple - implementations will be considered for inclusion in extended or core - conformance levels. Filter-specific configuration for such filters - is specified using the ExtensionRef field. `Type` should be set to - "ExtensionRef" for custom filters. - - - Implementers are encouraged to define custom implementation types to - extend the core API with implementation-specific behavior. - - - If a reference to a custom filter type cannot be resolved, the filter - MUST NOT be skipped. Instead, requests that would have been processed by - that filter MUST receive a HTTP error response. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. - enum: - - RequestHeaderModifier - - ResponseHeaderModifier - - RequestMirror - - RequestRedirect - - URLRewrite - - ExtensionRef - type: string - urlRewrite: - description: |- - URLRewrite defines a schema for a filter that modifies a request during forwarding. - - - Support: Extended - properties: - hostname: - description: |- - Hostname is the value to be used to replace the Host header value during - forwarding. - - - Support: Extended - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - path: + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: description: |- - Path defines a path rewrite. - - - Support: Extended + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. properties: - replaceFullPath: - description: |- - ReplaceFullPath specifies the value with which to replace the full path - of a request during a rewrite or redirect. - maxLength: 1024 - type: string - replacePrefixMatch: + name: description: |- - ReplacePrefixMatch specifies the value with which to replace the prefix - match of a request during a rewrite or redirect. For example, a request - to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch - of "/xyz" would be modified to "/xyz/bar". - - - Note that this matches the behavior of the PathPrefix match type. This - matches full path elements. A path element refers to the list of labels - in the path split by the `/` separator. When specified, a trailing `/` is - ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all - match the prefix `/abc`, but the path `/abcd` would not. - - - ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. - Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in - the implementation setting the Accepted Condition for the Route to `status: False`. - - - Request Path | Prefix Match | Replace Prefix | Modified Path - -------------|--------------|----------------|---------- - /foo/bar | /foo | /xyz | /xyz/bar - /foo/bar | /foo | /xyz/ | /xyz/bar - /foo/bar | /foo/ | /xyz | /xyz/bar - /foo/bar | /foo/ | /xyz/ | /xyz/bar - /foo | /foo | /xyz | /xyz - /foo/ | /foo | /xyz | /xyz/ - /foo/bar | /foo | | /bar - /foo/ | /foo | | / - /foo | /foo | | / - /foo/ | /foo | / | / - /foo | /foo | / | / - maxLength: 1024 + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: + default: Exact description: |- - Type defines the type of path modifier. Additional types may be - added in a future release of the API. - - - Note that values may be added to this enum, implementations - must ensure that unknown values will not cause a crash. - - - Unknown values here must result in the implementation setting the - Accepted Condition for the Route to `status: False`, with a - Reason of `UnsupportedValue`. + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. enum: - - ReplaceFullPath - - ReplacePrefixMatch + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 type: string required: - - type + - name + - value type: object - type: object - required: - - type - type: object - maxItems: 16 - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming - HTTP requests. Each match is independent, i.e. this rule will be matched - if **any** one of the matches is satisfied. - - - For example, take the following matches configuration: - - - ``` - matches: - - path: - value: "/foo" - headers: - - name: "version" - value: "v2" - - path: - value: "/v2/foo" - ``` - - - For a request to match against this rule, a request must satisfy - EITHER of the two conditions: - - - - path prefixed with `/foo` AND contains the header `version: v2` - - path prefix of `/v2/foo` - - - See the documentation for HTTPRouteMatch on how to specify multiple - match conditions that should be ANDed together. - - - If no matches are specified, the default is a prefix - path match on "/", which has the effect of matching every - HTTP request. - - - Proxy or Load Balancer routing configuration generated from HTTPRoutes - MUST prioritize matches based on the following criteria, continuing on - ties. Across all rules specified on applicable Routes, precedence must be - given to the match having: - - - * "Exact" path match. - * "Prefix" path match with largest number of characters. - * Method match. - * Largest number of header matches. - * Largest number of query param matches. - - - Note: The precedence of RegularExpression path matches are implementation-specific. - - - If ties still exist across multiple Routes, matching precedence MUST be - determined in order of the following criteria, continuing on ties: - - - * The oldest Route based on creation timestamp. - * The Route appearing first in alphabetical order by - "{namespace}/{name}". - - - If ties still exist within an HTTPRoute, matching precedence MUST be granted - to the FIRST matching rule (in list order) with a match meeting the above - criteria. - - - When no rules matching a request have been successfully attached to the - parent a request is coming from, a HTTP 404 status code MUST be returned. - items: - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - path: - description: Path specifies a HTTP request path matcher. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match against. - maxLength: 1024 - type: string - type: object - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string type: - default: Exact + default: PathPrefix description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. enum: - - Exact - - RegularExpression + - Exact + - PathPrefix + - RegularExpression type: string value: - description: Value is the value of HTTP query param to be matched. + default: / + description: Value of the HTTP path to match against. maxLength: 1024 - minLength: 1 type: string - required: - - name - - value type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - weight: - description: Weight indicate how many percentage of traffic the canary pods should receive + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + weight: + description: Weight indicate how many percentage of traffic the canary pods should receive + format: int32 + maximum: 100 + minimum: 0 + type: integer + type: object + type: object + required: + - targets + type: object + targetType: + description: TargetType defines the GroupVersionKind of target resource + properties: + apiVersion: + description: |- + APIVersion is the group/version for the resource being referenced. + If APIVersion is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIVersion is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + required: + - kind + type: object + trafficTopologyRefs: + description: |- + TrafficTopologyRefs defines the networking traffic relationships between + workloads, backend services, and routes. + items: + type: string + type: array + webhooks: + description: Webhooks defines rollout webhook configuration + items: + properties: + clientConfig: + description: |- + ClientConfig defines how to communicate with the hook. + Required + properties: + caBundle: + description: |- + `caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. + If unspecified, system trust roots' CA on the node. + format: byte + type: string + periodSeconds: + default: 10 + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 10 + description: |- + TimeoutSeconds specifies the timeout for this webhook. After the timeout passes, + the webhook call will be ignored or the API call will fail based on the + failure policy. format: int32 - maximum: 100 - minimum: 0 type: integer + url: + description: |- + `url` gives the location of the webhook, in standard URL form + (`scheme://host:port/path`). Exactly one of `url` or `service` + must be specified. + + + The `host` should not refer to a service running in the cluster; use + the `service` field instead. The host might be resolved via external + DNS in some apiservers (e.g., `kube-apiserver` cannot resolve + in-cluster DNS as that would be a layering violation). `host` may + also be an IP address. + + + Please note that using `localhost` or `127.0.0.1` as a `host` is + risky unless you take great care to run this webhook on all hosts + which run an apiserver which might need to make calls to this + webhook. Such installs are likely to be non-portable, i.e., not easy + to turn up in a new cluster. + + + The scheme must be "https"; the URL must begin with "https://". + + + A path is optional, and if present may be any string permissible in + a URL. You may use the path to pass an arbitrary string to the + webhook, for example, a cluster identifier. + + + Attempting to use a user or basic auth e.g. "user:password@" is not + allowed. Fragments ("#...") and query parameters ("?...") are not + allowed, either. + type: string type: object - type: object - required: - - targets - type: object - targetType: - description: TargetType defines the GroupVersionKind of target resource - properties: - apiVersion: - description: |- - APIVersion is the group/version for the resource being referenced. - If APIVersion is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIVersion is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - required: - - kind - type: object - trafficTopologyRefs: - description: |- - TrafficTopologyRefs defines the networking traffic relationships between - workloads, backend services, and routes. - items: - type: string - type: array - webhooks: - description: Webhooks defines rollout webhook configuration - items: - properties: - clientConfig: - description: |- - ClientConfig defines how to communicate with the hook. - Required - properties: - caBundle: - description: |- - `caBundle` is a PEM encoded CA bundle which will be used to validate the webhook's server certificate. - If unspecified, system trust roots' CA on the node. - format: byte + failurePolicy: + description: |- + FailurePolicy defines how unrecognized errors from the admission endpoint are handled - + allowed values are Ignore or Fail. Defaults to Ignore. + type: string + failureThreshold: + default: 3 + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + minimum: 1 + type: integer + hookTypes: + description: |- + HookTypes defines when to communicate with the hook, specifies the types of events + that trigger the webhook. + Required + items: + description: Webhook type type: string - periodSeconds: - default: 10 - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - minimum: 1 - type: integer - timeoutSeconds: - default: 10 - description: |- - TimeoutSeconds specifies the timeout for this webhook. After the timeout passes, - the webhook call will be ignored or the API call will fail based on the - failure policy. - format: int32 - type: integer - url: - description: |- - `url` gives the location of the webhook, in standard URL form - (`scheme://host:port/path`). Exactly one of `url` or `service` - must be specified. - - - The `host` should not refer to a service running in the cluster; use - the `service` field instead. The host might be resolved via external - DNS in some apiservers (e.g., `kube-apiserver` cannot resolve - in-cluster DNS as that would be a layering violation). `host` may - also be an IP address. - - - Please note that using `localhost` or `127.0.0.1` as a `host` is - risky unless you take great care to run this webhook on all hosts - which run an apiserver which might need to make calls to this - webhook. Such installs are likely to be non-portable, i.e., not easy - to turn up in a new cluster. - - - The scheme must be "https"; the URL must begin with "https://". - - - A path is optional, and if present may be any string permissible in - a URL. You may use the path to pass an arbitrary string to the - webhook, for example, a cluster identifier. - - - Attempting to use a user or basic auth e.g. "user:password@" is not - allowed. Fragments ("#...") and query parameters ("?...") are not - allowed, either. + type: array + name: + description: Name is the identity of webhook + type: string + properties: + additionalProperties: type: string - type: object - failurePolicy: - description: |- - FailurePolicy defines how unrecognized errors from the admission endpoint are handled - - allowed values are Ignore or Fail. Defaults to Ignore. - type: string - failureThreshold: - default: 3 - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. + description: Properties provide additional data for webhook. + type: object + provider: + description: |- + By default, rollout communicates with the webhook through the structure RolloutWebhookReview. + If provider is set, then the protocol of the interaction will be determined by the provider + type: string + type: object + type: array + type: object + status: + properties: + batchStatus: + description: BatchStatus describes the state of the active batch release + properties: + currentBatchIndex: + description: CurrentBatchIndex defines the current batch index of batch release progress. format: int32 - minimum: 1 type: integer - hookTypes: - description: |- - HookTypes defines when to communicate with the hook, specifies the types of events - that trigger the webhook. - Required + currentBatchState: + description: CurrentBatchState indicates the current batch state. + type: string + records: + description: Records contains all batches status details. items: - description: Webhook type - type: string + properties: + finishTime: + description: FinishTime is the time when the stage finished + format: date-time + type: string + index: + description: Index is the id of the batch + format: int32 + type: integer + startTime: + description: StartTime is the time when the stage started + format: date-time + type: string + state: + description: State is Rollout step state + type: string + targets: + description: WorkloadDetails contains release details for each workload + items: + properties: + availableReplicas: + description: AvailableReplicas is the number of service available pods targeted by workload. + format: int32 + type: integer + cluster: + description: Cluster defines which cluster the workload is in. + type: string + generation: + description: Generation is the found in workload metadata. + format: int64 + type: integer + name: + description: Name is the workload name + type: string + observedGeneration: + description: ObservedGeneration is the most recent generation observed for this workload. + format: int64 + type: integer + replicas: + description: Replicas is the desired number of pods targeted by workload + format: int32 + type: integer + stableRevision: + description: StableRevision is the old stable revision used to generate pods. + type: string + updatedAvailableReplicas: + description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReadyReplicas: + description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedRevision: + description: UpdatedRevision is the updated template revision used to generate pods. + type: string + type: object + type: array + webhooks: + description: Webhooks contains webhook status + items: + properties: + code: + description: Code is a globally unique identifier + type: string + failureCount: + description: Failure count + format: int32 + type: integer + finishTime: + description: FinishTime is the time when the hook finished + format: date-time + type: string + hookType: + description: Webhook Type + type: string + message: + description: A human-readable message indicating details about the transition. + type: string + name: + description: Webhook Name + type: string + reason: + description: A human-readable short word + type: string + startTime: + description: StartTime is the time when the hook started + format: date-time + type: string + state: + description: Current webhook worker state + type: string + type: object + type: array + type: object type: array - name: - description: Name is the identity of webhook - type: string - properties: - additionalProperties: - type: string - description: Properties provide additional data for webhook. - type: object - provider: - description: |- - By default, rollout communicates with the webhook through the structure RolloutWebhookReview. - If provider is set, then the protocol of the interaction will be determined by the provider - type: string + required: + - currentBatchIndex type: object - type: array - type: object - status: - properties: - batchStatus: - description: BatchStatus describes the state of the active batch release - properties: - currentBatchIndex: - description: CurrentBatchIndex defines the current batch index of batch release progress. - format: int32 - type: integer - currentBatchState: - description: CurrentBatchState indicates the current batch state. - type: string - records: - description: Records contains all batches status details. - items: - properties: - finishTime: - description: FinishTime is the time when the stage finished - format: date-time - type: string - index: - description: Index is the id of the batch - format: int32 - type: integer - startTime: - description: StartTime is the time when the stage started - format: date-time - type: string - state: - description: State is Rollout step state - type: string - targets: - description: WorkloadDetails contains release details for each workload - items: - properties: - availableReplicas: - description: AvailableReplicas is the number of service available pods targeted by workload. - format: int32 - type: integer - cluster: - description: Cluster defines which cluster the workload is in. - type: string - generation: - description: Generation is the found in workload metadata. - format: int64 - type: integer - name: - description: Name is the workload name - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed for this workload. - format: int64 - type: integer - replicas: - description: Replicas is the desired number of pods targeted by workload - format: int32 - type: integer - stableRevision: - description: StableRevision is the old stable revision used to generate pods. - type: string - updatedAvailableReplicas: - description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedRevision: - description: UpdatedRevision is the updated template revision used to generate pods. - type: string - required: - - replicas - - updatedAvailableReplicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: array - webhooks: - description: Webhooks contains webhook status - items: - properties: - code: - description: Code is a globally unique identifier - type: string - failureCount: - description: Failure count - format: int32 - type: integer - finishTime: - description: FinishTime is the time when the hook finished - format: date-time - type: string - hookType: - description: Webhook Type - type: string - message: - description: A human-readable message indicating details about the transition. - type: string - name: - description: Webhook Name - type: string - reason: - description: A human-readable short word - type: string - startTime: - description: StartTime is the time when the hook started - format: date-time - type: string - state: - description: Current webhook worker state - type: string - type: object - type: array - type: object - type: array - required: - - currentBatchIndex - type: object - canaryStatus: - description: CanaryStatus describes the state of the active canary release - properties: - finishTime: - description: FinishTime is the time when the stage finished - format: date-time - type: string - index: - description: Index is the id of the batch - format: int32 - type: integer - startTime: - description: StartTime is the time when the stage started - format: date-time - type: string - state: - description: State is Rollout step state - type: string - targets: - description: WorkloadDetails contains release details for each workload - items: - properties: - availableReplicas: - description: AvailableReplicas is the number of service available pods targeted by workload. - format: int32 - type: integer - cluster: - description: Cluster defines which cluster the workload is in. - type: string - generation: - description: Generation is the found in workload metadata. - format: int64 - type: integer - name: - description: Name is the workload name - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed for this workload. - format: int64 - type: integer - replicas: - description: Replicas is the desired number of pods targeted by workload - format: int32 - type: integer - stableRevision: - description: StableRevision is the old stable revision used to generate pods. - type: string - updatedAvailableReplicas: - description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedRevision: - description: UpdatedRevision is the updated template revision used to generate pods. - type: string - required: - - replicas - - updatedAvailableReplicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: array - webhooks: - description: Webhooks contains webhook status - items: - properties: - code: - description: Code is a globally unique identifier - type: string - failureCount: - description: Failure count - format: int32 - type: integer - finishTime: - description: FinishTime is the time when the hook finished - format: date-time - type: string - hookType: - description: Webhook Type - type: string - message: - description: A human-readable message indicating details about the transition. - type: string - name: - description: Webhook Name - type: string - reason: - description: A human-readable short word - type: string - startTime: - description: StartTime is the time when the hook started - format: date-time - type: string - state: - description: Current webhook worker state - type: string - type: object - type: array - type: object - conditions: - description: Conditions is the list of conditions - items: - description: |- - Condition defines the condition of a resource - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties + canaryStatus: + description: CanaryStatus describes the state of the active canary release properties: - lastTransitionTime: - description: Last time the condition transitioned from one status to another. + finishTime: + description: FinishTime is the time when the stage finished format: date-time type: string - lastUpdateTime: - description: The last time this condition was updated. + index: + description: Index is the id of the batch + format: int32 + type: integer + startTime: + description: StartTime is the time when the stage started format: date-time type: string - message: - description: A human-readable message indicating details about the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. + state: + description: State is Rollout step state type: string - type: - description: Type of the condition. - type: string - required: - - status - - type + targets: + description: WorkloadDetails contains release details for each workload + items: + properties: + availableReplicas: + description: AvailableReplicas is the number of service available pods targeted by workload. + format: int32 + type: integer + cluster: + description: Cluster defines which cluster the workload is in. + type: string + generation: + description: Generation is the found in workload metadata. + format: int64 + type: integer + name: + description: Name is the workload name + type: string + observedGeneration: + description: ObservedGeneration is the most recent generation observed for this workload. + format: int64 + type: integer + replicas: + description: Replicas is the desired number of pods targeted by workload + format: int32 + type: integer + stableRevision: + description: StableRevision is the old stable revision used to generate pods. + type: string + updatedAvailableReplicas: + description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReadyReplicas: + description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedRevision: + description: UpdatedRevision is the updated template revision used to generate pods. + type: string + type: object + type: array + webhooks: + description: Webhooks contains webhook status + items: + properties: + code: + description: Code is a globally unique identifier + type: string + failureCount: + description: Failure count + format: int32 + type: integer + finishTime: + description: FinishTime is the time when the hook finished + format: date-time + type: string + hookType: + description: Webhook Type + type: string + message: + description: A human-readable message indicating details about the transition. + type: string + name: + description: Webhook Name + type: string + reason: + description: A human-readable short word + type: string + startTime: + description: StartTime is the time when the hook started + format: date-time + type: string + state: + description: Current webhook worker state + type: string + type: object + type: array type: object - type: array - error: - description: Error indicates the error info of progressing - properties: - code: - description: Code is a globally unique identifier - type: string - message: - description: A human-readable message indicating details about the transition. - type: string - reason: - description: A human-readable short word - type: string - type: object - lastUpdateTime: - description: The last time this status was updated. - format: date-time - type: string - observedGeneration: - description: |- - ObservedGeneration is the most recent generation observed for this Rollout. It corresponds to the - Rollout's generation, which is updated on mutation by the API Server. - format: int64 - type: integer - phase: - description: Phase indecates the current phase of rollout - type: string - targetStatuses: - description: TargetStatuses describes the referenced workloads status - items: + conditions: + description: Conditions is the list of conditions + items: + description: |- + Condition defines the condition of a resource + See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human-readable message indicating details about the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of the condition. + type: string + required: + - status + - type + type: object + type: array + error: + description: Error indicates the error info of progressing properties: - availableReplicas: - description: AvailableReplicas is the number of service available pods targeted by workload. - format: int32 - type: integer - cluster: - description: Cluster defines which cluster the workload is in. + code: + description: Code is a globally unique identifier type: string - generation: - description: Generation is the found in workload metadata. - format: int64 - type: integer - name: - description: Name is the workload name - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed for this workload. - format: int64 - type: integer - replicas: - description: Replicas is the desired number of pods targeted by workload - format: int32 - type: integer - stableRevision: - description: StableRevision is the old stable revision used to generate pods. + message: + description: A human-readable message indicating details about the transition. type: string - updatedAvailableReplicas: - description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedRevision: - description: UpdatedRevision is the updated template revision used to generate pods. + reason: + description: A human-readable short word type: string - required: - - replicas - - updatedAvailableReplicas - - updatedReadyReplicas - - updatedReplicas type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} + lastUpdateTime: + description: The last time this status was updated. + format: date-time + type: string + observedGeneration: + description: |- + ObservedGeneration is the most recent generation observed for this Rollout. It corresponds to the + Rollout's generation, which is updated on mutation by the API Server. + format: int64 + type: integer + phase: + description: Phase indecates the current phase of rollout + type: string + targetStatuses: + description: TargetStatuses describes the referenced workloads status + items: + properties: + availableReplicas: + description: AvailableReplicas is the number of service available pods targeted by workload. + format: int32 + type: integer + cluster: + description: Cluster defines which cluster the workload is in. + type: string + generation: + description: Generation is the found in workload metadata. + format: int64 + type: integer + name: + description: Name is the workload name + type: string + observedGeneration: + description: ObservedGeneration is the most recent generation observed for this workload. + format: int64 + type: integer + replicas: + description: Replicas is the desired number of pods targeted by workload + format: int32 + type: integer + stableRevision: + description: StableRevision is the old stable revision used to generate pods. + type: string + updatedAvailableReplicas: + description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReadyReplicas: + description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedRevision: + description: UpdatedRevision is the updated template revision used to generate pods. + type: string + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/rollout.kusionstack.io_rollouts.yaml b/config/crd/bases/rollout.kusionstack.io_rollouts.yaml index 305b2fa..53eff15 100644 --- a/config/crd/bases/rollout.kusionstack.io_rollouts.yaml +++ b/config/crd/bases/rollout.kusionstack.io_rollouts.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -12,276 +11,4705 @@ spec: listKind: RolloutList plural: rollouts shortNames: - - ro + - ro singular: rollout scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=='Available')].status - name: Available - type: string - - jsonPath: .status.phase - name: Phase - type: string - - jsonPath: .status.rolloutID - name: ID - type: string - - format: date-time - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: Rollout is the Schema for the rollouts API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: RolloutSpec defines the desired state of Rollout - properties: - disabled: - description: |- - Disabled means that rollout will not response for new event. - Default value is false. - type: boolean - historyLimit: - default: 10 - description: |- - HistoryLimit defines the maximum number of completed rolloutRun - history records to keep. - The HistoryLimit can start from 0 (no retained RolloutRun history). - When not set or set to math.MaxInt32, the Rollout will keep all RolloutRun history records. - format: int32 - type: integer - strategyRef: - description: StrategyRef is the reference to the rollout strategy - type: string - trafficTopologyRefs: - description: |- - TrafficTopologyRefs defines the networking traffic relationships between - workloads, backend services, and routes. - items: - type: string - type: array - triggerPolicy: - default: Auto - description: TriggerPolicy defines when rollout will be triggered - type: string - workloadRef: - description: WorkloadRef is a reference to a kind of workloads - properties: - apiVersion: - description: |- - APIVersion is the group/version for the resource being referenced. - If APIVersion is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIVersion is required. - type: string - kind: - description: Kind is the type of resource being referenced - type: string - match: - description: Match indicates how to match workloads. only one - workload should be matches in one cluster - properties: - names: - description: Names is a list of workload name - items: - description: CrossClusterObjectNameReference contains cluster - and name reference to a k8s object + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Available')].status + name: Available + type: string + - jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .status.rolloutID + name: ID + type: string + - format: date-time + jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Rollout is the Schema for the rollouts API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: RolloutSpec defines the desired state of Rollout + properties: + batchStrategy: + description: |- + BatchStrategy defines the inline batch strategy. + This allows specifying batch deployment details directly in Rollout + without requiring a separate RolloutStrategy resource. + Mutually exclusive with StrategyRef. + properties: + batches: + description: Batches define the order of phases to execute release in batch release + items: + properties: + breakpoint: + description: If set to true, the rollout will be paused before the step starts. + type: boolean properties: - cluster: - description: Cluster indicates the name of cluster - type: string - name: - description: Name is the resource name + additionalProperties: type: string - required: - - name - type: object - type: array - selector: - description: Selector is a label query over a set of resources, - in this case resource - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. + description: Properties contains additional information for step + type: object + targets: + description: desired target replicas items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. properties: - key: - description: key is the label key that the selector - applies to. + cluster: + description: Cluster indicates the name of cluster type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + name: + description: Name is the resource name type: string - values: + replicaSlidingWindow: + anyOf: + - type: integer + - type: string description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array + ReplicaSlidingWindow used to control the number of pods that are allowed to be upgraded in + a sliding window for progressive rollout smoothly. + x-kubernetes-int-or-string: true + replicas: + anyOf: + - type: integer + - type: string + description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded + x-kubernetes-int-or-string: true required: - - key - - operator + - name + - replicas type: object type: array - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + traffic: + description: traffic strategy + properties: + http: + properties: + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + stableTraffic: + description: StableTraffic indicate the base traffic rule + properties: + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + weight: + description: Weight indicate how many percentage of traffic the canary pods should receive + format: int32 + maximum: 100 + minimum: 0 + type: integer + type: object type: object + required: + - targets type: object - x-kubernetes-map-type: atomic - type: object - required: - - kind - - match - type: object - type: object - status: - description: RolloutStatus defines the observed state of Rollout - properties: - conditions: - description: Conditions is the list of conditions - items: + type: array + toleration: + description: Toleration is the toleration policy of the canary strategy + properties: + initialDelaySeconds: + description: Number of seconds after the toleration check has started before the task are initiated. + format: int32 + type: integer + taskFailureThreshold: + anyOf: + - type: integer + - type: string + description: |- + FailureThreshold indicates how many failed pods can be tolerated before marking the rollout task as success + If not set, the default value is 0, which means no failed pods can be tolerated + This is a task level threshold. + x-kubernetes-int-or-string: true + workloadTotalFailureThreshold: + anyOf: + - type: integer + - type: string + description: |- + WorkloadFailureThreshold indicates how many failed pods can be tolerated in all upgraded pods of one workload. + The default value is 0, which means no failed pods can be tolerated. + This is a workload level threshold. + x-kubernetes-int-or-string: true + type: object + type: object + canaryStrategy: description: |- - Condition defines the condition of a resource - See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties + CanaryStrategy defines the inline canary strategy. + This allows specifying canary deployment details directly in Rollout + without requiring a separate RolloutStrategy resource. + Mutually exclusive with StrategyRef. properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human-readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of the condition. - type: string + podTemplateMetadataPatch: + description: PodTemplateMetadataPatch defines a patch for workload podTemplate metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations are additional metadata that can be included. + type: object + labels: + additionalProperties: + type: string + description: Labels are additional metadata that can be included. + type: object + type: object + properties: + additionalProperties: + type: string + description: Properties contains additional information for step + type: object + targets: + description: desired target replicas + items: + properties: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + replicaSlidingWindow: + anyOf: + - type: integer + - type: string + description: |- + ReplicaSlidingWindow used to control the number of pods that are allowed to be upgraded in + a sliding window for progressive rollout smoothly. + x-kubernetes-int-or-string: true + replicas: + anyOf: + - type: integer + - type: string + description: Replicas is the replicas of the rollout task, which represents the number of pods to be upgraded + x-kubernetes-int-or-string: true + required: + - name + - replicas + type: object + type: array + traffic: + description: traffic strategy + properties: + http: + properties: + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + stableTraffic: + description: StableTraffic indicate the base traffic rule + properties: + filters: + description: |- + Filters define the filters that are applied to requests that match + this rule. + + + The effects of ordering of multiple behaviors are currently unspecified. + This can change in the future based on feedback during the alpha stage. + + + Conformance-levels at this level are defined based on the type of filter: + + + - ALL core filters MUST be supported by all implementations. + - Implementers are encouraged to support extended filters. + - Implementation-specific custom filters have no API guarantees across + implementations. + + + Specifying the same filter multiple times is not supported unless explicitly + indicated in the filter. + + + All filters are expected to be compatible with each other except for the + URLRewrite and RequestRedirect filters, which may not be combined. If an + implementation can not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to be set to status + `False`, implementations may use the `IncompatibleFilters` reason to specify + this configuration error. + + + Support: Core + items: + description: |- + HTTPRouteFilter defines processing steps that must be completed during the + request or response lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway implementations. Some + examples include request or response modification, implementing + authentication strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: |- + ExtensionRef is an optional, implementation-specific extension to the + "filter" behavior. For example, resource "myroutefilter" in group + "networking.example.net"). ExtensionRef MUST NOT be used for core and + extended filters. + + + This filter can be used multiple times within the same rule. + + + Support: Implementation-specific + properties: + group: + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: |- + RequestHeaderModifier defines a schema for a filter that modifies request + headers. + + + Support: Core + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: |- + RequestMirror defines a schema for a filter that mirrors requests. + Requests are sent to the specified destination, but responses from + that destination are ignored. + + + This filter can be used multiple times within the same rule. Note that + not all implementations will be able to support mirroring to multiple + backends. + + + Support: Extended + + + + properties: + backendRef: + description: |- + BackendRef references a resource where mirrored requests are sent. + + + Mirrored requests must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many endpoints are present + within this BackendRef. + + + If the referent cannot be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure the "ResolvedRefs" + condition on the Route status is set to `status: False` and not configure + this backend in the underlying implementation. + + + If there is a cross-namespace reference to an *existing* object + that is not allowed by a ReferenceGrant, the controller must ensure the + "ResolvedRefs" condition on the Route is set to `status: False`, + with the "RefNotPermitted" reason and not configure this backend in the + underlying implementation. + + + In either error case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about the problem. + + + Support: Extended for Kubernetes Service + + + Support: Implementation-specific for any other resource + properties: + group: + default: "" + description: |- + Group is the group of the referent. For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + + Defaults to "Service" when not specified. + + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations SHOULD NOT + support ExternalName Services. + + + Support: Core (Services with a type other than ExternalName) + + + Support: Implementation-specific (Services with type ExternalName) + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the backend. When unspecified, the local + namespace is inferred. + + + Note that when a namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. + + + Support: Core + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: |- + Port specifies the destination port number to use for this resource. + Port is required when the referent is a Kubernetes Service. In this + case, the port number is the service port number, not the target port. + For other resources, destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + fraction: + description: |- + Fraction represents the fraction of requests that should be + mirrored to BackendRef. + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + percent: + description: |- + Percent represents the percentage of requests that should be + mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + requests) and its maximum value is 100 (indicating 100% of requests). + + + Only one of Fraction or Percent may be specified. If neither field + is specified, 100% of requests will be mirrored. + + + + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + description: |- + RequestRedirect defines a schema for a filter that responds to the + request with an HTTP redirection. + + + Support: Core + properties: + hostname: + description: |- + Hostname is the hostname to be used in the value of the `Location` + header in the response. + When empty, the hostname in the `Host` header of the request is used. + + + Support: Core + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines parameters used to modify the path of the incoming request. + The modified path is then used to construct the `Location` header. When + empty, the request path is used as-is. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: |- + Port is the port to be used in the value of the `Location` + header in the response. + + + If no port is specified, the redirect port MUST be derived using the + following rules: + + + * If redirect scheme is not-empty, the redirect port MUST be the well-known + port associated with the redirect scheme. Specifically "http" to port 80 + and "https" to port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway SHOULD be used. + * If redirect scheme is empty, the redirect port MUST be the Gateway + Listener port. + + + Implementations SHOULD NOT add the port number in the 'Location' + header in the following cases: + + + * A Location header that will use HTTP (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 80. + * A Location header that will use HTTPS (whether that is determined via + the Listener protocol or the Scheme field) _and_ use port 443. + + + Support: Extended + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: |- + Scheme is the scheme to be used in the value of the `Location` header in + the response. When empty, the scheme of the request is used. + + + Scheme redirects can affect the port of the redirect, for more information, + refer to the documentation for the port field of this filter. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Extended + enum: + - http + - https + type: string + statusCode: + default: 302 + description: |- + StatusCode is the HTTP status code to be used in response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + + + Support: Core + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: |- + ResponseHeaderModifier defines a schema for a filter that modifies response + headers. + + + Support: Extended + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: |- + Type identifies the type of filter to apply. As with other API fields, + types are classified into three conformance levels: + + + - Core: Filter types and their corresponding configuration defined by + "Support: Core" in this package, e.g. "RequestHeaderModifier". All + implementations must support core filters. + + + - Extended: Filter types and their corresponding configuration defined by + "Support: Extended" in this package, e.g. "RequestMirror". Implementers + are encouraged to support extended filters. + + + - Implementation-specific: Filters that are defined and supported by + specific vendors. + In the future, filters showing convergence in behavior across multiple + implementations will be considered for inclusion in extended or core + conformance levels. Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` should be set to + "ExtensionRef" for custom filters. + + + Implementers are encouraged to define custom implementation types to + extend the core API with implementation-specific behavior. + + + If a reference to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: |- + URLRewrite defines a schema for a filter that modifies a request during forwarding. + + + Support: Extended + properties: + hostname: + description: |- + Hostname is the value to be used to replace the Host header value during + forwarding. + + + Support: Extended + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: |- + Path defines a path rewrite. + + + Support: Extended + properties: + replaceFullPath: + description: |- + ReplaceFullPath specifies the value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: |- + ReplacePrefixMatch specifies the value with which to replace the prefix + match of a request during a rewrite or redirect. For example, a request + to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch + of "/xyz" would be modified to "/xyz/bar". + + + Note that this matches the behavior of the PathPrefix match type. This + matches full path elements. A path element refers to the list of labels + in the path split by the `/` separator. When specified, a trailing `/` is + ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + match the prefix `/abc`, but the path `/abcd` would not. + + + ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in + the implementation setting the Accepted Condition for the Route to `status: False`. + + + Request Path | Prefix Match | Replace Prefix | Modified Path + -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | /xyz/bar + /foo/bar | /foo | /xyz/ | /xyz/bar + /foo/bar | /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | /xyz/bar + /foo | /foo | /xyz | /xyz + /foo/ | /foo | /xyz | /xyz/ + /foo/bar | /foo | | /bar + /foo/ | /foo | | / + /foo | /foo | | / + /foo/ | /foo | / | / + /foo | /foo | / | / + maxLength: 1024 + type: string + type: + description: |- + Type defines the type of path modifier. Additional types may be + added in a future release of the API. + + + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + + + Unknown values here must result in the implementation setting the + Accepted Condition for the Route to `status: False`, with a + Reason of `UnsupportedValue`. + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + description: |- + Matches define conditions used for matching the rule against incoming + HTTP requests. Each match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. + + + For example, take the following matches configuration: + + + ``` + matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "v2" + - path: + value: "/v2/foo" + ``` + + + For a request to match against this rule, a request must satisfy + EITHER of the two conditions: + + + - path prefixed with `/foo` AND contains the header `version: v2` + - path prefix of `/v2/foo` + + + See the documentation for HTTPRouteMatch on how to specify multiple + match conditions that should be ANDed together. + + + If no matches are specified, the default is a prefix + path match on "/", which has the effect of matching every + HTTP request. + + + Proxy or Load Balancer routing configuration generated from HTTPRoutes + MUST prioritize matches based on the following criteria, continuing on + ties. Across all rules specified on applicable Routes, precedence must be + given to the match having: + + + * "Exact" path match. + * "Prefix" path match with largest number of characters. + * Method match. + * Largest number of header matches. + * Largest number of query param matches. + + + Note: The precedence of RegularExpression path matches are implementation-specific. + + + If ties still exist across multiple Routes, matching precedence MUST be + determined in order of the following criteria, continuing on ties: + + + * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by + "{namespace}/{name}". + + + If ties still exist within an HTTPRoute, matching precedence MUST be granted + to the FIRST matching rule (in list order) with a match meeting the above + criteria. + + + When no rules matching a request have been successfully attached to the + parent a request is coming from, a HTTP 404 status code MUST be returned. + items: + properties: + headers: + description: |- + Headers specifies HTTP request header matchers. Multiple match values are + ANDed together, meaning, a request must match all the specified headers + to select the route. + items: + description: |- + HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request + headers. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + + + When a header is repeated in an HTTP request, it is + implementation-specific behavior as to how this is represented. + Generally, proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + processing a repeated header, with special handling for "Set-Cookie". + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the header. + + + Support: Core (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression HeaderMatchType has implementation-specific + conformance, implementations can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's documentation to + determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + path: + description: Path specifies a HTTP request path matcher. + properties: + type: + default: PathPrefix + description: |- + Type specifies how to match against the path Value. + + + Support: Core (Exact, PathPrefix) + + + Support: Implementation-specific (RegularExpression) + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: |- + QueryParams specifies HTTP query parameter matchers. Multiple match + values are ANDed together, meaning, a request must match all the + specified query parameters to select the route. + + + Support: Extended + items: + description: |- + HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP + query parameters. + properties: + name: + description: |- + Name is the name of the HTTP query param to be matched. This must be an + exact string match. (See + https://tools.ietf.org/html/rfc7230#section-2.7.3). + + + If multiple entries specify equivalent query param names, only the first + entry with an equivalent name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST be ignored. + + + If a query param is repeated in an HTTP request, the behavior is + purposely left undefined, since different data planes have different + capabilities. However, it is *recommended* that implementations should + match against the first value of the param if the data plane supports it, + as this behavior is expected in other load balancing contexts outside of + the Gateway API. + + + Users SHOULD NOT route traffic based on repeated query params to guard + themselves against potential differences in the implementations. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: |- + Type specifies how to match against the value of the query parameter. + + + Support: Extended (Exact) + + + Support: Implementation-specific (RegularExpression) + + + Since RegularExpression QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the implementation's + documentation to determine the supported dialect. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + weight: + description: Weight indicate how many percentage of traffic the canary pods should receive + format: int32 + maximum: 100 + minimum: 0 + type: integer + type: object + type: object required: - - status - - type + - targets type: object - type: array - lastUpdateTime: - description: The last time this status was updated. - format: date-time - type: string - observedGeneration: - description: |- - ObservedGeneration is the most recent generation observed for this Rollout. It corresponds to the - Rollout's generation, which is updated on mutation by the API Server. - format: int64 - type: integer - phase: - description: Phase indicates the current phase of rollout - type: string - rolloutID: - description: RolloutID is reference to rolloutRun name. - type: string - workloadStatuses: - description: WorkloadStatuses describes the referenced workloads status - items: + disabled: + description: |- + Disabled means that rollout will not response for new event. + Default value is false. + type: boolean + historyLimit: + default: 10 + description: |- + HistoryLimit defines the maximum number of completed rolloutRun + history records to keep. + The HistoryLimit can start from 0 (no retained RolloutRun history). + When not set or set to math.MaxInt32, the Rollout will keep all RolloutRun history records. + format: int32 + type: integer + strategyRef: + description: |- + StrategyRef is the reference to the rollout strategy. + Mutually exclusive with CanaryStrategy and BatchStrategy. + If specified, CanaryStrategy and BatchStrategy must be empty. + type: string + trafficTopologyRefs: + description: |- + TrafficTopologyRefs defines the networking traffic relationships between + workloads, backend services, and routes. + items: + type: string + type: array + triggerPolicy: + default: Auto + description: TriggerPolicy defines when rollout will be triggered + type: string + workloadRef: + description: WorkloadRef is a reference to a kind of workloads properties: - availableReplicas: - description: AvailableReplicas is the number of service available - pods targeted by workload. - format: int32 - type: integer - cluster: - description: Cluster defines which cluster the workload is in. + apiVersion: + description: |- + APIVersion is the group/version for the resource being referenced. + If APIVersion is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIVersion is required. type: string - generation: - description: Generation is the found in workload metadata. - format: int64 - type: integer - name: - description: Name is the workload name - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation - observed for this workload. - format: int64 - type: integer - replicas: - description: Replicas is the desired number of pods targeted - by workload - format: int32 - type: integer - stableRevision: - description: StableRevision is the old stable revision used - to generate pods. - type: string - updatedAvailableReplicas: - description: UpdatedAvailableReplicas is the number of service - available pods targeted by workload that have the updated - template spec. - format: int32 - type: integer - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of ready pods - targeted by workload that have the updated template spec. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of pods targeted - by workload that have the updated template spec. - format: int32 - type: integer - updatedRevision: - description: UpdatedRevision is the updated template revision - used to generate pods. + kind: + description: Kind is the type of resource being referenced type: string + match: + description: Match indicates how to match workloads. only one workload should be matches in one cluster + properties: + names: + description: Names is a list of workload name + items: + description: CrossClusterObjectNameReference contains cluster and name reference to a k8s object + properties: + cluster: + description: Cluster indicates the name of cluster + type: string + name: + description: Name is the resource name + type: string + required: + - name + type: object + type: array + selector: + description: Selector is a label query over a set of resources, in this case resource + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object required: - - replicas - - updatedAvailableReplicas - - updatedReadyReplicas - - updatedReplicas + - kind + - match type: object - type: array - type: object - type: object - served: true - storage: true - subresources: - status: {} + type: object + status: + description: RolloutStatus defines the observed state of Rollout + properties: + conditions: + description: Conditions is the list of conditions + items: + description: |- + Condition defines the condition of a resource + See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human-readable message indicating details about the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of the condition. + type: string + required: + - status + - type + type: object + type: array + lastUpdateTime: + description: The last time this status was updated. + format: date-time + type: string + observedGeneration: + description: |- + ObservedGeneration is the most recent generation observed for this Rollout. It corresponds to the + Rollout's generation, which is updated on mutation by the API Server. + format: int64 + type: integer + phase: + description: Phase indicates the current phase of rollout + type: string + rolloutID: + description: RolloutID is reference to rolloutRun name. + type: string + workloadStatuses: + description: WorkloadStatuses describes the referenced workloads status + items: + properties: + availableReplicas: + description: AvailableReplicas is the number of service available pods targeted by workload. + format: int32 + type: integer + cluster: + description: Cluster defines which cluster the workload is in. + type: string + generation: + description: Generation is the found in workload metadata. + format: int64 + type: integer + name: + description: Name is the workload name + type: string + observedGeneration: + description: ObservedGeneration is the most recent generation observed for this workload. + format: int64 + type: integer + replicas: + description: Replicas is the desired number of pods targeted by workload + format: int32 + type: integer + stableRevision: + description: StableRevision is the old stable revision used to generate pods. + type: string + updatedAvailableReplicas: + description: UpdatedAvailableReplicas is the number of service available pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReadyReplicas: + description: UpdatedReadyReplicas is the number of ready pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas is the number of pods targeted by workload that have the updated template spec. + format: int32 + type: integer + updatedRevision: + description: UpdatedRevision is the updated template revision used to generate pods. + type: string + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/go.mod b/go.mod index 84f51fe..c4b22f3 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( k8s.io/klog/v2 v2.130.1 k8s.io/kubernetes v1.22.2 k8s.io/utils v0.0.0-20241210054802-24370beab758 - kusionstack.io/kube-api v0.7.5-0.20251222101808-6d5bc2b4ac64 + kusionstack.io/kube-api v0.7.5-0.20260306081812-18b6128bc6fb kusionstack.io/kube-utils v0.2.1-0.20251125083928-1134a582b341 kusionstack.io/resourceconsist v0.0.4 sigs.k8s.io/controller-runtime v0.21.0 diff --git a/go.sum b/go.sum index 2b24975..210f4b5 100644 --- a/go.sum +++ b/go.sum @@ -1021,10 +1021,8 @@ k8s.io/sample-apiserver v0.22.2/go.mod h1:h+/DIV5EmuNq4vfPr5TSXy9mIBVXXlPAKQMPbj k8s.io/system-validators v1.5.0/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6gRrl0Q= k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -kusionstack.io/kube-api v0.7.4 h1:9fM+SZtYvuVn5L/DuG7oAC+Z17uSDAeVbiAfjugI3SQ= -kusionstack.io/kube-api v0.7.4/go.mod h1:e1jtrQH2LK5fD2nTyfIXG6nYrYbU8VXShRxTRwVPaLk= -kusionstack.io/kube-api v0.7.5-0.20251222101808-6d5bc2b4ac64 h1:iXxFN0KuDBLRlTs5lJgFBSitzSVn9kiV2l0uZZZo6Dg= -kusionstack.io/kube-api v0.7.5-0.20251222101808-6d5bc2b4ac64/go.mod h1:e1jtrQH2LK5fD2nTyfIXG6nYrYbU8VXShRxTRwVPaLk= +kusionstack.io/kube-api v0.7.5-0.20260306081812-18b6128bc6fb h1:ODxnOte9umQL5yjsNjnGj+OmNqZRx/NtjaYgJteemW8= +kusionstack.io/kube-api v0.7.5-0.20260306081812-18b6128bc6fb/go.mod h1:e1jtrQH2LK5fD2nTyfIXG6nYrYbU8VXShRxTRwVPaLk= kusionstack.io/kube-utils v0.2.1-0.20251125083928-1134a582b341 h1:dnMtHJvIpU3338WpqGiNN2qXWZFiXaoiuzR9jwhvWpg= kusionstack.io/kube-utils v0.2.1-0.20251125083928-1134a582b341/go.mod h1:Lz5SBYWg9+jw+kP0CAyf/b62D5DeUPf6+jE1d0WC4cI= kusionstack.io/resourceconsist v0.0.4 h1:wRqLJuNh8O4TT6p0uOklFpHUKiRdRxcAH71Sw/q9LhE= diff --git a/pkg/controllers/rollout/CLAUDE.md b/pkg/controllers/rollout/CLAUDE.md new file mode 100644 index 0000000..28bd03d --- /dev/null +++ b/pkg/controllers/rollout/CLAUDE.md @@ -0,0 +1,201 @@ +# Rollout Controller 目录逻辑说明 + +## 概述 + +Rollout Controller 是 KusionStack Rollout 的核心控制器之一,负责管理 Rollout 资源的生命周期,协调工作负载的渐进式发布流程。基于 [渐进式交付 Rollout 设计文档](https://yuque.antfin.com/antcloud-paas/dp4wap/ae5myagvwh96cugn),Rollout Controller 实现了跨集群的发布管理功能。 + +## 核心职责 + +1. **管理 Rollout 生命周期** - 监听 Rollout 资源变化,计算状态 +2. **关联工作负载** - 根据 WorkloadRef 匹配并标记受管工作负载 +3. **触发发布流程** - 根据触发策略创建 RolloutRun +4. **协调 RolloutRun** - 监控 RolloutRun 状态,处理用户命令 +5. **资源清理** - 清理历史 RolloutRun,处理 Finalizer + +## 目录结构 + +``` +rollout/ +├── rollout_controller.go # 主控制器逻辑 +├── event_handler.go # 事件处理器 +├── utils.go # 工具函数 +└── initializer.go # 控制器初始化 +``` + +## 核心数据结构 + +### RolloutReconciler + +```go +type RolloutReconciler struct { + *mixin.ReconcilerMixin // 混入基础控制器能力 + workloadRegistry registry.WorkloadRegistry // 工作负载注册表 + expectation expectations.ControllerExpectationsInterface // 控制器期望 + rvExpectation expectations.ResourceVersionExpectationInterface // 资源版本期望 +} +``` + +## Reconcile 流程 + +### SetupWithManager + +```go +func (r *RolloutReconciler) SetupWithManager(mgr ctrl.Manager) error +``` + +监听的资源: +- `Rollout` - 使用 `ResourceVersionChangedPredicate` 过滤 +- `RolloutRun` (跨集群) - 使用创建观察处理器 +- `RolloutStrategy` - 策略变化触发 +- 所有已注册的 workload 类型 (Deployment, CloneSet, CollaSet 等) + +### Reconcile 八步流程 + +```go +func (r *RolloutReconciler) Reconcile(ctx context.Context, req ctrl.Request) +``` + +1. **检查期望满足** + - 资源版本期望 + - 控制器期望 + +2. **计算新状态** + - 根据对象状态计算 Phase: `Initialized`/`Progressing`/`Disabled`/`Terminating` + +3. **管理 Finalizer** + - 添加/删除 `rollout.kusionstack.io/cleanup` finalizer + +4. **查找工作负载** (跨集群) + - 根据资源匹配规则查找关联的工作负载 + +5. **获取 RolloutRun 列表** + - 当前运行的 RolloutRun + - 历史完成的 RolloutRun + +6. **清理历史记录** + - 根据 `HistoryLimit` 删除旧的完成 RolloutRun + +7. **按阶段处理** + - `Disabled`: 仅同步状态 + - `Terminating`: 执行清理 + - `Progressing`/`Waiting`: 处理发布逻辑 + +8. **更新状态** + - 更新 RolloutStatus + +## 关键函数 + +### 状态计算 + +| 函数 | 说明 | +|------|------| +| `calculateStatus()` | 根据对象状态计算 Phase | +| `updateStatusOnly()` | 仅更新状态,不触发 reconcile 回头 | + +### Finalizer 管理 + +| 函数 | 说明 | +|------|------| +| `ensureFinalizer()` | 添加/删除 Finalizer | +| `handleFinalizing()` | 清理工作负载标签 | + +### 发布触发 + +| 函数 | 说明 | +|------|------| +| `shouldTrigger()` | 判断是否应该触发发布 | +| `syncRun()` | 同步 RolloutRun 创建/状态 | + +### 触发策略 + +#### Auto (自动触发) - 默认 +- 当所有关联的工作负载都标记为 `waiting for rollout` 时触发 + +#### Manual (手动触发) +- 禁止自动触发,完全由用户控制 + +#### Annotation (主动触发) +- 添加 annotation `rollout.kusionstack.io/trigger: "triggerName"` +- 强制创建 RolloutRun,即使工作负载未全部就绪 + +### 工作负载管理 + +| 函数 | 说明 | +|------|------| +| `findWorkloadsCrossCluster()` | 跨集群查找工作负载 | +| `ensureWorkloadsLabelAndAnnotations()` | 添加 rollout 管理标签 | + +### 历史清理 + +| 函数 | 说明 | +|------|------| +| `leanupHistory()` | 根据 HistoryLimit 删除旧记录 | +| `getAllRolloutRun()` | 获取所有 RolloutRun | + +### 命令处理 + +| 函数 | 说明 | +|------|------| +| `handleRunManualCommand()` | 处理用户手动命令 | +| `applyOneTimeStrategy()` | 应用一次性策略 | + +## Phase 状态机 + +``` +┌──────────────┐ +│ Disabled │ ← spec.disabled = true +└──────────────┘ + ↓ +┌──────────────┐ +│ Initialized │ ← 默认初始状态 +└──────────────┘ + ↓ (触发) +┌──────────────┐ +│ Progressing │ ← RolloutRun 运行中 +└──────────────┘ + ↓ +┌──────────────┐ +│ Terminating │ ← deletionTimestamp != nil +└──────────────┘ +``` + +## Annotation 用途 + +| Annotation | 说明 | +|------------|------| +| `rollout.kusionstack.io/trigger` | 主动触发 RolloutRun | +| `rollout.kusionstack.io/manual-command` | 手动命令传递 | +| `rollout.kusionstack.io/one-time-strategy` | 一次性策略 | + +## Label 用途 + +| Label | 说明 | +|-------|------| +| `rollout.kusionstack.io/workload` | 标记被 Rollout 管理的工作负载 | +| `rollout.kusionstack.io/disabled` | 跳过 Rollout 流程 | + +## 事件记录 + +通过 `recordCondition()` 记录以下条件: + +| Condition | 说明 | +|-----------|------| +| `Available` | 依赖资源是否就绪 | +| `Trigger` | 触发状态 | +| `Progressing` | 进度状态 | +| `Terminating` | 终止状态 | + +## Finalizer 用途 + +``` +rollout.kusionstack.io/cleanup +``` + +保证 Rollout 被删除时能正确清理工作负载的标签和 annotation。 + +## 关键设计决策 + +1. **期望机制** - 使用期望减少不必要的 reconcile +2. **ResourceVersion 过滤** - 只处理实际变化的资源 +3. **跨集群支持** - 通过 clusterinfo 管理多集群 +4. **createCommand 优先** - 处理命令优先于状态检查 \ No newline at end of file diff --git a/pkg/controllers/rollout/inline_strategy.go b/pkg/controllers/rollout/inline_strategy.go new file mode 100644 index 0000000..26fcab8 --- /dev/null +++ b/pkg/controllers/rollout/inline_strategy.go @@ -0,0 +1,184 @@ +// Copyright 2025 The KusionStack Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rollout + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + rolloutapi "kusionstack.io/kube-api/rollout" + rolloutv1alpha1 "kusionstack.io/kube-api/rollout/v1alpha1" + + "kusionstack.io/rollout/pkg/features" + "kusionstack.io/rollout/pkg/features/ontimestrategy" + "kusionstack.io/rollout/pkg/workload" +) + +// constructRolloutRunFromInlineStrategy constructs RolloutRun from inline strategy +// Returns the constructed RolloutRun and a boolean indicating if inline strategy was used +func constructRolloutRunFromInlineStrategy( + obj *rolloutv1alpha1.Rollout, + workloadWrappers []*workload.Info, + rolloutId string, +) (*rolloutv1alpha1.RolloutRun, bool) { + if obj.Spec.BatchStrategy == nil { + return nil, false + } + + // Build workload map for validation + workloadMap := buildWorkloadMap(workloadWrappers) + + owner := metav1.NewControllerRef(obj, rolloutv1alpha1.SchemeGroupVersion.WithKind("Rollout")) + run := &rolloutv1alpha1.RolloutRun{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: obj.Namespace, + Name: rolloutId, + Labels: map[string]string{}, + Annotations: map[string]string{}, + OwnerReferences: []metav1.OwnerReference{*owner}, + Finalizers: []string{rolloutapi.FinalizerRolloutProtection}, + }, + Spec: rolloutv1alpha1.RolloutRunSpec{ + TargetType: rolloutv1alpha1.ObjectTypeRef{ + APIVersion: obj.Spec.WorkloadRef.APIVersion, + Kind: obj.Spec.WorkloadRef.Kind, + }, + TrafficTopologyRefs: obj.Spec.TrafficTopologyRefs, + Webhooks: []rolloutv1alpha1.RolloutWebhook{}, // Empty for inline strategy + }, + } + + if obj.Spec.CanaryStrategy != nil { + canary := validateAndCopyCanaryStrategy(obj.Spec.CanaryStrategy, workloadMap) + run.Spec.Canary = canary + } + + batch := validateAndCopyBatchStrategy(obj.Spec.BatchStrategy, workloadMap) + run.Spec.Batch = batch + + // Set OneTimeStrategy annotation for inline batch strategy + if features.DefaultFeatureGate.Enabled(features.OneTimeStrategy) { + onetime := ontimestrategy.ConvertFromInline(run.Spec.Batch) + data := onetime.JSONData() + run.Annotations[ontimestrategy.AnnoOneTimeStrategy] = string(data) + } + + if features.DefaultFeatureGate.Enabled(features.RolloutClassPredicate) { + class, ok := obj.Labels[rolloutapi.LabelRolloutClass] + if ok { + run.Labels[rolloutapi.LabelRolloutClass] = class + } + } + + return run, true +} + +// validateAndCopyCanaryStrategy validates targets and creates a copy for RolloutRun +// For inline strategy, targets are already pre-resolved by user +func validateAndCopyCanaryStrategy( + canary *rolloutv1alpha1.RolloutRunCanaryStrategy, + workloadMap map[string]*workload.Info, +) *rolloutv1alpha1.RolloutRunCanaryStrategy { + if canary == nil { + return nil + } + + // Validate targets exist + validatedTargets := make([]rolloutv1alpha1.RolloutRunStepTarget, 0, len(canary.Targets)) + for _, target := range canary.Targets { + key := workloadKey(target.Cluster, target.Name) + if _, exists := workloadMap[key]; !exists { + // Skip targets that don't exist in actual workloads + continue + } + // Direct copy - targets are already in correct format + validatedTargets = append(validatedTargets, target) + } + + return &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: validatedTargets, + Traffic: canary.Traffic, + Properties: canary.Properties, + TemplateMetadataPatch: canary.TemplateMetadataPatch, + } +} + +// validateAndCopyBatchStrategy validates and creates a copy for RolloutRun +// For inline strategy, targets are already pre-resolved by user +func validateAndCopyBatchStrategy( + batch *rolloutv1alpha1.RolloutRunBatchStrategy, + workloadMap map[string]*workload.Info, +) *rolloutv1alpha1.RolloutRunBatchStrategy { + if batch == nil { + return nil + } + + if len(batch.Batches) == 0 { + // Return as-is if no batches defined + return &rolloutv1alpha1.RolloutRunBatchStrategy{ + Toleration: batch.Toleration, + Batches: []rolloutv1alpha1.RolloutRunStep{}, + } + } + + validatedBatches := make([]rolloutv1alpha1.RolloutRunStep, 0, len(batch.Batches)) + + for _, step := range batch.Batches { + if len(step.Targets) == 0 { + // Skip steps without targets + continue + } + + // Validate and filter targets that exist + validatedTargets := make([]rolloutv1alpha1.RolloutRunStepTarget, 0, len(step.Targets)) + for _, target := range step.Targets { + key := workloadKey(target.Cluster, target.Name) + if _, exists := workloadMap[key]; !exists { + // Skip targets that don't exist in actual workloads + continue + } + // Direct copy - targets are already in correct format + validatedTargets = append(validatedTargets, target) + } + + if len(validatedTargets) > 0 { + validatedStep := rolloutv1alpha1.RolloutRunStep{ + Targets: validatedTargets, + Traffic: step.Traffic, + Breakpoint: step.Breakpoint, + Properties: step.Properties, + } + validatedBatches = append(validatedBatches, validatedStep) + } + } + + return &rolloutv1alpha1.RolloutRunBatchStrategy{ + Toleration: batch.Toleration, + Batches: validatedBatches, + } +} + +// Helper functions + +func buildWorkloadMap(workloads []*workload.Info) map[string]*workload.Info { + m := make(map[string]*workload.Info) + for _, wl := range workloads { + key := workloadKey(wl.ClusterName, wl.Name) + m[key] = wl + } + return m +} + +func workloadKey(cluster, name string) string { + return cluster + "/" + name +} diff --git a/pkg/controllers/rollout/inline_strategy_test.go b/pkg/controllers/rollout/inline_strategy_test.go new file mode 100644 index 0000000..0ca1aec --- /dev/null +++ b/pkg/controllers/rollout/inline_strategy_test.go @@ -0,0 +1,619 @@ +// Copyright 2025 The KusionStack Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rollout + +import ( + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" + rolloutv1alpha1 "kusionstack.io/kube-api/rollout/v1alpha1" + + "kusionstack.io/rollout/pkg/workload" +) + +func Test_constructRolloutRunFromInlineStrategy(t *testing.T) { + tests := []struct { + name string + obj *rolloutv1alpha1.Rollout + workloadWrappers []*workload.Info + rolloutId string + wantRun bool + wantCanary bool + wantBatch bool + }{ + { + name: "no inline strategy - return nil, false", + obj: &rolloutv1alpha1.Rollout{ + Spec: rolloutv1alpha1.RolloutSpec{ + StrategyRef: "default-strategy", + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantRun: false, + }, + { + name: "only canary strategy - should return nil (batch strategy required)", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + CanaryStrategy: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantRun: false, // Canary alone is not supported, need BatchStrategy + wantCanary: false, + wantBatch: false, + }, + { + name: "only batch strategy", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Breakpoint: true, + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("100%"), + }, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantRun: true, + wantCanary: false, + wantBatch: true, + }, + { + name: "canary + batch strategy together", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + CanaryStrategy: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("5%"), + }, + }, + }, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Breakpoint: true, + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("25%"), + }, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantRun: true, + wantCanary: true, + wantBatch: true, + }, + { + name: "filter non-existent workloads", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", // This workload doesn't exist + Name: "test-1", + }, + Replicas: intstr.FromString("30%"), + }, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + // cluster-b/test-1 is not in workloads + }, + rolloutId: "test-rollout-1", + wantRun: true, + wantCanary: false, + wantBatch: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + run, gotInline := constructRolloutRunFromInlineStrategy(tt.obj, tt.workloadWrappers, tt.rolloutId) + if gotInline != tt.wantRun { + t.Errorf("constructRolloutRunFromInlineStrategy() gotInline = %v, want %v", gotInline, tt.wantRun) + return + } + + if !tt.wantRun { + if run != nil { + t.Errorf("constructRolloutRunFromInlineStrategy() expected nil run, got %v", run) + } + return + } + + if run == nil { + t.Errorf("constructRolloutRunFromInlineStrategy() expected non-nil run, got nil") + return + } + + // Verify basic fields + if run.Name != tt.rolloutId { + t.Errorf("run.Name = %v, want %v", run.Name, tt.rolloutId) + } + if run.Namespace != tt.obj.Namespace { + t.Errorf("run.Namespace = %v, want %v", run.Namespace, tt.obj.Namespace) + } + + // Verify Canary + if tt.wantCanary { + if run.Spec.Canary == nil { + t.Errorf("run.Spec.Canary = nil, want non-nil") + } else if len(run.Spec.Canary.Targets) == 0 { + t.Errorf("run.Spec.Canary.Targets is empty") + } + } + + // Verify Batch + if tt.wantBatch { + if run.Spec.Batch == nil { + t.Errorf("run.Spec.Batch = nil, want non-nil") + } else if len(run.Spec.Batch.Batches) == 0 { + t.Errorf("run.Spec.Batch.Batches is empty") + } + } + + // Verify owner reference + if len(run.OwnerReferences) != 1 { + t.Errorf("len(run.OwnerReferences) = %v, want 1", len(run.OwnerReferences)) + } + }) + } +} + +func Test_validateAndCopyBatchStrategy(t *testing.T) { + tests := []struct { + name string + batch *rolloutv1alpha1.RolloutRunBatchStrategy + workloadMap map[string]*workload.Info + want *rolloutv1alpha1.RolloutRunBatchStrategy + }{ + { + name: "nil batch", + batch: nil, + workloadMap: map[string]*workload.Info{}, + want: nil, + }, + { + name: "empty batches", + batch: &rolloutv1alpha1.RolloutRunBatchStrategy{}, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + }, + want: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{}, + }, + }, + { + name: "batch with targets - all exist", + batch: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Breakpoint: true, + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", + Name: "test-1", + }, + Replicas: intstr.FromString("30%"), + ReplicaSlidingWindow: ptr.To(intstr.FromString("10%")), + }, + }, + }, + }, + }, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + "cluster-b/test-1": newTestInfo("cluster-b", "test", "test-1"), + }, + want: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Breakpoint: true, + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", + Name: "test-1", + }, + Replicas: intstr.FromString("30%"), + ReplicaSlidingWindow: ptr.To(intstr.FromString("10%")), + }, + }, + }, + }, + }, + }, + { + name: "batch with targets - filter non-existent", + batch: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", // Doesn't exist + Name: "test-1", + }, + Replicas: intstr.FromString("30%"), + }, + }, + }, + }, + }, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + // cluster-b/test-1 is missing + }, + want: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + }, + }, + }, + { + name: "batch with toleration preserved", + batch: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Toleration: &rolloutv1alpha1.TolerationStrategy{ + WorkloadFailureThreshold: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, + }, + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("50%"), + }, + }, + }, + }, + }, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + }, + want: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Toleration: &rolloutv1alpha1.TolerationStrategy{ + WorkloadFailureThreshold: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, + }, + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("50%"), + }, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := validateAndCopyBatchStrategy(tt.batch, tt.workloadMap) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("validateAndCopyBatchStrategy() = %v, want %v", spew.Sdump(got), spew.Sdump(tt.want)) + } + }) + } +} + +func Test_validateAndCopyCanaryStrategy(t *testing.T) { + tests := []struct { + name string + canary *rolloutv1alpha1.RolloutRunCanaryStrategy + workloadMap map[string]*workload.Info + want *rolloutv1alpha1.RolloutRunCanaryStrategy + }{ + { + name: "nil canary", + canary: nil, + workloadMap: map[string]*workload.Info{}, + want: nil, + }, + { + name: "canary with all targets existing", + canary: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + }, + }, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + }, + want: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + }, + }, + }, + { + name: "canary with filtered targets", + canary: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", // Doesn't exist + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + // cluster-b/test-1 is missing + }, + want: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + }, + }, + }, + { + name: "canary with all non-existent targets", + canary: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-b", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + }, + }, + workloadMap: map[string]*workload.Info{ + "cluster-a/test-1": newTestInfo("cluster-a", "test", "test-1"), + // cluster-b/test-1 is missing + }, + want: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := validateAndCopyCanaryStrategy(tt.canary, tt.workloadMap) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("validateAndCopyCanaryStrategy() = %v, want %v", spew.Sdump(got), spew.Sdump(tt.want)) + } + }) + } +} + +func Test_buildWorkloadMap(t *testing.T) { + workloads := []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + newTestInfo("cluster-b", "test", "test-2"), + } + + m := buildWorkloadMap(workloads) + + if len(m) != 2 { + t.Errorf("len(m) = %v, want 2", len(m)) + } + + if _, ok := m["cluster-a/test-1"]; !ok { + t.Errorf("m['cluster-a/test-1'] not found") + } + + if _, ok := m["cluster-b/test-2"]; !ok { + t.Errorf("m['cluster-b/test-2'] not found") + } + + if _, ok := m["cluster-a/test-2"]; ok { + t.Errorf("m['cluster-a/test-2'] should not exist") + } +} + +func Test_workloadKey(t *testing.T) { + tests := []struct { + cluster string + name string + want string + }{ + {"cluster-a", "test-1", "cluster-a/test-1"}, + {"cluster-b", "test-2", "cluster-b/test-2"}, + {"cluster-a", "", "cluster-a/"}, + } + + for _, tt := range tests { + t.Run(tt.want, func(t *testing.T) { + got := workloadKey(tt.cluster, tt.name) + if got != tt.want { + t.Errorf("workloadKey() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/controllers/rollout/rollout_controller.go b/pkg/controllers/rollout/rollout_controller.go index 02aa7ce..13a45c4 100644 --- a/pkg/controllers/rollout/rollout_controller.go +++ b/pkg/controllers/rollout/rollout_controller.go @@ -327,16 +327,22 @@ func (r *RolloutReconciler) handleProgressing(ctx context.Context, obj *rolloutv func (r *RolloutReconciler) getDependentResources(ctx context.Context, obj *rolloutv1alpha1.Rollout) (ros *rolloutv1alpha1.RolloutStrategy, ttopos []*rolloutv1alpha1.TrafficTopology, errs []error) { ctx = clusterinfo.WithCluster(ctx, clusterinfo.Fed) - var strategy rolloutv1alpha1.RolloutStrategy - err := r.Client.Get( - ctx, - client.ObjectKey{Namespace: obj.Namespace, Name: obj.Spec.StrategyRef}, - &strategy, - ) - if err != nil { - errs = append(errs, err) - } else { - ros = &strategy + + // Check if using inline strategy (BatchStrategy) + // If using inline strategy, we don't need to fetch RolloutStrategy + if obj.Spec.BatchStrategy == nil && len(obj.Spec.StrategyRef) > 0 { + // Only fetch RolloutStrategy if using StrategyRef (not inline strategy) + var strategy rolloutv1alpha1.RolloutStrategy + err := r.Client.Get( + ctx, + client.ObjectKey{Namespace: obj.Namespace, Name: obj.Spec.StrategyRef}, + &strategy, + ) + if err != nil { + errs = append(errs, err) + } else { + ros = &strategy + } } for _, tt := range obj.Spec.TrafficTopologyRefs { @@ -670,12 +676,21 @@ func (r *RolloutReconciler) applyOneTimeStrategy(ctx context.Context, obj *rollo return nil } - batch := rolloutv1alpha1.RolloutRunBatchStrategy{ - Batches: constructRolloutRunBatches(&strategy.Batch, workloads), - Toleration: strategy.Batch.Toleration, + var batch *rolloutv1alpha1.RolloutRunBatchStrategy + + // Check if using InlineBatch (for inline batch strategy scenario) + if strategy.InlineBatch != nil { + workloadMap := buildWorkloadMap(workloads) + batch = validateAndCopyBatchStrategy(strategy.InlineBatch, workloadMap) + } else { + // Use original Batch field (for StrategyRef scenario) + batch = &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: constructRolloutRunBatches(&strategy.Batch, workloads), + Toleration: strategy.Batch.Toleration, + } } - if batch.Toleration == nil { + if batch.Toleration == nil && run.Spec.Batch != nil { batch.Toleration = run.Spec.Batch.Toleration } @@ -693,7 +708,7 @@ func (r *RolloutReconciler) applyOneTimeStrategy(ctx context.Context, obj *rollo // update strategy in annotation in.Annotations[ontimestrategy.AnnoOneTimeStrategy] = strategyStr // update batch in spec - in.Spec.Batch = &batch + in.Spec.Batch = batch return nil }) if err != nil { diff --git a/pkg/controllers/rollout/rollout_controller_test.go b/pkg/controllers/rollout/rollout_controller_test.go new file mode 100644 index 0000000..924505f --- /dev/null +++ b/pkg/controllers/rollout/rollout_controller_test.go @@ -0,0 +1,436 @@ +// Copyright 2023 The KusionStack Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rollout + +import ( + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + rolloutapi "kusionstack.io/kube-api/rollout" + rolloutv1alpha1 "kusionstack.io/kube-api/rollout/v1alpha1" + "kusionstack.io/kube-api/rollout/v1alpha1/condition" + "kusionstack.io/kube-utils/multicluster/clusterinfo" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ = Describe("Rollout Controller Integration Tests", func() { + const ( + timeout = time.Second * 30 + interval = time.Millisecond * 250 + ) + + Context("Rollout initialize", func() { + var ( + namespace = "test-ns-rollout-init" + rolloutKey = types.NamespacedName{ + Namespace: namespace, + Name: "test-rollout-init", + } + ) + + It("should create rollout with finalizer", func() { + Expect(createNamespace(namespace)).Should(Succeed()) + + // Create a basic rollout + rollout := newTestRollout(rolloutKey.Name, namespace) + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for finalizer to be added + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return containsString(r.Finalizers, rolloutapi.FinalizerRolloutProtection) + }, timeout, interval).Should(BeTrue()) + }) + + It("initialize rollout with correct phase", func() { + // Wait for rollout to be initialized + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return r.Status.Phase == rolloutv1alpha1.RolloutPhaseInitialized + }, timeout, interval).Should(BeTrue()) + }) + }) + + Context("Rollout with StrategyRef", func() { + var ( + namespace = "test-ns-rollout-strategy" + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout"} + strategyKey = types.NamespacedName{Namespace: namespace, Name: "test-strategy"} + ) + + It("should resolve strategy reference successfully", func() { + Expect(createNamespace(namespace)).Should(Succeed()) + + // Create rollout strategy + strategy := newTestRolloutStrategy(strategyKey.Name, namespace) + Expect(c.Create(clusterinfo.WithCluster(ctx, clusterinfo.Fed), strategy)).Should(Succeed()) + + rollout := newTestRollout(rolloutKey.Name, namespace) + rollout.Spec.StrategyRef = strategyKey.Name + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for Available condition to become True + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return condition.IsAvailable(r.Status.Conditions) + }, timeout, interval).Should(BeTrue()) + }) + + It("should fail when strategy reference does not exist", func() { + rolloutKey = types.NamespacedName{ + Namespace: namespace, + Name: "test-rollout-no-strategy", + } + rollout := newTestRollout(rolloutKey.Name, namespace) + rollout.Spec.StrategyRef = "non-existent-strategy" + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for Available condition to become False + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return !condition.IsAvailable(r.Status.Conditions) + }, timeout, interval).Should(BeTrue()) + }) + + It("should create rolloutRun using strategyRef", func() { + rolloutKey = types.NamespacedName{ + Namespace: namespace, + Name: "test-rollout-with-run", + } + + rollout := newTestRollout(rolloutKey.Name, namespace) + rollout.Spec.StrategyRef = strategyKey.Name + rollout.Annotations = map[string]string{ + rolloutapi.AnnoRolloutTrigger: "trigger-from-strategy-ref", + } + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for rolloutRun to be created + Eventually(func() bool { + runList := &rolloutv1alpha1.RolloutRunList{} + if err := c.List(clusterinfo.WithCluster(ctx, clusterinfo.Fed), runList, client.InNamespace(namespace)); err != nil { + return false + } + for _, run := range runList.Items { + owner := metav1.GetControllerOf(&run) + if owner != nil && owner.Name == rolloutKey.Name && run.Name == "trigger-from-strategy-ref" { + return true + } + } + return false + }, timeout, interval).Should(BeTrue()) + }) + }) + + Context("Rollout with Inline Strategy", func() { + var ( + namespace = "test-ns-inline" + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout"} + ) + + It("should create rollout with inline batch strategy", func() { + Expect(createNamespace(namespace)).Should(Succeed()) + + rollout := newTestRolloutWithInlineBatch(rolloutKey.Name, namespace) + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Verify rollout is created and has finalizer + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return containsString(r.Finalizers, rolloutapi.FinalizerRolloutProtection) + }, timeout, interval).Should(BeTrue()) + }) + + It("should create rollout with inline canary strategy", func() { + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-canary"} + rollout := newTestRolloutWithInlineCanary(rolloutKey.Name, namespace) + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Verify rollout is created + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return r.Status.Phase == rolloutv1alpha1.RolloutPhaseInitialized + }, timeout, interval).Should(BeTrue()) + }) + + It("should create rolloutRun with inline batch strategy and trigger", func() { + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-inline-batch-trigger"} + rollout := newTestRolloutWithInlineBatch(rolloutKey.Name, namespace) + rollout.Annotations = map[string]string{ + rolloutapi.AnnoRolloutTrigger: "inline-batch-trigger", + } + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for rolloutRun to be created + Eventually(func() bool { + runList := &rolloutv1alpha1.RolloutRunList{} + if err := c.List(clusterinfo.WithCluster(ctx, clusterinfo.Fed), runList, client.InNamespace(namespace)); err != nil { + return false + } + for _, run := range runList.Items { + owner := metav1.GetControllerOf(&run) + if owner != nil && owner.Name == rolloutKey.Name && run.Name == "inline-batch-trigger" { + return run.Spec.Batch != nil + } + } + return false + }, timeout, interval).Should(BeTrue()) + }) + + It("should create rolloutRun with inline canary strategy and trigger", func() { + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-inline-canary-trigger"} + rollout := newTestRolloutWithInlineCanary(rolloutKey.Name, namespace) + rollout.Annotations = map[string]string{ + rolloutapi.AnnoRolloutTrigger: "inline-canary-trigger", + } + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for rolloutRun to be created + Eventually(func() bool { + runList := &rolloutv1alpha1.RolloutRunList{} + if err := c.List(clusterinfo.WithCluster(ctx, clusterinfo.Fed), runList, client.InNamespace(namespace)); err != nil { + return false + } + for _, run := range runList.Items { + owner := metav1.GetControllerOf(&run) + if owner != nil && owner.Name == rolloutKey.Name && run.Name == "inline-canary-trigger" { + return run.Spec.Canary != nil + } + } + return false + }, timeout, interval).Should(BeTrue()) + }) + }) + + Context("Trigger Policy", func() { + var ( + namespace = "test-ns-manual-policy" + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-manual-policy"} + ) + + It("should not auto-trigger when trigger policy is manual", func() { + Expect(createNamespace(namespace)).Should(Succeed()) + + rollout := newTestRolloutWithInlineBatch(rolloutKey.Name, namespace) + rollout.Spec.TriggerPolicy = rolloutv1alpha1.ManualTriggerPolicy + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait a bit to ensure no rolloutRun is created + Consistently(func() int { + runList := &rolloutv1alpha1.RolloutRunList{} + _ = c.List(clusterinfo.WithCluster(ctx, clusterinfo.Fed), runList, client.InNamespace(namespace)) + return len(runList.Items) + }, time.Second*3, interval).Should(Equal(0)) + }) + + It("should auto-trigger when trigger policy is auto (default)", func() { + // Use different rolloutKey for this test + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-auto-policy"} + + // Create rollout without trigger annotation + rollout := newTestRollout(rolloutKey.Name, namespace) + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait and verify rolloutRun is not created without trigger annotation + // The controller needs workloads to be in waiting-rollout state + Consistently(func() int { + runList := &rolloutv1alpha1.RolloutRunList{} + _ = c.List(clusterinfo.WithCluster(ctx, clusterinfo.Fed), runList, client.InNamespace(namespace)) + return len(runList.Items) + }, time.Second*3, interval).Should(Equal(0)) + }) + }) + + Context("Status Updates", func() { + var ( + namespace = "test-ns-status" + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-obs-gen"} + ) + + It("should update observed generation", func() { + Expect(createNamespace(namespace)).Should(Succeed()) + + rollout := newTestRollout(rolloutKey.Name, namespace) + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for observed generation to be set + Eventually(func() int64 { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return 0 + } + return r.Status.ObservedGeneration + }, timeout, interval).Should(Equal(rollout.Generation)) + }) + + It("should record conditions properly", func() { + rolloutKey = types.NamespacedName{Namespace: namespace, Name: "test-rollout-conditions"} + + rollout := newTestRollout(rolloutKey.Name, namespace) + Expect(c.Create(ctx, rollout)).Should(Succeed()) + + // Wait for conditions to be recorded + Eventually(func() bool { + r := &rolloutv1alpha1.Rollout{} + if err := c.Get(ctx, rolloutKey, r); err != nil { + return false + } + return len(r.Status.Conditions) > 0 + }, timeout, interval).Should(BeTrue()) + }) + }) +}) + +// Helper functions + +func newTestRollout(name, namespace string) *rolloutv1alpha1.Rollout { + return &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: map[string]string{}, + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "StatefulSet", + }, + }, + } +} + +func newTestRolloutWithInlineBatch(name, namespace string) *rolloutv1alpha1.Rollout { + rollout := newTestRollout(name, namespace) + rollout.Spec.BatchStrategy = &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Breakpoint: true, + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "", + Name: "test-workload", + }, + Replicas: intstr.FromString("25%"), + }, + }, + }, + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "", + Name: "test-workload", + }, + Replicas: intstr.FromString("100%"), + }, + }, + }, + }, + } + return rollout +} + +func newTestRolloutWithInlineCanary(name, namespace string) *rolloutv1alpha1.Rollout { + rollout := newTestRollout(name, namespace) + rollout.Spec.BatchStrategy = &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Name: "test-workload", + }, + Replicas: intstr.FromString("100%"), + }, + }, + }, + }, + } + rollout.Spec.CanaryStrategy = &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Name: "test-workload", + }, + Replicas: intstr.FromString("10%"), + }, + }, + } + return rollout +} + +func newTestRolloutStrategy(name, namespace string) *rolloutv1alpha1.RolloutStrategy { + return &rolloutv1alpha1.RolloutStrategy{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Batch: &rolloutv1alpha1.BatchStrategy{ + Batches: []rolloutv1alpha1.RolloutStep{ + { + Breakpoint: true, + Replicas: intstr.FromString("25%"), + }, + { + Replicas: intstr.FromString("100%"), + }, + }, + }, + } +} + +func containsString(slice []string, s string) bool { + for _, item := range slice { + if item == s { + return true + } + } + return false +} + +func createNamespace(namespace string) error { + // Create test namespace + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + return c.Create(ctx, ns) +} diff --git a/pkg/controllers/rollout/suite_test.go b/pkg/controllers/rollout/suite_test.go new file mode 100644 index 0000000..53608f0 --- /dev/null +++ b/pkg/controllers/rollout/suite_test.go @@ -0,0 +1,89 @@ +package rollout + +import ( + "context" + "os" + "path/filepath" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/klog/v2" + "k8s.io/klog/v2/klogr" + rolloutv1alpha1 "kusionstack.io/kube-api/rollout/v1alpha1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/manager" + + "kusionstack.io/rollout/pkg/controllers/registry" +) + +var ( + env *envtest.Environment + mgr manager.Manager + + ctx context.Context + cancel context.CancelFunc + c client.Client +) + +var _ = BeforeSuite(func() { + By("bootstrapping test environment") + + ctx, cancel = context.WithCancel(context.TODO()) + logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true))) + + testScheme := scheme.Scheme + err := rolloutv1alpha1.AddToScheme(testScheme) + Expect(err).NotTo(HaveOccurred()) + + env = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, + ControlPlaneStopTimeout: 60, // 60 seconds timeout for apiserver and etcd to stop + } + + config, err := env.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(config).NotTo(BeNil()) + + klog.InitFlags(nil) + defer klog.Flush() + ctrl.SetLogger(klogr.New()) + mgr, err = manager.New(config, manager.Options{ + MetricsBindAddress: "0", + Scheme: testScheme, + Logger: ctrl.Log, + }) + Expect(err).NotTo(HaveOccurred()) + + c = mgr.GetClient() + + // Use empty workload registry for testing + // Controller will handle workload lookup failures gracefully + registry.InitWorkloadRegistry(mgr) + Expect(NewReconciler(mgr, registry.Workloads).SetupWithManager(mgr)).NotTo(HaveOccurred()) + + go func() { + Expect(mgr.Start(ctx)).NotTo(HaveOccurred()) + }() +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + + cancel() + // Give manager time to stop gracefully before stopping envtest + time.Sleep(3 * time.Second) + _ = env.Stop() +}) + +func TestRolloutReconciler(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Testing Rollout Suite") +} diff --git a/pkg/controllers/rollout/utils.go b/pkg/controllers/rollout/utils.go index cc03646..687ccde 100644 --- a/pkg/controllers/rollout/utils.go +++ b/pkg/controllers/rollout/utils.go @@ -69,8 +69,16 @@ func filterWorkloadsByMatch(workloads []*workload.Info, match *rolloutv1alpha1.R } func constructRolloutRun(obj *rolloutv1alpha1.Rollout, strategy *rolloutv1alpha1.RolloutStrategy, workloadWrappers []*workload.Info, rolloutId string) *rolloutv1alpha1.RolloutRun { + var run *rolloutv1alpha1.RolloutRun + var hasInline bool + // Try inline strategy first + if run, hasInline = constructRolloutRunFromInlineStrategy(obj, workloadWrappers, rolloutId); hasInline { + return run + } + + // Fall back to strategy reference owner := metav1.NewControllerRef(obj, rolloutv1alpha1.SchemeGroupVersion.WithKind("Rollout")) - run := &rolloutv1alpha1.RolloutRun{ + run = &rolloutv1alpha1.RolloutRun{ ObjectMeta: metav1.ObjectMeta{ Namespace: obj.Namespace, Name: rolloutId, diff --git a/pkg/controllers/rollout/utils_test.go b/pkg/controllers/rollout/utils_test.go index 65f4e03..51615ad 100644 --- a/pkg/controllers/rollout/utils_test.go +++ b/pkg/controllers/rollout/utils_test.go @@ -178,3 +178,294 @@ func Test_constructRolloutRunBatches(t *testing.T) { }) } } + +func Test_constructRolloutRun(t *testing.T) { + tests := []struct { + name string + obj *rolloutv1alpha1.Rollout + strategy *rolloutv1alpha1.RolloutStrategy + workloadWrappers []*workload.Info + rolloutId string + wantInline bool // true if should use inline strategy + }{ + { + name: "inline batch strategy takes precedence over StrategyRef", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("20%"), + }, + }, + }, + }, + }, + }, + }, + strategy: &rolloutv1alpha1.RolloutStrategy{ + Batch: &rolloutv1alpha1.BatchStrategy{ + Batches: []rolloutv1alpha1.RolloutStep{ + { + Replicas: intstr.FromString("50%"), + Match: &rolloutv1alpha1.ResourceMatch{ + Names: []rolloutv1alpha1.CrossClusterObjectNameReference{ + {Cluster: "cluster-a", Name: "test-1"}, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantInline: true, + }, + { + name: "inline canary strategy takes precedence over StrategyRef", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + CanaryStrategy: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("10%"), + }, + }, + }, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("100%"), + }, + }, + }, + }, + }, + }, + }, + strategy: &rolloutv1alpha1.RolloutStrategy{ + Canary: &rolloutv1alpha1.CanaryStrategy{ + Replicas: intstr.FromString("20%"), + Match: &rolloutv1alpha1.ResourceMatch{ + Names: []rolloutv1alpha1.CrossClusterObjectNameReference{ + {Cluster: "cluster-a", Name: "test-1"}, + }, + }, + }, + Batch: &rolloutv1alpha1.BatchStrategy{ + Batches: []rolloutv1alpha1.RolloutStep{ + { + Replicas: intstr.FromString("100%"), + Match: &rolloutv1alpha1.ResourceMatch{ + Names: []rolloutv1alpha1.CrossClusterObjectNameReference{ + {Cluster: "cluster-a", Name: "test-1"}, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantInline: true, + }, + { + name: "fallback to StrategyRef when no inline strategy", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + }, + }, + strategy: &rolloutv1alpha1.RolloutStrategy{ + Batch: &rolloutv1alpha1.BatchStrategy{ + Batches: []rolloutv1alpha1.RolloutStep{ + { + Replicas: intstr.FromString("50%"), + Match: &rolloutv1alpha1.ResourceMatch{ + Names: []rolloutv1alpha1.CrossClusterObjectNameReference{ + {Cluster: "cluster-a", Name: "test-1"}, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantInline: false, + }, + { + name: "inline batch with canary together", + obj: &rolloutv1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test-rollout", + }, + Spec: rolloutv1alpha1.RolloutSpec{ + WorkloadRef: rolloutv1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + BatchStrategy: &rolloutv1alpha1.RolloutRunBatchStrategy{ + Batches: []rolloutv1alpha1.RolloutRunStep{ + { + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("25%"), + }, + }, + }, + }, + }, + CanaryStrategy: &rolloutv1alpha1.RolloutRunCanaryStrategy{ + Targets: []rolloutv1alpha1.RolloutRunStepTarget{ + { + CrossClusterObjectNameReference: rolloutv1alpha1.CrossClusterObjectNameReference{ + Cluster: "cluster-a", + Name: "test-1", + }, + Replicas: intstr.FromString("5%"), + }, + }, + }, + }, + }, + strategy: &rolloutv1alpha1.RolloutStrategy{ + Batch: &rolloutv1alpha1.BatchStrategy{ + Batches: []rolloutv1alpha1.RolloutStep{ + { + Replicas: intstr.FromString("50%"), + Match: &rolloutv1alpha1.ResourceMatch{ + Names: []rolloutv1alpha1.CrossClusterObjectNameReference{ + {Cluster: "cluster-a", Name: "test-1"}, + }, + }, + }, + }, + }, + }, + workloadWrappers: []*workload.Info{ + newTestInfo("cluster-a", "test", "test-1"), + }, + rolloutId: "test-rollout-1", + wantInline: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + run := constructRolloutRun(tt.obj, tt.strategy, tt.workloadWrappers, tt.rolloutId) + + if run == nil { + t.Errorf("constructRolloutRun() returned nil") + return + } + + // Verify basic fields + if run.Name != tt.rolloutId { + t.Errorf("run.Name = %v, want %v", run.Name, tt.rolloutId) + } + if run.Namespace != tt.obj.Namespace { + t.Errorf("run.Namespace = %v, want %v", run.Namespace, tt.obj.Namespace) + } + + if tt.wantInline { + // Verify that inline strategy was used (BatchSpec should be set based on inline config) + if tt.obj.Spec.BatchStrategy != nil { + if run.Spec.Batch == nil { + t.Errorf("run.Spec.Batch is nil, expected inline batch strategy to be used") + return + } + // Verify batch content matches inline config + if len(run.Spec.Batch.Batches) != len(tt.obj.Spec.BatchStrategy.Batches) { + t.Errorf("run.Spec.Batch.Batches length = %d, want %d", + len(run.Spec.Batch.Batches), len(tt.obj.Spec.BatchStrategy.Batches)) + } + } + + if tt.obj.Spec.CanaryStrategy != nil { + if run.Spec.Canary == nil { + t.Errorf("run.Spec.Canary is nil, expected inline canary strategy to be used") + return + } + // Verify canary content matches inline config + if len(run.Spec.Canary.Targets) != len(tt.obj.Spec.CanaryStrategy.Targets) { + t.Errorf("run.Spec.Canary.Targets length = %d, want %d", + len(run.Spec.Canary.Targets), len(tt.obj.Spec.CanaryStrategy.Targets)) + } + } + } else { + // Verify that StrategyRef was used + if run.Spec.Batch == nil { + t.Errorf("run.Spec.Batch is nil, expected StrategyRef batch to be used") + return + } + // Verify batch content matches strategy config + if len(run.Spec.Batch.Batches) != len(tt.strategy.Batch.Batches) { + t.Errorf("run.Spec.Batch.Batches length = %d, want %d", + len(run.Spec.Batch.Batches), len(tt.strategy.Batch.Batches)) + } + } + + // Verify owner reference exists + if len(run.OwnerReferences) != 1 { + t.Errorf("len(run.OwnerReferences) = %d, want 1", len(run.OwnerReferences)) + } else { + owner := run.OwnerReferences[0] + if owner.Kind != "Rollout" || owner.Name != tt.obj.Name { + t.Errorf("ownerReference = {Kind:%s, Name:%s}, want {Kind:Rollout, Name:%s}", + owner.Kind, owner.Name, tt.obj.Name) + } + } + }) + } +} diff --git a/pkg/controllers/rolloutrun/CLAUDE.md b/pkg/controllers/rolloutrun/CLAUDE.md new file mode 100644 index 0000000..6b5c934 --- /dev/null +++ b/pkg/controllers/rolloutrun/CLAUDE.md @@ -0,0 +1,338 @@ +# RolloutRun Controller 目录逻辑说明 + +## 概述 + +RolloutRun Controller 负责执行单次渐进式发布过程(RolloutRun),是 Rollout 的一次具体运行实例。它通过 Executor 来编排 Canary(金丝雀)和 Batch(分批)两种发布策略的执行流程。 + +## 核心职责 + +1. **执行发布流程** - 管理 RolloutRun 生命周期状态转换 +2. **协调执行器** - 调用 Executor 执行具体发布逻辑 +3. **等待工作负载就绪** - 监控工作负载状态,确保发布安全 +4. **管理流量路由** - 协调 TrafficManager 处理流量切换 +5. **支持 Webhook 钩子** - 在关键节点调用外部 Webhook + +## 目录结构 + +``` +rolloutrun/ +├── rolloutrun_controller.go # 主控制器逻辑 +├── initializer.go # 控制器初始化 +└── executor/ # 执行器模块 + ├── default.go # 主执行器 + ├── canary.go # 金丝雀发布执行器 + ├── batch.go # 分批发布执行器 + ├── context.go # 执行上下文 + ├── step_lifecycle.go # 步骤生命周期 + ├── command.go # 命令处理 + └── webhook/ # Webhook 模块 + ├── manager.go # Webhook 管理器 + ├── worker.go # Webhook 工作线程 + └── do_hook.go # Webhook 执行器 +``` + +## 核心数据结构 + +### RolloutRunReconciler + +```go +type RolloutRunReconciler struct { + *mixin.ReconcilerMixin + workloadRegistry registry.WorkloadRegistry + rvExpectation expectations.ResourceVersionExpectationInterface + executor *executor.Executor +} +``` + +### Executor + +```go +type Executor struct { + logger logr.Logger + canary *canaryExecutor // 金丝雀执行器 + batch *batchExecutor // 分批执行器 +} +``` + +## Reconcile 流程 + +### SetupWithManager + +```go +func (r *RolloutRunReconciler) SetupWithManager(mgr ctrl.Manager) error +``` + +监听的资源: +- `RolloutRun` - 使用 `ResourceVersionChangedPredicate` 和 `RolloutClassMatchesPredicate` + +### Reconcile 步骤 + +```go +func (r *RolloutRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) +``` + +1. **获取 RolloutRun 对象** +2. **检查期望满足** - 资源版本期望 +3. **管理 Finalizer** +4. **跳过已完成** - `IsCompleted()` 则直接返回 +5. **查找工作负载** (跨集群) - 普通负载 + 金丝雀负载 +6. **同步 RolloutRun** - 调用 Executor.Do() +7. **清理 Annotation** +8. **更新状态** + +## 生命周期状态机 + +``` +┌──────────────┐ +│ Initial │ +└──────────────┘ + ↓ +┌──────────────┐ +│ PreRollout │ ← PreRolloutHook +└──────────────┘ + ↓ +┌──────────────┐ +│ Progressing │ ← 执行 Canary + Batch +└──────────────┘ + ↓ +┌──────────────┐ +│ PostRollout │ ← PostRolloutHook +└──────────────┘ + ↓ +┌──────────────┐ +│ Succeeded │ ← 终态 +└──────────────┘ + +┌──────────────┐ +│ Pausing │ ──→ Paused ← 暂停/继续命令 +└──────────────┘ + +┌──────────────┐ +│ Canceling │ ──→ Canceled ← 终态 +└──────────────┘ +``` + +## Executor 执行流程 + +### 生命周期处理 + +```go +func (e *Executor) lifecycle(ctx *ExecutorContext) (done bool, result ctrl.Result, err error) +``` + +1. **命令优先检查** - 如果存在手动命令,先执行命令 +2. **删除检测** - 触发 Canceling 状态 +3. **状态转换** + +### Processing 处理 + +```go +func (e *Executor) doProcessing(ctx *ExecutorContext) (bool, ctrl.Result, error) +``` + +按顺序执行: +1. ** Canary 发布** (如果配置) +2. **Batch 分批发布** + +## Canary 发布状态机 + +``` +┌──────────────┐ +│ None │ +└──────────────┘ + ↓ +┌──────────────┐ +│ Pending │ +└──────────────┘ + ↓ +┌──────────────┐ +│PreCanaryHook │ ← 调用 PreCanaryStepHook Webhook +└──────────────┘ + ↓ +┌──────────────┐ +│ Running │ ──→ 流量分叉 ──→ 创建金丝雀资源 ──→ 添加金丝雀路由 +└──────────────┘ │ │ │ + ↓ ↓ ↓ + 等待就绪 等待就绪 等待就绪 + ↓ +┌──────────────┐ +│PostCanaryHook│ ← 调用 PostCanaryStepHook Webhook (完成后暂停) +└──────────────┘ + ↓ +┌──────────────┐ +│ResourceRecyc │ ← 删除金丝雀路由 ──→ 删除金丝雀资源 ──→ 重置路由 ──→ 删除分叉后端 +└──────────────┘ + ↓ +┌──────────────┐ +│ Succeeded │ +└──────────────┘ +``` + +### Canary 执行步骤 + +| 步骤 | 操作 | 说明 | +|------|------|------| +| `doInit()` | 初始化 | 添加金丝雀标记,初始化流量管理 | +| `doPreStepHook()` | 前置钩子 | 调用外部 Webhook | +| `doCanary()` | 金丝雀执行 | 1. Fork 流量后端
2. 初始化路由
3. 创建金丝雀资源
4. 添加金丝雀路由 | +| `doPostStepHook()` | 后置钩子 | 调用外部 Webhook (完成后自动暂停) | +| `release()` | 资源回收 | 删除金丝雀路由、资源、流量后端 | + +## Batch 发布状态机 + +``` +┌──────────────┐ +│ None │ +└──────────────┘ + ↓ +┌──────────────┐ +│ Pending │ +└──────────────┘ + ↓ +┌──────────────┐ +│PreBatchHook │ ← 调用 PreBatchStepHook Webhook +└──────────────┘ + ↓ +┌──────────────┐ +│ Running │ ──→ 更新 Partition ──→ 等待就绪 +└──────────────┘ + ↓ +┌──────────────┐ +│PostBatchHook │ ← 调用 PostBatchStepHook Webhook +└──────────────┘ + ↓ +┌──────────────┐ +│ResourceRecyc │ ← 清理进度标记 (最后一批) +└──────────────┘ + ↓ +┌──────────────┐ +│ Succeeded │ +└──────────────┘ +``` + +### Batch 执行步骤 + +| 步骤 | 操作 | 说明 | +|------|------|------| +| `doPausing()` | 暂停检查 | 初始化进度信息,检查 breakpoint | +| `doPreStepHook()` | 前置钩子 | 调用外部 Webhook | +| `doBatchUpgrading()` | 分批升级 | 更新 Partition,等待副本就绪 (支持滑动窗口) | +| `doPostStepHook()` | 后置钩子 | 调用外部 Webhook | +| `doRecycle()` | 资源回收 | 清理进度标记 (仅最后一批) | + +## 流量管理 + +Canary 发布涉及的流量操作: + +| 操作 | 说明 | +|------|------| +| `ForkBackends` | 分叉流量后端 | +| `InitializeRoute` | 初始化路由 | +| `AddCanaryRoute` | 添加金丝雀路由 | +| `DeleteCanaryRoute` | 删除金丝雀路由 | +| `ResetRoute` | 重置路由 | +| `DeleteForkedBackends` | 删除分叉的后端 | + +## 手动命令 + +| 命令 | 说明 | +|------|------| +| `pause` | 暂停发布 | +| `resume`/`continue` | 从暂停状态继续 | +| `retry` | 从错误状态重试 | +| `skip` | 跳过当前批次 (错误时) | +| `cancel` | 取消发布 | +| `forceSkipCurrentBatch` | 强制跳过当前批次 | + +## Webhook 系统 + +### 支持的钩子类型 + +| HookType | 触发时机 | +|----------|----------| +| `PreCanaryStepHook` | 金丝雀发布前 | +| `PostCanaryStepHook` | 金丝雀发布后 (完成后暂停) | +| `PreBatchStepHook` | 每个批次开始前 | +| `PostBatchStepHook` | 每个批次完成后 | + +### Webhook 协议 + +请求: `RolloutWebhookReview` +返回状态: `OK`/`Error`/`Processing` + +## Step 状态引擎 + +```go +type stepStateEngine struct { + lifecycle []stepLifecycle +} +``` + +每个步骤定义 `do()` 和 `cancel()` 函数: +- `do()` 返回 `(done bool, retry time.Duration, error)` +- `cancel()` 支持优雅取消 + +## Control 模块 + +### BatchReleaseControl + +| 方法 | 说明 | +|------|------| +| `Initialize()` | 预检查,添加进度标记 | +| `UpdatePartition()` | 更新工作负载 partition | +| `Finalize()` | 删除进度标记 | + +### CanaryReleaseControl + +| 方法 | 说明 | +|------|------| +| `Initialize()` | 预检查,添加进度标记 | +| `Finalize()` | 删除金丝雀资源,清理标记 | +| `CreateOrUpdate()` | 创建或更新金丝雀资源 | + +## 关键设计决策 + +1. **状态机模式** - 使用状态机管理复杂的状态转换 +2. **执行器分离** - Canary 和 Batch 独立执行器,支持组合 +3. **Webhook 扩展** - 提供标准化的 Webhook 集成点 +4. **滑动窗口** - Batch 支持渐进式副本调整 +5. **流量解耦** - 通过 TrafficManager 抽象流量操作 + +## Annotation 用途 + +| Annotation | 说明 | +|------------|------| +| `rollout.kusionstack.io/manual-command` | 手动命令传递 | + +## Finalizer 用途 + +``` +rollout.kusionstack.io/cleanup # RolloutRun 保护 +rollout.kusionstack.io/canary Protection # 金丝雀资源保护 +``` + +## ExecutorContext + +```go +type ExecutorContext struct { + context.Context + Client client.Client + Recorder record.EventRecorder + Accessor workload.Accessor + OwnerKind string + OwnerName string + RolloutRun *rolloutv1alpha1.RolloutRun + NewStatus *rolloutv1alpha1.RolloutRunStatus + Workloads *workload.Set + TrafficManager *trafficcontrol.Manager +} +``` + +执行上下文封装了执行所需的所有资源。 + +## 参考 + +- [渐进式交付 Rollout 设计文档](https://yuque.antfin.com/antcloud-paas/dp4wap/ae5myagvwh96cugn) +- Rollout Controller - 负责触发和管理 RolloutRun +- Traffic Control - 流量路由管理模块 +- Workload Registry - 工作负载适配层 \ No newline at end of file diff --git a/pkg/features/ontimestrategy/ontimestrategy.go b/pkg/features/ontimestrategy/ontimestrategy.go index 7babe3a..f607662 100644 --- a/pkg/features/ontimestrategy/ontimestrategy.go +++ b/pkg/features/ontimestrategy/ontimestrategy.go @@ -28,7 +28,16 @@ const ( ) type OneTimeStrategy struct { + // Batch is the original field for StrategyRef scenario. + // Used when referencing a RolloutStrategy CRD with match/replicas. + // Mutually exclusive with InlineBatch. Batch rolloutv1alpha1.BatchStrategy `json:"batch,omitempty"` + + // InlineBatch is for inline batch strategy scenario. + // Used when RolloutSpec uses BatchStrategy inline configuration. + // Mutually exclusive with Batch. + // Directly reuses RolloutRunBatchStrategy type. + InlineBatch *rolloutv1alpha1.RolloutRunBatchStrategy `json:"inlineBatch,omitempty"` } func (s *OneTimeStrategy) JSONData() []byte { @@ -36,8 +45,22 @@ func (s *OneTimeStrategy) JSONData() []byte { return data } +// ConvertFrom creates a OneTimeStrategy from RolloutStrategy (for StrategyRef scenario) func ConvertFrom(in *rolloutv1alpha1.RolloutStrategy) *OneTimeStrategy { + if in == nil || in.Batch == nil { + return &OneTimeStrategy{} + } return &OneTimeStrategy{ Batch: *in.Batch, } } + +// ConvertFromInline creates a OneTimeStrategy for inline batch strategy scenario +func ConvertFromInline(batchStrategy *rolloutv1alpha1.RolloutRunBatchStrategy) *OneTimeStrategy { + if batchStrategy == nil { + return &OneTimeStrategy{} + } + return &OneTimeStrategy{ + InlineBatch: batchStrategy, + } +} diff --git a/pkg/workload/info.go b/pkg/workload/info.go index 2b9074b..a3f2d8b 100644 --- a/pkg/workload/info.go +++ b/pkg/workload/info.go @@ -109,7 +109,7 @@ func (o *Info) CheckUpdatedReady(replicas int32, strictCheck bool) (bool, string if o.Status.UpdatedAvailableReplicas < replicas { return false, "workload updated available replicas is not satisfied" } - if strictCheck && o.Status.ObservedReplicas > o.Status.DesiredReplicas { + if strictCheck && (o.Status.ObservedReplicas > o.Status.DesiredReplicas || o.Status.TerminatingReplicas != 0) { return false, "workload observed replicas is more than desiredReplicas" } return true, ""