From 814e5568027274620fbfdec1584e3f835bcdcafd Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:04:59 -0400 Subject: [PATCH 01/10] chore: move Containerfiles to build/ dir Signed-off-by: Shane Utt --- .dockerignore | 4 +--- Makefile | 6 +++--- .../Containerfile.controlplane | 0 Containerfile.dataplane => build/Containerfile.dataplane | 0 Containerfile.udp_server => build/Containerfile.udp_server | 0 5 files changed, 4 insertions(+), 6 deletions(-) rename Containerfile.controlplane => build/Containerfile.controlplane (100%) rename Containerfile.dataplane => build/Containerfile.dataplane (100%) rename Containerfile.udp_server => build/Containerfile.udp_server (100%) diff --git a/.dockerignore b/.dockerignore index 8eeb3001..349b82d1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,6 @@ # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file # Ignore build and test binaries. .github/ -bin/ -testbin/ -bin/ +build/bin config/ *.md diff --git a/Makefile b/Makefile index 544ae9bb..ddaf1ae0 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,9 @@ BLIXT_DATAPLANE_IMAGE ?= ghcr.io/kubernetes-sigs/blixt-dataplane BLIXT_UDP_SERVER_IMAGE ?= ghcr.io/kubernetes-sigs/blixt-udp-test-server # Dockerfile paths for each service -CONTROLPLANE_DOCKERFILE ?= Containerfile.controlplane -DATAPLANE_DOCKERFILE ?= Containerfile.dataplane -UDP_SERVER_DOCKERFILE ?= Containerfile.udp_server +CONTROLPLANE_DOCKERFILE ?= build/Containerfile.controlplane +DATAPLANE_DOCKERFILE ?= build/Containerfile.dataplane +UDP_SERVER_DOCKERFILE ?= build/Containerfile.udp_server # Other testing variables EXISTING_CLUSTER ?= diff --git a/Containerfile.controlplane b/build/Containerfile.controlplane similarity index 100% rename from Containerfile.controlplane rename to build/Containerfile.controlplane diff --git a/Containerfile.dataplane b/build/Containerfile.dataplane similarity index 100% rename from Containerfile.dataplane rename to build/Containerfile.dataplane diff --git a/Containerfile.udp_server b/build/Containerfile.udp_server similarity index 100% rename from Containerfile.udp_server rename to build/Containerfile.udp_server From 56644f65514d956abd8ea0fc5fabf5854707fc50 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:11:01 -0400 Subject: [PATCH 02/10] chore: remove bpfd builds and testing The integration with bpfd is quite old, and in fact the project has since been renamed to bpfman. We have an open issue to add a bpfman integration, but in the meantime we can remove the old code. Signed-off-by: Shane Utt --- Makefile | 26 ---- config/bpf-bytecode/kustomization.yaml | 5 - config/bpf-bytecode/tc-egress.yaml | 21 --- config/bpf-bytecode/tc-ingress.yaml | 18 --- config/bpfd-install/kustomization.yaml | 15 --- config/bpfd-install/patch.yaml | 11 -- config/bpfd/bpfd.yaml | 23 ---- config/bpfd/kustomization.yaml | 50 ------- .../tests/integration-bpfd/kustomization.yaml | 12 -- dataplane/loader/src/main.rs | 39 +----- test/integration/suite_test.go | 124 ++---------------- 11 files changed, 11 insertions(+), 333 deletions(-) delete mode 100644 config/bpf-bytecode/kustomization.yaml delete mode 100644 config/bpf-bytecode/tc-egress.yaml delete mode 100644 config/bpf-bytecode/tc-ingress.yaml delete mode 100644 config/bpfd-install/kustomization.yaml delete mode 100644 config/bpfd-install/patch.yaml delete mode 100644 config/bpfd/bpfd.yaml delete mode 100644 config/bpfd/kustomization.yaml delete mode 100644 config/tests/integration-bpfd/kustomization.yaml diff --git a/Makefile b/Makefile index ddaf1ae0..f68c575a 100644 --- a/Makefile +++ b/Makefile @@ -241,38 +241,12 @@ build.all.images: $(MAKE) build.image.dataplane $(MAKE) build.image.udp_server -.PHONY: build.bytecode.images -build.bytecode.images: build - docker build \ - --build-arg PROGRAM_NAME=blixt-tc-ingress \ - --build-arg BPF_FUNCTION_NAME=tc_ingress \ - --build-arg PROGRAM_TYPE=tc \ - --build-arg BYTECODE_FILENAME=loader \ - -f https://raw.githubusercontent.com/bpfd-dev/bpfd/main/packaging/container-deployment/Containerfile.bytecode \ - ./target/bpfel-unknown-none/debug -t quay.io/bpfd-bytecode/blixt-tc-ingress:latest - docker build \ - --build-arg PROGRAM_NAME=blixt-tc-egress \ - --build-arg BPF_FUNCTION_NAME=tc_egress \ - --build-arg PROGRAM_TYPE=tc \ - --build-arg BYTECODE_FILENAME=loader \ - -f https://raw.githubusercontent.com/bpfd-dev/bpfd/main/packaging/container-deployment/Containerfile.bytecode \ - ./target/bpfel-unknown-none/debug -t quay.io/bpfd-bytecode/blixt-tc-egress:latest - -.PHONY: push.bytecode.images -push.bytecode.images: build.bytecode.images - docker push quay.io/bpfd-bytecode/blixt-tc-egress:latest - docker push quay.io/bpfd-bytecode/blixt-tc-ingress:latest - ##@ Deployment ifndef ignore-not-found ignore-not-found = false endif -.PHONY: install-bpfd -install-bpfd: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/bpfd | kubectl apply -f - - .PHONY: install install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/crd | kubectl apply -f - diff --git a/config/bpf-bytecode/kustomization.yaml b/config/bpf-bytecode/kustomization.yaml deleted file mode 100644 index d505e0e7..00000000 --- a/config/bpf-bytecode/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- tc-ingress.yaml -- tc-egress.yaml diff --git a/config/bpf-bytecode/tc-egress.yaml b/config/bpf-bytecode/tc-egress.yaml deleted file mode 100644 index 73b18b73..00000000 --- a/config/bpf-bytecode/tc-egress.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: bpfd.dev/v1alpha1 -kind: TcProgram -metadata: - labels: - app.kubernetes.io/name: blixt-tc-egress - name: tc-egress -spec: - bpffunctionname: tc_egress - # Select all nodes - nodeselector: {} - interfaceselector: - primarynodeinterface: true - priority: 0 - direction: egress - bytecode: - image: - url: quay.io/bpfd-bytecode/blixt-tc-egress:latest - imagepullpolicy: Always - mapownerselector: - matchLabels: - bpfd.dev/ownedByProgram: blixt-tc-ingress diff --git a/config/bpf-bytecode/tc-ingress.yaml b/config/bpf-bytecode/tc-ingress.yaml deleted file mode 100644 index 8ce35773..00000000 --- a/config/bpf-bytecode/tc-ingress.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: bpfd.dev/v1alpha1 -kind: TcProgram -metadata: - labels: - app.kubernetes.io/name: blixt-tc-ingress - name: tc-ingress -spec: - bpffunctionname: tc_ingress - # Select all nodes - nodeselector: {} - interfaceselector: - primarynodeinterface: true - priority: 0 - direction: ingress - bytecode: - image: - url: quay.io/bpfd-bytecode/blixt-tc-ingress:latest - imagepullpolicy: Always diff --git a/config/bpfd-install/kustomization.yaml b/config/bpfd-install/kustomization.yaml deleted file mode 100644 index a6abf901..00000000 --- a/config/bpfd-install/kustomization.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -## bpfd CRDs -- https://github.com/bpfd-dev/bpfd/releases/download/v0.3.0/bpfd-crds-install-v0.3.0.yaml -## bpfd Operator -- https://github.com/bpfd-dev/bpfd/releases/download/v0.3.0/bpfd-operator-install-v0.3.0.yaml - -patches: -- path: patch.yaml - target: - kind: ConfigMap - name: config - version: v1 - name: bpfd-config diff --git a/config/bpfd-install/patch.yaml b/config/bpfd-install/patch.yaml deleted file mode 100644 index 10f002e9..00000000 --- a/config/bpfd-install/patch.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: config -data: - ## Can be configured at runtime - bpfd.log.level: "debug" - bpfd.agent.log.level: "debug" - bpfd.enable.csi: "true" - ## Custom temporary blixt build - bpfd.image: quay.io/bpfd/bpfd:blixt diff --git a/config/bpfd/bpfd.yaml b/config/bpfd/bpfd.yaml deleted file mode 100644 index 1c9cb956..00000000 --- a/config/bpfd/bpfd.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: dataplane - namespace: system -spec: - template: - spec: - containers: - - name: dataplane - securityContext: - privileged: false - volumeMounts: - - name: bpf-maps - mountPath: /run/bpfd/fs/maps - readOnly: true - volumes: - - name: bpf-maps - csi: - driver: csi.bpfd.dev - volumeAttributes: - csi.bpfd.dev/program: blixt-tc-egress - csi.bpfd.dev/maps: AYA_LOGS,AYA_LOG_BUF,BACKENDS,BLIXT_CONNTRACK,GATEWAY_INDEXES diff --git a/config/bpfd/kustomization.yaml b/config/bpfd/kustomization.yaml deleted file mode 100644 index b98d7f7f..00000000 --- a/config/bpfd/kustomization.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Adds namespace to all resources. -namespace: blixt-system - -# Value of this field is prepended to the -# names of all resources, e.g. a deployment named -# "wordpress" becomes "alices-wordpress". -# Note that it should also match with the prefix (text before '-') of the namespace -# field above. -namePrefix: blixt- - -# Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue - -# - ../crd # TODO: no CRDs yet -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controlplane to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. - -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -#- manager_config_patch.yaml - -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- ../bpf-bytecode -- ../rbac -- ../manager -- ../dataplane -patches: -- path: bpfd.yaml diff --git a/config/tests/integration-bpfd/kustomization.yaml b/config/tests/integration-bpfd/kustomization.yaml deleted file mode 100644 index e3ab1994..00000000 --- a/config/tests/integration-bpfd/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ - -images: -- name: ghcr.io/kubernetes-sigs/blixt-dataplane - newTag: integration-tests -- name: ghcr.io/kubernetes-sigs/blixt-controlplane - newTag: integration-tests -- name: ghcr.io/kubernetes-sigs/blixt-udp-test-server - newTag: integration-tests -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- ../../bpfd diff --git a/dataplane/loader/src/main.rs b/dataplane/loader/src/main.rs index e14882bf..2ec5ffe8 100644 --- a/dataplane/loader/src/main.rs +++ b/dataplane/loader/src/main.rs @@ -4,11 +4,11 @@ Copyright 2023 The Kubernetes Authors. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -use std::{net::Ipv4Addr, path::Path}; +use std::net::Ipv4Addr; use anyhow::Context; use api_server::start as start_api_server; -use aya::maps::{HashMap, Map, MapData}; +use aya::maps::HashMap; use aya::programs::{tc, SchedClassifier, TcAttachType}; use aya::{include_bytes_aligned, Bpf}; use aya_log::BpfLogger; @@ -26,42 +26,8 @@ struct Opt { async fn main() -> Result<(), anyhow::Error> { let opt = Opt::parse(); - // TODO(astoycos) Let's determine a better way to let processes know bpfd is up and running, - // Maybe if we're not running as a privileged deployment ALWAYS wait for bpfd?. - std::thread::sleep(std::time::Duration::from_secs(5)); env_logger::init(); - // If bpfd loaded the programs just load the maps. - let bpfd_maps = Path::new("/run/bpfd/fs/maps"); - - if bpfd_maps.exists() { - info!("programs loaded via bpfd"); - let backends: HashMap<_, BackendKey, BackendList> = Map::HashMap( - MapData::from_pin(bpfd_maps.join("BACKENDS")).expect("no maps named BACKENDS"), - ) - .try_into()?; - - let gateway_indexes: HashMap<_, BackendKey, u16> = Map::HashMap( - MapData::from_pin(bpfd_maps.join("GATEWAY_INDEXES")) - .expect("no maps named GATEWAY_INDEXES"), - ) - .try_into()?; - let tcp_conns: HashMap<_, ClientKey, LoadBalancerMapping> = Map::HashMap( - MapData::from_pin(bpfd_maps.join("LB_CONNECTIONS")) - .expect("no maps named LB_CONNECTIONS"), - ) - .try_into()?; - - info!("starting api server"); - start_api_server( - Ipv4Addr::new(0, 0, 0, 0), - 9874, - backends, - gateway_indexes, - tcp_conns, - ) - .await?; - } else { info!("loading ebpf programs"); #[cfg(debug_assertions)] @@ -115,7 +81,6 @@ async fn main() -> Result<(), anyhow::Error> { tcp_conns, ) .await?; - } info!("Exiting..."); diff --git a/test/integration/suite_test.go b/test/integration/suite_test.go index c6e47b35..4bdc4da5 100644 --- a/test/integration/suite_test.go +++ b/test/integration/suite_test.go @@ -55,20 +55,13 @@ var ( useExistingCluster = func() bool { return os.Getenv("BLIX_USE_EXISTING_KIND_CLUSTER") == "true" }() keepTestCluster = func() bool { return os.Getenv("BLIXT_TEST_KEEP_CLUSTER") == "true" || useExistingCluster }() keepKustomizeDeploys = func() bool { return os.Getenv("BLIXT_TEST_KEEP_KUSTOMIZE_DEPLOYS") == "true" }() - blixtUseBpfd = func() bool { return os.Getenv("BLIXT_USE_BPFD") == "true" && useExistingCluster }() mainCleanupKey = "main" ) const ( gwCRDsKustomize = "https://github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v0.8.1" - testKustomizeBpfdInstall = "../../config/bpfd-install" testKustomize = "../../config/tests/integration" - testKustomizeBpfd = "../../config/tests/integration-bpfd" - bpfdNs = "bpfd" - bpfdConfigName = "bpfd-config" - bpfdOperatorName = "bpfd-operator" - bpfdDsName = "bpfd-daemon" ) func TestMain(m *testing.M) { @@ -128,23 +121,6 @@ func TestMain(m *testing.M) { gwclient, err = versioned.NewForConfig(env.Cluster().Config()) exitOnErr(err) - if blixtUseBpfd { - // deploy bpfd for blixt - fmt.Println("INFO: deploying bpfd") - exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), testKustomizeBpfdInstall)) - if !keepKustomizeDeploys { - addCleanup(mainCleanupKey, func(context.Context) error { - cleanupLog("delete bpfd configmap to cleanup bpfd daemon") - env.Cluster().Client().CoreV1().ConfigMaps(bpfdNs).Delete(ctx, bpfdConfigName, metav1.DeleteOptions{}) - waitForBpfdConfigDelete(ctx, env) - cleanupLog("deleting bpfd namespace") - return env.Cluster().Client().CoreV1().Namespaces().Delete(ctx, bpfdNs, metav1.DeleteOptions{}) - }) - } - - exitOnErr(waitForBpfdReadiness(ctx, env)) - } - // deploy the Gateway API CRDs fmt.Println("INFO: deploying Gateway API CRDs") exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), gwCRDsKustomize)) @@ -155,28 +131,15 @@ func TestMain(m *testing.M) { }) } - if blixtUseBpfd { - // deploy the blixt controlplane and dataplane, rbac permissions, e.t.c. - // this is what the tests will actually run against. - fmt.Println("INFO: deploying blixt via config/test-bpfd kustomize") - exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), testKustomizeBpfd)) - if !keepKustomizeDeploys { - addCleanup(mainCleanupKey, func(context.Context) error { - cleanupLog("cleaning up blixt via config/test kustomize") - return clusters.KustomizeDeleteForCluster(ctx, env.Cluster(), testKustomizeBpfd) - }) - } - } else { - // deploy the blixt controlplane and dataplane, rbac permissions, e.t.c. - // this is what the tests will actually run against. - fmt.Println("INFO: deploying blixt via config/test kustomize") - exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), testKustomize)) - if !keepKustomizeDeploys { - addCleanup(mainCleanupKey, func(context.Context) error { - cleanupLog("cleaning up blixt via config/test kustomize") - return clusters.KustomizeDeleteForCluster(ctx, env.Cluster(), testKustomize) - }) - } + // deploy the blixt controlplane and dataplane, rbac permissions, e.t.c. + // this is what the tests will actually run against. + fmt.Println("INFO: deploying blixt via config/test kustomize") + exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), testKustomize)) + if !keepKustomizeDeploys { + addCleanup(mainCleanupKey, func(context.Context) error { + cleanupLog("cleaning up blixt via config/test kustomize") + return clusters.KustomizeDeleteForCluster(ctx, env.Cluster(), testKustomize) + }) } fmt.Println("INFO: waiting for Blixt component readiness") @@ -245,75 +208,6 @@ func runCleanup(cleanupKey string) (cleanupErr error) { return } -func waitForBpfdReadiness(ctx context.Context, env environments.Environment) error { - for { - time.Sleep(2 * time.Second) - select { - case <-ctx.Done(): - if err := ctx.Err(); err != nil { - return fmt.Errorf("context completed while waiting for components: %w", err) - } - return fmt.Errorf("context completed while waiting for components") - default: - fmt.Println("INFO: waiting for bpfd") - var controlplaneReady, dataplaneReady bool - - controlplane, err := env.Cluster().Client().AppsV1().Deployments(bpfdNs).Get(ctx, bpfdOperatorName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - fmt.Println("INFO: bpfd-operator dep not found yet") - continue - } - return err - } - if controlplane.Status.AvailableReplicas > 0 { - controlplaneReady = true - } - - dataplane, err := env.Cluster().Client().AppsV1().DaemonSets(bpfdNs).Get(ctx, bpfdDsName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - fmt.Println("INFO: bpfd daemon not found yet") - continue - } - return err - } - if dataplane.Status.NumberAvailable > 0 { - dataplaneReady = true - } - - if controlplaneReady && dataplaneReady { - fmt.Println("INFO: bpfd-operator is ready") - return nil - } - } - } -} - -func waitForBpfdConfigDelete(ctx context.Context, env environments.Environment) error { - for { - time.Sleep(2 * time.Second) - select { - case <-ctx.Done(): - if err := ctx.Err(); err != nil { - return fmt.Errorf("context completed while waiting for components: %w", err) - } - return fmt.Errorf("context completed while waiting for components") - default: - fmt.Println("INFO: waiting for bpfd config deletion") - - _, err := env.Cluster().Client().CoreV1().ConfigMaps(bpfdNs).Get(ctx, bpfdConfigName, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - fmt.Println("INFO: bpfd configmap deleted successfully") - return nil - } - return err - } - } - } -} - func waitForDataplaneReadiness(ctx context.Context, env environments.Environment) error { for { select { From 94fb2ac68456cf7b1dc974f644d3a7d9a8b99334 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:13:49 -0400 Subject: [PATCH 03/10] chore: put the build binaries in the build dir Signed-off-by: Shane Utt --- .gitignore | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 0ae4531e..d5a6c915 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ *.dll *.so *.dylib -bin/* +build/bin/* # xtask targets target/ diff --git a/Makefile b/Makefile index f68c575a..ab53a728 100644 --- a/Makefile +++ b/Makefile @@ -267,7 +267,7 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi ##@ Build Dependencies ## Location to install dependencies to -LOCALBIN ?= $(shell pwd)/bin +LOCALBIN ?= $(shell pwd)/build/bin $(LOCALBIN): mkdir -p $(LOCALBIN) From defc60a0a33a3945962161a45a8581f215e48bdb Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:16:20 -0400 Subject: [PATCH 04/10] docs: update CHANGELOG.md Signed-off-by: Shane Utt --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c671588..2ea38139 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,16 @@ ## Table of Contents +- [v0.3.0](#v030) - [v0.2.0](#v020) - [v0.1.0](#v010) ## Unreleased -### Added +- The Golang control-plane has been removed, and replaced by a control-plane + written in Rust using [kube-rs](https://github.com/kube-rs). + +## v0.3.0 - A new test suite was added to run conformance tests. We now have initial support for running [Gateway API Conformance][gwconf] tests. From 7eefb376a18045aa3f7ed0df9727e6c477556cab Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:25:21 -0400 Subject: [PATCH 05/10] fix: enable default features for anyhow dependency Signed-off-by: Shane Utt --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f71db32f..5ca399a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "dataplane/api-server", "dataplane/common", @@ -15,7 +16,7 @@ repository = "https://github.com/kubernetes-sigs/blixt" version = "0.3.0" [workspace.dependencies] -anyhow = { version = "1", default-features = false } +anyhow = { version = "1", default-features = true } api-server = { version = "0.3.0", path = "./dataplane/api-server" } aya = { version = "0.12.0", default-features = false } aya-ebpf = { git = "https://github.com/aya-rs/aya", default-features = false } From 4e98bd066e2f8b1fe992aad7bed06e11a8bc6c80 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:11:57 -0400 Subject: [PATCH 06/10] chore: remove the golang control-plane Signed-off-by: Shane Utt --- .gitattributes | 4 - .github/workflows/ci.yaml | 147 ----- .github/workflows/codeql.yml | 82 --- .github/workflows/lint.yaml | 40 -- .github/workflows/test.yaml | 162 ------ .gitignore | 9 - PROJECT | 30 - controllers/dataplane_controller.go | 172 ------ controllers/docs.go | 20 - controllers/gateway_controller.go | 201 ------- controllers/gateway_controller_status.go | 229 -------- controllers/gateway_controller_test.go | 472 ---------------- controllers/gateway_controller_utils.go | 389 ------------- controllers/gatewayclass_controller.go | 121 ---- controllers/suite_test.go | 77 --- controllers/tcproute_controller.go | 252 --------- .../tcproute_controller_watch_utils.go | 108 ---- controllers/udproute_controller.go | 251 --------- .../udproute_controller_watch_utils.go | 108 ---- controllers/utils.go | 35 -- controlplane/Dockerfile | 15 - go.mod | 114 ---- go.sum | 393 ------------- hack/boilerplate.go.txt | 0 internal/dataplane/client/backends.pb.go | 520 ------------------ internal/dataplane/client/backends_grpc.pb.go | 184 ------- internal/dataplane/client/client.go | 228 -------- internal/dataplane/client/utils.go | 238 -------- internal/test/utils/utils.go | 151 ----- main.go | 216 -------- pkg/vars/vars.go | 57 -- test/conformance/gateway_conformance_test.go | 122 ---- test/conformance/suite_test.go | 108 ---- test/performance/suite_test.go | 99 ---- 34 files changed, 5354 deletions(-) delete mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/codeql.yml delete mode 100644 .github/workflows/lint.yaml delete mode 100644 .github/workflows/test.yaml delete mode 100644 PROJECT delete mode 100644 controllers/dataplane_controller.go delete mode 100644 controllers/docs.go delete mode 100644 controllers/gateway_controller.go delete mode 100644 controllers/gateway_controller_status.go delete mode 100644 controllers/gateway_controller_test.go delete mode 100644 controllers/gateway_controller_utils.go delete mode 100644 controllers/gatewayclass_controller.go delete mode 100644 controllers/suite_test.go delete mode 100644 controllers/tcproute_controller.go delete mode 100644 controllers/tcproute_controller_watch_utils.go delete mode 100644 controllers/udproute_controller.go delete mode 100644 controllers/udproute_controller_watch_utils.go delete mode 100644 controllers/utils.go delete mode 100644 controlplane/Dockerfile delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 hack/boilerplate.go.txt delete mode 100644 internal/dataplane/client/backends.pb.go delete mode 100644 internal/dataplane/client/backends_grpc.pb.go delete mode 100644 internal/dataplane/client/client.go delete mode 100644 internal/dataplane/client/utils.go delete mode 100644 internal/test/utils/utils.go delete mode 100644 main.go delete mode 100644 pkg/vars/vars.go delete mode 100644 test/conformance/gateway_conformance_test.go delete mode 100644 test/conformance/suite_test.go delete mode 100644 test/performance/suite_test.go diff --git a/.gitattributes b/.gitattributes index 2a92c284..5ca518e9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +1,4 @@ bin/** linguist-detectable=false config/** linguist-detectable=false -controllers/** linguist-detectable=false -internal/** linguist-detectable=false -pkg/** linguist-detectable=false test/** linguist-detectable=false tools/** linguist-detectable=false -hack/** linguist-detectable=false diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index 7a2ac0bd..00000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,147 +0,0 @@ -name: CI -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} -on: - pull_request: {} - push: - branches: - - main - -jobs: - get-changed-files: - name: Get Changed Files - runs-on: ubuntu-20.04 - outputs: - changed-files: ${{ steps.changed-files.outputs.all_changed_and_modified_files }} - control-plane-changed: ${{ steps.control-plane-changed.outputs.any_modified }} - dataplane-changed: ${{ steps.dataplane-changed.outputs.any_modified }} - workflow-changed: ${{ steps.workflow-changed.outputs.any_modified }} - steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - with: - fetch-depth: 0 - - name: Get list of all changes - uses: tj-actions/changed-files@716b1e13042866565e00e85fd4ec490e186c4a2f - id: changed-files - - name: Check if any files related to the building of the control plane image have changed (see the Dockerfiles) - uses: tj-actions/changed-files@716b1e13042866565e00e85fd4ec490e186c4a2f - id: control-plane-changed - with: - files: | - Containerfile.controlplane - go.mod - go.sum - main.go - controllers/ - LICENSE - - name: Check if any files related to the building of the dataplane image have changed (see the Dockerfiles) - uses: tj-actions/changed-files@716b1e13042866565e00e85fd4ec490e186c4a2f - id: dataplane-changed - with: - files: | - Containerfile.dataplane - dataplane/go.mod - dataplane/go.sum - dataplane/main.go - dataplane/xdp.c - dataplane/LICENCE - - name: Check if any of the workflow files have changed - uses: tj-actions/changed-files@716b1e13042866565e00e85fd4ec490e186c4a2f - id: workflow-changed - with: - files: | - .github/workflows/ - - name: List all changed files - run: | - for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - echo "$file" - done - - pr-docker-build: - name: PR Docker build - needs: [ get-changed-files ] - if: >- - github.event_name == 'pull_request' - && ( - needs.get-changed-files.outputs.control-plane-changed == 'true' - || needs.get-changed-files.outputs.dataplane-changed == 'true' - || needs.get-changed-files.outputs.workflow-changed == 'true' - ) - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c74574e6c82eeedc46366be1b0d287eff9085eb6 - with: - install: true - - name: Docker build - Control Plane - uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 - with: - context: . - file: Containerfile.controlplane - cache-from: type=gha - cache-to: type=gha,mode=max - tags: kubernetes-sigs/blixt-controlplane:pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} - outputs: type=docker,dest=/tmp/blixt-controlplane.tar - - name: Upload Image Artifact - Control Plane - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 - with: - name: blixt-controlplane - path: /tmp/blixt-controlplane.tar - - name: Docker build - Dataplane - uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 - with: - context: . - file: Containerfile.dataplane - cache-from: type=gha - cache-to: type=gha,mode=max - tags: kubernetes-sigs/blixt-dataplane:pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} - outputs: type=docker,dest=/tmp/blixt-dataplane.tar - - name: Upload Image Artifact - Dataplane - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 - with: - name: blixt-dataplane - path: /tmp/blixt-dataplane.tar - - main-docker-build: - name: Main branch Docker build - needs: [ get-changed-files ] - if: >- - github.event_name == 'push' - && ( - needs.get-changed-files.outputs.control-plane-changed == 'true' - || needs.get-changed-files.outputs.dataplane-changed == 'true' - || needs.get-changed-files.outputs.workflow-changed == 'true' - ) - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c74574e6c82eeedc46366be1b0d287eff9085eb6 - with: - install: true - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Docker build - Control Plane - uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 - with: - context: . - file: Containerfile.controlplane - push: false # TODO: https://github.com/kubernetes-sigs/blixt/issues/106 - cache-from: type=gha - cache-to: type=gha,mode=max - tags: ghcr.io/kubernetes-sigs/blixt-controlplane:latest - - name: Docker build - Data Plane - uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 - with: - context: . - file: Containerfile.dataplane - push: false # TODO: https://github.com/kubernetes-sigs/blixt/issues/106 - cache-from: type=gha - cache-to: type=gha,mode=max - tags: ghcr.io/kubernetes-sigs/blixt-dataplane:latest diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 32a329ba..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,82 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ "main" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "main" ] - schedule: - - cron: '25 5 * * 0' - -jobs: - analyze: - name: Analyze - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners - # Consider using larger runners for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'go' ] - # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] - # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml deleted file mode 100644 index df8d967b..00000000 --- a/.github/workflows/lint.yaml +++ /dev/null @@ -1,40 +0,0 @@ -name: lint - -on: - pull_request: - branches: - - '*' - push: - branches: - - 'main' - tags: - - '*' - workflow_dispatch: {} - -jobs: - golangci-lint: - runs-on: ubuntu-latest - steps: - - - name: Setup go - uses: actions/setup-go@v3 - with: - go-version: '^1.19' - - - name: Cache Go modules - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-build-codegen-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-build-codegen- - - - name: Checkout repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Run Linters - uses: golangci/golangci-lint-action@v3 - with: - args: --timeout 3m --verbose diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 1c12ee24..00000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,162 +0,0 @@ -name: tests - -on: - pull_request: - branches: - - '*' - push: - branches: - - 'main' - tags: - - '*' - workflow_dispatch: {} - -jobs: - unit-tests: - runs-on: ubuntu-latest - steps: - - - name: setup golang - uses: actions/setup-go@v3 - with: - go-version: '^1.19' - - - name: cache go modules - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-build-codegen-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-build-codegen- - - - name: checkout repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: run unit tests - run: go test -race -v ./... - - integration-tests: - runs-on: ubuntu-latest - steps: - - - name: setup golang - uses: actions/setup-go@v3 - with: - go-version: '^1.19' - - - name: cache go modules - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-build-codegen-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-build-codegen- - - - name: cache image builds - uses: actions/cache@v3 - with: - path: /var/lib/docker/ - key: ${{ runner.os }}-build-image-cache - restore-keys: | - ${{ runner.os }}-build-image-cache- - - - name: checkout repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: build images - run: make build.all.images TAG=integration-tests - - - name: Set cluster name in enviornment - run: echo "BLIXT_TEST_CLUSTER_NAME=`echo blixt-ci-${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV - - - name: run integration tests - run: make test.integration - env: - BLIXT_TEST_KEEP_CLUSTER: true - BLIXT_CONTROLPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-controlplane" - BLIXT_DATAPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-dataplane" - BLIXT_UDP_SERVER_IMAGE: "ghcr.io/kubernetes-sigs/blixt-udp-test-server" - TAG: "integration-tests" - - - name: run integration tests - run: make test.icmp.integration - env: - BLIXT_USE_EXISTING_KIND_CLUSTER: true - BLIXT_CONTROLPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-controlplane" - BLIXT_DATAPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-dataplane" - BLIXT_UDP_SERVER_IMAGE: "ghcr.io/kubernetes-sigs/blixt-udp-test-server" - TAG: "integration-tests" - - # temporarily disabled due to upstream changes in bpfman (previously bpfd) - # ref: https://github.com/kubernetes-sigs/blixt/issues/152 - # - name: run integration tests with bpfd - # run: make test.integration - # env: - # BLIXT_CONTROLPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-controlplane" - # BLIXT_DATAPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-dataplane" - # BLIXT_UDP_SERVER_IMAGE: "ghcr.io/kubernetes-sigs/blixt-udp-test-server" - # BLIXT_USE_BPFD: true - # TAG: "integration-tests" - - ## Upload diagnostics if integration test step failed. - - name: upload diagnostics - if: ${{ failure() }} - uses: actions/upload-artifact@v3 - with: - name: blixt-integration-test-diag - path: /tmp/ktf-diag* - if-no-files-found: ignore - - conformance-tests: - runs-on: ubuntu-latest - steps: - - - name: setup golang - uses: actions/setup-go@v3 - with: - go-version: '^1.19' - - - name: cache go modules - uses: actions/cache@v3 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-build-codegen-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-build-codegen- - - - name: cache image builds - uses: actions/cache@v3 - with: - path: /var/lib/docker/ - key: ${{ runner.os }}-build-image-cache - restore-keys: | - ${{ runner.os }}-build-image-cache- - - - name: checkout repository - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: build images - run: make build.all.images TAG=conformance-tests - - - name: run conformance tests - run: make test.conformance - env: - BLIXT_CONTROLPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-controlplane" - BLIXT_DATAPLANE_IMAGE: "ghcr.io/kubernetes-sigs/blixt-dataplane" - BLIXT_UDP_SERVER_IMAGE: "ghcr.io/kubernetes-sigs/blixt-udp-test-server" - TAG: "conformance-tests" - - ## Upload diagnostics if conformance test step failed. - - name: upload diagnostics - if: ${{ failure() }} - uses: actions/upload-artifact@v3 - with: - name: blixt-integration-test-diag - path: /tmp/ktf-diag* - if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index d5a6c915..df1ae6ad 100644 --- a/.gitignore +++ b/.gitignore @@ -9,14 +9,5 @@ build/bin/* # xtask targets target/ -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - # Personal TODO lists TODO diff --git a/PROJECT b/PROJECT deleted file mode 100644 index f06bc31a..00000000 --- a/PROJECT +++ /dev/null @@ -1,30 +0,0 @@ -domain: blixt.gateway.networking.k8s.io -layout: -- go.kubebuilder.io/v3 -plugins: - manifests.sdk.operatorframework.io/v2: {} - scorecard.sdk.operatorframework.io/v2: {} -projectName: blixt -repo: github.com/kubernetes-sigs/blixt -resources: -- controller: true - domain: networking.k8s.io - group: gateway - kind: Gateway - version: v1beta1 -- controller: true - domain: networking.k8s.io - group: gateway - kind: GatewayClass - version: v1beta1 -- controller: true - domain: networking.k8s.io - group: gateway - kind: UDPRoute - version: v1alpha2 -- controller: true - domain: networking.k8s.io - group: gateway - kind: TCPRoute - version: v1alpha2 -version: "3" diff --git a/controllers/dataplane_controller.go b/controllers/dataplane_controller.go deleted file mode 100644 index caeb02ad..00000000 --- a/controllers/dataplane_controller.go +++ /dev/null @@ -1,172 +0,0 @@ -package controllers - -import ( - "context" - "fmt" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/predicate" - - dataplane "github.com/kubernetes-sigs/blixt/internal/dataplane/client" - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/finalizers,verbs=update - -//+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=core,resources=services/status,verbs=get - -//+kubebuilder:rbac:groups=core,resources=endpoints,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=core,resources=endpoints/status,verbs=get - -// DataplaneReconciler reconciles the dataplane pods. -type DataplaneReconciler struct { - client.Client - scheme *runtime.Scheme - - backendsClientManager *dataplane.BackendsClientManager - - updates chan event.GenericEvent -} - -func NewDataplaneReconciler(client client.Client, schema *runtime.Scheme, manager *dataplane.BackendsClientManager) *DataplaneReconciler { - return &DataplaneReconciler{ - Client: client, - scheme: schema, - backendsClientManager: manager, - updates: make(chan event.GenericEvent, 1), - } -} - -var ( - podOwnerKey = ".metadata.controller" - apiGVStr = appsv1.SchemeGroupVersion.String() -) - -// SetupWithManager loads the controller into the provided controller manager. -func (r *DataplaneReconciler) SetupWithManager(mgr ctrl.Manager) error { - - // In order to allow our reconciler to quickly look up Pods by their owner, we’ll - // need an index. We declare an index key that we can later use with the client - // as a pseudo-field name, and then describe how to extract the indexed value from - // the Pod object. The indexer will automatically take care of namespaces for us, - // so we just have to extract the owner name if the Pod has a DaemonSet owner. - if err := mgr.GetFieldIndexer().IndexField(context.Background(), &corev1.Pod{}, podOwnerKey, func(rawObj client.Object) []string { - // grab the pod object, extract the owner... - pod := rawObj.(*corev1.Pod) - owner := metav1.GetControllerOf(pod) - if owner == nil { - return nil - } - // ...make sure it's a DaemonSet... - if owner.APIVersion != apiGVStr || owner.Kind != "DaemonSet" { - return nil - } - - // ...and if so, return it - return []string{owner.Name} - }); err != nil { - return err - } - - return ctrl.NewControllerManagedBy(mgr). - For(&appsv1.DaemonSet{}, - builder.WithPredicates(predicate.NewPredicateFuncs(r.daemonsetHasMatchingAnnotations)), - ). - WithEventFilter(predicate.Funcs{ - UpdateFunc: func(e event.UpdateEvent) bool { - return true - }, - }). - Complete(r) -} - -func (r *DataplaneReconciler) daemonsetHasMatchingAnnotations(obj client.Object) bool { - log := log.FromContext(context.Background()) - - daemonset, ok := obj.(*appsv1.DaemonSet) - if !ok { - log.Error(fmt.Errorf("received unexpected type in daemonset watch predicates: %T", obj), "THIS SHOULD NEVER HAPPEN!") - return false - } - - // determine if this is a blixt daemonset - matchLabels := daemonset.Spec.Selector.MatchLabels - app, ok := matchLabels["app"] - if !ok || app != vars.DefaultDataPlaneAppLabel { - return false - } - - // verify that it's the dataplane daemonset - component, ok := matchLabels["component"] - if !ok || component != vars.DefaultDataPlaneComponentLabel { - return false - } - - return true -} - -// Reconcile provisions (and de-provisions) resources relevant to this controller. -func (r *DataplaneReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - - ds := new(appsv1.DaemonSet) - if err := r.Client.Get(ctx, req.NamespacedName, ds); err != nil { - if errors.IsNotFound(err) { - logger.Info("DataplaneReconciler", "reconcile status", "object enqueued no longer exists, skipping") - return ctrl.Result{}, nil - } - return ctrl.Result{}, err - } - - var childPods corev1.PodList - if err := r.List(ctx, &childPods, client.InNamespace(req.Namespace), client.MatchingFields{podOwnerKey: req.Name}); err != nil { - logger.Error(err, "DataplaneReconciler", "reconcile status", "unable to list child pods") - return ctrl.Result{}, err - } - - readyPodByNN := make(map[types.NamespacedName]corev1.Pod) - for _, pod := range childPods.Items { - for _, container := range pod.Status.ContainerStatuses { - if container.Name == vars.DefaultDataPlaneComponentLabel && container.Ready { - key := types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name} - readyPodByNN[key] = pod - } - } - } - - logger.Info("DataplaneReconciler", "reconcile status", "setting updated backends client list", "num ready pods", len(readyPodByNN)) - updated, err := r.backendsClientManager.SetClientsList(readyPodByNN) - if updated { - logger.Info("DataplaneReconciler", "reconcile status", "backends client list updated, sending generic event") - select { - case r.updates <- event.GenericEvent{Object: ds}: - logger.Info("DataplaneReconciler", "reconcile status", "generic event sent") - default: - logger.Info("DataplaneReconciler", "reconcile status", "generic event skipped - channel is full") - } - } - if err != nil { - logger.Error(err, "DataplaneReconciler", "reconcile status", "partial failure for backends client list update") - return ctrl.Result{Requeue: true}, err - } - - logger.Info("DataplaneReconciler", "reconcile status", "done") - return ctrl.Result{}, nil -} - -func (r *DataplaneReconciler) GetUpdates() <-chan event.GenericEvent { - return r.updates -} diff --git a/controllers/docs.go b/controllers/docs.go deleted file mode 100644 index 8f80dee0..00000000 --- a/controllers/docs.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers contains the controllers which manage the lifecycle of -// the resources relevant to the operator, such as DataPlanes and ControlPlane -// resources. -package controllers diff --git a/controllers/gateway_controller.go b/controllers/gateway_controller.go deleted file mode 100644 index cda1b5e9..00000000 --- a/controllers/gateway_controller.go +++ /dev/null @@ -1,201 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "fmt" - "reflect" - "strings" - "time" - - "github.com/go-logr/logr" - "github.com/kubernetes-sigs/blixt/pkg/vars" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/builder" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/predicate" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" -) - -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/finalizers,verbs=update - -//+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=core,resources=services/status,verbs=get - -//+kubebuilder:rbac:groups=core,resources=endpoints,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=core,resources=endpoints/status,verbs=get - -//+kubebuilder:rbac:groups=core,resources=events,verbs=get;list;watch - -const gatewayServiceLabel = "blixt.gateway.networking.k8s.io/owned-by-gateway" - -// GatewayReconciler reconciles a Gateway object -type GatewayReconciler struct { - client.Client - Scheme *runtime.Scheme - Log logr.Logger -} - -// SetupWithManager loads the controller into the provided controller manager. -func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error { - r.Log = log.FromContext(context.Background()) - - return ctrl.NewControllerManagedBy(mgr). - For(&gatewayv1beta1.Gateway{}, - builder.WithPredicates(predicate.NewPredicateFuncs(r.gatewayHasMatchingGatewayClass)), - ). - Watches( - &corev1.Service{}, - handler.EnqueueRequestsFromMapFunc(mapServiceToGateway), - ). - Watches( - &gatewayv1beta1.GatewayClass{}, - handler.EnqueueRequestsFromMapFunc(r.mapGatewayClassToGateway), - ). - Complete(r) -} - -func (r *GatewayReconciler) gatewayHasMatchingGatewayClass(obj client.Object) bool { - gateway, ok := obj.(*gatewayv1beta1.Gateway) - if !ok { - r.Log.Error(fmt.Errorf("unexpected object type in gateway watch predicates"), "expected", "*gatewayv1beta1.Gateway", "found", reflect.TypeOf(obj)) - return false - } - - gatewayClass := &gatewayv1beta1.GatewayClass{} - if err := r.Client.Get(context.Background(), client.ObjectKey{Name: string(gateway.Spec.GatewayClassName)}, gatewayClass); err != nil { - if errors.IsNotFound(err) { - return false - } - r.Log.Error(err, "couldn't retrieve gatewayclass for unknown reason, enqueing gateway anyway to avoid miss", "gatewayclass", gateway.Spec.GatewayClassName) - return true - } - - return gatewayClass.Spec.ControllerName == vars.GatewayClassControllerName -} - -// Reconcile provisions (and de-provisions) resources relevant to this controller. -// TODO: this whole thing needs a rewrite -func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - log := log.FromContext(ctx) - - gateway := new(gatewayv1beta1.Gateway) - if err := r.Client.Get(ctx, req.NamespacedName, gateway); err != nil { - if errors.IsNotFound(err) { - log.Info("object enqueued no longer exists, skipping") - return ctrl.Result{}, nil - } - return ctrl.Result{}, err - } - - gatewayClass := new(gatewayv1beta1.GatewayClass) - if err := r.Client.Get(ctx, types.NamespacedName{Name: string(gateway.Spec.GatewayClassName)}, gatewayClass); err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err - } - - if gatewayClass.Spec.ControllerName != vars.GatewayClassControllerName { - return ctrl.Result{}, nil - } - - log.Info("found a supported Gateway, determining whether the gateway has been accepted") - oldGateway := gateway.DeepCopy() - if !isGatewayAccepted(gateway) { - log.Info("gateway not yet accepted") - setGatewayListenerStatus(gateway) - setGatewayStatus(gateway) - updateConditionGeneration(gateway) - return ctrl.Result{}, r.Status().Patch(ctx, gateway, client.MergeFrom(oldGateway)) - } - - log.Info("checking for Service for Gateway") - svc, err := r.getServiceForGateway(ctx, gateway) - if err != nil { - return ctrl.Result{}, err - } - if svc == nil { - log.Info("creating Service for Gateway") - return ctrl.Result{}, r.createServiceForGateway(ctx, gateway) // service creation will requeue gateway - } - - log.Info("checking Service configuration") - needsUpdate, err := r.ensureServiceConfiguration(ctx, svc, gateway) - if err != nil { - return ctrl.Result{}, err - } - if needsUpdate { - return ctrl.Result{}, r.Client.Update(ctx, svc) - } - - log.Info("checking Service status", "namespace", svc.Namespace, "name", svc.Name) - switch t := svc.Spec.Type; t { - case corev1.ServiceTypeLoadBalancer: - if err := r.svcIsHealthy(ctx, svc); err != nil { - // TODO: only handles metallb right now https://github.com/kubernetes-sigs/blixt/issues/96 - if strings.Contains(err.Error(), "Failed to allocate IP") { - r.Log.Info("failed to allocate IP for Gateway", gateway.Namespace, gateway.Name) - setCond(gateway, metav1.Condition{ - Type: string(gatewayv1beta1.GatewayConditionProgrammed), - ObservedGeneration: gateway.Generation, - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(gatewayv1beta1.GatewayReasonAddressNotUsable), - Message: err.Error(), - }) - updateConditionGeneration(gateway) - return ctrl.Result{Requeue: true}, r.Status().Patch(ctx, gateway, client.MergeFrom(oldGateway)) - } - return ctrl.Result{}, err - } - - if svc.Spec.ClusterIP == "" || len(svc.Status.LoadBalancer.Ingress) < 1 { - log.Info("waiting for Service to be ready") - return ctrl.Result{RequeueAfter: time.Second}, nil - } - default: - return ctrl.Result{}, fmt.Errorf("found unsupported Service type: %s (only LoadBalancer type is currently supported)", t) - } - - // hack for metallb - https://github.com/metallb/metallb/issues/1640 - // no need to enforce the gateway status here, as this endpoint is not reconciled by the controller - // and no reconciliation loop is triggered upon its change or deletion. - created, err := r.hackEnsureEndpoints(ctx, svc) - if err != nil { - return ctrl.Result{}, err - } - if created { - return ctrl.Result{Requeue: true}, nil - } - - log.Info("Service is ready, setting Gateway as programmed") - setGatewayStatusAddresses(gateway, svc) - setGatewayListenerConditionsAndProgrammed(gateway) - updateConditionGeneration(gateway) - return ctrl.Result{}, r.Status().Patch(ctx, gateway, client.MergeFrom(oldGateway)) -} diff --git a/controllers/gateway_controller_status.go b/controllers/gateway_controller_status.go deleted file mode 100644 index 135a13f4..00000000 --- a/controllers/gateway_controller_status.go +++ /dev/null @@ -1,229 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" -) - -func setGatewayStatusAddresses(gateway *gatewayv1beta1.Gateway, svc *corev1.Service) { - gwaddrs := []gatewayv1beta1.GatewayStatusAddress{} - for _, addr := range svc.Status.LoadBalancer.Ingress { - if addr.IP != "" { - gwaddrs = append(gwaddrs, gatewayv1beta1.GatewayStatusAddress{ - Type: &ipAddrType, - Value: addr.IP, - }) - } - if addr.Hostname != "" { - gwaddrs = append(gwaddrs, gatewayv1beta1.GatewayStatusAddress{ - Type: &hostAddrType, - Value: addr.Hostname, - }) - } - } - gateway.Status.Addresses = gwaddrs -} - -func setGatewayListenerConditionsAndProgrammed(gateway *gatewayv1beta1.Gateway) { - programmed := metav1.Condition{ - Type: string(gatewayv1beta1.GatewayConditionProgrammed), - Status: metav1.ConditionTrue, - Reason: string(gatewayv1beta1.GatewayReasonProgrammed), - ObservedGeneration: gateway.Generation, - LastTransitionTime: metav1.Now(), - Message: "the gateway is ready to route traffic", - } - - listenersStatus := make([]gatewayv1beta1.ListenerStatus, 0, len(gateway.Spec.Listeners)) - for _, l := range gateway.Spec.Listeners { - supportedKinds, resolvedRefsCondition := getSupportedKinds(gateway.Generation, l) - listenerProgrammedStatus := corev1.ConditionTrue - listenerProgrammedReason := gatewayv1beta1.ListenerReasonProgrammed - if resolvedRefsCondition.Status == metav1.ConditionFalse { - listenerProgrammedStatus = corev1.ConditionStatus(metav1.ConditionFalse) - listenerProgrammedReason = gatewayv1beta1.ListenerReasonResolvedRefs - } - listenersStatus = append(listenersStatus, gatewayv1beta1.ListenerStatus{ - Name: l.Name, - SupportedKinds: supportedKinds, - Conditions: []metav1.Condition{ - { - Type: string(gatewayv1beta1.ListenerConditionAccepted), - Status: metav1.ConditionTrue, - Reason: string(gatewayv1beta1.ListenerReasonAccepted), - ObservedGeneration: gateway.Generation, - LastTransitionTime: metav1.Now(), - }, - { - Type: string(gatewayv1beta1.ListenerConditionProgrammed), - Status: metav1.ConditionStatus(listenerProgrammedStatus), - Reason: string(listenerProgrammedReason), - ObservedGeneration: gateway.Generation, - LastTransitionTime: metav1.Now(), - }, - resolvedRefsCondition, - }, - }) - if resolvedRefsCondition.Status == metav1.ConditionFalse { - programmed.Status = metav1.ConditionFalse - programmed.Reason = string(gatewayv1beta1.GatewayReasonAddressNotAssigned) - programmed.Message = "the gateway is not ready to route traffic" - } - } - gateway.Status.Listeners = listenersStatus - setCond(gateway, programmed) -} - -func setGatewayListenerStatus(gateway *gatewayv1beta1.Gateway) { - gateway.Status.Listeners = make([]gatewayv1beta1.ListenerStatus, 0, len(gateway.Spec.Listeners)) - for _, l := range gateway.Spec.Listeners { - supportedKinds, resolvedRefsCondition := getSupportedKinds(gateway.Generation, l) - gateway.Status.Listeners = append(gateway.Status.Listeners, gatewayv1beta1.ListenerStatus{ - Name: l.Name, - SupportedKinds: supportedKinds, - Conditions: []metav1.Condition{ - { - Type: string(gatewayv1beta1.ListenerConditionProgrammed), - Status: metav1.ConditionFalse, - Reason: string(gatewayv1beta1.ListenerReasonPending), - ObservedGeneration: gateway.Generation, - LastTransitionTime: metav1.Now(), - }, - resolvedRefsCondition, - }, - }) - } -} - -func getSupportedKinds(generation int64, listener gatewayv1beta1.Listener) (supportedKinds []gatewayv1beta1.RouteGroupKind, resolvedRefsCondition metav1.Condition) { - supportedKinds = make([]gatewayv1beta1.RouteGroupKind, 0) - resolvedRefsCondition = metav1.Condition{ - Type: string(gatewayv1beta1.ListenerConditionResolvedRefs), - Status: metav1.ConditionTrue, - Reason: string(gatewayv1beta1.ListenerReasonResolvedRefs), - ObservedGeneration: generation, - LastTransitionTime: metav1.Now(), - } - if len(listener.AllowedRoutes.Kinds) == 0 { - // When unspecified or empty, the kinds of Routes selected are determined using the Listener protocol. - switch listener.Protocol { - case gatewayv1beta1.TCPProtocolType: - supportedKinds = append(supportedKinds, gatewayv1beta1.RouteGroupKind{ - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "TCPRoute", - }) - case gatewayv1beta1.UDPProtocolType: - supportedKinds = append(supportedKinds, gatewayv1beta1.RouteGroupKind{ - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "UDPRoute", - }) - // TODO: this is a hack to workaround defaults listener configurations - // that were present in the Gateway API conformance tests, so that we - // can still pass the tests. For now, we just treat an HTTP/S listener - // as a TCP listener to workaround this (but we don't actually support - // HTTPRoute). - case gatewayv1beta1.HTTPProtocolType: - supportedKinds = append(supportedKinds, gatewayv1beta1.RouteGroupKind{ - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "HTTPRoute", - }) - case gatewayv1beta1.HTTPSProtocolType: - supportedKinds = append(supportedKinds, gatewayv1beta1.RouteGroupKind{ - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "HTTPRoute", - }) - default: - resolvedRefsCondition.Status = metav1.ConditionFalse - resolvedRefsCondition.Reason = string(gatewayv1beta1.ListenerReasonInvalidRouteKinds) - } - } - - for _, k := range listener.AllowedRoutes.Kinds { - if (k.Group != nil && *k.Group != "" && *k.Group != gatewayv1beta1.Group(gatewayv1beta1.GroupVersion.Group)) || - (k.Kind != "UDPRoute" && k.Kind != "TCPRoute") { - resolvedRefsCondition.Status = metav1.ConditionFalse - resolvedRefsCondition.Reason = string(gatewayv1beta1.ListenerReasonInvalidRouteKinds) - continue - } - supportedKinds = append(supportedKinds, gatewayv1beta1.RouteGroupKind{ - Group: k.Group, - Kind: k.Kind, - }) - } - return supportedKinds, resolvedRefsCondition -} - -// updateConditionGeneration takes the old gateway conditions not transitioned and copies them -// into the new gateway status, so that only the transitioning conditions gets actually patched. -func updateConditionGeneration(gateway *gatewayv1beta1.Gateway) { - for i := 0; i < len(gateway.Status.Conditions); i++ { - gateway.Status.Conditions[0].ObservedGeneration = gateway.Generation - } - - for i := 0; i < len(gateway.Status.Listeners); i++ { - updatedListenerConditions := []metav1.Condition{} - for _, cond := range gateway.Status.Listeners[0].Conditions { - cond.ObservedGeneration = gateway.Generation - updatedListenerConditions = append(updatedListenerConditions, cond) - } - gateway.Status.Listeners[0].Conditions = updatedListenerConditions - } -} - -func isGatewayAccepted(gateway *gatewayv1beta1.Gateway) bool { - accepted := getAcceptedConditionForGateway(gateway) - if accepted == nil { - return false - } - return accepted.Status == metav1.ConditionTrue -} - -func getAcceptedConditionForGateway(gateway *gatewayv1beta1.Gateway) *metav1.Condition { - return getCond(gateway, string(gatewayv1beta1.GatewayConditionAccepted)) -} - -func setCond(gateway *gatewayv1beta1.Gateway, setCond metav1.Condition) { - updatedConditions := make([]metav1.Condition, 0, len(gateway.Status.Conditions)) - - found := false - for _, oldCond := range gateway.Status.Conditions { - if oldCond.Type == setCond.Type { - found = true - updatedConditions = append(updatedConditions, setCond) - } else { - updatedConditions = append(updatedConditions, oldCond) - } - } - - if !found { - updatedConditions = append(updatedConditions, setCond) - } - - gateway.Status.Conditions = updatedConditions -} - -func getCond(gateway *gatewayv1beta1.Gateway, requestedType string) *metav1.Condition { - for _, cond := range gateway.Status.Conditions { - if cond.Type == requestedType { - return &cond - } - } - return nil -} diff --git a/controllers/gateway_controller_test.go b/controllers/gateway_controller_test.go deleted file mode 100644 index f08e87be..00000000 --- a/controllers/gateway_controller_test.go +++ /dev/null @@ -1,472 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes/scheme" - controllerruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" - fakectrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/kubernetes-sigs/blixt/internal/test/utils" - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -func init() { - _ = gatewayv1beta1.AddToScheme(scheme.Scheme) -} - -func TestGatewayReconciler_gatewayHasMatchingGatewayClass(t *testing.T) { - logger, output := utils.NewBytesBufferLogger() - managedGWC, unmanagedGWC, fakeClient := utils.NewFakeClientWithGatewayClasses() - r := GatewayReconciler{ - Client: fakeClient, - Scheme: fakeClient.Scheme(), - Log: logger, - } - - for _, tt := range []struct { - name string - obj controllerruntimeclient.Object - expected bool - logEntryExpected string - }{ - { - name: "a gateway with a gatewayclass managed by our controller name matches", - obj: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "managed-gateway", - Namespace: corev1.NamespaceDefault, - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: managedGWC, - }, - }, - expected: true, - }, - { - name: "a gateway with a gatewayclass NOT managed by our controller name doesn't match", - obj: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "unmanaged-gateway", - Namespace: corev1.NamespaceDefault, - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: unmanagedGWC, - }, - }, - expected: false, - }, - { - name: "a gateway with a gatewayclass which is missing doesn't match", - obj: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "unmanaged-gateway", - Namespace: corev1.NamespaceDefault, - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: "non-existent-gateway-class", - }, - }, - expected: false, - }, - { - name: "if inexplicably controller-runtime feeds the predicate a non-gateway object, it doesn't match", - obj: &gatewayv1beta1.HTTPRoute{}, - expected: false, - logEntryExpected: "unexpected object type in gateway watch predicates", - }, - } { - obj := tt.obj - expected := tt.expected - logEntry := tt.logEntryExpected - - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, expected, r.gatewayHasMatchingGatewayClass(obj)) - if logEntry == "" { - assert.Equal(t, logEntry, output.String()) - } else { - assert.Contains(t, output.String(), logEntry) - } - }) - - output.Reset() - } -} - -func TestGatewayReconciler_reconcile(t *testing.T) { - testCases := []struct { - name string - gatewayReq reconcile.Request - gatewayClass *gatewayv1beta1.GatewayClass - gateway *gatewayv1beta1.Gateway - objectsToAdd []controllerruntimeclient.Object - - run func(t *testing.T, reconciler GatewayReconciler, gatewayReq reconcile.Request, gatewayClass *gatewayv1beta1.Gateway) - }{ - { - name: "gatewayclass not accepted", - gatewayReq: reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - }, - gatewayClass: &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gatewayclass", - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: gatewayv1beta1.GatewayController("mismatch-controller-name"), - }, - }, - gateway: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: "test-gatewayclass", - Listeners: []gatewayv1beta1.Listener{ - { - Name: "udp", - Protocol: gatewayv1beta1.UDPProtocolType, - Port: 9875, - }, - }, - }, - }, - run: func(t *testing.T, reconciler GatewayReconciler, gatewayReq reconcile.Request, gateway *gatewayv1beta1.Gateway) { - ctx := context.Background() - _, err := reconciler.Reconcile(ctx, gatewayReq) - require.NoError(t, err) - newGateway := &gatewayv1beta1.Gateway{} - err = reconciler.Client.Get(ctx, gatewayReq.NamespacedName, newGateway) - require.NoError(t, err) - require.Len(t, newGateway.Status.Conditions, 0) - require.Len(t, newGateway.Status.Listeners, 0) - require.Len(t, newGateway.Status.Addresses, 0) - }, - }, - { - name: "gatewayclass accepted, gateway ready", - gatewayReq: reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - }, - gatewayClass: &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gatewayclass", - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: vars.GatewayClassControllerName, - }, - }, - gateway: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: "test-gatewayclass", - Listeners: []gatewayv1beta1.Listener{ - { - Name: "udp", - Protocol: gatewayv1beta1.UDPProtocolType, - Port: 9875, - AllowedRoutes: &gatewayv1beta1.AllowedRoutes{}, - }, - }, - }, - }, - objectsToAdd: []controllerruntimeclient.Object{ - &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-namespace", - Name: "service-for-gateway-test-gateway", - Labels: map[string]string{ - gatewayServiceLabel: "test-gateway", - }, - }, - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, - ClusterIP: "1.1.1.1", - Ports: []corev1.ServicePort{ - { - Name: "udp", - Protocol: corev1.ProtocolUDP, - Port: 9875, - }, - }, - }, - Status: corev1.ServiceStatus{ - LoadBalancer: corev1.LoadBalancerStatus{ - Ingress: []corev1.LoadBalancerIngress{ - { - IP: "1.2.3.4", - }, - }, - }, - }, - }, - &corev1.Endpoints{ - ObjectMeta: metav1.ObjectMeta{ - Name: "service-for-gateway-test-gateway", - Namespace: "test-namespace", - }, - }, - }, - run: func(t *testing.T, reconciler GatewayReconciler, gatewayReq reconcile.Request, gateway *gatewayv1beta1.Gateway) { - ctx := context.Background() - // first reconcile to initialize the Gateway status - _, err := reconciler.Reconcile(ctx, gatewayReq) - require.NoError(t, err) - // second reconcile to have a complete status - _, err = reconciler.Reconcile(ctx, gatewayReq) - require.NoError(t, err) - newGateway := &gatewayv1beta1.Gateway{} - err = reconciler.Client.Get(ctx, gatewayReq.NamespacedName, newGateway) - require.NoError(t, err) - require.Len(t, newGateway.Status.Addresses, 1) - require.Len(t, newGateway.Status.Conditions, 2) - require.Equal(t, newGateway.Status.Conditions[0].Status, metav1.ConditionTrue) - require.Len(t, newGateway.Status.Listeners, 1) - require.Equal(t, newGateway.Status.Listeners[0].SupportedKinds, []gatewayv1beta1.RouteGroupKind{ - { - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "UDPRoute", - }, - }) - for _, c := range newGateway.Status.Listeners[0].Conditions { - require.Equal(t, c.Status, metav1.ConditionTrue) - } - - }, - }, - { - name: "gatewayclass accepted, gateway not ready because resources are missing", - gatewayReq: reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - }, - gatewayClass: &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gatewayclass", - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: vars.GatewayClassControllerName, - }, - }, - gateway: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: "test-gatewayclass", - Listeners: []gatewayv1beta1.Listener{ - { - Name: "udp", - Protocol: gatewayv1beta1.UDPProtocolType, - Port: 9875, - AllowedRoutes: &gatewayv1beta1.AllowedRoutes{}, - }, - }, - }, - }, - run: func(t *testing.T, reconciler GatewayReconciler, gatewayReq reconcile.Request, gateway *gatewayv1beta1.Gateway) { - ctx := context.Background() - _, err := reconciler.Reconcile(ctx, gatewayReq) - require.NoError(t, err) - newGateway := &gatewayv1beta1.Gateway{} - err = reconciler.Client.Get(ctx, gatewayReq.NamespacedName, newGateway) - require.NoError(t, err) - require.Len(t, newGateway.Status.Addresses, 0) - require.Len(t, newGateway.Status.Conditions, 2) - require.Equal(t, newGateway.Status.Conditions[0].Status, metav1.ConditionTrue) - require.Equal(t, newGateway.Status.Conditions[1].Status, metav1.ConditionFalse) - require.Len(t, newGateway.Status.Listeners, 1) - require.Equal(t, newGateway.Status.Listeners[0].SupportedKinds, []gatewayv1beta1.RouteGroupKind{ - { - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "UDPRoute", - }, - }) - for _, c := range newGateway.Status.Listeners[0].Conditions { - if c.Type == string(gatewayv1beta1.ListenerConditionResolvedRefs) { - require.Equal(t, c.Status, metav1.ConditionTrue) - } else { - require.Equal(t, c.Status, metav1.ConditionFalse) - } - } - }, - }, - { - name: "gatewayclass accepted, gateway not ready because resolvedrefs is false", - gatewayReq: reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - }, - gatewayClass: &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gatewayclass", - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: vars.GatewayClassControllerName, - }, - }, - gateway: &gatewayv1beta1.Gateway{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-gateway", - Namespace: "test-namespace", - }, - Spec: gatewayv1beta1.GatewaySpec{ - GatewayClassName: "test-gatewayclass", - Listeners: []gatewayv1beta1.Listener{ - { - Name: "http", - Protocol: gatewayv1beta1.HTTPProtocolType, - Port: 9875, - AllowedRoutes: &gatewayv1beta1.AllowedRoutes{}, - }, - { - Name: "udp", - Protocol: gatewayv1beta1.UDPProtocolType, - Port: 9875, - AllowedRoutes: &gatewayv1beta1.AllowedRoutes{}, - }, - }, - }, - }, - objectsToAdd: []controllerruntimeclient.Object{ - &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-namespace", - Name: "service-for-gateway-test-gateway", - Labels: map[string]string{ - gatewayServiceLabel: "test-gateway", - }, - }, - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, - ClusterIP: "1.1.1.1", - Ports: []corev1.ServicePort{ - { - Name: "udp", - Protocol: corev1.ProtocolUDP, - Port: 9875, - }, - }, - }, - Status: corev1.ServiceStatus{ - LoadBalancer: corev1.LoadBalancerStatus{ - Ingress: []corev1.LoadBalancerIngress{ - { - IP: "1.2.3.4", - }, - }, - }, - }, - }, - &corev1.Endpoints{ - ObjectMeta: metav1.ObjectMeta{ - Name: "service-for-gateway-test-gateway", - Namespace: "test-namespace", - }, - }, - }, - run: func(t *testing.T, reconciler GatewayReconciler, gatewayReq reconcile.Request, gateway *gatewayv1beta1.Gateway) { - ctx := context.Background() - // first reconcile to initialize the Gateway status - _, err := reconciler.Reconcile(ctx, gatewayReq) - require.NoError(t, err) - // second reconcile to have a complete status - _, err = reconciler.Reconcile(ctx, gatewayReq) - require.NoError(t, err) - newGateway := &gatewayv1beta1.Gateway{} - err = reconciler.Client.Get(ctx, gatewayReq.NamespacedName, newGateway) - require.NoError(t, err) - require.Len(t, newGateway.Status.Addresses, 0) - require.Len(t, newGateway.Status.Conditions, 2) - require.Equal(t, newGateway.Status.Conditions[0].Status, metav1.ConditionTrue) - require.Equal(t, newGateway.Status.Conditions[1].Status, metav1.ConditionFalse) - require.Len(t, newGateway.Status.Listeners, 2) - for _, l := range newGateway.Status.Listeners { - if l.Name == "http" { - require.Len(t, l.SupportedKinds, 1) - for _, c := range l.Conditions { - if c.Type == string(gatewayv1beta1.ListenerConditionResolvedRefs) { - require.Equal(t, c.Status, metav1.ConditionTrue) // TODO: https://github.com/kubernetes-sigs/gateway-api/issues/2403 - } else { - require.Equal(t, c.Status, metav1.ConditionFalse) - } - } - } - if l.Name == "udp" { - require.Equal(t, l.SupportedKinds, []gatewayv1beta1.RouteGroupKind{ - { - Group: (*gatewayv1beta1.Group)(&gatewayv1beta1.GroupVersion.Group), - Kind: "UDPRoute", - }, - }) - require.Equal(t, l.Conditions[0].Status, metav1.ConditionFalse) - } - } - }, - }, - } - - for _, tc := range testCases { - tc := tc - - t.Run(tc.name, func(t *testing.T) { - objectsToAdd := []controllerruntimeclient.Object{ - tc.gatewayClass, - tc.gateway, - } - objectsToAdd = append(objectsToAdd, tc.objectsToAdd...) - - fakeClient := fakectrlruntimeclient. - NewClientBuilder(). - WithScheme(scheme.Scheme). - WithObjects(objectsToAdd...). - WithStatusSubresource(objectsToAdd...). - Build() - - reconciler := GatewayReconciler{ - Client: fakeClient, - } - - tc.run(t, reconciler, tc.gatewayReq, tc.gateway) - }) - } -} diff --git a/controllers/gateway_controller_utils.go b/controllers/gateway_controller_utils.go deleted file mode 100644 index 4fe61e6f..00000000 --- a/controllers/gateway_controller_utils.go +++ /dev/null @@ -1,389 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "fmt" - "reflect" - - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" -) - -func (r *GatewayReconciler) getServiceForGateway(ctx context.Context, gw *gatewayv1beta1.Gateway) (*corev1.Service, error) { - svcs := new(corev1.ServiceList) - if err := r.List(ctx, svcs, client.InNamespace(gw.Namespace), client.MatchingLabels{gatewayServiceLabel: gw.Name}); err != nil { - return nil, err - } - - if len(svcs.Items) > 1 { - return nil, fmt.Errorf("more than 1 Service found for Gateway %s/%s, not currently supported", gw.Namespace, gw.Name) - } - - for _, svc := range svcs.Items { - return &svc, nil - } - - return nil, nil -} - -func (r *GatewayReconciler) createServiceForGateway(ctx context.Context, gw *gatewayv1beta1.Gateway) error { - svc := corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: gw.Namespace, - GenerateName: fmt.Sprintf("service-for-gateway-%s-", gw.Name), - Labels: map[string]string{ - gatewayServiceLabel: gw.Name, - }, - }, - } - - if len(gw.Spec.Addresses) > 0 { - addr := gw.Spec.Addresses[0] - - if *addr.Type != gatewayv1beta1.IPAddressType { - // TODO: update status https://github.com/Kong/blixt/issues/96 - return fmt.Errorf("status addresses of type %s are not supported, only IP addresses are supported", *addr.Type) - } - - svc.Spec.LoadBalancerIP = addr.Value - } - - if len(gw.Spec.Addresses) > 1 { - // TODO: update status https://github.com/Kong/blixt/issues/96 - r.Log.Error( - fmt.Errorf("assigning multiple static IPs for a Gateway is not currently supported"), - fmt.Sprintf("%d addresses were requested, only %s will be allocated", len(gw.Spec.Addresses), svc.Spec.LoadBalancerIP), - ) - } - - _, err := r.ensureServiceConfiguration(ctx, &svc, gw) - if err != nil { - return err - } - - setOwnerReference(&svc, gw) - - return r.Client.Create(ctx, &svc) -} - -func setOwnerReference(svc *corev1.Service, gw client.Object) { - gvk := gw.GetObjectKind().GroupVersionKind() - svc.ObjectMeta.OwnerReferences = []metav1.OwnerReference{{ - APIVersion: fmt.Sprintf("%s/%s", gvk.Group, gvk.Version), - Kind: gvk.Kind, - Name: gw.GetName(), - UID: gw.GetUID(), - Controller: ptr.To(true), - }} -} - -func (r *GatewayReconciler) svcIsHealthy(ctx context.Context, svc *corev1.Service) error { - if len(svc.Status.LoadBalancer.Ingress) > 0 { - return nil - } - - // FIXME: the following is a hack to use metallb events to determine if the - // service is having trouble getting an IP allocated for it. This was created - // in a hurry and needs to be replaced with something robust. - events := &corev1.EventList{} - if err := r.Client.List(ctx, events, &client.ListOptions{ - // TODO: add a field selector - Namespace: svc.Namespace, - }); err != nil { - return err - } - - var allocationFailed *corev1.Event - var allocationSucceeded *corev1.Event - - for _, event := range events.Items { - currentEvent := event - - if currentEvent.InvolvedObject.Name == svc.Name && currentEvent.Reason == "AllocationFailed" { // TODO: only handles metallb right now https://github.com/Kong/blixt/issues/96 - if allocationFailed != nil { - if currentEvent.EventTime.After(allocationFailed.EventTime.Time) { - allocationFailed = ¤tEvent - } - } else { - allocationFailed = ¤tEvent - } - } - - if currentEvent.InvolvedObject.Name == svc.Name && currentEvent.Reason == "IPAllocated" { - if allocationSucceeded != nil { - if currentEvent.EventTime.After(allocationSucceeded.EventTime.Time) { - allocationSucceeded = ¤tEvent - } - } else { - allocationSucceeded = ¤tEvent - } - } - } - - if allocationFailed != nil { - if allocationSucceeded != nil && allocationSucceeded.EventTime.After(allocationFailed.EventTime.Time) { - return nil - } - return fmt.Errorf("%s", allocationFailed.Message) - } - - return nil -} - -func (r *GatewayReconciler) ensureServiceConfiguration(ctx context.Context, svc *corev1.Service, gw *gatewayv1beta1.Gateway) (bool, error) { - updated := false - - if len(gw.Spec.Addresses) > 0 && svc.Spec.LoadBalancerIP != gw.Spec.Addresses[0].Value { - if len(gw.Spec.Addresses) > 1 { - r.Log.Info(fmt.Sprintf("found %d addresses on gateway, but currently we only support 1", len(gw.Spec.Addresses)), gw.Namespace, gw.Name) - } - r.Log.Info(fmt.Sprintf("using address %s for gateway", gw.Spec.Addresses[0].Value), gw.Namespace, gw.Name) - svc.Spec.LoadBalancerIP = gw.Spec.Addresses[0].Value - updated = true - } - - if svc.Spec.LoadBalancerIP != "" && len(gw.Spec.Addresses) == 0 { - r.Log.Info("service for gateway had a left over address that's no longer specified, removing", gw.Namespace, gw.Name) - svc.Spec.LoadBalancerIP = "" - updated = true - } - - if svc.Spec.Type != corev1.ServiceTypeLoadBalancer { - svc.Spec.Type = corev1.ServiceTypeLoadBalancer - updated = true - } - - ports := make([]corev1.ServicePort, 0, len(gw.Spec.Listeners)) - for _, listener := range gw.Spec.Listeners { - switch proto := listener.Protocol; proto { - case gatewayv1beta1.TCPProtocolType: - ports = append(ports, corev1.ServicePort{ - Name: string(listener.Name), - Protocol: corev1.ProtocolTCP, - Port: int32(listener.Port), - }) - case gatewayv1beta1.UDPProtocolType: - ports = append(ports, corev1.ServicePort{ - Name: string(listener.Name), - Protocol: corev1.ProtocolUDP, - Port: int32(listener.Port), - }) - // TODO: this is a hack to workaround defaults listener configurations - // that were present in the Gateway API conformance tests, so that we - // can still pass the tests. For now, we just treat an HTTP/S listener - // as a TCP listener to workaround this (but we don't actually support - // HTTPRoute). - case gatewayv1beta1.HTTPProtocolType: - ports = append(ports, corev1.ServicePort{ - Name: string(listener.Name), - Protocol: corev1.ProtocolTCP, - Port: int32(listener.Port), - }) - case gatewayv1beta1.HTTPSProtocolType: - ports = append(ports, corev1.ServicePort{ - Name: string(listener.Name), - Protocol: corev1.ProtocolTCP, - Port: int32(listener.Port), - }) - } - } - - newPorts := make(map[string]portAndProtocol, len(ports)) - for _, newPort := range ports { - newPorts[newPort.Name] = portAndProtocol{ - port: newPort.Port, - protocol: newPort.Protocol, - } - } - - oldPorts := make(map[string]portAndProtocol, len(svc.Spec.Ports)) - for _, oldPort := range svc.Spec.Ports { - oldPorts[oldPort.Name] = portAndProtocol{ - port: oldPort.Port, - protocol: oldPort.Protocol, - } - } - - if !reflect.DeepEqual(newPorts, oldPorts) { - svc.Spec.Ports = ports - updated = true - } - - return updated, nil -} - -var ( - ipAddrType = gatewayv1beta1.IPAddressType - hostAddrType = gatewayv1beta1.HostnameAddressType -) - -// hackEnsureEndpoints is a temporary hack around how metallb'd L2 mode works, re: https://github.com/metallb/metallb/issues/1640 -func (r *GatewayReconciler) hackEnsureEndpoints(ctx context.Context, svc *corev1.Service) (bool, error) { - nsn := types.NamespacedName{Namespace: svc.Namespace, Name: svc.Name} - lbaddr := "" - for _, addr := range svc.Status.LoadBalancer.Ingress { - if addr.IP != "" { - lbaddr = addr.IP - break - } - if addr.Hostname != "" { - lbaddr = addr.Hostname - break - } - } - - endpoints := new(corev1.Endpoints) - err := r.Client.Get(ctx, nsn, endpoints) - if err != nil { - if errors.IsNotFound(err) { - eports := make([]corev1.EndpointPort, 0, len(svc.Spec.Ports)) - for _, svcPort := range svc.Spec.Ports { - eports = append(eports, corev1.EndpointPort{ - Port: svcPort.Port, - Protocol: svcPort.Protocol, - }) - } - - endpoints = &corev1.Endpoints{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: svc.Namespace, - Name: svc.Name, - }, - Subsets: []corev1.EndpointSubset{{ - Addresses: []corev1.EndpointAddress{{IP: lbaddr}}, - Ports: eports, - }}, - } - - return true, r.Client.Create(ctx, endpoints) - } - return false, err - } - - return false, nil -} - -func (r *GatewayReconciler) mapGatewayClassToGateway(_ context.Context, obj client.Object) (recs []reconcile.Request) { - gatewayClass, ok := obj.(*gatewayv1beta1.GatewayClass) - if !ok { - r.Log.Error(fmt.Errorf("unexpected object type in gateway watch predicates"), "expected", "*gatewayv1beta1.GatewayClass", "found", reflect.TypeOf(obj)) - return - } - - gateways := &gatewayv1beta1.GatewayList{} - if err := r.Client.List(context.Background(), gateways); err != nil { - // TODO: https://github.com/kubernetes-sigs/controller-runtime/issues/1996 - r.Log.Error(err, "could not map gatewayclass event to gateways") - return - } - - for _, gateway := range gateways.Items { - if gateway.Spec.GatewayClassName == gatewayv1beta1.ObjectName(gatewayClass.Name) { - recs = append(recs, reconcile.Request{NamespacedName: types.NamespacedName{ - Namespace: gateway.Namespace, - Name: gateway.Name, - }}) - } - } - - return -} - -func mapServiceToGateway(_ context.Context, obj client.Object) (reqs []reconcile.Request) { - svc, ok := obj.(*corev1.Service) - if !ok { - return - } - - for _, ownerRef := range svc.OwnerReferences { - if ownerRef.APIVersion == fmt.Sprintf("%s/%s", gatewayv1beta1.GroupName, gatewayv1beta1.GroupVersion.Version) { - reqs = append(reqs, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: svc.Namespace, - Name: ownerRef.Name, - }, - }) - } - } - - return -} - -func setGatewayStatus(gateway *gatewayv1beta1.Gateway) { - newAccepted := determineGatewayAcceptance(gateway) - newProgrammed := determineGatewayProgrammed(gateway) - setCond(gateway, newAccepted) - setCond(gateway, newProgrammed) -} - -func determineGatewayAcceptance(gateway *gatewayv1beta1.Gateway) metav1.Condition { - // this is the default accepted condition, it may get overidden if there are - // unsupported values in the specification. - accepted := metav1.Condition{ - Type: string(gatewayv1beta1.GatewayConditionAccepted), - Status: metav1.ConditionTrue, - Reason: string(gatewayv1beta1.GatewayReasonAccepted), - ObservedGeneration: gateway.Generation, - LastTransitionTime: metav1.Now(), - Message: "blixt controlplane accepts responsibility for the Gateway", - } - - // verify that all addresses are supported - for _, addr := range gateway.Spec.Addresses { - if addr.Type != nil && *addr.Type != gatewayv1beta1.IPAddressType { - accepted.Status = metav1.ConditionFalse - accepted.Reason = string(gatewayv1beta1.GatewayReasonUnsupportedAddress) - accepted.Message = fmt.Sprintf("found an address of type %s, only IPAddress is supported", *addr.Type) - } - } - - return accepted -} - -func determineGatewayProgrammed(gateway *gatewayv1beta1.Gateway) metav1.Condition { - // TODO: give this client access and make it dynamic - return metav1.Condition{ - Type: string(gatewayv1beta1.GatewayConditionProgrammed), - ObservedGeneration: gateway.Generation, - Status: metav1.ConditionFalse, - LastTransitionTime: metav1.Now(), - Reason: string(gatewayv1beta1.GatewayReasonPending), - Message: "dataplane not yet configured", - } -} - -// cmpCond returns true if the conditions are the same, minus the timestamp. -func cmpCond(cond1, cond2 metav1.Condition) bool { //nolint:unused - return cond1.Type == cond2.Type && - cond1.Status == cond2.Status && - cond1.ObservedGeneration == cond2.ObservedGeneration && - cond1.Reason == cond2.Reason && - cond1.Message == cond2.Message -} - -type portAndProtocol struct { - port int32 - protocol corev1.Protocol -} diff --git a/controllers/gatewayclass_controller.go b/controllers/gatewayclass_controller.go deleted file mode 100644 index 345a4144..00000000 --- a/controllers/gatewayclass_controller.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/predicate" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses/finalizers,verbs=update - -// GatewayClassReconciler reconciles a GatewayClass object -type GatewayClassReconciler struct { - client.Client - Scheme *runtime.Scheme -} - -// SetupWithManager loads the controller into the provided controller manager. -func (r *GatewayClassReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&gatewayv1beta1.GatewayClass{}). - WithEventFilter(predicate.NewPredicateFuncs(func(obj client.Object) bool { - gwc, ok := obj.(*gatewayv1beta1.GatewayClass) - if !ok { - return false - } - return gwc.Spec.ControllerName == vars.GatewayClassControllerName // filter out unmanaged GWCs - })). - Complete(r) -} - -// Reconcile provisions (and de-provisions) resources relevant to this controller. -func (r *GatewayClassReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - log := log.FromContext(ctx) - - gwc := new(gatewayv1beta1.GatewayClass) - if err := r.Client.Get(ctx, req.NamespacedName, gwc); err != nil { - if errors.IsNotFound(err) { - log.Info("object enqueued no longer exists, skipping") - return ctrl.Result{}, nil - } - return ctrl.Result{}, err - } - - if gwc.Spec.ControllerName != vars.GatewayClassControllerName { - return ctrl.Result{}, nil - } - - if !r.isAccepted(gwc) { - log.Info("marking GatwayClass as accepted", "name", gwc.Name) - return ctrl.Result{}, r.accept(ctx, gwc) - } - - return ctrl.Result{}, nil - -} - -func (r *GatewayClassReconciler) isAccepted(gwc *gatewayv1beta1.GatewayClass) bool { - for _, cond := range gwc.Status.Conditions { - if cond.Type == string(gatewayv1beta1.GatewayClassConditionStatusAccepted) { - if cond.Status == metav1.ConditionTrue { - return true - } - } - } - - return false -} - -func (r *GatewayClassReconciler) accept(ctx context.Context, gwc *gatewayv1beta1.GatewayClass) error { - previousGWC := gwc.DeepCopy() - acceptedCond := metav1.Condition{ - Type: string(gatewayv1beta1.GatewayClassConditionStatusAccepted), - Status: metav1.ConditionTrue, - ObservedGeneration: gwc.Generation, - LastTransitionTime: metav1.Now(), - Reason: string(gatewayv1beta1.GatewayClassReasonAccepted), - Message: "the gatewayclass has been accepted by the operator", - } - setCondition(acceptedCond, gwc) - return r.Status().Patch(ctx, gwc, client.MergeFrom(previousGWC)) -} - -func setCondition(condition metav1.Condition, gwc *gatewayv1beta1.GatewayClass) { - newConds := make([]metav1.Condition, 0, len(gwc.Status.Conditions)) - - for i := 0; i < len(gwc.Status.Conditions); i++ { - if gwc.Status.Conditions[i].Type != condition.Type { - newConds = append(newConds, gwc.Status.Conditions[i]) - } - } - - newConds = append(newConds, condition) - gwc.Status.Conditions = newConds -} diff --git a/controllers/suite_test.go b/controllers/suite_test.go deleted file mode 100644 index 75f05074..00000000 --- a/controllers/suite_test.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "path/filepath" - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" - - // "sigs.k8s.io/controller-runtime/pkg/envtest/printer" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - //+kubebuilder:scaffold:imports -) - -// These tests use Ginkgo (BDD-style Go testing framework). Refer to -// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -var cfg *rest.Config -var k8sClient client.Client -var testEnv *envtest.Environment - -func TestAPIs(t *testing.T) { - RegisterFailHandler(Fail) - - RunSpecs(t, "Controller Suite") -} - -var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) - - By("bootstrapping test environment") - testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, - ErrorIfCRDPathMissing: false, - } - - var err error - // cfg is defined in this file globally. - cfg, err = testEnv.Start() - Expect(err).NotTo(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) - - //+kubebuilder:scaffold:scheme - - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) - Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) - -}) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - err := testEnv.Stop() - Expect(err).NotTo(HaveOccurred()) -}) diff --git a/controllers/tcproute_controller.go b/controllers/tcproute_controller.go deleted file mode 100644 index a141d670..00000000 --- a/controllers/tcproute_controller.go +++ /dev/null @@ -1,252 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "encoding/binary" - "fmt" - "time" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/source" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - dataplane "github.com/kubernetes-sigs/blixt/internal/dataplane/client" - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=tcproutes,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=tcproutes/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=tcproutes/finalizers,verbs=update -//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch -//+kubebuilder:rbac:groups=core,resources=pods/status,verbs=get -//+kubebuilder:rbac:groups=apps,resources=daemonsets,verbs=get;list;watch -//+kubebuilder:rbac:groups=apps,resources=daemonsets/status,verbs=get - -// TCPRouteReconciler reconciles a TCPRoute object -type TCPRouteReconciler struct { - client.Client - Scheme *runtime.Scheme - - log logr.Logger - ClientReconcileRequestChan <-chan event.GenericEvent - BackendsClientManager *dataplane.BackendsClientManager -} - -// SetupWithManager sets up the controller with the Manager. -func (r *TCPRouteReconciler) SetupWithManager(mgr ctrl.Manager) error { - r.log = log.FromContext(context.Background()) - - return ctrl.NewControllerManagedBy(mgr). - For(&gatewayv1alpha2.TCPRoute{}). - WatchesRawSource( - &source.Channel{Source: r.ClientReconcileRequestChan}, - handler.EnqueueRequestsFromMapFunc(r.mapDataPlaneDaemonsetToTCPRoutes), - ). - Watches( - &gatewayv1beta1.Gateway{}, - handler.EnqueueRequestsFromMapFunc(r.mapGatewayToTCPRoutes), - ). - Complete(r) -} - -// Reconcile reconciles TCPRoute object -func (r *TCPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - tcproute := new(gatewayv1alpha2.TCPRoute) - if err := r.Get(ctx, req.NamespacedName, tcproute); err != nil { - if errors.IsNotFound(err) { - r.log.Info("object enqueued no longer exists, skipping") - return ctrl.Result{}, nil - } - r.log.Info("Error retrieving tcp route", "Err : ", err) - return ctrl.Result{}, err - } - - isManaged, gateway, err := r.isTCPRouteManaged(ctx, *tcproute) - if err != nil { - return ctrl.Result{}, err - } - if !isManaged { - // TODO: enable orphan checking https://github.com/kubernetes-sigs/blixt/issues/47 - return ctrl.Result{}, nil - } - - if !controllerutil.ContainsFinalizer(tcproute, DataPlaneFinalizer) { - if tcproute.DeletionTimestamp != nil { - // if the finalizer isn't set, AND the object is being deleted then there's - // no reason to bother with dataplane configuration for it its already - // handled. - return ctrl.Result{}, nil - } - // if the finalizer is not set, and the object is not being deleted, set the - // finalizer before we do anything else to ensure we don't lose track of - // dataplane configuration. - return ctrl.Result{}, setDataPlaneFinalizer(ctx, r.Client, tcproute) - } - - // if the TCPRoute is being deleted, remove it from the DataPlane - // TODO: enable deletion grace period https://github.com/Kong/blixt/issues/48 - if tcproute.DeletionTimestamp != nil { - return ctrl.Result{}, r.ensureTCPRouteDeletedInDataPlane(ctx, tcproute, gateway) - } - - // in all other cases ensure the TCPRoute is configured in the dataplane - if err := r.ensureTCPRouteConfiguredInDataPlane(ctx, tcproute, gateway); err != nil { - if err.Error() == "endpoints not ready" { - r.log.Info("endpoints not yet ready for TCPRoute, retrying", "namespace", tcproute.Namespace, "name", tcproute.Name) - return ctrl.Result{RequeueAfter: time.Second}, nil - } - return ctrl.Result{}, err - } - - return ctrl.Result{}, nil -} - -// isTCPRouteManaged verifies wether a provided TCPRoute is managed by this -// controller, according to it's Gateway and GatewayClass. -func (r *TCPRouteReconciler) isTCPRouteManaged(ctx context.Context, tcproute gatewayv1alpha2.TCPRoute) (bool, *gatewayv1beta1.Gateway, error) { - var supportedGateways []gatewayv1beta1.Gateway - - //Use the retrieve objects its parent ref to look for the gateway. - for _, parentRef := range tcproute.Spec.ParentRefs { - //Build Gateway object to retrieve - gw := new(gatewayv1beta1.Gateway) - - ns := tcproute.Namespace - if parentRef.Namespace != nil { - ns = string(*parentRef.Namespace) - } - - //Get Gateway for TCP Route - if err := r.Get(ctx, types.NamespacedName{Name: string(parentRef.Name), Namespace: ns}, gw); err != nil { - if !errors.IsNotFound(err) { - return false, nil, err - } - continue - } - - //Get GatewayClass for the Gateway and match to our name of controler - gwc := new(gatewayv1beta1.GatewayClass) - if err := r.Get(ctx, types.NamespacedName{Name: string(gw.Spec.GatewayClassName), Namespace: ns}, gwc); err != nil { - if !errors.IsNotFound(err) { - return false, nil, err - } - continue - } - - if gwc.Spec.ControllerName != vars.GatewayClassControllerName { - // not managed by this implementation, check the next parent ref - continue - } - - //Check if referred gateway has the at least one listener with properties defined from TCPRoute parentref. - if err := r.verifyListener(ctx, gw, parentRef); err != nil { - // until the Gateway has a relevant listener, we can't operate on the route. - // Updates to the relevant Gateway will re-enqueue the TCPRoute reconcilation to retry. - r.log.Info("No matching listener found for referred gateway", "GatewayName", parentRef.Name, "GatewayPort", parentRef.Port) - //Check next parent ref. - continue - } - - supportedGateways = append(supportedGateways, *gw) - } - - if len(supportedGateways) < 1 { - return false, nil, nil - } - - // TODO: support multiple gateways https://github.com/Kong/blixt/issues/40 - referredGateway := &supportedGateways[0] - r.log.Info("TCP Route appeared referring to Gateway", "Gateway ", referredGateway.Name, "GatewayClass Name", referredGateway.Spec.GatewayClassName) - - return true, referredGateway, nil -} - -// verifyListener verifies that the provided gateway has at least one listener -// matching the provided ParentReference. -func (r *TCPRouteReconciler) verifyListener(_ context.Context, gw *gatewayv1beta1.Gateway, tcprouteSpec gatewayv1alpha2.ParentReference) error { - for _, listener := range gw.Spec.Listeners { - if (listener.Protocol == gatewayv1beta1.TCPProtocolType) && (listener.Port == gatewayv1beta1.PortNumber(*tcprouteSpec.Port)) { - return nil - } - } - return fmt.Errorf("No matching Gateway listener found for defined Parentref") -} - -func (r *TCPRouteReconciler) ensureTCPRouteConfiguredInDataPlane(ctx context.Context, tcproute *gatewayv1alpha2.TCPRoute, gateway *gatewayv1beta1.Gateway) error { - // build the dataplane configuration from the TCPRoute and its Gateway - targets, err := dataplane.CompileTCPRouteToDataPlaneBackend(ctx, r.Client, tcproute, gateway) - if err != nil { - return err - } - - if _, err = r.BackendsClientManager.Update(ctx, targets); err != nil { - return err - } - - r.log.Info("successful data-plane UPDATE") - - return nil -} - -func (r *TCPRouteReconciler) ensureTCPRouteDeletedInDataPlane(ctx context.Context, tcproute *gatewayv1alpha2.TCPRoute, gateway *gatewayv1beta1.Gateway) error { - // get the gateway IP and port. - gwIP, err := dataplane.GetGatewayIP(gateway) - if err != nil { - return err - } - gatewayIP := binary.BigEndian.Uint32(gwIP.To4()) - gwPort, err := dataplane.GetGatewayPort(gateway, tcproute.Spec.ParentRefs) - if err != nil { - return err - } - - vip := dataplane.Vip{ - Ip: gatewayIP, - Port: gwPort, - } - - // delete the target from the dataplane - if _, err = r.BackendsClientManager.Delete(ctx, &vip); err != nil { - return err - } - - r.log.Info("successful data-plane DELETE") - - oldFinalizers := tcproute.GetFinalizers() - newFinalizers := make([]string, 0, len(oldFinalizers)-1) - for _, finalizer := range oldFinalizers { - if finalizer != DataPlaneFinalizer { - newFinalizers = append(newFinalizers, finalizer) - } - } - tcproute.SetFinalizers(newFinalizers) - - return r.Client.Update(ctx, tcproute) - -} diff --git a/controllers/tcproute_controller_watch_utils.go b/controllers/tcproute_controller_watch_utils.go deleted file mode 100644 index 59eb60b2..00000000 --- a/controllers/tcproute_controller_watch_utils.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "fmt" - "reflect" - - appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -// mapDataPlaneDaemonsetToTCPRoutes is a mapping function to map dataplane -// DaemonSet updates to TCPRoute reconcilations. This enables changes to the -// DaemonSet such as adding new Pods for a new Node to result in new dataplane -// instances getting fully configured. -func (r *TCPRouteReconciler) mapDataPlaneDaemonsetToTCPRoutes(ctx context.Context, obj client.Object) (reqs []reconcile.Request) { - daemonset, ok := obj.(*appsv1.DaemonSet) - if !ok { - return - } - - // determine if this is a blixt daemonset - matchLabels := daemonset.Spec.Selector.MatchLabels - app, ok := matchLabels["app"] - if !ok || app != vars.DefaultDataPlaneAppLabel { - return - } - - // verify that it's the dataplane daemonset - component, ok := matchLabels["component"] - if !ok || component != vars.DefaultDataPlaneComponentLabel { - return - } - - tcproutes := &gatewayv1alpha2.TCPRouteList{} - if err := r.Client.List(ctx, tcproutes); err != nil { - // TODO: https://github.com/kubernetes-sigs/controller-runtime/issues/1996 - r.log.Error(err, "could not enqueue TCPRoutes for DaemonSet update") - return - } - - for _, tcproute := range tcproutes.Items { - reqs = append(reqs, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: tcproute.Namespace, - Name: tcproute.Name, - }, - }) - } - - return -} - -// mapGatewayToTCPRoutes enqueues reconcilation for all TCPRoutes whenever -// an event occurs on a relevant Gateway. -func (r *TCPRouteReconciler) mapGatewayToTCPRoutes(_ context.Context, obj client.Object) (reqs []reconcile.Request) { - gateway, ok := obj.(*gatewayv1beta1.Gateway) - if !ok { - r.log.Error(fmt.Errorf("invalid type in map func"), "failed to map gateways to tcproutes", "expected", "*gatewayv1beta1.Gateway", "received", reflect.TypeOf(obj)) - return - } - - tcproutes := new(gatewayv1alpha2.TCPRouteList) - if err := r.Client.List(context.Background(), tcproutes); err != nil { - // TODO: https://github.com/kubernetes-sigs/controller-runtime/issues/1996 - r.log.Error(err, "could not enqueue TCPRoutes for Gateway update") - return - } - - for _, tcproute := range tcproutes.Items { - for _, parentRef := range tcproute.Spec.ParentRefs { - namespace := tcproute.Namespace - if parentRef.Namespace != nil { - namespace = string(*parentRef.Namespace) - } - if parentRef.Name == gatewayv1alpha2.ObjectName(gateway.Name) && namespace == gateway.Namespace { - reqs = append(reqs, reconcile.Request{NamespacedName: types.NamespacedName{ - Namespace: tcproute.Namespace, - Name: tcproute.Name, - }}) - } - } - } - - return -} diff --git a/controllers/udproute_controller.go b/controllers/udproute_controller.go deleted file mode 100644 index e01a1b89..00000000 --- a/controllers/udproute_controller.go +++ /dev/null @@ -1,251 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "encoding/binary" - "fmt" - "time" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/handler" - "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/source" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - dataplane "github.com/kubernetes-sigs/blixt/internal/dataplane/client" - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=udproutes,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=udproutes/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=udproutes/finalizers,verbs=update -//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch -//+kubebuilder:rbac:groups=core,resources=pods/status,verbs=get -//+kubebuilder:rbac:groups=apps,resources=daemonsets,verbs=get;list;watch -//+kubebuilder:rbac:groups=apps,resources=daemonsets/status,verbs=get - -// UDPRouteReconciler reconciles a UDPRoute object -type UDPRouteReconciler struct { - client.Client - Scheme *runtime.Scheme - - log logr.Logger - ClientReconcileRequestChan <-chan event.GenericEvent - BackendsClientManager *dataplane.BackendsClientManager -} - -// SetupWithManager sets up the controller with the Manager. -func (r *UDPRouteReconciler) SetupWithManager(mgr ctrl.Manager) error { - r.log = log.FromContext(context.Background()) - - return ctrl.NewControllerManagedBy(mgr). - For(&gatewayv1alpha2.UDPRoute{}). - WatchesRawSource( - &source.Channel{Source: r.ClientReconcileRequestChan}, - handler.EnqueueRequestsFromMapFunc(r.mapDataPlaneDaemonsetToUDPRoutes), - ). - Watches( - &gatewayv1beta1.Gateway{}, - handler.EnqueueRequestsFromMapFunc(r.mapGatewayToUDPRoutes), - ). - Complete(r) -} - -// Reconcile reconciles UDPRoute object -func (r *UDPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - udproute := new(gatewayv1alpha2.UDPRoute) - if err := r.Get(ctx, req.NamespacedName, udproute); err != nil { - if errors.IsNotFound(err) { - r.log.Info("object enqueued no longer exists, skipping") - return ctrl.Result{}, nil - } - r.log.Info("Error retrieving udp route", "Err : ", err) - return ctrl.Result{}, err - } - - isManaged, gateway, err := r.isUDPRouteManaged(ctx, *udproute) - if err != nil { - return ctrl.Result{}, err - } - if !isManaged { - // TODO: enable orphan checking https://github.com/kubernetes-sigs/blixt/issues/47 - return ctrl.Result{}, nil - } - - if !controllerutil.ContainsFinalizer(udproute, DataPlaneFinalizer) { - if udproute.DeletionTimestamp != nil { - // if the finalizer isn't set, AND the object is being deleted then there's - // no reason to bother with dataplane configuration for it its already - // handled. - return ctrl.Result{}, nil - } - // if the finalizer is not set, and the object is not being deleted, set the - // finalizer before we do anything else to ensure we don't lose track of - // dataplane configuration. - return ctrl.Result{}, setDataPlaneFinalizer(ctx, r.Client, udproute) - } - - // if the UDPRoute is being deleted, remove it from the DataPlane - // TODO: enable deletion grace period https://github.com/kubernetes-sigs/blixt/issues/48 - if udproute.DeletionTimestamp != nil { - return ctrl.Result{}, r.ensureUDPRouteDeletedInDataPlane(ctx, udproute, gateway) - } - - // in all other cases ensure the UDPRoute is configured in the dataplane - if err := r.ensureUDPRouteConfiguredInDataPlane(ctx, udproute, gateway); err != nil { - if err.Error() == "endpoints not ready" { - r.log.Info("endpoints not yet ready for UDPRoute, retrying", "namespace", udproute.Namespace, "name", udproute.Name) - return ctrl.Result{RequeueAfter: time.Second}, nil - } - return ctrl.Result{}, err - } - - return ctrl.Result{}, nil -} - -// isUDPRouteManaged verifies wether a provided UDPRoute is managed by this -// controller, according to it's Gateway and GatewayClass. -func (r *UDPRouteReconciler) isUDPRouteManaged(ctx context.Context, udproute gatewayv1alpha2.UDPRoute) (bool, *gatewayv1beta1.Gateway, error) { - var supportedGateways []gatewayv1beta1.Gateway - - //Use the retrieve objects its parent ref to look for the gateway. - for _, parentRef := range udproute.Spec.ParentRefs { - //Build Gateway object to retrieve - gw := new(gatewayv1beta1.Gateway) - - ns := udproute.Namespace - if parentRef.Namespace != nil { - ns = string(*parentRef.Namespace) - } - - //Get Gateway for UDP Route - if err := r.Get(ctx, types.NamespacedName{Name: string(parentRef.Name), Namespace: ns}, gw); err != nil { - if !errors.IsNotFound(err) { - return false, nil, err - } - continue - } - - //Get GatewayClass for the Gateway and match to our name of controler - gwc := new(gatewayv1beta1.GatewayClass) - if err := r.Get(ctx, types.NamespacedName{Name: string(gw.Spec.GatewayClassName), Namespace: ns}, gwc); err != nil { - if !errors.IsNotFound(err) { - return false, nil, err - } - continue - } - - if gwc.Spec.ControllerName != vars.GatewayClassControllerName { - // not managed by this implementation, check the next parent ref - continue - } - - //Check if referred gateway has the at least one listener with properties defined from UDPRoute parentref. - if err := r.verifyListener(ctx, gw, parentRef); err != nil { - // until the Gateway has a relevant listener, we can't operate on the route. - // Updates to the relevant Gateway will re-enqueue the UDPRoute reconcilation to retry. - r.log.Info("No matching listener found for referred gateway", "GatewayName", parentRef.Name, "GatewayPort", parentRef.Port) - //Check next parent ref. - continue - } - - supportedGateways = append(supportedGateways, *gw) - } - - if len(supportedGateways) < 1 { - return false, nil, nil - } - - // TODO: support multiple gateways https://github.com/kubernetes-sigs/blixt/issues/40 - referredGateway := &supportedGateways[0] - r.log.Info("UDP Route appeared referring to Gateway", "Gateway ", referredGateway.Name, "GatewayClass Name", referredGateway.Spec.GatewayClassName) - - return true, referredGateway, nil -} - -// verifyListener verifies that the provided gateway has at least one listener -// matching the provided ParentReference. -func (r *UDPRouteReconciler) verifyListener(_ context.Context, gw *gatewayv1beta1.Gateway, udprouteSpec gatewayv1alpha2.ParentReference) error { - for _, listener := range gw.Spec.Listeners { - if (listener.Protocol == gatewayv1beta1.UDPProtocolType) && (listener.Port == gatewayv1beta1.PortNumber(*udprouteSpec.Port)) { - return nil - } - } - return fmt.Errorf("No matching Gateway listener found for defined Parentref") -} - -func (r *UDPRouteReconciler) ensureUDPRouteConfiguredInDataPlane(ctx context.Context, udproute *gatewayv1alpha2.UDPRoute, gateway *gatewayv1beta1.Gateway) error { - // build the dataplane configuration from the UDPRoute and its Gateway - targets, err := dataplane.CompileUDPRouteToDataPlaneBackend(ctx, r.Client, udproute, gateway) - if err != nil { - return err - } - - if _, err = r.BackendsClientManager.Update(ctx, targets); err != nil { - return err - } - - r.log.Info("successful data-plane UPDATE") - - return nil -} - -func (r *UDPRouteReconciler) ensureUDPRouteDeletedInDataPlane(ctx context.Context, udproute *gatewayv1alpha2.UDPRoute, gateway *gatewayv1beta1.Gateway) error { - // get the gateway IP and port. - gwIP, err := dataplane.GetGatewayIP(gateway) - if err != nil { - return err - } - gatewayIP := binary.BigEndian.Uint32(gwIP.To4()) - gwPort, err := dataplane.GetGatewayPort(gateway, udproute.Spec.ParentRefs) - if err != nil { - return err - } - - vip := dataplane.Vip{ - Ip: gatewayIP, - Port: gwPort, - } - - // delete the target from the dataplane - if _, err = r.BackendsClientManager.Delete(ctx, &vip); err != nil { - return err - } - - r.log.Info("successful data-plane DELETE") - - oldFinalizers := udproute.GetFinalizers() - newFinalizers := make([]string, 0, len(oldFinalizers)-1) - for _, finalizer := range oldFinalizers { - if finalizer != DataPlaneFinalizer { - newFinalizers = append(newFinalizers, finalizer) - } - } - udproute.SetFinalizers(newFinalizers) - - return r.Client.Update(ctx, udproute) -} diff --git a/controllers/udproute_controller_watch_utils.go b/controllers/udproute_controller_watch_utils.go deleted file mode 100644 index 58901aac..00000000 --- a/controllers/udproute_controller_watch_utils.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - "fmt" - "reflect" - - appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/reconcile" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -// mapDataPlaneDaemonsetToUDPRoutes is a mapping function to map dataplane -// DaemonSet updates to UDPRoute reconcilations. This enables changes to the -// DaemonSet such as adding new Pods for a new Node to result in new dataplane -// instances getting fully configured. -func (r *UDPRouteReconciler) mapDataPlaneDaemonsetToUDPRoutes(ctx context.Context, obj client.Object) (reqs []reconcile.Request) { - daemonset, ok := obj.(*appsv1.DaemonSet) - if !ok { - return - } - - // determine if this is a blixt daemonset - matchLabels := daemonset.Spec.Selector.MatchLabels - app, ok := matchLabels["app"] - if !ok || app != vars.DefaultDataPlaneAppLabel { - return - } - - // verify that it's the dataplane daemonset - component, ok := matchLabels["component"] - if !ok || component != vars.DefaultDataPlaneComponentLabel { - return - } - - udproutes := &gatewayv1alpha2.UDPRouteList{} - if err := r.Client.List(ctx, udproutes); err != nil { - // TODO: https://github.com/kubernetes-sigs/controller-runtime/issues/1996 - r.log.Error(err, "could not enqueue UDPRoutes for DaemonSet update") - return - } - - for _, udproute := range udproutes.Items { - reqs = append(reqs, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: udproute.Namespace, - Name: udproute.Name, - }, - }) - } - - return -} - -// mapGatewayToUDPRoutes enqueues reconcilation for all UDPRoutes whenever -// an event occurs on a relevant Gateway. -func (r *UDPRouteReconciler) mapGatewayToUDPRoutes(_ context.Context, obj client.Object) (reqs []reconcile.Request) { - gateway, ok := obj.(*gatewayv1beta1.Gateway) - if !ok { - r.log.Error(fmt.Errorf("invalid type in map func"), "failed to map gateways to udproutes", "expected", "*gatewayv1beta1.Gateway", "received", reflect.TypeOf(obj)) - return - } - - udproutes := new(gatewayv1alpha2.UDPRouteList) - if err := r.Client.List(context.Background(), udproutes); err != nil { - // TODO: https://github.com/kubernetes-sigs/controller-runtime/issues/1996 - r.log.Error(err, "could not enqueue UDPRoutes for Gateway update") - return - } - - for _, udproute := range udproutes.Items { - for _, parentRef := range udproute.Spec.ParentRefs { - namespace := udproute.Namespace - if parentRef.Namespace != nil { - namespace = string(*parentRef.Namespace) - } - if parentRef.Name == gatewayv1alpha2.ObjectName(gateway.Name) && namespace == gateway.Namespace { - reqs = append(reqs, reconcile.Request{NamespacedName: types.NamespacedName{ - Namespace: udproute.Namespace, - Name: udproute.Name, - }}) - } - } - } - - return -} diff --git a/controllers/utils.go b/controllers/utils.go deleted file mode 100644 index 754c2dae..00000000 --- a/controllers/utils.go +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 controllers - -import ( - "context" - - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - // DataPlaneFinalizer is the finalizer which indicates that an object needs to - // have its configuration removed from the dataplane before it can be deleted. - DataPlaneFinalizer = "blixt/dataplane-configuration" -) - -func setDataPlaneFinalizer(ctx context.Context, c client.Client, obj client.Object) error { - finalizers := obj.GetFinalizers() - obj.SetFinalizers(append(finalizers, DataPlaneFinalizer)) - return c.Update(ctx, obj) -} diff --git a/controlplane/Dockerfile b/controlplane/Dockerfile deleted file mode 100644 index 3ba7f876..00000000 --- a/controlplane/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx - -FROM --platform=$BUILDPLATFORM rust:alpine -ARG TARGETPLATFORM - -RUN apk add clang lld -COPY --from=xx / / - -WORKDIR /workspace - -RUN --mount=type=bind,source=src,target=src \ - --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ - --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ - xx-cargo build --release --target-dir ./build && \ - xx-verify ./build/$(xx-cargo --print-target-triple)/release/controller diff --git a/go.mod b/go.mod deleted file mode 100644 index 248ea159..00000000 --- a/go.mod +++ /dev/null @@ -1,114 +0,0 @@ -module github.com/kubernetes-sigs/blixt - -go 1.21 - -require ( - github.com/go-logr/logr v1.4.2 - github.com/go-logr/stdr v1.2.2 - github.com/google/uuid v1.6.0 - github.com/kong/kubernetes-testing-framework v0.39.1 - github.com/onsi/ginkgo/v2 v2.17.1 - github.com/onsi/gomega v1.32.0 - github.com/stretchr/testify v1.9.0 - github.com/vishvananda/netlink v1.1.0 - golang.org/x/net v0.26.0 - google.golang.org/grpc v1.64.0 - google.golang.org/protobuf v1.34.2 - k8s.io/api v0.29.3 - k8s.io/apiextensions-apiserver v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/client-go v0.29.3 - k8s.io/utils v0.0.0-20240102154912-e7106e64919e - sigs.k8s.io/controller-runtime v0.17.2 - sigs.k8s.io/gateway-api v0.8.2-0.20231009182848-335be6a634e7 -) - -require ( - github.com/Microsoft/go-winio v0.6.0 // indirect - github.com/avast/retry-go/v4 v4.5.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v26.1.4+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/emicklei/go-restful/v3 v3.11.2 // indirect - github.com/evanphx/json-patch v5.9.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-errors/errors v1.4.2 // indirect - github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/jsonreference v0.20.4 // indirect - github.com/go-openapi/swag v0.22.9 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/gorilla/websocket v1.5.1 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/spdystream v0.2.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc2 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.18.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.47.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect - github.com/xlab/treeprint v1.2.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect - go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.29.3 // indirect - k8s.io/klog/v2 v2.120.1 // indirect - k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kind v0.20.0 // indirect - sigs.k8s.io/kustomize/api v0.14.0 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index c9e23955..00000000 --- a/go.sum +++ /dev/null @@ -1,393 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= -github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= -github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU= -github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= -github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= -github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= -github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= -github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kong/kubernetes-testing-framework v0.39.1 h1:30dTVe0Muda3r6NAMQHvdGLuB+nkhZRXnJA8AJjuvO4= -github.com/kong/kubernetes-testing-framework v0.39.1/go.mod h1:12TQ5gAkZhuxh47IJcW03iumky1X/T7ZCStuClQ1vzs= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= -github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= -github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= -github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= -github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= -github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= -go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= -go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= -golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= -gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= -k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= -k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= -k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= -k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= -k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= -k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232 h1:MMq4iF9pHuAz/9dLnHwBQKEoeigXClzs3MFh/seyqtA= -k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232/go.mod h1:Pa1PvrP7ACSkuX6I7KYomY6cmMA0Tx86waBhDUgoKPw= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= -sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= -sigs.k8s.io/gateway-api v0.8.2-0.20231009182848-335be6a634e7 h1:Z4u5jx1D+UGu+aHyKKpKlbSoFDdRbhAdT0v17vA1/iE= -sigs.k8s.io/gateway-api v0.8.2-0.20231009182848-335be6a634e7/go.mod h1:+QpYENjk9s31/abu2Pv5BpK2v88UQDK2aeQCwCvy6ck= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kind v0.20.0 h1:f0sc3v9mQbGnjBUaqSFST1dwIuiikKVGgoTwpoP33a8= -sigs.k8s.io/kind v0.20.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs= -sigs.k8s.io/kustomize/api v0.14.0 h1:6+QLmXXA8X4eDM7ejeaNUyruA1DDB3PVIjbpVhDOJRA= -sigs.k8s.io/kustomize/api v0.14.0/go.mod h1:vmOXlC8BcmcUJQjiceUbcyQ75JBP6eg8sgoyzc+eLpQ= -sigs.k8s.io/kustomize/kyaml v0.14.3 h1:WpabVAKZe2YEp/irTSHwD6bfjwZnTtSDewd2BVJGMZs= -sigs.k8s.io/kustomize/kyaml v0.14.3/go.mod h1:npvh9epWysfQ689Rtt/U+dpOJDTBn8kUnF1O6VzvmZA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/internal/dataplane/client/backends.pb.go b/internal/dataplane/client/backends.pb.go deleted file mode 100644 index da7eaa46..00000000 --- a/internal/dataplane/client/backends.pb.go +++ /dev/null @@ -1,520 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v3.14.0 -// source: dataplane/api-server/proto/backends.proto - -package client - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Vip struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ip uint32 `protobuf:"varint,1,opt,name=ip,proto3" json:"ip,omitempty"` - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` -} - -func (x *Vip) Reset() { - *x = Vip{} - if protoimpl.UnsafeEnabled { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Vip) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Vip) ProtoMessage() {} - -func (x *Vip) ProtoReflect() protoreflect.Message { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Vip.ProtoReflect.Descriptor instead. -func (*Vip) Descriptor() ([]byte, []int) { - return file_dataplane_api_server_proto_backends_proto_rawDescGZIP(), []int{0} -} - -func (x *Vip) GetIp() uint32 { - if x != nil { - return x.Ip - } - return 0 -} - -func (x *Vip) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -type Target struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Daddr uint32 `protobuf:"varint,1,opt,name=daddr,proto3" json:"daddr,omitempty"` - Dport uint32 `protobuf:"varint,2,opt,name=dport,proto3" json:"dport,omitempty"` - Ifindex *uint32 `protobuf:"varint,3,opt,name=ifindex,proto3,oneof" json:"ifindex,omitempty"` -} - -func (x *Target) Reset() { - *x = Target{} - if protoimpl.UnsafeEnabled { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Target) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Target) ProtoMessage() {} - -func (x *Target) ProtoReflect() protoreflect.Message { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Target.ProtoReflect.Descriptor instead. -func (*Target) Descriptor() ([]byte, []int) { - return file_dataplane_api_server_proto_backends_proto_rawDescGZIP(), []int{1} -} - -func (x *Target) GetDaddr() uint32 { - if x != nil { - return x.Daddr - } - return 0 -} - -func (x *Target) GetDport() uint32 { - if x != nil { - return x.Dport - } - return 0 -} - -func (x *Target) GetIfindex() uint32 { - if x != nil && x.Ifindex != nil { - return *x.Ifindex - } - return 0 -} - -type Targets struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Vip *Vip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` - Targets []*Target `protobuf:"bytes,2,rep,name=targets,proto3" json:"targets,omitempty"` -} - -func (x *Targets) Reset() { - *x = Targets{} - if protoimpl.UnsafeEnabled { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Targets) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Targets) ProtoMessage() {} - -func (x *Targets) ProtoReflect() protoreflect.Message { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Targets.ProtoReflect.Descriptor instead. -func (*Targets) Descriptor() ([]byte, []int) { - return file_dataplane_api_server_proto_backends_proto_rawDescGZIP(), []int{2} -} - -func (x *Targets) GetVip() *Vip { - if x != nil { - return x.Vip - } - return nil -} - -func (x *Targets) GetTargets() []*Target { - if x != nil { - return x.Targets - } - return nil -} - -type Confirmation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Confirmation string `protobuf:"bytes,1,opt,name=confirmation,proto3" json:"confirmation,omitempty"` -} - -func (x *Confirmation) Reset() { - *x = Confirmation{} - if protoimpl.UnsafeEnabled { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Confirmation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Confirmation) ProtoMessage() {} - -func (x *Confirmation) ProtoReflect() protoreflect.Message { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Confirmation.ProtoReflect.Descriptor instead. -func (*Confirmation) Descriptor() ([]byte, []int) { - return file_dataplane_api_server_proto_backends_proto_rawDescGZIP(), []int{3} -} - -func (x *Confirmation) GetConfirmation() string { - if x != nil { - return x.Confirmation - } - return "" -} - -type PodIP struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ip uint32 `protobuf:"varint,1,opt,name=ip,proto3" json:"ip,omitempty"` -} - -func (x *PodIP) Reset() { - *x = PodIP{} - if protoimpl.UnsafeEnabled { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PodIP) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PodIP) ProtoMessage() {} - -func (x *PodIP) ProtoReflect() protoreflect.Message { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PodIP.ProtoReflect.Descriptor instead. -func (*PodIP) Descriptor() ([]byte, []int) { - return file_dataplane_api_server_proto_backends_proto_rawDescGZIP(), []int{4} -} - -func (x *PodIP) GetIp() uint32 { - if x != nil { - return x.Ip - } - return 0 -} - -type InterfaceIndexConfirmation struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ifindex uint32 `protobuf:"varint,1,opt,name=ifindex,proto3" json:"ifindex,omitempty"` -} - -func (x *InterfaceIndexConfirmation) Reset() { - *x = InterfaceIndexConfirmation{} - if protoimpl.UnsafeEnabled { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterfaceIndexConfirmation) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterfaceIndexConfirmation) ProtoMessage() {} - -func (x *InterfaceIndexConfirmation) ProtoReflect() protoreflect.Message { - mi := &file_dataplane_api_server_proto_backends_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InterfaceIndexConfirmation.ProtoReflect.Descriptor instead. -func (*InterfaceIndexConfirmation) Descriptor() ([]byte, []int) { - return file_dataplane_api_server_proto_backends_proto_rawDescGZIP(), []int{5} -} - -func (x *InterfaceIndexConfirmation) GetIfindex() uint32 { - if x != nil { - return x.Ifindex - } - return 0 -} - -var File_dataplane_api_server_proto_backends_proto protoreflect.FileDescriptor - -var file_dataplane_api_server_proto_backends_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2d, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x62, 0x61, 0x63, - 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x22, 0x29, 0x0a, 0x03, 0x56, 0x69, 0x70, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, - 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, - 0x22, 0x5f, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x61, 0x64, 0x64, 0x72, - 0x12, 0x14, 0x0a, 0x05, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x05, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x07, 0x69, 0x66, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x07, 0x69, 0x66, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x69, 0x66, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x22, 0x56, 0x0a, 0x07, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x03, - 0x76, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x61, 0x63, 0x6b, - 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x56, 0x69, 0x70, 0x52, 0x03, 0x76, 0x69, 0x70, 0x12, 0x2a, 0x0a, - 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0x32, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, - 0x05, 0x50, 0x6f, 0x64, 0x49, 0x50, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x02, 0x69, 0x70, 0x22, 0x36, 0x0a, 0x1a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x69, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x32, 0xbc, - 0x01, 0x0a, 0x08, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x12, 0x4a, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x12, 0x0f, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x50, 0x6f, 0x64, 0x49, - 0x50, 0x1a, 0x24, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x12, 0x11, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x73, 0x1a, 0x16, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x06, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x0d, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, - 0x73, 0x2e, 0x56, 0x69, 0x70, 0x1a, 0x16, 0x2e, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x73, - 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x31, 0x5a, - 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x6f, 0x6e, 0x67, - 0x2f, 0x62, 0x6c, 0x69, 0x78, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_dataplane_api_server_proto_backends_proto_rawDescOnce sync.Once - file_dataplane_api_server_proto_backends_proto_rawDescData = file_dataplane_api_server_proto_backends_proto_rawDesc -) - -func file_dataplane_api_server_proto_backends_proto_rawDescGZIP() []byte { - file_dataplane_api_server_proto_backends_proto_rawDescOnce.Do(func() { - file_dataplane_api_server_proto_backends_proto_rawDescData = protoimpl.X.CompressGZIP(file_dataplane_api_server_proto_backends_proto_rawDescData) - }) - return file_dataplane_api_server_proto_backends_proto_rawDescData -} - -var file_dataplane_api_server_proto_backends_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_dataplane_api_server_proto_backends_proto_goTypes = []interface{}{ - (*Vip)(nil), // 0: backends.Vip - (*Target)(nil), // 1: backends.Target - (*Targets)(nil), // 2: backends.Targets - (*Confirmation)(nil), // 3: backends.Confirmation - (*PodIP)(nil), // 4: backends.PodIP - (*InterfaceIndexConfirmation)(nil), // 5: backends.InterfaceIndexConfirmation -} -var file_dataplane_api_server_proto_backends_proto_depIdxs = []int32{ - 0, // 0: backends.Targets.vip:type_name -> backends.Vip - 1, // 1: backends.Targets.targets:type_name -> backends.Target - 4, // 2: backends.backends.GetInterfaceIndex:input_type -> backends.PodIP - 2, // 3: backends.backends.Update:input_type -> backends.Targets - 0, // 4: backends.backends.Delete:input_type -> backends.Vip - 5, // 5: backends.backends.GetInterfaceIndex:output_type -> backends.InterfaceIndexConfirmation - 3, // 6: backends.backends.Update:output_type -> backends.Confirmation - 3, // 7: backends.backends.Delete:output_type -> backends.Confirmation - 5, // [5:8] is the sub-list for method output_type - 2, // [2:5] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_dataplane_api_server_proto_backends_proto_init() } -func file_dataplane_api_server_proto_backends_proto_init() { - if File_dataplane_api_server_proto_backends_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_dataplane_api_server_proto_backends_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Vip); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_dataplane_api_server_proto_backends_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Target); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_dataplane_api_server_proto_backends_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Targets); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_dataplane_api_server_proto_backends_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Confirmation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_dataplane_api_server_proto_backends_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PodIP); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_dataplane_api_server_proto_backends_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfaceIndexConfirmation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_dataplane_api_server_proto_backends_proto_msgTypes[1].OneofWrappers = []interface{}{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_dataplane_api_server_proto_backends_proto_rawDesc, - NumEnums: 0, - NumMessages: 6, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_dataplane_api_server_proto_backends_proto_goTypes, - DependencyIndexes: file_dataplane_api_server_proto_backends_proto_depIdxs, - MessageInfos: file_dataplane_api_server_proto_backends_proto_msgTypes, - }.Build() - File_dataplane_api_server_proto_backends_proto = out.File - file_dataplane_api_server_proto_backends_proto_rawDesc = nil - file_dataplane_api_server_proto_backends_proto_goTypes = nil - file_dataplane_api_server_proto_backends_proto_depIdxs = nil -} diff --git a/internal/dataplane/client/backends_grpc.pb.go b/internal/dataplane/client/backends_grpc.pb.go deleted file mode 100644 index 16486c9e..00000000 --- a/internal/dataplane/client/backends_grpc.pb.go +++ /dev/null @@ -1,184 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v3.14.0 -// source: dataplane/api-server/proto/backends.proto - -package client - -import ( - context "context" - - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - Backends_GetInterfaceIndex_FullMethodName = "/backends.backends/GetInterfaceIndex" - Backends_Update_FullMethodName = "/backends.backends/Update" - Backends_Delete_FullMethodName = "/backends.backends/Delete" -) - -// BackendsClient is the client API for Backends service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type BackendsClient interface { - GetInterfaceIndex(ctx context.Context, in *PodIP, opts ...grpc.CallOption) (*InterfaceIndexConfirmation, error) - Update(ctx context.Context, in *Targets, opts ...grpc.CallOption) (*Confirmation, error) - Delete(ctx context.Context, in *Vip, opts ...grpc.CallOption) (*Confirmation, error) -} - -type backendsClient struct { - cc grpc.ClientConnInterface -} - -func NewBackendsClient(cc grpc.ClientConnInterface) BackendsClient { - return &backendsClient{cc} -} - -func (c *backendsClient) GetInterfaceIndex(ctx context.Context, in *PodIP, opts ...grpc.CallOption) (*InterfaceIndexConfirmation, error) { - out := new(InterfaceIndexConfirmation) - err := c.cc.Invoke(ctx, Backends_GetInterfaceIndex_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *backendsClient) Update(ctx context.Context, in *Targets, opts ...grpc.CallOption) (*Confirmation, error) { - out := new(Confirmation) - err := c.cc.Invoke(ctx, Backends_Update_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *backendsClient) Delete(ctx context.Context, in *Vip, opts ...grpc.CallOption) (*Confirmation, error) { - out := new(Confirmation) - err := c.cc.Invoke(ctx, Backends_Delete_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// BackendsServer is the server API for Backends service. -// All implementations must embed UnimplementedBackendsServer -// for forward compatibility -type BackendsServer interface { - GetInterfaceIndex(context.Context, *PodIP) (*InterfaceIndexConfirmation, error) - Update(context.Context, *Targets) (*Confirmation, error) - Delete(context.Context, *Vip) (*Confirmation, error) - mustEmbedUnimplementedBackendsServer() -} - -// UnimplementedBackendsServer must be embedded to have forward compatible implementations. -type UnimplementedBackendsServer struct { -} - -func (UnimplementedBackendsServer) GetInterfaceIndex(context.Context, *PodIP) (*InterfaceIndexConfirmation, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetInterfaceIndex not implemented") -} -func (UnimplementedBackendsServer) Update(context.Context, *Targets) (*Confirmation, error) { - return nil, status.Errorf(codes.Unimplemented, "method Update not implemented") -} -func (UnimplementedBackendsServer) Delete(context.Context, *Vip) (*Confirmation, error) { - return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") -} -func (UnimplementedBackendsServer) mustEmbedUnimplementedBackendsServer() {} - -// UnsafeBackendsServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to BackendsServer will -// result in compilation errors. -type UnsafeBackendsServer interface { - mustEmbedUnimplementedBackendsServer() -} - -func RegisterBackendsServer(s grpc.ServiceRegistrar, srv BackendsServer) { - s.RegisterService(&Backends_ServiceDesc, srv) -} - -func _Backends_GetInterfaceIndex_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PodIP) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BackendsServer).GetInterfaceIndex(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Backends_GetInterfaceIndex_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BackendsServer).GetInterfaceIndex(ctx, req.(*PodIP)) - } - return interceptor(ctx, in, info, handler) -} - -func _Backends_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Targets) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BackendsServer).Update(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Backends_Update_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BackendsServer).Update(ctx, req.(*Targets)) - } - return interceptor(ctx, in, info, handler) -} - -func _Backends_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Vip) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BackendsServer).Delete(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Backends_Delete_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BackendsServer).Delete(ctx, req.(*Vip)) - } - return interceptor(ctx, in, info, handler) -} - -// Backends_ServiceDesc is the grpc.ServiceDesc for Backends service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var Backends_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "backends.backends", - HandlerType: (*BackendsServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetInterfaceIndex", - Handler: _Backends_GetInterfaceIndex_Handler, - }, - { - MethodName: "Update", - Handler: _Backends_Update_Handler, - }, - { - MethodName: "Delete", - Handler: _Backends_Delete_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "dataplane/api-server/proto/backends.proto", -} diff --git a/internal/dataplane/client/client.go b/internal/dataplane/client/client.go deleted file mode 100644 index 723504e4..00000000 --- a/internal/dataplane/client/client.go +++ /dev/null @@ -1,228 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 client - -import ( - "context" - "errors" - "fmt" - "sync" - - "github.com/go-logr/logr" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/log" - - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -// clientInfo encapsulates the gathered information about a BackendsClient -// along with the gRPC client connection. -type clientInfo struct { - conn *grpc.ClientConn - client BackendsClient - name string -} - -// BackendsClientManager is managing the connections and interactions with -// the available BackendsClient servers. -type BackendsClientManager struct { - log logr.Logger - clientset *kubernetes.Clientset - - mu sync.RWMutex - clients map[types.NamespacedName]clientInfo -} - -// NewBackendsClientManager returns an initialized instance of BackendsClientManager. -func NewBackendsClientManager(config *rest.Config) (*BackendsClientManager, error) { - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - return nil, err - } - - return &BackendsClientManager{ - log: log.FromContext(context.Background()), - clientset: clientset, - mu: sync.RWMutex{}, - clients: map[types.NamespacedName]clientInfo{}, - }, nil -} - -func (c *BackendsClientManager) SetClientsList(readyPods map[types.NamespacedName]corev1.Pod) (bool, error) { - // TODO: close and connect to the different clients concurrently. - clientListUpdated := false - var err error - - // Remove old clients - for nn, backendInfo := range c.clients { - if _, ok := readyPods[nn]; !ok { - c.mu.Lock() - delete(c.clients, nn) - c.mu.Unlock() - - if closeErr := backendInfo.conn.Close(); closeErr != nil { - err = errors.Join(err, closeErr) - continue - } - clientListUpdated = true - } - } - - // Add new clients - for _, pod := range readyPods { - key := types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name} - if _, ok := c.clients[key]; !ok { - - if pod.Status.PodIP == "" { - continue - } - - endpoint := fmt.Sprintf("%s:%d", pod.Status.PodIP, vars.DefaultDataPlaneAPIPort) - c.log.Info("BackendsClientManager", "status", "connecting", "pod", pod.GetName(), "endpoint", endpoint) - - conn, dialErr := grpc.NewClient(endpoint, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) //nolint:staticcheck - if dialErr != nil { - c.log.Error(dialErr, "BackendsClientManager", "status", "connection failure", "pod", pod.GetName()) - err = errors.Join(err, dialErr) - continue - } - - c.mu.Lock() - c.clients[key] = clientInfo{ - conn: conn, - client: NewBackendsClient(conn), - name: pod.Name, - } - c.mu.Unlock() - - c.log.Info("BackendsClientManager", "status", "connected", "pod", pod.GetName()) - - clientListUpdated = true - } - } - - return clientListUpdated, err -} - -func (c *BackendsClientManager) Close() { - c.log.Info("BackendsClientManager", "status", "shutting down") - - c.mu.Lock() - defer c.mu.Unlock() - - var wg sync.WaitGroup - wg.Add(len(c.clients)) - - for key, cc := range c.clients { - go func(cc clientInfo) { - defer wg.Done() - cc.conn.Close() - }(cc) - - delete(c.clients, key) - } - - wg.Wait() - - c.log.Info("BackendsClientManager", "status", "shutdown completed") -} - -func (c *BackendsClientManager) getClientsInfo() []clientInfo { - c.mu.RLock() - defer c.mu.RUnlock() - - backends := make([]clientInfo, 0, len(c.clients)) - for _, backendClient := range c.clients { - backends = append(backends, backendClient) - } - - return backends -} - -// Update sends an update request to all available BackendsClient servers concurrently. -func (c *BackendsClientManager) Update(ctx context.Context, in *Targets, opts ...grpc.CallOption) (*Confirmation, error) { - clientsInfo := c.getClientsInfo() - - var wg sync.WaitGroup - wg.Add(len(clientsInfo)) - - errs := make(chan error, len(clientsInfo)) - - for _, ci := range clientsInfo { - go func(ci clientInfo) { - defer wg.Done() - - conf, err := ci.client.Update(ctx, in, opts...) - if err != nil { - c.log.Error(err, "BackendsClientManager", "operation", "update", "pod", ci.name) - errs <- err - return - } - c.log.Info("BackendsClientManager", "operation", "update", "pod", ci.name, "confirmation", conf.Confirmation) - }(ci) - } - - wg.Wait() - close(errs) - - var err error - for e := range errs { - err = errors.Join(err, e) - } - - return nil, err -} - -// Delete sends an delete request to all available BackendsClient servers concurrently. -func (c *BackendsClientManager) Delete(ctx context.Context, in *Vip, opts ...grpc.CallOption) (*Confirmation, error) { - clientsInfo := c.getClientsInfo() - - var wg sync.WaitGroup - wg.Add(len(clientsInfo)) - - errs := make(chan error, len(clientsInfo)) - - for _, ci := range clientsInfo { - go func(ci clientInfo) { - defer wg.Done() - - conf, err := ci.client.Delete(ctx, in, opts...) - if err != nil { - c.log.Error(err, "BackendsClientManager", "operation", "delete", "pod", ci.name) - errs <- err - return - } - c.log.Info("BackendsClientManager", "operation", "delete", "pod", ci.name, "confirmation", conf.Confirmation) - - }(ci) - } - - wg.Wait() - close(errs) - - var err error - for e := range errs { - err = errors.Join(err, e) - } - - return nil, err -} diff --git a/internal/dataplane/client/utils.go b/internal/dataplane/client/utils.go deleted file mode 100644 index 8eef5c1a..00000000 --- a/internal/dataplane/client/utils.go +++ /dev/null @@ -1,238 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 client - -import ( - context "context" - "encoding/binary" - "fmt" - "net" - - corev1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" -) - -// CompileUDPRouteToDataPlaneBackend takes a UDPRoute and the Gateway it is -// attached to and produces Backend Targets for the DataPlane to configure. -func CompileUDPRouteToDataPlaneBackend(ctx context.Context, c client.Client, udproute *gatewayv1alpha2.UDPRoute, gateway *gatewayv1beta1.Gateway) (*Targets, error) { - gatewayIP, err := GetGatewayIP(gateway) - if gatewayIP == nil { - return nil, err - } - - gatewayPort, err := GetGatewayPort(gateway, udproute.Spec.ParentRefs) - if err != nil { - return nil, err - } - var backendTargets []*Target - for _, rule := range udproute.Spec.Rules { - for _, backendRef := range rule.BackendRefs { - endpoints, err := endpointsFromBackendRef(ctx, c, udproute.Namespace, backendRef) - if err != nil { - return nil, err - } - - for _, subset := range endpoints.Subsets { - if len(subset.Addresses) < 1 { - return nil, fmt.Errorf("addresses not ready for endpoints") - } - if len(subset.Ports) < 1 { - return nil, fmt.Errorf("ports not ready for endpoints") - } - - for _, addr := range subset.Addresses { - if addr.IP == "" { - return nil, fmt.Errorf("empty IP for endpoint subset") - } - - ip := net.ParseIP(addr.IP) - podip := binary.BigEndian.Uint32(ip.To4()) - podPort, err := getBackendPort(ctx, c, udproute.Namespace, backendRef, subset.Ports) - if err != nil { - return nil, err - } - - target := &Target{ - Daddr: podip, - Dport: uint32(podPort), - } - backendTargets = append(backendTargets, target) - } - } - } - } - - if len(backendTargets) == 0 { - return nil, fmt.Errorf("no healthy backends") - } - - ipint := binary.BigEndian.Uint32(gatewayIP.To4()) - - targets := &Targets{ - Vip: &Vip{ - Ip: ipint, - Port: gatewayPort, - }, - Targets: backendTargets, - } - - return targets, nil -} - -// CompileTCPRouteToDataPlaneBackend takes a TCPRoute and the Gateway it is -// attached to and produces Backend Targets for the DataPlane to configure. -func CompileTCPRouteToDataPlaneBackend(ctx context.Context, c client.Client, - tcproute *gatewayv1alpha2.TCPRoute, gateway *gatewayv1beta1.Gateway) (*Targets, error) { - gatewayIP, err := GetGatewayIP(gateway) - if gatewayIP == nil { - return nil, err - } - - gatewayPort, err := GetGatewayPort(gateway, tcproute.Spec.ParentRefs) - if err != nil { - return nil, err - } - var backendTargets []*Target - for _, rule := range tcproute.Spec.Rules { - for _, backendRef := range rule.BackendRefs { - endpoints, err := endpointsFromBackendRef(ctx, c, tcproute.Namespace, backendRef) - if err != nil { - return nil, err - } - - if len(endpoints.Subsets) < 1 { - return nil, fmt.Errorf("endpoint has no subsets") - } - for _, subset := range endpoints.Subsets { - if len(subset.Addresses) < 1 { - return nil, fmt.Errorf("addresses not ready for endpoints") - } - if len(subset.Ports) < 1 { - return nil, fmt.Errorf("ports not ready for endpoints") - } - - for _, addr := range subset.Addresses { - if addr.IP == "" { - return nil, fmt.Errorf("empty IP for endpoint subset") - } - - ip := net.ParseIP(addr.IP) - podip := binary.BigEndian.Uint32(ip.To4()) - podPort, err := getBackendPort(ctx, c, tcproute.Namespace, backendRef, subset.Ports) - if err != nil { - return nil, err - } - - target := &Target{ - Daddr: podip, - Dport: uint32(podPort), - } - backendTargets = append(backendTargets, target) - } - } - } - } - - if len(backendTargets) == 0 { - return nil, fmt.Errorf("no healthy backends") - } - - ipint := binary.BigEndian.Uint32(gatewayIP.To4()) - - targets := &Targets{ - Vip: &Vip{ - Ip: ipint, - Port: gatewayPort, - }, - Targets: backendTargets, - } - - return targets, nil -} - -func endpointsFromBackendRef(ctx context.Context, c client.Client, namespace string, backendRef gatewayv1alpha2.BackendRef) (*corev1.Endpoints, error) { - if backendRef.Namespace != nil { - namespace = string(*backendRef.Namespace) - } - - endpoints := new(corev1.Endpoints) - if err := c.Get(ctx, client.ObjectKey{ - Namespace: namespace, - Name: string(backendRef.Name), - }, endpoints); err != nil { - return nil, err - } - - return endpoints, nil -} - -func getBackendPort(ctx context.Context, c client.Client, ns string, backendRef gatewayv1alpha2.BackendRef, - epPorts []corev1.EndpointPort) (int32, error) { - svc := new(corev1.Service) - if backendRef.Namespace != nil { - ns = string(*backendRef.Namespace) - } - key := client.ObjectKey{ - Namespace: ns, - Name: string(backendRef.Name), - } - if err := c.Get(ctx, key, svc); err != nil { - return 0, err - } - - for _, port := range svc.Spec.Ports { - // backendRef must have a port if the backend is a Service. - if port.Port == int32(*backendRef.Port) { - if port.TargetPort.IntValue() == 0 { - return port.Port, nil - } - return int32(port.TargetPort.IntValue()), nil - } - } - return 0, fmt.Errorf("could not find target port for backend ref: %s", key.String()) -} - -func GetGatewayIP(gw *gatewayv1beta1.Gateway) (ip net.IP, err error) { - if len(gw.Status.Addresses) > 1 { - return nil, fmt.Errorf("Gateway %s/%s had %d addresses but we only currently support 1", gw.Namespace, gw.Name, len(gw.Status.Addresses)) - } - - for _, address := range gw.Status.Addresses { - if address.Type != nil && *address.Type == gatewayv1beta1.IPAddressType { - ip = net.ParseIP(address.Value) - return - } - } - - err = fmt.Errorf("IP address not ready for Gateway %s/%s", gw.Namespace, gw.Name) - return -} - -func GetGatewayPort(gw *gatewayv1beta1.Gateway, refs []gatewayv1alpha2.ParentReference) (uint32, error) { - if len(refs) > 1 { - // TODO: https://github.com/Kong/blixt/issues/10 - return 0, fmt.Errorf("multiple parentRefs not yet supported") - } - - if refs[0].Port == nil { - return 0, fmt.Errorf("port not found for parentRef") - } - - return uint32(*refs[0].Port), nil -} diff --git a/internal/test/utils/utils.go b/internal/test/utils/utils.go deleted file mode 100644 index e6105d32..00000000 --- a/internal/test/utils/utils.go +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 utils - -import ( - "bytes" - "context" - "fmt" - "log" - "testing" - "time" - - "github.com/go-logr/logr" - "github.com/go-logr/stdr" - "github.com/kong/kubernetes-testing-framework/pkg/clusters" - "github.com/kong/kubernetes-testing-framework/pkg/environments" - "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -const BlixtReadinessTimeout = time.Minute * 7 - -// NewBytesBufferLogger creates a standard logger with a *bytes.Buffer as the -// output wrapped in a logr.Logger implementation to provide to reconcilers. -func NewBytesBufferLogger() (logr.Logger, *bytes.Buffer) { - output := new(bytes.Buffer) - stdr.SetVerbosity(1) - return stdr.NewWithOptions(log.New(output, "", log.Default().Flags()), stdr.Options{}), output -} - -// NewFakeClientWithGatewayClasses creates a new fake controller-runtime -// client.Client for testing, with two GatewayClasses pre-loaded into the -// client: one that's managed by our GatewayClassControllerName, and one that -// isn't. You can also optionally provide more init objects to pre-load if -// needed. -func NewFakeClientWithGatewayClasses(initObjects ...client.Object) (gatewayv1beta1.ObjectName, gatewayv1beta1.ObjectName, client.Client) { - managedGatewayClass := &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "managed-gateway-class", - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: vars.GatewayClassControllerName, - }, - } - unmanagedGatewayClass := &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: "unmanaged-gateway-class", - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: "kubernetes.io/unmanaged", - }, - } - - scheme := runtime.NewScheme() - utilruntime.Must(gatewayv1beta1.AddToScheme(scheme)) - - fakeClient := fake.NewClientBuilder().WithObjects( - managedGatewayClass, - unmanagedGatewayClass, - ). - WithObjects(initObjects...). - WithScheme(scheme). - Build() - - return gatewayv1beta1.ObjectName(managedGatewayClass.Name), - gatewayv1beta1.ObjectName(unmanagedGatewayClass.Name), - fakeClient -} - -// WaitForBlixtReadiness waits for Blixt to be ready in the provided testing -// environment (but deploying Blixt is expected to have already been handled -// elsewhere). -func WaitForBlixtReadiness(ctx context.Context, env environments.Environment) error { - ticker := time.NewTicker(BlixtReadinessTimeout) - for { - select { - case <-ticker.C: - fmt.Printf("ERROR: timed out waiting for blixt readiness for cluster %s. dumping diagnostics\n", env.Cluster().Name()) - dir, err := env.Cluster().DumpDiagnostics(ctx, "wait-for-blixt-readiness-timeout") - if err != nil { - return fmt.Errorf("error after timeout waiting for blixt components when trying to dump diagnostics: %w", err) - } - return fmt.Errorf("timeout waiting for blixt components exceeded, diagnostics dumped to %s", dir) - case <-ctx.Done(): - if err := ctx.Err(); err != nil { - return fmt.Errorf("context completed while waiting for components: %w", err) - } - dir, diagErr := env.Cluster().DumpDiagnostics(ctx, "wait-for-blixt-readiness-context-completed") - if diagErr != nil { - return fmt.Errorf("error after timeout waiting for blixt components when trying to dump diagnostics: %w", diagErr) - } - return fmt.Errorf("context completed while waiting for components, diagnostics dumped to %s", dir) - default: - var controlplaneReady, dataplaneReady bool - - controlplane, err := env.Cluster().Client().AppsV1().Deployments(vars.DefaultNamespace).Get(ctx, vars.DefaultControlPlaneDeploymentName, metav1.GetOptions{}) - if err != nil { - fmt.Printf("Error while checking controlplane components: %s\n", err) - return err - } - if controlplane.Status.AvailableReplicas > 0 { - controlplaneReady = true - } - - dataplane, err := env.Cluster().Client().AppsV1().DaemonSets(vars.DefaultNamespace).Get(ctx, vars.DefaultDataPlaneDaemonSetName, metav1.GetOptions{}) - if err != nil { - fmt.Printf("Error while checking dataplane components: %s\n", err) - return err - } - if dataplane.Status.NumberAvailable > 0 { - dataplaneReady = true - } - - if controlplaneReady && dataplaneReady { - return nil - } - } - } -} - -// DumpDiagnosticsIfFailed dumps the diagnostics if the test failed. -func DumpDiagnosticsIfFailed(ctx context.Context, t *testing.T, clusters clusters.Cluster) { - t.Helper() - - if t.Failed() { - output, err := clusters.DumpDiagnostics(ctx, t.Name()) - t.Logf("%s failed, dumped diagnostics to %s", t.Name(), output) - assert.NoError(t, err) - } -} diff --git a/main.go b/main.go deleted file mode 100644 index 9c0219dd..00000000 --- a/main.go +++ /dev/null @@ -1,216 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 main - -import ( - "context" - "flag" - "os" - - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - "sigs.k8s.io/controller-runtime/pkg/metrics/server" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - - "github.com/kubernetes-sigs/blixt/controllers" - "github.com/kubernetes-sigs/blixt/internal/dataplane/client" - //+kubebuilder:scaffold:imports -) - -var ( - scheme = runtime.NewScheme() - setupLog = ctrl.Log.WithName("setup") -) - -func init() { - utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - utilruntime.Must(gatewayv1beta1.AddToScheme(scheme)) - utilruntime.Must(gatewayv1alpha2.AddToScheme(scheme)) - - //+kubebuilder:scaffold:scheme -} - -func main() { - var metricsAddr string - var enableLeaderElection bool - var probeAddr string - flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") - flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") - flag.BoolVar(&enableLeaderElection, "leader-elect", false, - "Enable leader election for controller manager. "+ - "Enabling this will ensure there is only one active controller manager.") - opts := zap.Options{ - Development: true, - } - opts.BindFlags(flag.CommandLine) - flag.Parse() - - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - - cfg := ctrl.GetConfigOrDie() - mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - Metrics: server.Options{ - BindAddress: metricsAddr, - }, - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "59c634c5.blixt.gateway.networking.k8s.io", - // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily - // when the Manager ends. This requires the binary to immediately end when the - // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly - // speeds up voluntary leader transitions as the new leader don't have to wait - // LeaseDuration time first. - // - // In the default scaffold provided, the program ends immediately after - // the manager stops, so would be fine to enable this option. However, - // if you are doing or is intended to do any operation such as perform cleanups - // after the manager stops then its usage might be unsafe. - // LeaderElectionReleaseOnCancel: true, - }) - if err != nil { - setupLog.Error(err, "unable to start manager") - os.Exit(1) - } - - clientsManager, err := client.NewBackendsClientManager(cfg) - if err != nil { - setupLog.Error(err, "unable to create backends client manager") - os.Exit(1) - } - defer clientsManager.Close() - - dataplaneReconciler := controllers.NewDataplaneReconciler(mgr.GetClient(), mgr.GetScheme(), clientsManager) - if err = dataplaneReconciler.SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Dataplane") - os.Exit(1) - } - - ctx := ctrl.SetupSignalHandler() - udpReconcileRequestChan, tcpReconcileRequestChan := tee(ctx, dataplaneReconciler.GetUpdates()) - - if err = (&controllers.GatewayReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Gateway") - os.Exit(1) - } - if err = (&controllers.GatewayClassReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "GatewayClass") - os.Exit(1) - } - if err = (&controllers.UDPRouteReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - ClientReconcileRequestChan: udpReconcileRequestChan, - BackendsClientManager: clientsManager, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "UDPRoute") - os.Exit(1) - } - if err = (&controllers.TCPRouteReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - ClientReconcileRequestChan: tcpReconcileRequestChan, - BackendsClientManager: clientsManager, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "TCPRoute") - os.Exit(1) - } - //+kubebuilder:scaffold:builder - - if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up health check") - os.Exit(1) - } - if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up ready check") - os.Exit(1) - } - - setupLog.Info("starting manager") - if err := mgr.Start(ctx); err != nil { - setupLog.Error(err, "problem running manager") - os.Exit(1) - } -} - -// Tee consumes the received channel and mirrors the messages into 2 new channels. -func tee(ctx context.Context, in <-chan event.GenericEvent) (_, _ <-chan event.GenericEvent) { - out1, out2 := make(chan event.GenericEvent), make(chan event.GenericEvent) - - OrDone := func(ctx context.Context, in <-chan event.GenericEvent) <-chan event.GenericEvent { - out := make(chan event.GenericEvent) - go func() { - defer close(out) - - for { - select { - case <-ctx.Done(): - return - case i, ok := <-in: - if !ok { - return - } - select { - case out <- i: - case <-ctx.Done(): - } - } - } - }() - return out - } - - go func() { - defer close(out1) - defer close(out2) - - for val := range OrDone(ctx, in) { - select { - case <-ctx.Done(): - return - case out1 <- val: - select { - case <-ctx.Done(): - case out2 <- val: - } - - case out2 <- val: - select { - case <-ctx.Done(): - case out1 <- val: - } - } - } - }() - return out1, out2 -} diff --git a/pkg/vars/vars.go b/pkg/vars/vars.go deleted file mode 100644 index 28c46e90..00000000 --- a/pkg/vars/vars.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2023 The Kubernetes 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 vars - -// ----------------------------------------------------------------------------- -// ControlPlane Constants -// ----------------------------------------------------------------------------- - -const ( - // GatewayClassControllerName is the unique identifier indicating controller - // responsible for relevant resources. - GatewayClassControllerName = "gateway.networking.k8s.io/blixt" -) - -// ----------------------------------------------------------------------------- -// Component Defaults -// ----------------------------------------------------------------------------- - -const ( - // DefaultControlPlaneDeploymentName is the name that will be used for the - // controlplane's Deployment (by default). - DefaultControlPlaneDeploymentName = "blixt-controlplane" - - // DefaultDataPlaneDaemonSetName is the name that will be used for the - // dataplane's DaemonSet (by default). - DefaultDataPlaneDaemonSetName = "blixt-dataplane" - - // DefaultNamespace is the namespace used for the controlplane and - // dataplane components (by default). - DefaultNamespace = "blixt-system" - - // DefaultDataPlaneAPIPort is the network port that will be used to - // communicate with the DataPlane API (by default). - DefaultDataPlaneAPIPort = 9874 - - // DefaultDataPlaneAppLabel indicates the label value that can be used - // to identify dataplane components (by default). - DefaultDataPlaneAppLabel = "blixt" - - // DefaultDataPlaneComponentLabel indicates the label value that can be used - // to identify dataplane Pods (by default). - DefaultDataPlaneComponentLabel = "dataplane" -) diff --git a/test/conformance/gateway_conformance_test.go b/test/conformance/gateway_conformance_test.go deleted file mode 100644 index 78655b2e..00000000 --- a/test/conformance/gateway_conformance_test.go +++ /dev/null @@ -1,122 +0,0 @@ -//go:build conformance_tests -// +build conformance_tests - -/* -Copyright 2023 The Kubernetes 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 conformance - -import ( - "testing" - - "github.com/go-logr/logr" - "github.com/google/uuid" - "github.com/kong/kubernetes-testing-framework/pkg/clusters" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" - gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - "sigs.k8s.io/gateway-api/conformance/apis/v1alpha1" - "sigs.k8s.io/gateway-api/conformance/tests" - "sigs.k8s.io/gateway-api/conformance/utils/suite" - - "github.com/kubernetes-sigs/blixt/pkg/vars" -) - -const ( - showDebug = true - shouldCleanup = true - enableAllSupportedFeatures = true -) - -const ( - gatewayAPICRDKustomize = "https://github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v0.8.1" - conformanceTestsBaseManifests = "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.8.1/conformance/base/manifests.yaml" -) - -func TestGatewayConformance(t *testing.T) { - t.Log("configuring environment for gateway conformance tests") - log.SetLogger(logr.FromContextOrDiscard(ctx)) - c, err := client.New(env.Cluster().Config(), client.Options{}) - require.NoError(t, err) - require.NoError(t, gatewayv1alpha2.AddToScheme(c.Scheme())) - require.NoError(t, gatewayv1beta1.AddToScheme(c.Scheme())) - - t.Log("deploying Gateway API CRDs") - require.NoError(t, clusters.KustomizeDeployForCluster(ctx, env.Cluster(), gatewayAPICRDKustomize)) - - t.Log("deploying conformance test suite base manifests") - require.NoError(t, clusters.ApplyManifestByURL(ctx, env.Cluster(), conformanceTestsBaseManifests)) - - t.Log("starting the controller manager") - require.NoError(t, clusters.KustomizeDeployForCluster(ctx, env.Cluster(), "../../config/tests/conformance/")) - - t.Log("creating GatewayClass for gateway conformance tests") - gatewayClass := &gatewayv1beta1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: uuid.NewString(), - }, - Spec: gatewayv1beta1.GatewayClassSpec{ - ControllerName: vars.GatewayClassControllerName, - }, - } - require.NoError(t, c.Create(ctx, gatewayClass)) - t.Cleanup(func() { assert.NoError(t, c.Delete(ctx, gatewayClass)) }) - - t.Log("configuring the gateway conformance test suite") - supportedFeatures := suite.GatewayCoreFeatures.Clone() - supportedFeatures.Insert(suite.SupportGatewayStaticAddresses) - cSuite, err := suite.NewExperimentalConformanceTestSuite( - suite.ExperimentalConformanceOptions{ - Options: suite.Options{ - Client: c, - GatewayClassName: gatewayClass.Name, - Debug: showDebug, - CleanupBaseResources: shouldCleanup, - BaseManifests: conformanceTestsBaseManifests, - SupportedFeatures: supportedFeatures, - SkipTests: []string{ - // TODO: these tests are broken because they incorrectly require HTTP support - // see https://github.com/kubernetes-sigs/gateway-api/issues/2403 - "GatewayInvalidRouteKind", - "GatewayInvalidTLSConfiguration", - // TODO: these tests are disabled because we don't actually support them - // properly yet. - "GatewayModifyListeners", - "GatewayClassObservedGenerationBump", - "GatewayWithAttachedRoutes", - }, - UsableNetworkAddresses: []gatewayv1beta1.GatewayAddress{{Value: "172.18.0.242"}}, - UnusableNetworkAddresses: []gatewayv1beta1.GatewayAddress{{Value: "1.1.1.1"}}, - }, - Implementation: v1alpha1.Implementation{ - Organization: "kubernetes-sigs", - Project: "blixt", - URL: "https://github.com/kubernetes-sigs/blixt", - Version: "v0.2.0", - Contact: []string{"https://github.com/kubernetes-sigs/blixt/issues/new"}, - }, - }, - ) - require.NoError(t, err) - - t.Log("executing the gateway conformance test suite") - cSuite.Setup(t) - cSuite.Run(t, tests.ConformanceTests) //nolint:errcheck -} diff --git a/test/conformance/suite_test.go b/test/conformance/suite_test.go deleted file mode 100644 index 8b76c7d4..00000000 --- a/test/conformance/suite_test.go +++ /dev/null @@ -1,108 +0,0 @@ -//go:build conformance_tests -// +build conformance_tests - -/* -Copyright 2023 The Kubernetes 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 conformance - -import ( - "context" - "fmt" - "os" - "testing" - - "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/loadimage" - "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/metallb" - "github.com/kong/kubernetes-testing-framework/pkg/clusters/types/kind" - "github.com/kong/kubernetes-testing-framework/pkg/environments" -) - -var ( - ctx context.Context - env environments.Environment - - controlplaneImage = os.Getenv("BLIXT_CONTROLPLANE_IMAGE") - dataplaneImage = os.Getenv("BLIXT_DATAPLANE_IMAGE") - udpServerImage = os.Getenv("BLIXT_UDP_SERVER_IMAGE") - - useExistingCluster = func() bool { return os.Getenv("BLIX_USE_EXISTING_KIND_CLUSTER") == "true" }() - clusterName = os.Getenv("BLIXT_TEST_CLUSTER_NAME") -) - -func TestMain(m *testing.M) { - var cancel context.CancelFunc - ctx, cancel = context.WithCancel(context.Background()) - defer cancel() - - if useExistingCluster { - fmt.Printf("INFO: using existing kind cluster %s for test environment\n", clusterName) - cluster, err := kind.NewFromExisting(clusterName) - exitOnErr(err) - env, err = environments.NewBuilder().WithExistingCluster(cluster).Build(ctx) - exitOnErr(err) - } else { - fmt.Println("INFO: loading custom images for conformance tests") - imageLoader, err := loadimage.NewBuilder().WithImage(controlplaneImage) - exitOnErr(err) - imageLoader, err = imageLoader.WithImage(dataplaneImage) - exitOnErr(err) - imageLoader, err = imageLoader.WithImage(udpServerImage) - exitOnErr(err) - - fmt.Println("INFO: building the test environment and cluster") - builder := environments.NewBuilder().WithAddons(metallb.New(), imageLoader.Build()) - if clusterName != "" { - builder.WithName(clusterName) - } - env, err = builder.Build(ctx) - exitOnErr(err) - addCleanup(env.Cleanup) - } - - fmt.Println("INFO: waiting for testing environment to be ready") - exitOnErr(<-env.WaitForReady(ctx)) - - fmt.Println("INFO: running tests") - code := m.Run() - os.Exit(code) -} - -func exitOnErr(err error) { - if err != nil { - fmt.Println(err.Error()) - if cleanupErr := runCleanup(); cleanupErr != nil { - fmt.Printf("ERROR: failed during cleanup: %v", cleanupErr) - os.Exit(2) - } - os.Exit(1) - } -} - -var cleanupJobs []func(ctx context.Context) error - -func addCleanup(job func(ctx context.Context) error) { - cleanupJobs = append(cleanupJobs, job) -} - -func runCleanup() error { - for _, job := range cleanupJobs { - if err := job(ctx); err != nil { - return err - } - } - return nil -} diff --git a/test/performance/suite_test.go b/test/performance/suite_test.go deleted file mode 100644 index 35635cc4..00000000 --- a/test/performance/suite_test.go +++ /dev/null @@ -1,99 +0,0 @@ -//go:build performance_tests -// +build performance_tests - -/* -Copyright 2023 The Kubernetes 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 performance - -import ( - "context" - "fmt" - "os" - "testing" - - "github.com/kong/kubernetes-testing-framework/pkg/clusters" - "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/loadimage" - "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/metallb" - "github.com/kong/kubernetes-testing-framework/pkg/environments" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" - - testutils "github.com/kubernetes-sigs/blixt/internal/test/utils" -) - -var ( - ctx context.Context - cancel context.CancelFunc - env environments.Environment - cleanup map[string]([]func(context.Context) error) - - gwclient *versioned.Clientset - k8sclient *clientset.Clientset - - controlplaneImage = os.Getenv("BLIXT_CONTROLPLANE_IMAGE") - dataplaneImage = os.Getenv("BLIXT_DATAPLANE_IMAGE") -) - -const ( - gwCRDsKustomize = "https://github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v0.8.1" - testKustomize = "../../config/tests/performance" -) - -func TestMain(m *testing.M) { - if controlplaneImage == "" || dataplaneImage == "" { - exitOnErr(fmt.Errorf("BLIXT_CONTROLPLANE_IMAGE and BLIXT_DATAPLANE_IMAGE must be provided")) - } - - ctx, cancel = context.WithCancel(context.Background()) - defer cancel() - - fmt.Println("INFO: creating a new kind cluster") - loadImages, err := loadimage.NewBuilder().WithImage(controlplaneImage) - exitOnErr(err) - loadImages, err = loadImages.WithImage(dataplaneImage) - exitOnErr(err) - - env, err = environments.NewBuilder().WithAddons(metallb.New(), loadImages.Build()).Build(ctx) - exitOnErr(err) - - fmt.Printf("INFO: new kind cluster %s was created\n", env.Cluster().Name()) - gwclient, err = versioned.NewForConfig(env.Cluster().Config()) - exitOnErr(err) - k8sclient, err = clientset.NewForConfig(env.Cluster().Config()) - exitOnErr(err) - - fmt.Println("INFO: deploying Gateway API CRDs") - exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), gwCRDsKustomize)) - - fmt.Println("INFO: deploying blixt via config/test kustomize") - exitOnErr(clusters.KustomizeDeployForCluster(ctx, env.Cluster(), testKustomize)) - exitOnErr(testutils.WaitForBlixtReadiness(ctx, env)) - - fmt.Println("INFO: running performance tests") - exit := m.Run() - - exitOnErr(env.Cluster().Cleanup(ctx)) - - os.Exit(exit) -} - -func exitOnErr(err error) { - if err != nil { - fmt.Fprint(os.Stderr, err.Error()) - os.Exit(1) - } -} From f861f23f2502c5638c6fa230babaeed7722c0d8e Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:33:24 -0400 Subject: [PATCH 07/10] chore: switch controlplane image build to Rust Signed-off-by: Shane Utt --- build/Containerfile.controlplane | 41 +++++++++----------------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/build/Containerfile.controlplane b/build/Containerfile.controlplane index eac09d63..3ba7f876 100644 --- a/build/Containerfile.controlplane +++ b/build/Containerfile.controlplane @@ -1,34 +1,15 @@ -# Build the manager binary -FROM golang:1.22 as builder +FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx -LABEL org.opencontainers.image.source=https://github.com/kubernetes-sigs/blixt -LABEL org.opencontainers.image.description="An experimental layer 4 load-balancer built using eBPF/XDP with ebpf-go \ -for use in Kubernetes via the Kubernetes Gateway API" -LABEL org.opencontainers.image.licenses=Apache-2.0 +FROM --platform=$BUILDPLATFORM rust:alpine +ARG TARGETPLATFORM -WORKDIR /workspace -# Copy the Go Modules manifests -COPY go.mod go.mod -COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer -RUN go mod download - -# Copy the go source -COPY main.go main.go -COPY controllers/ controllers/ -COPY pkg/ pkg/ -COPY internal/ internal/ +RUN apk add clang lld +COPY --from=xx / / -# Build -RUN CGO_ENABLED=0 GOOS=linux go build -a -o manager main.go - -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot -WORKDIR / -COPY --from=builder /workspace/manager . -COPY LICENSE /workspace/LICENSE -USER 65532:65532 +WORKDIR /workspace -ENTRYPOINT ["/manager"] +RUN --mount=type=bind,source=src,target=src \ + --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ + --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ + xx-cargo build --release --target-dir ./build && \ + xx-verify ./build/$(xx-cargo --print-target-triple)/release/controller From 5279aa48b1e39e3cef5f237995299d962a64ccfd Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 16:48:47 -0400 Subject: [PATCH 08/10] chore: cleanup Makefile Signed-off-by: Shane Utt --- .github/workflows/build.yaml | 6 +- Makefile | 335 ++++++++++++----------------------- 2 files changed, 114 insertions(+), 227 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index aaf1f663..9bf07c2e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -38,12 +38,12 @@ jobs: - name: Build all rust crates (dataplane, test server) run: | - make build.rust + make build - name: Check formatting run: | - make check.format.rust + make check.format - name: Check clippy run: | - make lint.rust + make lint diff --git a/Makefile b/Makefile index ab53a728..a6689540 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,7 @@ +# ------------------------------------------------------------------------------ +# Build Variables +# ------------------------------------------------------------------------------ + # IMAGES used when running tests. BLIXT_CONTROLPLANE_IMAGE ?= ghcr.io/kubernetes-sigs/blixt-controlplane BLIXT_DATAPLANE_IMAGE ?= ghcr.io/kubernetes-sigs/blixt-dataplane @@ -20,7 +24,6 @@ BUILD_PLATFORMS ?= linux/amd64 endif BUILD_ARGS ?= --load - # VERSION defines the project version for the bundle. # Update this value when you upgrade the version of your project. # To re-generate a bundle for another specific version without changing the standard setup, you can: @@ -84,144 +87,91 @@ endif SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec -.PHONY: all -all: build.rust - -##@ General - -# The help target prints out all targets with their descriptions organized -# beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the -# entire set of makefiles included in this invocation, looking for lines of the -# file as xyz: ## something, and then pretty-format the target and help. Then, -# if there's a line with ##@ something, that gets pretty-printed as a category. -# More info on the usage of ANSI control characters for terminal formatting: -# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters -# More info on the awk command: -# http://linuxcommand.org/lc3_adv_awk.php - -.PHONY: help -help: ## Display this help. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) - -##@ Development - -.PHONY: manifests -manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases - -.PHONY: generate -generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." - -.PHONY: generate.grpc-client -generate.grpc-client: - protoc \ - --go_out=. --go_opt=paths=import \ - --go_opt=module=github.com/kubernetes-sigs/blixt \ - --go-grpc_out=. --go-grpc_opt=paths=import \ - --go-grpc_opt=module=github.com/kubernetes-sigs/blixt \ - --experimental_allow_proto3_optional \ - dataplane/api-server/proto/backends.proto +# Ensure missing resources are not skipped when applying changes (by default) +ifndef ignore-not-found + ignore-not-found = false +endif -.PHONY: fmt -fmt: ## Run go fmt against code. - go fmt ./... +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/build/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) -.PHONY: vet -vet: ## Run go vet against code. - go vet ./... +## Tool Binaries +KUSTOMIZE ?= $(LOCALBIN)/kustomize +ENVTEST ?= $(LOCALBIN)/setup-envtest +KIND ?= $(LOCALBIN)/kind +KTF ?= $(LOCALBIN)/ktf -.PHONY: lint -lint: ## Lint go code - golangci-lint run +## Tool Versions +KUSTOMIZE_VERSION ?= v5.3.0 +CONTROLLER_TOOLS_VERSION ?= v0.14.0 +KIND_VERSION ?= v0.22.0 -.PHONY: clean -clean: ## Cargo clean - cargo clean +KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -.PHONY: fix.format.rust -fix.format.rust: ## Autofix rust code formatting - cargo fmt --manifest-path Cargo.toml --all +# ------------------------------------------------------------------------------ +# Build Dependencies +# ------------------------------------------------------------------------------ -.PHONY: check.format.rust -check.format.rust: ## Check rust code formatting - cargo fmt --manifest-path Cargo.toml --all -- --check +.PHONY: kustomize +kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. +$(KUSTOMIZE): $(LOCALBIN) + test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } -.PHONY: lint.rust -lint.rust: ## Lint rust code - cargo clippy --all -- -D warnings +.PHONY: kind +kind: $(KIND) +$(KIND): $(LOCALBIN) + test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/kind@$(KIND_VERSION) -.PHONY: test -test: manifests generate fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile cover.out +.PHONY: ktf +ktf: $(KTF) $(KIND) +$(KTF): $(LOCALBIN) + test -s $(LOCALBIN)/ktf || GOBIN=$(LOCALBIN) go install github.com/kong/kubernetes-testing-framework/cmd/ktf@latest -.PHONY: test.integration -test.integration: manifests generate fmt vet - go clean -testcache - BLIXT_CONTROLPLANE_IMAGE=$(BLIXT_CONTROLPLANE_IMAGE):$(TAG) \ - BLIXT_DATAPLANE_IMAGE=$(BLIXT_DATAPLANE_IMAGE):$(TAG) \ - BLIXT_UDP_SERVER_IMAGE=$(BLIXT_UDP_SERVER_IMAGE):$(TAG) \ - GOFLAGS="-tags=integration_tests" go test -race -v ./test/integration/... +.PHONY: bundle +bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files. + operator-sdk generate kustomize manifests -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle $(BUNDLE_GEN_FLAGS) + operator-sdk bundle validate ./bundle -.PHONY: test.icmp.integration -test.icmp.integration: - go clean -testcache - # This needs to run as sudo as the test involves listening for raw ICMP packets, which - # requires you to be root. - sudo env PATH=$(PATH) \ - BLIXT_CONTROLPLANE_IMAGE=$(BLIXT_CONTROLPLANE_IMAGE):$(TAG) \ - BLIXT_DATAPLANE_IMAGE=$(BLIXT_DATAPLANE_IMAGE):$(TAG) \ - BLIXT_UDP_SERVER_IMAGE=$(BLIXT_UDP_SERVER_IMAGE):$(TAG) \ - RUN_ICMP_TEST=true \ - go test --tags=integration_tests -run "TestUDPRouteNoReach" -race -v ./test/integration/... +.PHONY: bundle-build +bundle-build: ## Build the bundle image. + DOCKER_BUILDKIT=1 docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . -.PHONY: test.performance -test.performance: manifests generate fmt vet - go clean -testcache - GOFLAGS="-tags=performance_tests" go test -race -v ./test/performance/... +.PHONY: bundle-push +bundle-push: ## Push the bundle image. + $(MAKE) docker-push IMG=$(BUNDLE_IMG) -.PHONY: test.conformance -test.conformance: manifests generate fmt vet - go clean -testcache - BLIXT_CONTROLPLANE_IMAGE=$(BLIXT_CONTROLPLANE_IMAGE):$(TAG) \ - BLIXT_DATAPLANE_IMAGE=$(BLIXT_DATAPLANE_IMAGE):$(TAG) \ - BLIXT_UDP_SERVER_IMAGE=$(BLIXT_UDP_SERVER_IMAGE):$(TAG) \ - BLIXT_USE_EXISTING_CLUSTER=$(EXISTING_CLUSTER) \ - GOFLAGS="-tags=conformance_tests" go test -race -v ./test/conformance/... +# ------------------------------------------------------------------------------ +# Build +# ------------------------------------------------------------------------------ -.PHONY: debug.conformance -debug.conformance: manifests generate fmt vet - go clean -testcache - BLIXT_CONTROLPLANE_IMAGE=$(BLIXT_CONTROLPLANE_IMAGE):$(TAG) \ - BLIXT_DATAPLANE_IMAGE=$(BLIXT_DATAPLANE_IMAGE):$(TAG) \ - BLIXT_UDP_SERVER_IMAGE=$(BLIXT_UDP_SERVER_IMAGE):$(TAG) \ - BLIXT_USE_EXISTING_CLUSTER=$(EXISTING_CLUSTER) \ - GOFLAGS="-tags=conformance_tests" dlv test ./test/conformance/... +.PHONY: all +all: build -##@ Build +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -.PHONY: build.go -build.go: generate fmt vet ## Build manager binary. - go build -o bin/manager main.go +.PHONY: clean +clean: ## Cargo clean + cargo clean -.PHONY: build.rust -build.rust: ## Build dataplane +.PHONY: build +build: ## Build dataplane cargo xtask build-ebpf cargo build -.PHONY: build.rust.release -build.rust.release: ## Build dataplane release +.PHONY: build.release +build.release: ## Build dataplane release cargo xtask build-ebpf --release cargo build --release -.PHONY: run.go -run.go: manifests generate fmt vet ## Run a controller from your host. - go run ./main.go - -.PHONY: debug.go -debug.go: manifests generate fmt vet ## Run a controller from your host via debugger. - dlv debug ./main.go +# ------------------------------------------------------------------------------ +# Build Images +# ------------------------------------------------------------------------------ .PHONY: build.image.controlplane build.image.controlplane: @@ -241,11 +191,51 @@ build.all.images: $(MAKE) build.image.dataplane $(MAKE) build.image.udp_server -##@ Deployment +# ------------------------------------------------------------------------------ +# Development +# ------------------------------------------------------------------------------ -ifndef ignore-not-found - ignore-not-found = false -endif +.PHONY: fix.format +fix.format.rust: ## Autofix Rust code formatting + cargo fmt --manifest-path Cargo.toml --all + +.PHONY: check.format +check.format.rust: ## Check Rust code formatting + cargo fmt --manifest-path Cargo.toml --all -- --check + +.PHONY: lint +lint: ## Lint Rust code + cargo clippy --all -- -D warnings + +# ------------------------------------------------------------------------------ +# Testing +# ------------------------------------------------------------------------------ + +.PHONY: test.integration.deprecated +test.integration.deprecated: ## Run the deprecated Golang integration tests + go clean -testcache + BLIXT_CONTROLPLANE_IMAGE=$(BLIXT_CONTROLPLANE_IMAGE):$(TAG) \ + BLIXT_DATAPLANE_IMAGE=$(BLIXT_DATAPLANE_IMAGE):$(TAG) \ + BLIXT_UDP_SERVER_IMAGE=$(BLIXT_UDP_SERVER_IMAGE):$(TAG) \ + GOFLAGS="-tags=integration_tests" go test -race -v ./test/integration/... + +.PHONY: test.icmp.integration.deprecated +test.icmp.integration.deprecated: ## Run the deprecated Golang integration tests for ICMP support + go clean -testcache + # This needs to run as sudo as the test involves listening for raw ICMP packets, which + # requires you to be root. + sudo env PATH=$(PATH) \ + BLIXT_CONTROLPLANE_IMAGE=$(BLIXT_CONTROLPLANE_IMAGE):$(TAG) \ + BLIXT_DATAPLANE_IMAGE=$(BLIXT_DATAPLANE_IMAGE):$(TAG) \ + BLIXT_UDP_SERVER_IMAGE=$(BLIXT_UDP_SERVER_IMAGE):$(TAG) \ + RUN_ICMP_TEST=true \ + go test --tags=integration_tests -run "TestUDPRouteNoReach" -race -v ./test/integration/... + +# ------------------------------------------------------------------------------ +# Deployment +# ------------------------------------------------------------------------------ + +KIND_CLUSTER ?= blixt-dev .PHONY: install install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. @@ -264,109 +254,6 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. $(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f - -##@ Build Dependencies - -## Location to install dependencies to -LOCALBIN ?= $(shell pwd)/build/bin -$(LOCALBIN): - mkdir -p $(LOCALBIN) - -## Tool Binaries -KUSTOMIZE ?= $(LOCALBIN)/kustomize -CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest -KIND ?= $(LOCALBIN)/kind -KTF ?= $(LOCALBIN)/ktf - -## Tool Versions -KUSTOMIZE_VERSION ?= v5.3.0 -CONTROLLER_TOOLS_VERSION ?= v0.14.0 -KIND_VERSION ?= v0.22.0 - -KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" -.PHONY: kustomize -kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. -$(KUSTOMIZE): $(LOCALBIN) - test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } - -.PHONY: controller-gen -controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. -$(CONTROLLER_GEN): $(LOCALBIN) - test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) - -.PHONY: envtest -envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. -$(ENVTEST): $(LOCALBIN) - test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest - -.PHONY: kind -kind: $(KIND) -$(KIND): $(LOCALBIN) - test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/kind@$(KIND_VERSION) - -.PHONY: ktf -ktf: $(KTF) $(KIND) -$(KTF): $(LOCALBIN) - test -s $(LOCALBIN)/ktf || GOBIN=$(LOCALBIN) go install github.com/kong/kubernetes-testing-framework/cmd/ktf@latest - -.PHONY: bundle -bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files. - operator-sdk generate kustomize manifests -q - cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) - $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle $(BUNDLE_GEN_FLAGS) - operator-sdk bundle validate ./bundle - -.PHONY: bundle-build -bundle-build: ## Build the bundle image. - DOCKER_BUILDKIT=1 docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . - -.PHONY: bundle-push -bundle-push: ## Push the bundle image. - $(MAKE) docker-push IMG=$(BUNDLE_IMG) - -.PHONY: opm -OPM = ./bin/opm -opm: ## Download opm locally if necessary. -ifeq (,$(wildcard $(OPM))) -ifeq (,$(shell which opm 2>/dev/null)) - @{ \ - set -e ;\ - mkdir -p $(dir $(OPM)) ;\ - OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ - curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\ - chmod +x $(OPM) ;\ - } -else -OPM = $(shell which opm) -endif -endif - -# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). -# These images MUST exist in a registry and be pull-able. -BUNDLE_IMGS ?= $(BUNDLE_IMG) - -# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). -CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) - -# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. -ifneq ($(origin CATALOG_BASE_IMG), undefined) -FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) -endif - -# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. -# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: -# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator -.PHONY: catalog-build -catalog-build: opm ## Build a catalog image. - $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) - -# Push the catalog image. -.PHONY: catalog-push -catalog-push: ## Push a catalog image. - $(MAKE) docker-push IMG=$(CATALOG_IMG) - -KIND_CLUSTER ?= blixt-dev - .PHONY: build.cluster build.cluster: $(KTF) # builds a KIND cluster which can be used for testing and development PATH="$(LOCALBIN):${PATH}" $(KTF) env create --name $(KIND_CLUSTER) --addon metallb From 1ab9382fab9cd897c1b0757b09cff95520fa497e Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Wed, 4 Sep 2024 17:03:45 -0400 Subject: [PATCH 09/10] chore: cleanup of the README.md Signed-off-by: Shane Utt --- README.md | 169 ++++++++++++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 469267b7..e093f845 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,76 @@ ![blixt](https://github.com/kubernetes-sigs/blixt/assets/5332524/387ce94a-88fd-43a9-bde9-73fb9005564d) -> **Warning**: Experimental. There is no intention to ever make this viable for production. **DO NOT USE IN PRODUCTION**. - -# Blixt +> **Warning**: The `main` branch is under heavy development, and is not fully +> functional yet as we are [rewriting our control-plane][rewrite]. if you're +> interested in using or testing Blixt, use the `archive/golang-control-plane` +> branch temporarily. -An experimental [layer 4][osi] load-balancer for [Kubernetes][k8s]. +> **Warning**: Experimental. There is no intention to ever make this viable for production. **DO NOT USE IN PRODUCTION**. -The control-plane is built using [Gateway API][gwapi] and written in -[Golang][go] with [Operator SDK][osdk]/[Controller Runtime][crn]. The -data-plane is built using [eBPF][ebpf] and is written in [Rust][rust] using -[Aya][aya]. +[rewrite]:https://github.com/kubernetes-sigs/blixt/milestone/8 -This project's main purpose is to be a fun sandbox for community members to experiment -with networking, and technologies such as eBPF. +# Blixt -> **Warning**: We've [decided](https://github.com/kubernetes-sigs/blixt/discussions/150) that we're going to rewrite -> the control-plane in Rust (as it was earlier on in this project's life), so please note that if you contribute to -> the Go control-plane in the interim before we take this warning down, things might get "lost" when we switch to the -> new version. See the [relevant milestone](https://github.com/kubernetes-sigs/blixt/milestone/8) and check in with -> us in the issues (or via discussions) if you're interested in working on something control-plane related! +An experimental [layer 4][osi] load-balancer for [Kubernetes] written in [Rust] +and employing [Gateway API] for the control-plane and [eBPF]/[Aya] for the +data-plane. -> **Note**: We use [Cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html) -> to manage the various crates spread across the Rust parts of the repo. However, there is one exception. -> The `dataplane/eBPF` crate must be kept as a standalone because it needs to re-implement the `panic` handler. -> All new crates should be added to the workspace, if possible. +This project is a sandbox for experimentation and learning. This repo is mainly +meant for those interested in experimenting. This project **intentionally does +not have end-users** and is a safe place to learn, break stuff and have fun! > **Note**: The word "blixt" means "lightning" in Swedish. [osi]:https://en.wikipedia.org/wiki/OSI_model -[k8s]:https://kubernetes.io -[gwapi]:https://gateway-api.sigs.k8s.io -[go]:https://go.dev -[osdk]:https://sdk.operatorframework.io/ -[crn]:https://github.com/kubernetes-sigs/controller-runtime -[ebpf]:https://www.tigera.io/learn/guides/ebpf/ebpf-xdp/ -[rust]:https://rust-lang.org -[aya]:https://aya-rs.dev +[Kubernetes]:https://kubernetes.io +[Rust]:https://rust-lang.org +[Gateway API]:https://gateway-api.sigs.k8s.io +[eBPF]:https://www.tigera.io/learn/guides/ebpf/ebpf-xdp/ +[Aya]:https://aya-rs.dev ## Current Status Current project goals are the following: -- [ ] support [Gateway][gw]/[GatewayClass][gwc] (partially complete) -- [ ] support [UDPRoute][udproute] (partially complete) -- [ ] support [TCPRoute][tcproute] (partially complete) -- [ ] use this as a basis for adding/improving [Gateway API Conformance Tests][gwcnf] -- [ ] plug this into [Gateway API][gwapi] CI to run conformance tests on PRs +- [ ] support [Gateway]/[GatewayClass] (partially complete) +- [ ] support [UDPRoute] (partially complete) +- [ ] support [TCPRoute] (partially complete) After these goals are achieved, further goals may be decided. -Given the goals and nature of this project, and the fact that everyone who works -on it is a volunteer, we try to optimize for time with a highly iterative -development approach. This project follows a **"Work -> Right -> Fast"** development -mentality, which is to say for any functionality or feature we focus on making sure -it **_works_** at a basic level first, then we'll focus on making it **_work right_**, -and then once we're happy with the code quality we'll move on to making it **_faster_** -and more efficient. This project is **currently still very much in the early parts of -the work stage and so the code may be a little rough and/or incomplete**. We would love -to have _you_ join us in iterating on it and helping us build it together! - -> **Note**: [TLSRoute][tlsroute] support may be on the table, but we're looking -> for someone from the community to champion this. - -> **Note**: [HTTPRoute][httproute] support may be on the table, but we're looking -> for someone from the community to champion this. - -> **Note**: The initial proof of concept was written as an XDP program, but -> with more features (including access to ip conntrack in newer kernels) -> available in TC, we made a switch to TC. - -[gw]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.Gateway -[gwc]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.GatewayClass -[udproute]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.UDPRoute -[tcproute]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute -[gwcnf]:https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance -[gwapi]:https://gateway-api.sigs.k8s.io -[tlsroute]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute -[httproute]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute +[Gateway]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.Gateway +[GatewayClass]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.GatewayClass +[UDPRoute]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.UDPRoute +[TCPRoute]:https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1alpha2.TCPRoute ## Usage -> **Note**: Currently usage is only possible on [Kubernetes In Docker -> (KIND)][kind] clusters. You can generate a new development cluster for -> testing with `make build.cluster`. +> **Warning**: Currently our container images are under migration from a private +> repository. At this moment, you **must** build and load images yourself locally. -> **Note**: Currently our container images are under migration from a private repository. -> At this moment, you should build and load images yourself. +> **Warning**: Currently usage is only possible on [Kubernetes In Docker +> (KIND)][kind] clusters. You can generate a new development cluster for testing +> with `make build.cluster`. -1. Deploy [Gateway API][gwapi] [CRDs][crds]: +Deploy the [Gateway API] [CRDs]: ```console kubectl apply -k https://github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v0.8.1 ``` -2. Build Blixt images: +Build container images: ```console make build.all.images TAG=latest ``` -3. Load images into your Kind cluster: +Load images into your Kind cluster: ```console make load.all.images TAG=latest ``` -4. Deploy Blixt: +Deploy Blixt: ```console kubectl apply -k config/default @@ -121,32 +86,60 @@ blixt-controlplane-cdccc685b-9dxj2 2/2 Running 0 83s blixt-dataplane-brsl9 1/1 Running 0 83s ``` -Check the `config/samples` directory for `Gateway` and `*Route` examples you -can now deploy. - -> **Note**: When developing the dataplane you can make changes in your local -> `dataplane/` directory, and within there quickly build an image and load it -> into the cluster created in the above steps with `make load.image`. This will -> build the eBPF loader and eBPF bytecode in a container image, load that image -> into the cluster, and then restart the dataplane pods to use the new build. +> **Note**: Check the `config/samples` directory for `Gateway` and `*Route` +> examples you can now deploy. [kind]:https://github.com/kubernetes-sigs/kind -[gwapi]:https://github.com/kubernetes-sigs/gateway-api -[crds]:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ +[Gateway API]:https://github.com/kubernetes-sigs/gateway-api +[CRDs]:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ + +## Development + +Development is generally done by making your changes locally, building images +with those changes locally and then deploying those images to a local `kind` +cluster (see the usage section above to get an environment set up). + +You can build the data-plane: + +```console +make build.image.dataplane +``` + +Then load it into the cluster and perform a rollout on the `Daemonset`: + +```console +make load.image.dataplane +``` + +The same can be done for the control-plane: + +```console +make build.image.controlplane +make load.image.controlplane +``` + +> **Warning**: The integration tests are currently written in Golang, which is +> a little awkward, but it is a temporary situation as we rewrite them in Rust. +> Run `make test.integration.deprecated` after deploying your custom images to +> the cluster. + +> **Note**: We use [Cargo workspaces] to manage the various crates spread across +> the Rust parts of the repo. However, there is one exception. The +> `dataplane/eBPF` crate must be kept as a standalone because it needs to +> re-implement the `panic` handler. All new crates should be added to the +> workspace, if possible. + +[Cargo Workspaces]:https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html ## Community -You can reach out to the community by creating [issue][issues] or -[discussions][disc]. You can also reach out on [Kubernetes Slack][kslack] on the -`#blixt` channel. There is also a `#ebpf` channel on Kubernetes Slack for general -eBPF related help. +You can reach out to the community by creating [issues] or [discussions]. You +can also reach out on [Kubernetes Slack] on the `#blixt` channel. There is also +an `#ebpf` channel on Kubernetes Slack for general eBPF related help! -[donation]:https://github.com/kubernetes/org/issues/3875 -[gwapi]:https://gateway-api.sigs.k8s.io/ -[gwapi-meet]:https://gateway-api.sigs.k8s.io/contributing/#meetings [issues]:https://github.com/kubernetes-sigs/blixt/issues -[disc]:https://github.com/kubernetes-sigs/blixt/discussions -[kslack]:https://kubernetes.slack.com +[discussions]:https://github.com/kubernetes-sigs/blixt/discussions +[Kubernetes Slack]:https://kubernetes.slack.com # License From 0e5a5897f1f9b1612dd70482d155e276ffa2fd71 Mon Sep 17 00:00:00 2001 From: Shane Utt Date: Thu, 5 Sep 2024 07:59:36 -0400 Subject: [PATCH 10/10] tests: add Rust Makefile test directive Signed-off-by: Shane Utt --- .github/workflows/build.yaml | 4 ++++ Makefile | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9bf07c2e..dc9546ae 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -47,3 +47,7 @@ jobs: - name: Check clippy run: | make lint + + - name: Run Tests + run: | + make test diff --git a/Makefile b/Makefile index a6689540..04b7817c 100644 --- a/Makefile +++ b/Makefile @@ -211,6 +211,10 @@ lint: ## Lint Rust code # Testing # ------------------------------------------------------------------------------ +.PHONY: test +test: ## Run tests + cargo test -vv + .PHONY: test.integration.deprecated test.integration.deprecated: ## Run the deprecated Golang integration tests go clean -testcache