Repository: Michaelpalacce/HomeLab Branch: master Commit: 23607982daba Files: 523 Total size: 1.7 MB Directory structure: gitextract_h1nphho3/ ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-report.md │ │ ├── feature-request.md │ │ └── question.md │ ├── PULL_REQUEST_TEMPLATE.md │ ├── linters/ │ │ ├── .markdownlint.yaml │ │ ├── .prettierignore │ │ ├── .prettierrc.yaml │ │ ├── .tflint.hcl │ │ └── .yamllint.yaml │ ├── renovate.json5 │ └── workflows/ │ ├── dependency.yaml │ └── lint.yaml ├── .gitignore ├── .gitmodules ├── Helm/ │ └── apps/ │ ├── changedetection/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── cyberchef/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── service.yaml │ │ └── values.yaml │ ├── diagrams/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── service.yaml │ │ └── values.yaml │ ├── firefly/ │ │ ├── .helmignore │ │ ├── CHANGELOG.md │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── firefly-bot-deployment.yaml │ │ │ ├── firefly-pvc.yaml │ │ │ └── gateway-api.yaml │ │ └── values.yaml │ ├── foldingathome/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── gateway-api.yaml │ │ │ └── statefulset.yaml │ │ └── values.yaml │ ├── freshrss/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── homebox/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── it-tools/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── pdb.yaml │ │ │ └── service.yaml │ │ └── values.yaml │ ├── linkwarden/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── mazanoke/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── service.yaml │ │ └── values.yaml │ ├── mealie/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── service.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── media/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── flaresolverr.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kavita.yaml │ │ │ ├── media-pvc.yaml │ │ │ ├── overseer.yaml │ │ │ ├── prowlarr.yaml │ │ │ ├── radarr.yaml │ │ │ ├── sonarr.yaml │ │ │ └── transmission.yaml │ │ └── values.yaml │ ├── n8n/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── nodered/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── nodered-pvc.yaml │ │ └── values.yaml │ ├── openbooks/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── reactiveresume/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── storage/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── gateway-api.yaml │ │ │ ├── storage-pvc.yaml │ │ │ └── syncthing.yaml │ │ └── values.yaml │ ├── uptimekuma/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── uptime-kuma-pvc.yaml │ │ └── values.yaml │ ├── vikunja/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ ├── wallabag/ │ │ ├── .helmignore │ │ ├── CHANGELOG.md │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates/ │ │ │ ├── database.yaml │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── pdb.yaml │ │ │ ├── service.yaml │ │ │ └── storage.yaml │ │ └── values.yaml │ └── website/ │ ├── .helmignore │ ├── CHANGELOG.md │ ├── Chart.yaml │ ├── README.md │ ├── templates/ │ │ ├── deployment.yaml │ │ ├── gateway-api.yaml │ │ ├── pdb.yaml │ │ └── service.yaml │ └── values.yaml ├── README.md ├── TODOS.md ├── ansible/ │ ├── hosts/ │ │ ├── group_vars/ │ │ │ ├── master/ │ │ │ │ └── k3s-config.yaml │ │ │ └── workers/ │ │ │ └── k3s-config.yaml │ │ └── inventory │ └── playbooks/ │ └── install/ │ ├── files/ │ │ ├── allContainerLogs │ │ ├── cleanUpOrphanedPods.py │ │ ├── cniLogs │ │ ├── multipath.conf │ │ └── podLogs │ ├── main.yml │ ├── requirements.yml │ └── vars/ │ └── main.yml ├── cluster/ │ └── homelab/ │ ├── age.agekey.public │ ├── apps/ │ │ ├── adminer/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── service.yaml │ │ ├── bentopdf/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── service.yaml │ │ ├── cert-manager/ │ │ │ ├── issuer.yaml │ │ │ ├── kustomization.yaml │ │ │ └── wildcard-certificate.yaml │ │ ├── changedetection/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── cyberchef/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── diagrams/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── firefly/ │ │ │ ├── cnpg.yaml │ │ │ ├── gateway-api.sensitive.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── foldingathome/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── freshrss/ │ │ │ ├── cnpg.yaml │ │ │ ├── gateway-api.sops.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── garden/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ ├── pdb.yaml │ │ │ └── service.yaml │ │ ├── go-ddns-controller/ │ │ │ ├── configMaps.sops.yaml │ │ │ ├── git-repo-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ ├── notifier.yaml │ │ │ ├── provider.yaml │ │ │ └── secret.sops.yaml │ │ ├── gotenberg/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── homebox/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── homepage/ │ │ │ ├── gateway-api.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── homepage-config.sops.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── it-tools/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── koffan/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ ├── secret.sops.yaml │ │ │ ├── service.yaml │ │ │ └── storage.yaml │ │ ├── kustomization.yaml │ │ ├── linkwarden/ │ │ │ ├── cnpg.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── mazanoke/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── mealie/ │ │ │ ├── gateway-api.sops.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── media/ │ │ │ ├── gateway-api.sops.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── shelfmark/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── service.yaml │ │ │ └── storage.yaml │ │ ├── n8n/ │ │ │ ├── cnpg.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── networking-toolbox/ │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── service.yaml │ │ ├── nodered/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── observeability/ │ │ │ ├── helm-release.sensitive.sops.yaml │ │ │ ├── kubernetes-server-metrics.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── loki-helm-release.yaml │ │ │ ├── namespace.yaml │ │ │ └── trivy.yaml │ │ ├── openbooks/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── paperless-ngx/ │ │ │ ├── gateway-api.sensitive.yaml │ │ │ ├── helm-release.yaml │ │ │ └── kustomization.yaml │ │ ├── reactiveresume/ │ │ │ ├── cnpg.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── replacedby/ │ │ │ ├── database.yaml │ │ │ ├── deployment.yaml │ │ │ ├── gateway-api.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── service.yaml │ │ ├── storage/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── tika/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── uptimekuma/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── vikunja/ │ │ │ ├── cnpg.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── wallabag/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ └── website/ │ │ ├── helm-release.yaml │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── secret.sops.yaml │ ├── base/ │ │ ├── .sops.yaml │ │ ├── apps.yaml │ │ ├── configs.yaml │ │ ├── core.yaml │ │ ├── crds.yaml │ │ ├── flux-system/ │ │ │ ├── gotk-components.yaml │ │ │ ├── gotk-patch.yaml │ │ │ ├── gotk-sync.yaml │ │ │ └── kustomization.yaml │ │ ├── helm.yaml │ │ └── terraform.yaml │ ├── configs/ │ │ ├── flux/ │ │ │ ├── alert.yaml │ │ │ ├── kustomization.yaml │ │ │ └── notification.sops.yaml │ │ ├── istio/ │ │ │ ├── external-gateway-adygenova.yaml │ │ │ ├── external-gateway-replacedby.yaml │ │ │ ├── external-gateway.yaml │ │ │ ├── internal-gateway.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── kustomization.yaml │ │ ├── kyverno/ │ │ │ ├── cleanup-empty-replicasets.yaml │ │ │ ├── default-network-policy.yaml │ │ │ ├── disallow-default.yaml │ │ │ ├── disallow-helm-tiller.yaml │ │ │ ├── disallow-latest-tag.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── inject-image-pull-secrets.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── no-privileged.yaml │ │ │ ├── require-drop-all.yaml │ │ │ ├── restrict-node-port.yaml │ │ │ └── restrict-service-external-ips.yaml │ │ ├── metallb/ │ │ │ ├── ip-pool.yaml │ │ │ ├── kustomization.yaml │ │ │ └── l2-advertisement.yaml │ │ ├── system-upgrade/ │ │ │ ├── README.md │ │ │ ├── kustomization.yaml │ │ │ └── plans/ │ │ │ ├── latest/ │ │ │ │ ├── agent.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── server.yaml │ │ │ └── stable/ │ │ │ ├── agent.yaml │ │ │ ├── kustomization.yaml │ │ │ └── server.yaml │ │ └── velero/ │ │ ├── kustomization.yaml │ │ └── schedule.yaml │ ├── core/ │ │ ├── archive/ │ │ │ ├── cgroup-gc/ │ │ │ │ ├── helm-release.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ └── kube-vip/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── cert-manager/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── secret.sops.yaml │ │ ├── cluster-critical/ │ │ │ ├── kustomization.yaml │ │ │ └── priority-classes.yaml │ │ ├── cnpg/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── descheduler/ │ │ │ ├── helm-release.yaml │ │ │ └── kustomization.yaml │ │ ├── istio/ │ │ │ ├── cni-helm-release.yaml │ │ │ ├── control-plane-helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── ztunnel-helm-release.yaml │ │ ├── kured/ │ │ │ ├── helm-release.sops.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── kustomization.yaml │ │ ├── kyverno/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── longhorn-system/ │ │ │ ├── db-storageclass.yaml │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── mariadb-operator/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── metallb/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── reflector/ │ │ │ ├── helm-release.yaml │ │ │ ├── image_pull_secret.sops.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── rook-ceph/ │ │ │ ├── helm-release.yaml │ │ │ └── kustomization.yaml │ │ ├── system-upgrade/ │ │ │ └── kustomization.yaml │ │ ├── tofu-controller/ │ │ │ ├── helm-release.yaml │ │ │ └── kustomization.yaml │ │ ├── trivy/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ └── velero/ │ │ ├── helm-release.yaml │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── secret.sops.yaml │ ├── crds/ │ │ ├── external-snapshotter/ │ │ │ ├── crds.yaml │ │ │ └── kustomization.yaml │ │ ├── gateway-api/ │ │ │ ├── crds.yaml │ │ │ └── kustomization.yaml │ │ ├── istio/ │ │ │ ├── helm-release.yaml │ │ │ ├── kustomization.yaml │ │ │ └── namespace.yaml │ │ ├── kustomization.yaml │ │ └── mariadb-operator/ │ │ ├── helm-release.yaml │ │ ├── kustomization.yaml │ │ └── namespace.yaml │ ├── helm/ │ │ ├── aqua/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── bjw-s/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── cert-manager/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── cnpg/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── descheduler/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── gabe565/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── go-ddns-controller/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── istio/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── k8s-at-home/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── kube-vip/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── kubereboot/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── kustomization.yaml │ │ ├── kyverno/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── longhorn-system/ │ │ │ ├── kustomization.yaml │ │ │ └── longhorn-repo.yaml │ │ ├── maikumori/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── mariadb-operator/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── metallb/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── metrics-server/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── observability/ │ │ │ ├── kube-prometheus-stack.yaml │ │ │ ├── kustomization.yaml │ │ │ └── loki-stack.yaml │ │ ├── reflector/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── rook/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── tika/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── tofu-controller/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ ├── unofficial/ │ │ │ ├── jameswynn.yaml │ │ │ └── kustomization.yaml │ │ ├── velero/ │ │ │ ├── kustomization.yaml │ │ │ └── repo.yaml │ │ └── wger/ │ │ ├── kustomization.yaml │ │ └── repo.yaml │ ├── storage/ │ │ ├── kustomization.yaml │ │ └── rook-ceph-cluster/ │ │ ├── helm-release.yaml │ │ └── kustomization.yaml │ ├── template.secret.yaml │ └── terraform/ │ ├── homelab-iac-secrets.sops.yaml │ ├── homelab-iac.yaml │ └── kustomization.yaml ├── docs/ │ ├── Backups.md │ ├── Flux.md │ ├── Getting Started.md │ ├── Longhorn.md │ ├── SettingUpCertManager.md │ ├── SettingUpRenovate.md │ ├── Sops.md │ ├── Troubleshooting.md │ └── tofu.md ├── local/ │ └── docker-compose.yaml └── upgrades/ └── v1.35.0+k3s1.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CODEOWNERS ================================================ # https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners * @Michaelpalacce ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: kind/bug assignees: '' --- # Details **What steps did you take and what happened:** **What did you expect to happen:** **Anything else you would like to add:** **Additional Information:** ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: '' labels: kind/enhancement assignees: '' --- # Details **Describe the solution you'd like:** **Anything else you would like to add:** **Additional Information:** ================================================ FILE: .github/ISSUE_TEMPLATE/question.md ================================================ --- name: Question about: Ask a question to the maintainer title: '' labels: kind/question assignees: '' --- # Details **Ask your question:** ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ **Description of the change** **Benefits** **Possible drawbacks** **Applicable issues** - fixes # **Additional information** ================================================ FILE: .github/linters/.markdownlint.yaml ================================================ --- default: true # MD013/line-length - Line length MD013: # Number of characters line_length: 240 # Number of characters for headings heading_line_length: 80 # Number of characters for code blocks code_block_line_length: 80 # Include code blocks code_blocks: true # Include tables tables: true # Include headings headings: true # Include headings headers: true # Strict length checking strict: false # Stern length checking stern: false ================================================ FILE: .github/linters/.prettierignore ================================================ *.sops.* gotk-components.yaml ================================================ FILE: .github/linters/.prettierrc.yaml ================================================ --- trailingComma: es5 tabWidth: 2 semi: false singleQuote: false ================================================ FILE: .github/linters/.tflint.hcl ================================================ ================================================ FILE: .github/linters/.yamllint.yaml ================================================ --- ignore: | gotk-*.yaml *jenkins* extends: default rules: truthy: false comments: min-spaces-from-content: 1 line-length: disable hyphens: disable braces: min-spaces-inside: 0 max-spaces-inside: 1 brackets: min-spaces-inside: 0 max-spaces-inside: 0 indentation: spaces: consistent ================================================ FILE: .github/renovate.json5 ================================================ { extends: [ ':enableRenovate', 'config:recommended', ':disableRateLimiting', ':dependencyDashboard', ':semanticCommits', ':separatePatchReleases', 'docker:enableMajor', ], enabled: true, semanticCommits: 'enabled', dependencyDashboard: true, dependencyDashboardTitle: 'Renovate Dashboard', suppressNotifications: [ ], rebaseWhen: 'conflicted', ignoreDeps: [ 'ghcr.io/fluxcd/helm-controller', 'ghcr.io/fluxcd/image-automation-controller', 'ghcr.io/fluxcd/image-reflector-controller', 'ghcr.io/fluxcd/kustomize-controller', 'ghcr.io/fluxcd/notification-controller', 'ghcr.io/fluxcd/source-controller', ], 'pre-commit': { enabled: true, }, flux: { managerFilePatterns: [ '/cluster/.+\\.ya?ml$/', ], }, 'helm-values': { managerFilePatterns: [ '/cluster/.+\\.ya?ml$/', ], }, kubernetes: { managerFilePatterns: [ '/cluster/.+\\.ya?ml$/', ], }, customManagers: [ { customType: 'regex', managerFilePatterns: [ '/cluster/.+\\.ya?ml$/', ], matchStrings: [ 'reference:\\s*(?[^\\s:]+):(?[^\\s\\n]+)', ], datasourceTemplate: 'docker', }, { customType: 'regex', managerFilePatterns: [ '/cluster/.+\\.ya?ml$/', ], matchStrings: [ 'registryUrl=(?.*?)\n *chart: (?.*?)\n *version: (?.*)\n', ], datasourceTemplate: 'helm', }, { customType: 'regex', managerFilePatterns: [ '/cluster/crds/cert-manager/.+\\.ya?ml$/', ], matchStrings: [ 'registryUrl=(?.*?) chart=(?.*?)\n.*\\/(?.*?)\\/', ], datasourceTemplate: 'helm', }, ], packageRules: [ { matchDatasources: [ 'helm', ], separateMinorPatch: true, ignoreDeprecated: true, }, { matchDatasources: [ 'docker', ], enabled: true, commitMessageTopic: 'container image {{depName}}', commitMessageExtra: 'to {{#if isSingleVersion}}v{{{newVersion}}}{{else}}{{{newValue}}}{{/if}}', matchUpdateTypes: [ 'major', 'minor', 'patch', ], }, { matchDatasources: [ 'docker', ], matchUpdateTypes: [ 'major', ], labels: [ 'renovate/image', 'dep/major', ], }, { matchDatasources: [ 'docker', ], matchUpdateTypes: [ 'minor', ], labels: [ 'renovate/image', 'dep/minor', ], automerge: true, }, { matchDatasources: [ 'docker', ], matchUpdateTypes: [ 'patch', ], labels: [ 'renovate/image', 'dep/patch', ], automerge: true, }, { matchDatasources: [ 'helm', ], matchUpdateTypes: [ 'major', ], labels: [ 'renovate/helm', 'dep/major', ], automerge: false, }, { matchDatasources: [ 'helm', ], matchUpdateTypes: [ 'minor', ], labels: [ 'renovate/helm', 'dep/minor', ], automerge: true, }, { matchDatasources: [ 'helm', ], matchUpdateTypes: [ 'patch', ], labels: [ 'renovate/helm', 'dep/patch', ], automerge: true, }, ], } ================================================ FILE: .github/workflows/dependency.yaml ================================================ name: 'Dependency Review' on: pull_request: permissions: contents: read jobs: dependency-review: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: 'Dependency Review' uses: actions/dependency-review-action@v4 ================================================ FILE: .github/workflows/lint.yaml ================================================ --- name: Lint on: # yamllint disable-line rule:truthy workflow_dispatch: pull_request: branches: - master env: # Currently no way to detect automatically DEFAULT_BRANCH: master jobs: build: name: Lint runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - name: Lint uses: github/super-linter/slim@v7 env: VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'workflow_dispatch' }} DEFAULT_BRANCH: "${{ env.DEFAULT_BRANCH }}" GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" MARKDOWN_CONFIG_FILE: .markdownlint.yaml TERRAFORM_TFLINT_CONFIG_FILE: .tflint.hcl YAML_CONFIG_FILE: .yamllint.yaml KUBERNETES_KUBEVAL_OPTIONS: --ignore-missing-schemas ================================================ FILE: .gitignore ================================================ .idea TestingEnv output/ .secret testing ansible/playbooks/restore/files/backup velero-credentials temp *.tfvars *.tfstate.backup .terraform docker-data ================================================ FILE: .gitmodules ================================================ [submodule "HomeLab-IaC"] path = HomeLab-IaC url = https://github.com/Michaelpalacce/HomeLab-IaC.git ================================================ FILE: Helm/apps/changedetection/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/changedetection/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install changedetection maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: changedetection type: application version: 2.0.0 ================================================ FILE: Helm/apps/changedetection/README.md ================================================ This chart is used to install changedetection ================================================ FILE: Helm/apps/changedetection/templates/deployment.yaml ================================================ --- {{- with .Values.changedetection }} apiVersion: apps/v1 kind: Deployment metadata: name: changedetection namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: changedetection app.kubernetes.io/name: changedetection spec: strategy: rollingUpdate: maxUnavailable: 0 replicas: 1 selector: matchLabels: app.kubernetes.io/instance: changedetection app.kubernetes.io/name: changedetection template: metadata: annotations: backup.velero.io/backup-volumes: data-config labels: app.kubernetes.io/instance: changedetection app.kubernetes.io/name: changedetection spec: containers: - name: browserless image: {{ .playwright.image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL ports: - name: browserless containerPort: {{ .playwright.port }} env: - name: DEFAULT_LAUNCH_ARGS value: "--window-size=1920.1080" resources: limits: memory: 2Gi volumeMounts: - name: shm-empty-playwright mountPath: /dev/shm livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 tcpSocket: port: {{ .playwright.port }} timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: {{ .playwright.port }} - name: selenium image: {{ .selenium.image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL ports: - name: selenium containerPort: {{ .selenium.port }} resources: limits: memory: 2Gi volumeMounts: - name: shm-empty mountPath: /dev/shm livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 tcpSocket: port: {{ .selenium.port }} timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: {{ .selenium.port }} - name: changedetection image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data-config mountPath: /datastore env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" - name: BASE_URL value: "{{ .baseUrl }}" - name: WEBDRIVER_URL value: "http://localhost:{{ .selenium.port }}/wd/hub" - name: PLAYWRIGHT_DRIVER_URL value: "ws://localhost:{{ .playwright.port }}/?stealth=1&--disable-web-security=true" livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 tcpSocket: port: {{ .port }} timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: data-config persistentVolumeClaim: claimName: changedetection-pvc - name: shm-empty emptyDir: medium: Memory - name: shm-empty-playwright emptyDir: medium: Memory --- apiVersion: v1 kind: Service metadata: name: changedetection namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: changedetection app.kubernetes.io/name: changedetection ports: - name: changedetection protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/changedetection/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: changedetection-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Monitors changes to websites gethomepage.dev/group: Automation gethomepage.dev/icon: changedetection gethomepage.dev/name: ChangeDetection.io gethomepage.dev/widget.type: changedetectionio gethomepage.dev/widget.url: https://changedetection.sgenov.dev gethomepage.dev/widget.key: 24f82bd47ffef64b0b533239ad38d945 # yeah, it's public, but it's not so secret spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "changedetection.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: changedetection port: {{ .Values.changedetection.port }} ================================================ FILE: Helm/apps/changedetection/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: changedetection-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.configSize }} ================================================ FILE: Helm/apps/changedetection/values.yaml ================================================ --- changedetection: image: dgtlmoon/changedetection.io:0.55.3 port: 5000 baseUrl: changedetection.sgenov.dev resources: requests: cpu: 10m memory: 125Mi selenium: image: selenium/standalone-chrome-debug:3.141.59 port: 4444 playwright: image: browserless/chrome:1.61-chrome-stable port: 3000 storage: configSize: 1Gi ================================================ FILE: Helm/apps/cyberchef/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/cyberchef/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install cyberchef maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: cyberchef type: application version: 3.0.0 ================================================ FILE: Helm/apps/cyberchef/README.md ================================================ This chart is used to install cyberchef. ================================================ FILE: Helm/apps/cyberchef/templates/deployment.yaml ================================================ --- {{- with .Values.cyberchef }} apiVersion: apps/v1 kind: Deployment metadata: name: cyberchef namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: cyberchef app.kubernetes.io/name: cyberchef spec: strategy: rollingUpdate: maxUnavailable: 0 replicas: 1 selector: matchLabels: app.kubernetes.io/instance: cyberchef app.kubernetes.io/name: cyberchef template: metadata: labels: app.kubernetes.io/instance: cyberchef app.kubernetes.io/name: cyberchef spec: containers: - name: cyberchef image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 5 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always {{- end }} ================================================ FILE: Helm/apps/cyberchef/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: cyberchef-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Swiss Army Knife of the internet gethomepage.dev/group: Tools gethomepage.dev/icon: cyberchef gethomepage.dev/name: CyberChef spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "cyberchef.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: cyberchef port: {{ .Values.cyberchef.port }} ================================================ FILE: Helm/apps/cyberchef/templates/service.yaml ================================================ --- {{- with .Values.cyberchef }} apiVersion: v1 kind: Service metadata: name: cyberchef namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: cyberchef app.kubernetes.io/name: cyberchef ports: - name: cyberchef protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/cyberchef/values.yaml ================================================ --- cyberchef: image: mpepping/cyberchef:v10.24.0 port: 8000 resources: requests: cpu: 10m memory: 50Mi ================================================ FILE: Helm/apps/diagrams/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/diagrams/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install diagrams maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: diagrams type: application version: 4.0.0 ================================================ FILE: Helm/apps/diagrams/README.md ================================================ This chart is used to install diagrams. Diagrams or draw.io is a free online diagram software for making flowcharts, process diagrams, org charts, UML, etc ================================================ FILE: Helm/apps/diagrams/templates/deployment.yaml ================================================ --- {{- with .Values.diagrams }} apiVersion: apps/v1 kind: Deployment metadata: name: diagrams namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: diagrams app.kubernetes.io/name: diagrams spec: replicas: 1 strategy: rollingUpdate: maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/instance: diagrams app.kubernetes.io/name: diagrams template: metadata: labels: app.kubernetes.io/instance: diagrams app.kubernetes.io/name: diagrams spec: containers: - name: diagrams image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} restartPolicy: Always {{- end }} ================================================ FILE: Helm/apps/diagrams/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: diagrams-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Make diagrams in your browser gethomepage.dev/group: Tools gethomepage.dev/icon: draw-io gethomepage.dev/name: Diagrams spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "diagrams.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: diagrams port: {{ .Values.diagrams.port }} ================================================ FILE: Helm/apps/diagrams/templates/service.yaml ================================================ --- {{- with .Values.diagrams }} apiVersion: v1 kind: Service metadata: name: diagrams namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: diagrams app.kubernetes.io/name: diagrams ports: - name: diagrams protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/diagrams/values.yaml ================================================ --- diagrams: image: jgraph/drawio:29.7.9 port: 8080 resources: requests: cpu: 10m memory: 10Mi ================================================ FILE: Helm/apps/firefly/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/firefly/CHANGELOG.md ================================================ #### [v4.0.0] - Better Selector #### [v3.0.0] * Added firefly-iii-bot #### [V2.0.0] * Added simplesecrets #### [V1.1.0] * New Version * Removed NodePort #### [V1.0.0] * Initial Deployment ================================================ FILE: Helm/apps/firefly/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install firefly maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: firefly type: application version: 4.0.0 ================================================ FILE: Helm/apps/firefly/README.md ================================================ This chart is used to install firefly ================================================ FILE: Helm/apps/firefly/templates/deployment.yaml ================================================ --- {{- with .Values.firefly }} apiVersion: apps/v1 kind: Deployment metadata: name: firefly namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: firefly app.kubernetes.io/name: firefly spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: firefly app.kubernetes.io/name: firefly template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app.kubernetes.io/instance: firefly app.kubernetes.io/name: firefly spec: containers: - name: firefly image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL privileged: false allowPrivilegeEscalation: false {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data mountPath: /var/www/html/storage env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" - name: DB_USERNAME valueFrom: secretKeyRef: name: cluster-postgres-app key: username - name: DB_PASSWORD valueFrom: secretKeyRef: name: cluster-postgres-app key: password - name: DB_DATABASE valueFrom: secretKeyRef: name: cluster-postgres-app key: dbname - name: DB_HOST valueFrom: secretKeyRef: name: cluster-postgres-app key: host - name: DB_PORT valueFrom: secretKeyRef: name: cluster-postgres-app key: port - name: DB_CONNECTION value: pgsql - name: APP_KEY valueFrom: secretKeyRef: name: app key: key - name: APP_URL value: "{{ .appUrl }}" - name: TRUSTED_PROXIES value: "**" livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 5 httpGet: path: /login port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 5 httpGet: path: /login port: {{ .port }} restartPolicy: Always volumes: - name: data persistentVolumeClaim: claimName: firefly-pvc --- apiVersion: v1 kind: Service metadata: name: firefly namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: firefly app.kubernetes.io/name: firefly ports: - name: web protocol: TCP port: 80 targetPort: 8080 {{- end }} ================================================ FILE: Helm/apps/firefly/templates/firefly-bot-deployment.yaml ================================================ --- {{- with .Values.fireflybot }} apiVersion: apps/v1 kind: Deployment metadata: name: fireflybot namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: fireflybot app.kubernetes.io/name: fireflybot spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: fireflybot app.kubernetes.io/name: fireflybot template: metadata: annotations: backup.velero.io/backup-volumes: sessions labels: app.kubernetes.io/instance: fireflybot app.kubernetes.io/name: fireflybot spec: containers: - name: fireflybot image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL privileged: false allowPrivilegeEscalation: false {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} volumeMounts: - name: sessions mountPath: /home/node/app/sessions envFrom: - secretRef: name: bot-env restartPolicy: Always volumes: - name: sessions persistentVolumeClaim: claimName: firefly-bot-pvc {{- end }} ================================================ FILE: Helm/apps/firefly/templates/firefly-pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: firefly-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.configSize }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: firefly-bot-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.botSessionSize }} ================================================ FILE: Helm/apps/firefly/templates/gateway-api.yaml ================================================ # --- # apiVersion: gateway.networking.k8s.io/v1 # kind: HTTPRoute # metadata: # name: firefly-external # namespace: {{ $.Release.Namespace }} # spec: # parentRefs: # - name: external # namespace: istio-gateway # hostnames: # - "firefly.sgenov.dev" # rules: # - matches: # - path: # type: PathPrefix # value: / # backendRefs: # - name: firefly # port: 80 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: firefly-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "firefly.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: firefly port: 80 ================================================ FILE: Helm/apps/firefly/values.yaml ================================================ --- firefly: image: fireflyiii/core:version-6.2.10 port: 8080 appUrl: https://firefly.sgenov.dev resources: requests: cpu: 500m memory: 2Gi fireflybot: image: cyxou/firefly-iii-telegram-bot:v2.3.1 resources: requests: cpu: 200m memory: 500Mi storage: configSize: 5Gi botSessionSize: 2Gi ================================================ FILE: Helm/apps/foldingathome/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/foldingathome/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install foldingathome maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: foldingathome type: application version: 3.1.0 ================================================ FILE: Helm/apps/foldingathome/README.md ================================================ This chart is used to install foldingathome ================================================ FILE: Helm/apps/foldingathome/templates/gateway-api.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: foldingathome-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "foldingathome.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: foldingathome port: {{ .Values.foldingathome.port }} ================================================ FILE: Helm/apps/foldingathome/templates/statefulset.yaml ================================================ --- {{- with .Values.foldingathome }} apiVersion: apps/v1 kind: StatefulSet metadata: name: foldingathome namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: foldingathome app.kubernetes.io/name: foldingathome spec: serviceName: foldingathome replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: foldingathome app.kubernetes.io/name: foldingathome template: metadata: annotations: backup.velero.io/backup-volumes: app-config labels: app.kubernetes.io/instance: foldingathome app.kubernetes.io/name: foldingathome spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app.kubernetes.io/instance: foldingathome app.kubernetes.io/name: foldingathome topologyKey: kubernetes.io/hostname restartPolicy: Always containers: - name: foldingathome image: {{ .image }} imagePullPolicy: IfNotPresent {{- if .resources }} resources: {{ toYaml .resources | indent 12 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: app-config mountPath: /config env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" - name: MACHINE_NAME valueFrom: fieldRef: fieldPath: metadata.name envFrom: - secretRef: name: app livenessProbe: failureThreshold: 5 initialDelaySeconds: 60 timeoutSeconds: 5 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 5 initialDelaySeconds: 10 tcpSocket: port: {{ .port }} volumeClaimTemplates: - metadata: name: app-config spec: accessModes: - ReadWriteOnce resources: requests: storage: {{ $.Values.storage.configSize | default "1Gi" }} --- apiVersion: v1 kind: Service metadata: name: foldingathome namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: foldingathome app.kubernetes.io/name: foldingathome ports: - name: foldingathome protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/foldingathome/values.yaml ================================================ --- foldingathome: image: lscr.io/linuxserver/foldingathome:8.5.5 port: 7396 replicas: 0 # One for each server resources: requests: cpu: 200m memory: 200Mi limits: cpu: 2 memory: 1Gi storage: configSize: 1Gi ================================================ FILE: Helm/apps/freshrss/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/freshrss/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install freshrss maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: freshrss type: application version: 3.1.0 ================================================ FILE: Helm/apps/freshrss/README.md ================================================ This chart is used to install freshrss ================================================ FILE: Helm/apps/freshrss/templates/deployment.yaml ================================================ --- {{- with .Values.freshrss }} apiVersion: apps/v1 kind: Deployment metadata: name: freshrss namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: freshrss app.kubernetes.io/name: freshrss spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: freshrss app.kubernetes.io/name: freshrss template: metadata: annotations: backup.velero.io/backup-volumes: app-config labels: app.kubernetes.io/instance: freshrss app.kubernetes.io/name: freshrss spec: containers: - name: freshrss image: {{ .image }} imagePullPolicy: IfNotPresent {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: app-config mountPath: /config env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" livenessProbe: failureThreshold: 5 initialDelaySeconds: 60 timeoutSeconds: 5 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 5 initialDelaySeconds: 10 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: app-config persistentVolumeClaim: claimName: freshrss-pvc --- apiVersion: v1 kind: Service metadata: name: freshrss namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: freshrss app.kubernetes.io/name: freshrss ports: - name: freshrss protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/freshrss/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: freshrss-external namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "freshrss.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: freshrss port: {{ .Values.freshrss.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: freshrss-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "freshrss.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: freshrss port: {{ .Values.freshrss.port }} ================================================ FILE: Helm/apps/freshrss/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: freshrss-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.configSize }} ================================================ FILE: Helm/apps/freshrss/values.yaml ================================================ --- freshrss: image: lscr.io/linuxserver/freshrss:1.28.1 port: 80 resources: requests: cpu: 200m memory: 200Mi storage: configSize: 1Gi ================================================ FILE: Helm/apps/homebox/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/homebox/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install homebox maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: homebox type: application version: 2.0.0 ================================================ FILE: Helm/apps/homebox/README.md ================================================ This chart is used to install homebox ================================================ FILE: Helm/apps/homebox/templates/deployment.yaml ================================================ --- {{- with .Values.homebox }} apiVersion: apps/v1 kind: Deployment metadata: name: homebox namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: homebox app.kubernetes.io/name: homebox spec: replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: homebox app.kubernetes.io/name: homebox template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app.kubernetes.io/instance: homebox app.kubernetes.io/name: homebox spec: containers: - name: homebox image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} env: - name: HBOX_LOG_LEVEL value: "info" - name: HBOX_LOG_FORMAT value: "json" - name: HBOX_WEB_MAX_UPLOAD_SIZE value: "100" - name: HBOX_ALLOW_REGISTRATION value: "true" volumeMounts: - mountPath: /data name: data livenessProbe: failureThreshold: 2 initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 periodSeconds: 5 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: data persistentVolumeClaim: claimName: data-pvc --- apiVersion: v1 kind: Service metadata: name: homebox namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: homebox app.kubernetes.io/name: homebox ports: - name: homebox protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/homebox/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: homebox-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Home Inventory gethomepage.dev/group: Storage gethomepage.dev/icon: homebox gethomepage.dev/name: Homebox spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "homebox.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: homebox port: {{ .Values.homebox.port }} ================================================ FILE: Helm/apps/homebox/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: data-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.dataSize }} ================================================ FILE: Helm/apps/homebox/values.yaml ================================================ --- homebox: image: ghcr.io/hay-kot/homebox:v0.10.3 port: 7745 replicas: 1 resources: requests: cpu: 10m memory: 50Mi storage: dataSize: 2Gi ================================================ FILE: Helm/apps/it-tools/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/it-tools/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install it-tools maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: it-tools type: application version: 2.0.0 ================================================ FILE: Helm/apps/it-tools/README.md ================================================ This chart is used to install it-tools. ================================================ FILE: Helm/apps/it-tools/templates/deployment.yaml ================================================ --- {{- with .Values.ittools }} apiVersion: apps/v1 kind: Deployment metadata: name: it-tools namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: it-tools app.kubernetes.io/name: it-tools spec: replicas: {{ .replicas }} strategy: rollingUpdate: maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/instance: it-tools app.kubernetes.io/name: it-tools template: metadata: labels: app.kubernetes.io/instance: it-tools app.kubernetes.io/name: it-tools spec: containers: - name: it-tools image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} restartPolicy: Always {{- end }} ================================================ FILE: Helm/apps/it-tools/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: it-tools-external namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "it-tools.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: it-tools port: {{ .Values.ittools.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: it-tools-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Usefull tools for IT professionals gethomepage.dev/group: Tools gethomepage.dev/icon: it-tools gethomepage.dev/name: IT Tools spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "it-tools.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: it-tools port: {{ .Values.ittools.port }} ================================================ FILE: Helm/apps/it-tools/templates/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: it-tools spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: it-tools app.kubernetes.io/name: it-tools ================================================ FILE: Helm/apps/it-tools/templates/service.yaml ================================================ --- {{- with .Values.ittools }} apiVersion: v1 kind: Service metadata: name: it-tools namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: it-tools app.kubernetes.io/name: it-tools ports: - name: it-tools protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/it-tools/values.yaml ================================================ --- ittools: replicas: 1 image: ghcr.io/corentinth/it-tools:nightly # The project doesn't have good docker tag hygiene port: 80 resources: requests: cpu: 10m memory: 10Mi ================================================ FILE: Helm/apps/linkwarden/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/linkwarden/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install linkwarden maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: linkwarden type: application version: 1.0.0 ================================================ FILE: Helm/apps/linkwarden/README.md ================================================ This chart is used to install linkwarden ================================================ FILE: Helm/apps/linkwarden/templates/deployment.yaml ================================================ --- {{- with .Values.linkwarden }} apiVersion: apps/v1 kind: Deployment metadata: name: linkwarden namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: linkwarden app.kubernetes.io/name: linkwarden spec: replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: linkwarden app.kubernetes.io/name: linkwarden template: metadata: annotations: backup.velero.io/backup-volumes: data-config labels: app.kubernetes.io/instance: linkwarden app.kubernetes.io/name: linkwarden spec: containers: - name: linkwarden image: {{ .image }} imagePullPolicy: IfNotPresent env: - name: "NEXT_PUBLIC_DISABLE_REGISTRATION" value: "true" - name: "DATABASE_URL" valueFrom: secretKeyRef: name: cluster-postgres-app key: fqdn-uri envFrom: - secretRef: name: app securityContext: privileged: false allowPrivilegeEscalation: false capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data-config mountPath: /data/data livenessProbe: failureThreshold: 5 initialDelaySeconds: 60 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 initialDelaySeconds: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: data-config persistentVolumeClaim: claimName: linkwarden-pvc --- apiVersion: v1 kind: Service metadata: name: linkwarden namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: linkwarden app.kubernetes.io/name: linkwarden ports: - name: linkwarden protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/linkwarden/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: linkwarden-external namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "linkwarden.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: linkwarden port: {{ .Values.linkwarden.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: linkwarden-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Bookmarks gethomepage.dev/group: Knowledge gethomepage.dev/icon: linkwarden gethomepage.dev/name: Linkwarden spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "linkwarden.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: linkwarden port: {{ .Values.linkwarden.port }} ================================================ FILE: Helm/apps/linkwarden/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: linkwarden-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.configSize }} ================================================ FILE: Helm/apps/linkwarden/values.yaml ================================================ --- linkwarden: replicas: 1 image: ghcr.io/linkwarden/linkwarden:v2.14.1 port: 3000 resources: requests: cpu: 10m memory: 256Mi storage: configSize: 25Gi ================================================ FILE: Helm/apps/mazanoke/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/mazanoke/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install mazanoke maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: mazanoke type: application version: 2.0.0 ================================================ FILE: Helm/apps/mazanoke/README.md ================================================ This chart is used to install mazanoke. ================================================ FILE: Helm/apps/mazanoke/templates/deployment.yaml ================================================ --- {{- with .Values.mazanoke }} apiVersion: apps/v1 kind: Deployment metadata: name: mazanoke namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: mazanoke app.kubernetes.io/name: mazanoke spec: replicas: 1 strategy: rollingUpdate: maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/instance: mazanoke app.kubernetes.io/name: mazanoke template: metadata: labels: app.kubernetes.io/instance: mazanoke app.kubernetes.io/name: mazanoke spec: containers: - name: mazanoke image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - NET_BIND_SERVICE - SETGID - SETUID drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} restartPolicy: Always {{- end }} ================================================ FILE: Helm/apps/mazanoke/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mazanoke-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Image Optimzier gethomepage.dev/group: Tools gethomepage.dev/icon: https://raw.githubusercontent.com/civilblur/mazanoke/refs/heads/main/favicon.ico gethomepage.dev/name: Mazanoke spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "mazanoke.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: mazanoke port: {{ .Values.mazanoke.port }} ================================================ FILE: Helm/apps/mazanoke/templates/service.yaml ================================================ --- {{- with .Values.mazanoke }} apiVersion: v1 kind: Service metadata: name: mazanoke namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: mazanoke app.kubernetes.io/name: mazanoke ports: - name: mazanoke protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/mazanoke/values.yaml ================================================ --- mazanoke: image: ghcr.io/civilblur/mazanoke:v1.1.5 port: 80 resources: requests: cpu: 10m memory: 10Mi ================================================ FILE: Helm/apps/mealie/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/mealie/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install mealie maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: mealie type: application version: 2.0.0 ================================================ FILE: Helm/apps/mealie/README.md ================================================ This chart is used to install mealie ================================================ FILE: Helm/apps/mealie/templates/deployment.yaml ================================================ --- {{- with .Values.mealie }} apiVersion: apps/v1 kind: Deployment metadata: name: mealie namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: mealie app.kubernetes.io/name: mealie spec: strategy: rollingUpdate: maxUnavailable: 0 replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: mealie app.kubernetes.io/name: mealie template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app.kubernetes.io/instance: mealie app.kubernetes.io/name: mealie spec: containers: - name: mealie image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL add: - CHOWN - SETUID - SETGID {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} env: - name: PUID value: "1000" - name: GUID value: "1000" - name: TZ value: "Europe/Sofia" - name: MAX_WORKERS value: "1" - name: WEB_CONCURRENCY value: "1" - name: BASE_URL value: "{{ .baseUrl }}" ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data mountPath: /app/data livenessProbe: failureThreshold: 5 initialDelaySeconds: 60 successThreshold: 1 tcpSocket: port: {{ .port }} timeoutSeconds: 2 startupProbe: failureThreshold: 10 successThreshold: 1 tcpSocket: port: {{ .port }} timeoutSeconds: 2 restartPolicy: Always volumes: - name: data persistentVolumeClaim: claimName: data-pvc {{- end }} ================================================ FILE: Helm/apps/mealie/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mealie-external namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "mealie.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: mealie port: {{ .Values.mealie.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mealie-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "mealie.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: mealie port: {{ .Values.mealie.port }} ================================================ FILE: Helm/apps/mealie/templates/service.yaml ================================================ {{- with .Values.mealie }} apiVersion: v1 kind: Service metadata: name: mealie namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: mealie app.kubernetes.io/name: mealie ports: - name: web protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/mealie/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: data-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.dataSize }} ================================================ FILE: Helm/apps/mealie/values.yaml ================================================ --- mealie: replicas: 1 image: ghcr.io/mealie-recipes/mealie:v3.16.0 port: 9000 baseUrl: https://mealie.sgenov.dev resources: requests: cpu: 10m memory: 50Mi storage: dataSize: 2Gi ================================================ FILE: Helm/apps/media/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/media/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install different media services maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: media type: application version: 9.0.0 ================================================ FILE: Helm/apps/media/README.md ================================================ This chart is used to install different media components. Since I use sonarr a lot, and it's the only one struggling really, there is an automatic backup solution in place, that will copy over files to an emptyDir, rather than using longhorn... this is a fix since longhorn is actually not the best, since it uses NFS ... ================================================ FILE: Helm/apps/media/templates/flaresolverr.yaml ================================================ --- {{- with .Values.flaresolverr }} apiVersion: apps/v1 kind: Deployment metadata: name: flaresolverr namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: flaresolverr app.kubernetes.io/name: flaresolverr spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: flaresolverr app.kubernetes.io/name: flaresolverr template: metadata: labels: app.kubernetes.io/instance: flaresolverr app.kubernetes.io/name: flaresolverr spec: containers: - name: flaresolverr image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL privileged: false allowPrivilegeEscalation: false {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} env: - name: LOG_LEVEL value: INFO ports: - name: web containerPort: {{ .port }} livenessProbe: failureThreshold: 2 initialDelaySeconds: 30 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} startupProbe: failureThreshold: 5 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: flaresolverr namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: flaresolverr app.kubernetes.io/name: flaresolverr ports: - name: flaresolverr protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: flaresolverr-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "flaresolverr.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: flaresolverr port: {{ .Values.flaresolverr.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: sonarr-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "sonarr.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: sonarr port: {{ .Values.sonarr.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: kavita-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "kavita.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: kavita port: {{ .Values.kavita.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: prowlarr-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "prowlarr.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: prowlarr port: {{ .Values.prowlarr.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: radarr-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "radarr.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: radarr port: {{ .Values.radarr.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: overseerr-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "overseerr.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: overseerr port: {{ .Values.overseerr.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: transmission-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "transmission.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: transmission port: {{ .Values.transmission.port }} ================================================ FILE: Helm/apps/media/templates/kavita.yaml ================================================ --- {{- with .Values.kavita }} apiVersion: apps/v1 kind: Deployment metadata: name: kavita namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: kavita app.kubernetes.io/name: kavita spec: strategy: type: Recreate replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: kavita app.kubernetes.io/name: kavita template: metadata: annotations: backup.velero.io/backup-volumes: config-data labels: app.kubernetes.io/instance: kavita app.kubernetes.io/name: kavita spec: containers: - name: kavita image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL privileged: false allowPrivilegeEscalation: false env: - name: PUID value: "1000" - name: GUID value: "1000" {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: config-data mountPath: /config - name: books-data-nfs mountPath: /books livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 httpGet: path: /login port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 httpGet: path: /login port: {{ .port }} restartPolicy: Always volumes: - name: config-data persistentVolumeClaim: claimName: kavita-config-pvc - name: books-data-nfs nfs: path: "/volume1/k3s/media/books" server: "192.168.1.39" --- apiVersion: v1 kind: Service metadata: name: kavita namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: kavita app.kubernetes.io/name: kavita ports: - name: kavita protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/templates/media-pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: transmission-config-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.transmission.config }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: kavita-config-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.kavita.config }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: overseer-config-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.overseer.config }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: sonarr-config-pvc spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: {{ .Values.storage.sonarr.config }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: radarr-config-pvc spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: {{ .Values.storage.radarr.config }} --- --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: prowlarr-config-pvc spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: {{ .Values.storage.prowlarr.config }} ================================================ FILE: Helm/apps/media/templates/overseer.yaml ================================================ --- {{- with .Values.overseerr }} apiVersion: apps/v1 kind: Deployment metadata: name: overseerr namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: overseerr app.kubernetes.io/name: overseerr spec: replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: overseerr app.kubernetes.io/name: overseerr template: metadata: annotations: backup.velero.io/backup-volumes: config-data labels: app.kubernetes.io/instance: overseerr app.kubernetes.io/name: overseerr spec: containers: - name: overseerr image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL privileged: false allowPrivilegeEscalation: false env: - name: PUID value: "1000" - name: GUID value: "1000" {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: config-data mountPath: /config livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 httpGet: path: /login port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 httpGet: path: /login port: {{ .port }} restartPolicy: Always volumes: - name: config-data persistentVolumeClaim: claimName: overseer-config-pvc --- apiVersion: v1 kind: Service metadata: name: overseerr namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: overseerr app.kubernetes.io/name: overseerr ports: - name: overseerr protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/templates/prowlarr.yaml ================================================ --- {{- with .Values.prowlarr }} apiVersion: apps/v1 kind: Deployment metadata: name: prowlarr namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: prowlarr app.kubernetes.io/name: prowlarr spec: replicas: {{ .replicas }} strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: prowlarr app.kubernetes.io/name: prowlarr template: metadata: annotations: backup.velero.io/backup-volumes: config labels: app.kubernetes.io/instance: prowlarr app.kubernetes.io/name: prowlarr spec: containers: - name: prowlarr image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL privileged: false allowPrivilegeEscalation: false env: - name: PUID value: "1000" - name: GUID value: "1000" {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: config mountPath: /config livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: config persistentVolumeClaim: claimName: prowlarr-config-pvc --- apiVersion: v1 kind: Service metadata: name: prowlarr namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: prowlarr app.kubernetes.io/name: prowlarr ports: - name: prowlarr protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/templates/radarr.yaml ================================================ --- {{- with .Values.radarr }} apiVersion: apps/v1 kind: Deployment metadata: name: radarr namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: radarr app.kubernetes.io/name: radarr spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: radarr app.kubernetes.io/name: radarr template: metadata: annotations: backup.velero.io/backup-volumes: config labels: app.kubernetes.io/instance: radarr app.kubernetes.io/name: radarr spec: containers: - name: radarr image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL privileged: false allowPrivilegeEscalation: false env: - name: PUID value: "1000" - name: GUID value: "1000" {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: config mountPath: /config - name: downloads-data mountPath: /downloads - name: movies-data-nfs mountPath: /tv livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: config persistentVolumeClaim: claimName: radarr-config-pvc - name: movies-data-nfs nfs: path: "/volume1/k3s/media/movies" server: "192.168.1.39" - name: downloads-data nfs: path: "/volume1/k3s/media/downloads" server: "192.168.1.39" --- apiVersion: v1 kind: Service metadata: name: radarr namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: radarr app.kubernetes.io/name: radarr ports: - name: radarr protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/templates/sonarr.yaml ================================================ --- {{- with .Values.sonarr }} apiVersion: apps/v1 kind: Deployment metadata: name: sonarr namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: sonarr app.kubernetes.io/name: sonarr spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: sonarr app.kubernetes.io/name: sonarr template: metadata: annotations: backup.velero.io/backup-volumes: config labels: app.kubernetes.io/instance: sonarr app.kubernetes.io/name: sonarr spec: containers: - name: sonarr image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL privileged: false allowPrivilegeEscalation: false env: - name: PUID value: "1000" - name: GUID value: "1000" {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: config mountPath: /config - name: downloads-data mountPath: /downloads - name: shows-data-nfs mountPath: /shows livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: shows-data-nfs nfs: path: "/volume1/k3s/media/shows" server: "192.168.1.39" - name: downloads-data nfs: path: "/volume1/k3s/media/downloads" server: "192.168.1.39" - name: config persistentVolumeClaim: claimName: sonarr-config-pvc --- apiVersion: v1 kind: Service metadata: name: sonarr namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: sonarr app.kubernetes.io/name: sonarr ports: - name: sonarr protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/templates/transmission.yaml ================================================ --- {{- with .Values.transmission }} apiVersion: apps/v1 kind: Deployment metadata: name: transmission namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: transmission app.kubernetes.io/name: transmission spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: transmission app.kubernetes.io/name: transmission template: metadata: annotations: backup.velero.io/backup-volumes: transmission-data labels: app.kubernetes.io/instance: transmission app.kubernetes.io/name: transmission spec: containers: - name: transmission image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: add: - CHOWN - SETGID - SETUID drop: - ALL privileged: false allowPrivilegeEscalation: false {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} env: - name: USER value: {{ .username }} - name: PASS value: {{ .password }} - name: PUID value: "1000" - name: GUID value: "1000" ports: - name: web containerPort: {{ .port }} - name: torrent-tcp protocol: TCP containerPort: 51413 - name: torrent-udp protocol: UDP containerPort: 51413 volumeMounts: - name: transmission-data mountPath: /config - name: downloads-data mountPath: /downloads livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: transmission-data persistentVolumeClaim: claimName: transmission-config-pvc - name: downloads-data nfs: path: "/volume1/k3s/media/downloads" server: "192.168.1.39" --- apiVersion: v1 kind: Service metadata: name: transmission namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: transmission app.kubernetes.io/name: transmission ports: - name: transmission protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/media/values.yaml ================================================ --- storage: transmission: config: 1Gi downloads: 200Gi kavita: config: 5Gi overseer: config: 5Gi radarr: config: 5Gi sonarr: config: 5Gi prowlarr: config: 10Gi flaresolverr: image: ghcr.io/flaresolverr/flaresolverr:v3.4.6 port: 8191 resources: requests: cpu: 512m memory: 1Gi transmission: image: lscr.io/linuxserver/transmission:4.1.1 port: 9091 username: username password: password resources: requests: cpu: 250m memory: 1Gi limits: cpu: 2 memory: 2Gi prowlarr: replicas: 1 image: ghcr.io/linuxserver/prowlarr:2.3.5 port: 9696 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2 memory: 2Gi radarr: image: ghcr.io/linuxserver/radarr:6.1.1 port: 7878 resources: requests: cpu: 10m memory: 50Mi overseerr: image: lscr.io/linuxserver/overseerr:1.35.0 port: 5055 replicas: 1 resources: requests: cpu: 10m memory: 50Mi sonarr: image: lscr.io/linuxserver/sonarr:4.0.17 port: 8989 resources: requests: cpu: 1 memory: 1Gi limits: cpu: 2 kavita: image: ghcr.io/linuxserver/kavita:0.9.0 port: 5000 replicas: 1 resources: requests: cpu: 100m memory: 500Mi ================================================ FILE: Helm/apps/n8n/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/n8n/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install n8n maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: n8n type: application version: 2.0.0 ================================================ FILE: Helm/apps/n8n/README.md ================================================ This chart is used to install n8n ================================================ FILE: Helm/apps/n8n/templates/deployment.yaml ================================================ --- {{- with .Values.n8n }} apiVersion: apps/v1 kind: Deployment metadata: name: n8n namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: n8n app.kubernetes.io/name: n8n spec: replicas: {{ .replicas }} strategy: rollingUpdate: maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/instance: n8n app.kubernetes.io/name: n8n template: metadata: labels: app.kubernetes.io/instance: n8n app.kubernetes.io/name: n8n spec: containers: - name: n8n image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL env: - name: N8N_BASIC_AUTH_ACTIVE value: "true" - name: N8N_BASIC_AUTH_USER valueFrom: secretKeyRef: name: app key: username - name: N8N_BASIC_AUTH_PASSWORD valueFrom: secretKeyRef: name: app key: password - name: DB_POSTGRESDB_HOST valueFrom: secretKeyRef: name: cluster-postgres-app key: host - name: DB_POSTGRESDB_DATABASE valueFrom: secretKeyRef: name: cluster-postgres-app key: dbname - name: DB_POSTGRESDB_PORT valueFrom: secretKeyRef: name: cluster-postgres-app key: port - name: DB_POSTGRESDB_USER valueFrom: secretKeyRef: name: cluster-postgres-app key: user - name: DB_POSTGRESDB_PASSWORD valueFrom: secretKeyRef: name: cluster-postgres-app key: password - name: DB_TYPE valueFrom: secretKeyRef: name: app key: type - name: N8N_PORT value: "{{ .port }}" - name: N8N_ENCRYPTION_KEY valueFrom: secretKeyRef: name: app key: encryption_key - name: N8N_PAYLOAD_SIZE_MAX valueFrom: secretKeyRef: name: app key: maxFileSizeMb {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data mountPath: /home/node - name: nas mountPath: /nas restartPolicy: Always volumes: - name: data persistentVolumeClaim: claimName: n8n-pvc - name: nas nfs: path: "{{ .nasPath }}" server: "{{ .nasIp }}" --- apiVersion: v1 kind: Service metadata: name: n8n namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: n8n app.kubernetes.io/name: n8n ports: - name: n8n protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/n8n/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: n8n-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Low-code automation gethomepage.dev/group: Automation gethomepage.dev/icon: n8n gethomepage.dev/name: N8N spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "n8n.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: n8n port: {{ .Values.n8n.port }} ================================================ FILE: Helm/apps/n8n/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: n8n-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.n8n.dataSize }} ================================================ FILE: Helm/apps/n8n/values.yaml ================================================ --- n8n: image: n8nio/n8n:2.19.2 dataSize: 10Gi port: 5678 replicas: 1 nasIp: 192.168.1.39 nasPath: /volume1/k3s resources: requests: cpu: 10m memory: 250Mi ================================================ FILE: Helm/apps/nodered/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/nodered/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install nodered maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: nodered type: application version: 3.0.0 ================================================ FILE: Helm/apps/nodered/README.md ================================================ This chart is used to install nodered ================================================ FILE: Helm/apps/nodered/templates/deployment.yaml ================================================ --- {{- with .Values.nodered }} apiVersion: apps/v1 kind: Deployment metadata: name: nodered namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: nodered app.kubernetes.io/name: nodered spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: nodered app.kubernetes.io/name: nodered template: metadata: annotations: backup.velero.io/backup-volumes: data-config labels: app.kubernetes.io/instance: nodered app.kubernetes.io/name: nodered spec: containers: - name: nodered image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data-config mountPath: /data - name: nas mountPath: /nas livenessProbe: periodSeconds: 60 tcpSocket: port: {{ .port }} startupProbe: initialDelaySeconds: 60 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: data-config persistentVolumeClaim: claimName: nodered-pvc - name: nas nfs: path: "/volume1/k3s" server: "192.168.1.39" --- apiVersion: v1 kind: Service metadata: name: nodered namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: nodered app.kubernetes.io/name: nodered ports: - name: nodered protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/nodered/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: nodered-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Low-code automation gethomepage.dev/group: Automation gethomepage.dev/icon: node-red gethomepage.dev/name: NodeRed spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "nodered.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: nodered port: {{ .Values.nodered.port }} ================================================ FILE: Helm/apps/nodered/templates/nodered-pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nodered-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.configSize }} ================================================ FILE: Helm/apps/nodered/values.yaml ================================================ --- nodered: image: nodered/node-red:3.1.15-16 port: 1880 resources: requests: cpu: 100m memory: 512Mi limits: memory: 2Gi storage: configSize: 5Gi ================================================ FILE: Helm/apps/openbooks/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/openbooks/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install openbooks maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: openbooks type: application version: 3.0.0 ================================================ FILE: Helm/apps/openbooks/README.md ================================================ This chart is used to install openbooks ================================================ FILE: Helm/apps/openbooks/templates/deployment.yaml ================================================ --- {{- with .Values.openbooks }} apiVersion: apps/v1 kind: Deployment metadata: name: openbooks namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: openbooks app.kubernetes.io/name: openbooks spec: strategy: rollingUpdate: maxUnavailable: 0 replicas: 1 selector: matchLabels: app.kubernetes.io/instance: openbooks app.kubernetes.io/name: openbooks template: metadata: labels: app.kubernetes.io/instance: openbooks app.kubernetes.io/name: openbooks spec: containers: - name: openbooks image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL privileged: false allowPrivilegeEscalation: false args: - --persist - -n stefan-g-home - -d /config {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: data-config mountPath: /config livenessProbe: failureThreshold: 2 initialDelaySeconds: 30 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} startupProbe: failureThreshold: 5 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} restartPolicy: Always volumes: - name: data-config persistentVolumeClaim: claimName: openbooks-pvc --- apiVersion: v1 kind: Service metadata: name: openbooks namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: openbooks app.kubernetes.io/name: openbooks ports: - name: openbooks protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/openbooks/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: openbooks-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: IRC Book Downloader gethomepage.dev/group: Media gethomepage.dev/icon: https://raw.githubusercontent.com/evan-buss/openbooks/master/server/app/public/favicon-32x32.png gethomepage.dev/name: OpenBooks spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "openbooks.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: openbooks port: {{ .Values.openbooks.port }} ================================================ FILE: Helm/apps/openbooks/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: openbooks-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.configSize }} ================================================ FILE: Helm/apps/openbooks/values.yaml ================================================ --- openbooks: image: ghcr.io/evan-buss/openbooks:4.5.0 port: 80 resources: requests: cpu: 10m memory: 256Mi storage: configSize: 1Gi ================================================ FILE: Helm/apps/reactiveresume/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/reactiveresume/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install reactiveresume maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: reactiveresume type: application version: 3.0.0 ================================================ FILE: Helm/apps/reactiveresume/README.md ================================================ This chart installs reactiveresume ================================================ FILE: Helm/apps/reactiveresume/templates/deployment.yaml ================================================ --- {{- with .Values.reactiveresume }} apiVersion: apps/v1 kind: Deployment metadata: name: reactiveresume namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: reactiveresume app.kubernetes.io/name: reactiveresume spec: replicas: 1 strategy: rollingUpdate: maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/instance: reactiveresume app.kubernetes.io/name: reactiveresume template: metadata: labels: app.kubernetes.io/instance: reactiveresume app.kubernetes.io/name: reactiveresume spec: containers: {{- with .api }} - name: api image: {{ .image }} securityContext: capabilities: drop: - ALL envFrom: - secretRef: name: app env: - name: PUBLIC_FLAG_DISABLE_SIGNUPS value: "true" - name: POSTGRES_HOST valueFrom: secretKeyRef: name: cluster-postgres-app key: host - name: POSTGRES_PORT valueFrom: secretKeyRef: name: cluster-postgres-app key: port - name: POSTGRES_DB valueFrom: secretKeyRef: name: cluster-postgres-app key: dbname - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: cluster-postgres-app key: password - name: POSTGRES_USER valueFrom: secretKeyRef: name: cluster-postgres-app key: user imagePullPolicy: IfNotPresent volumeMounts: - name: uploads mountPath: /app/server/dist/assets/uploads livenessProbe: initialDelaySeconds: 30 failureThreshold: 5 timeoutSeconds: 2 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 tcpSocket: port: {{ .port }} ports: - containerPort: {{ .port }} name: api protocol: TCP {{- end }} {{- with .frontend }} - name: frontend image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL env: - name: PUBLIC_FLAG_DISABLE_SIGNUPS value: "true" - name: PUBLIC_URL valueFrom: secretKeyRef: name: app key: PUBLIC_URL - name: PUBLIC_SERVER_URL valueFrom: secretKeyRef: name: app key: PUBLIC_SERVER_URL livenessProbe: initialDelaySeconds: 30 failureThreshold: 5 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} startupProbe: failureThreshold: 10 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} ports: - containerPort: {{ .port }} name: frontend protocol: TCP {{- end }} volumes: - name: uploads persistentVolumeClaim: claimName: reactiveresume-uploads-pvc --- apiVersion: v1 kind: Service metadata: name: reactiveresume namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: reactiveresume app.kubernetes.io/name: reactiveresume ports: - name: frontend protocol: TCP port: {{ .frontend.port }} - name: api protocol: TCP port: {{ .api.port }} {{- end }} ================================================ FILE: Helm/apps/reactiveresume/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reactiveresume-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Build your own CV gethomepage.dev/group: Personal gethomepage.dev/icon: https://raw.githubusercontent.com/AmruthPillai/Reactive-Resume/5513b909e79d2560b3ba313facb984d2457ef602/apps/artboard/public/favicon.svg gethomepage.dev/name: Reactive Resume spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "resume.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: reactiveresume port: 3000 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: reactiveresume-api-internal namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "resume-api.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: reactiveresume port: 3100 ================================================ FILE: Helm/apps/reactiveresume/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: reactiveresume-uploads-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.uploadSize }} ================================================ FILE: Helm/apps/reactiveresume/values.yaml ================================================ --- reactiveresume: api: image: amruthpillai/reactive-resume:server-3.6.18 port: 3100 frontendUrl: https://reactiveresume.sgenov.dev frontend: image: amruthpillai/reactive-resume:client-3.6.18 port: 3000 storage: uploadSize: 5Gi ================================================ FILE: Helm/apps/storage/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/storage/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install storage maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: storage type: application version: 2.0.0 ================================================ FILE: Helm/apps/storage/README.md ================================================ This chart is used to install syncthing and server emulator ================================================ FILE: Helm/apps/storage/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: syncthing-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: File synchronization gethomepage.dev/group: Storage gethomepage.dev/icon: syncthing gethomepage.dev/name: Syncthing spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "syncthing.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: syncthing port: {{ .Values.syncthing.port }} ================================================ FILE: Helm/apps/storage/templates/storage-pvc.yaml ================================================ {{- with .Values.syncthing }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: syncthing-config-pvc spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ $.Values.storage.syncthingConfigSize }} {{- end }} ================================================ FILE: Helm/apps/storage/templates/syncthing.yaml ================================================ --- {{- with .Values.syncthing }} apiVersion: apps/v1 kind: Deployment metadata: name: syncthing namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: syncthing app.kubernetes.io/name: syncthing spec: replicas: {{ .replicas }} strategy: rollingUpdate: maxUnavailable: 0 selector: matchLabels: app.kubernetes.io/instance: syncthing app.kubernetes.io/name: syncthing template: metadata: annotations: backup.velero.io/backup-volumes: app-config labels: app.kubernetes.io/instance: syncthing app.kubernetes.io/name: syncthing spec: containers: - name: syncthing image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL add: - CHOWN - SETGID - SETUID {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} - name: tcp containerPort: 22000 protocol: TCP - name: udp containerPort: 22000 protocol: UDP - name: udp2 containerPort: 21027 protocol: UDP volumeMounts: - name: app-config mountPath: /config - name: data-volume mountPath: /data restartPolicy: Always volumes: - name: app-config persistentVolumeClaim: claimName: syncthing-config-pvc - name: data-volume nfs: path: "/volume1/k3s/syncthing" server: {{ $.Values.storage.nasIp }} --- apiVersion: v1 kind: Service metadata: name: syncthing namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: syncthing app.kubernetes.io/name: syncthing ports: - name: syncthing protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/storage/values.yaml ================================================ --- syncthing: image: lscr.io/linuxserver/syncthing:2.0.16 replicas: 1 port: 8384 resources: requests: cpu: 10m memory: 50Mi storage: syncthingConfigSize: 1Gi nasIp: 192.168.1.39 ================================================ FILE: Helm/apps/uptimekuma/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/uptimekuma/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install uptimekuma maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: uptimekuma type: application version: 4.0.0 ================================================ FILE: Helm/apps/uptimekuma/README.md ================================================ This chart is used to install uptimekuma ================================================ FILE: Helm/apps/uptimekuma/templates/deployment.yaml ================================================ --- {{- with .Values.uptimekuma }} apiVersion: apps/v1 kind: Deployment metadata: name: uptimekuma namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: uptimekuma app.kubernetes.io/name: uptimekuma spec: replicas: {{ .replicas }} strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: uptimekuma app.kubernetes.io/name: uptimekuma template: metadata: annotations: backup.velero.io/backup-volumes: app-data labels: app.kubernetes.io/instance: uptimekuma app.kubernetes.io/name: uptimekuma spec: containers: - name: uptimekuma image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL add: - SETUID - SETGID {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} volumeMounts: - name: app-data mountPath: /app/data livenessProbe: failureThreshold: 5 tcpSocket: port: {{ .port }} startupProbe: failureThreshold: 5 initialDelaySeconds: 10 tcpSocket: port: {{ .port }} restartPolicy: Always volumes: - name: app-data persistentVolumeClaim: claimName: uptimekuma-pvc --- apiVersion: v1 kind: Service metadata: name: uptimekuma namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: uptimekuma app.kubernetes.io/name: uptimekuma ports: - name: uptimekuma protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/uptimekuma/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: uptimekuma-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Uptime Monitor gethomepage.dev/group: Monitoring gethomepage.dev/icon: uptime-kuma gethomepage.dev/name: Uptime Kuma spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "uptimekuma.sgenov.dev" - "uptime.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: uptimekuma port: {{ .Values.uptimekuma.port }} ================================================ FILE: Helm/apps/uptimekuma/templates/uptime-kuma-pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: uptimekuma-pvc spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: {{ .Values.storage.size }} ================================================ FILE: Helm/apps/uptimekuma/values.yaml ================================================ --- uptimekuma: image: louislam/uptime-kuma:1.23.17-debian replicas: 1 port: 3001 resources: requests: cpu: 10m memory: 512Mi storage: size: 10Gi ================================================ FILE: Helm/apps/vikunja/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/vikunja/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install vikunja maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: vikunja type: application version: 4.0.0 ================================================ FILE: Helm/apps/vikunja/README.md ================================================ This chart installs vikunja ================================================ FILE: Helm/apps/vikunja/templates/deployment.yaml ================================================ --- {{- with .Values.vikunja }} apiVersion: apps/v1 kind: Deployment metadata: name: vikunja namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: vikunja app.kubernetes.io/name: vikunja spec: replicas: 1 revisionHistoryLimit: 3 selector: matchLabels: app.kubernetes.io/instance: vikunja app.kubernetes.io/name: vikunja template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app.kubernetes.io/instance: vikunja app.kubernetes.io/name: vikunja name: vikunja spec: containers: - name: vikunja image: {{ .image }} securityContext: capabilities: drop: - ALL env: - name: VIKUNJA_SERVICE_FRONTENDURL value: "{{ .frontendUrl }}" - name: VIKUNJA_DATABASE_TYPE value: "postgres" - name: VIKUNJA_SERVICE_JWTSECRET valueFrom: secretKeyRef: name: app key: JWT_SECRET - name: VIKUNJA_MAILER_ENABLED value: "false" - name: VIKUNJA_DATABASE_HOST valueFrom: secretKeyRef: name: cluster-postgres-app key: host - name: VIKUNJA_DATABASE_USER valueFrom: secretKeyRef: name: cluster-postgres-app key: username - name: VIKUNJA_DATABASE_PASSWORD valueFrom: secretKeyRef: name: cluster-postgres-app key: password - name: VIKUNJA_DATABASE_DATABASE valueFrom: secretKeyRef: name: cluster-postgres-app key: dbname imagePullPolicy: IfNotPresent volumeMounts: - name: data mountPath: /app/vikunja/files livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 tcpSocket: port: {{ .port }} timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: {{ .port }} ports: - containerPort: {{ .port }} name: api protocol: TCP volumes: - name: data persistentVolumeClaim: claimName: vikunja-pvc --- apiVersion: v1 kind: Service metadata: name: vikunja namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: vikunja app.kubernetes.io/name: vikunja ports: - name: api protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/vikunja/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: vikunja-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Tasks gethomepage.dev/group: Knowledge gethomepage.dev/icon: vikunja gethomepage.dev/name: Vikunja spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "vikunja.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: vikunja port: {{ .Values.vikunja.port }} ================================================ FILE: Helm/apps/vikunja/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: vikunja-pvc namespace: {{ $.Release.Namespace }} spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.dataSize }} ================================================ FILE: Helm/apps/vikunja/values.yaml ================================================ --- vikunja: image: vikunja/vikunja:0.24.6 port: 3456 frontendUrl: https://vikunja.sgenov.dev storage: dataSize: 5Gi ================================================ FILE: Helm/apps/wallabag/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/wallabag/CHANGELOG.md ================================================ #### [v2.0.0] - Using Gateway API #### [v1.3.0] * Moved Env to simplesecret * Improved security #### [v1.2.1] * Added probes for wallabag so it will automatically fix itself if failed #### [v1.2.0] * Added ingress #### [V1.1.0] * Moved resources to values.yaml #### [V1.0.0] * Initial Deployment ================================================ FILE: Helm/apps/wallabag/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install wallabag maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: wallabag type: application version: 2.0.0 ================================================ FILE: Helm/apps/wallabag/README.md ================================================ This chart is used to install wallabag. ================================================ FILE: Helm/apps/wallabag/templates/database.yaml ================================================ --- {{- with .Values.postgres }} apiVersion: apps/v1 kind: Deployment metadata: name: postgres namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: postgres app.kubernetes.io/name: postgres spec: strategy: type: Recreate replicas: 1 selector: matchLabels: app.kubernetes.io/instance: postgres app.kubernetes.io/name: postgres template: metadata: annotations: backup.velero.io/backup-volumes: postgresql-data labels: app.kubernetes.io/instance: postgres app.kubernetes.io/name: postgres spec: securityContext: fsGroup: 999 containers: - name: postgresql image: {{ .image }} imagePullPolicy: IfNotPresent envFrom: - secretRef: name: db securityContext: runAsUser: 999 # postgres UID in the image runAsGroup: 999 allowPrivilegeEscalation: false privileged: false capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: db containerPort: {{ .port }} volumeMounts: - mountPath: /var/lib/postgresql/data subPath: data name: postgresql-data - name: shm-empty mountPath: /dev/shm livenessProbe: exec: command: - /bin/bash - -c - pg_isready - -U - $POSTGRES_USER - -d - $POSTGRES_DB failureThreshold: 2 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 2 startupProbe: exec: command: - /bin/bash - -c - pg_isready - -U - $POSTGRES_USER - -d - $POSTGRES_DB failureThreshold: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 2 restartPolicy: Always volumes: - name: postgresql-data persistentVolumeClaim: claimName: postgresql-pvc - name: shm-empty emptyDir: medium: Memory --- apiVersion: v1 kind: Service metadata: name: postgres namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: postgres app.kubernetes.io/name: postgres ports: - name: postgres protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/wallabag/templates/deployment.yaml ================================================ --- {{- with .Values.wallabag }} apiVersion: apps/v1 kind: Deployment metadata: name: wallabag namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: wallabag app.kubernetes.io/name: wallabag spec: replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: wallabag app.kubernetes.io/name: wallabag template: metadata: labels: app.kubernetes.io/instance: wallabag app.kubernetes.io/name: wallabag spec: restartPolicy: Always containers: - name: wallabag image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: privileged: false allowPrivilegeEscalation: false envFrom: - secretRef: name: app optional: false env: - name: PUID value: "1000" - name: GUID value: "1000" - name: SYMFONY__ENV__DOMAIN_NAME value: {{ .domainName }} {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} livenessProbe: failureThreshold: 10 initialDelaySeconds: 60 timeoutSeconds: 5 httpGet: port: {{ .port }} path: /login startupProbe: failureThreshold: 10 periodSeconds: 5 httpGet: port: {{ .port }} path: /login {{- end }} ================================================ FILE: Helm/apps/wallabag/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: wallabag-external namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "wallabag.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: wallabag port: {{ .Values.wallabag.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: wallabag-internal namespace: {{ $.Release.Namespace }} annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Self-Hosted Pocket gethomepage.dev/group: Knowledge gethomepage.dev/icon: wallabag gethomepage.dev/name: Wallabag spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "wallabag.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: wallabag port: {{ .Values.wallabag.port }} ================================================ FILE: Helm/apps/wallabag/templates/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: wallabag spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: wallabag app.kubernetes.io/name: wallabag ================================================ FILE: Helm/apps/wallabag/templates/service.yaml ================================================ --- {{- with .Values.wallabag }} apiVersion: v1 kind: Service metadata: name: wallabag namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: wallabag app.kubernetes.io/name: wallabag ports: - name: wallabag protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/wallabag/templates/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgresql-pvc labels: app.kubernetes.io/instance: postgres app.kubernetes.io/name: postgres app.kubernetes.io/component: database app.kubernetes.io/part-of: wallabag app.kubernetes.io/managed-by: helm spec: accessModes: - ReadWriteMany storageClassName: longhorn resources: requests: storage: {{ .Values.storage.postgresqlSize }} ================================================ FILE: Helm/apps/wallabag/values.yaml ================================================ --- wallabag: image: wallabag/wallabag:2.6.14 replicas: 1 port: 80 domainName: https://wallabag.sgenov.dev resources: requests: cpu: 100m memory: 500Mi postgres: image: postgres:16.13 port: 5432 resources: requests: cpu: 10m memory: 256Mi storage: postgresqlSize: 5Gi ================================================ FILE: Helm/apps/website/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: Helm/apps/website/CHANGELOG.md ================================================ #### [v4.0.0] - Using Gateway API #### [v3.0.0] - Better selectors - Better probes #### [V2.0.0] * Migrated to ghcr.io #### [V1.1.0] * Updated security #### [V1.0.0] * Initial Deployment ================================================ FILE: Helm/apps/website/Chart.yaml ================================================ --- apiVersion: v2 appVersion: 1.0.0 description: This chart is used to install website maintainers: - email: sgenov94@gmail.com name: Stefan Genov name: website type: application version: 4.0.0 ================================================ FILE: Helm/apps/website/README.md ================================================ This chart is used to install my personal website https://github.com/Michaelpalacce/personal-website-vue ================================================ FILE: Helm/apps/website/templates/deployment.yaml ================================================ --- {{- with .Values.website }} apiVersion: apps/v1 kind: Deployment metadata: name: website namespace: {{ $.Release.Namespace }} labels: app.kubernetes.io/instance: website app.kubernetes.io/name: website spec: replicas: {{ .replicas }} selector: matchLabels: app.kubernetes.io/instance: website app.kubernetes.io/name: website template: metadata: labels: app.kubernetes.io/instance: website app.kubernetes.io/name: website spec: restartPolicy: Always securityContext: fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch priorityClassName: critical-priority affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: website namespaces: - {{ $.Release.Namespace }} topologyKey: kubernetes.io/hostname weight: 1 containers: - name: website image: {{ .image }} imagePullPolicy: IfNotPresent securityContext: capabilities: drop: - ALL privileged: false allowPrivilegeEscalation: false {{- if .resources }} resources: {{ toYaml .resources | indent 22 }} {{- end }} ports: - name: web containerPort: {{ .port }} envFrom: - secretRef: name: website optional: false env: - name: CV_PATH value: "/cv/CV.pdf" volumeMounts: - name: cv mountPath: /cv livenessProbe: failureThreshold: 2 initialDelaySeconds: 10 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} startupProbe: failureThreshold: 5 timeoutSeconds: 2 httpGet: path: / port: {{ .port }} volumes: - name: cv nfs: path: "/volume1/k3s/CV" server: "192.168.1.39" {{- end }} ================================================ FILE: Helm/apps/website/templates/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: website-external namespace: {{ $.Release.Namespace }} spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: website port: {{ .Values.website.port }} --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: website-internal namespace: {{ $.Release.Namespace }} annotations: # nginx.ingress.kubernetes.io/proxy-body-size: "100m" gethomepage.dev/enabled: "true" gethomepage.dev/description: My Website gethomepage.dev/group: Personal gethomepage.dev/icon: https://sgenov.dev/favicon.ico gethomepage.dev/name: Website spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "sgenov.dev" - "website.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: website port: {{ .Values.website.port }} ================================================ FILE: Helm/apps/website/templates/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: website spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: website app.kubernetes.io/name: website ================================================ FILE: Helm/apps/website/templates/service.yaml ================================================ --- {{- with .Values.website }} apiVersion: v1 kind: Service metadata: name: website namespace: {{ $.Release.Namespace }} spec: selector: app.kubernetes.io/instance: website app.kubernetes.io/name: website ports: - name: website protocol: TCP port: {{ .port }} {{- end }} ================================================ FILE: Helm/apps/website/values.yaml ================================================ --- website: image: ghcr.io/michaelpalacce/website:v2.25.0 port: 80 replicas: 3 resources: requests: cpu: 500m memory: 512Mi ================================================ FILE: README.md ================================================ # Preface This repository contains basic HELM local charts for application installation as well as FluxCD2 HelmReleases for GitOps. I'm not going to move away from the local helm charts where possible as they make this repository pretty beginner-friendly. Also, big warning, this repo is things I've done on the side with time taken away from my family. # :open_book: Check out the Documentation * [Documentation](./docs) # Main tools used 1. **FluxCD 2** - GitOps for my HomeLab. 2. **Renovate** - Checks for updates to actions, helm charts, helm releases, docker containers. 3. **Istio + Gateway API** - Reverse proxy + SSL termination for services 4. **cert-manager + reflector** - cert-manager generates certificates for my services and reflector duplicates the generated ssl certificate secret to all the namespaces. The secret is called `ingress`. 5. **Longhorn** - K8S native storage. 6. **Ansible** - Used to provision the architecture 7. **Velero** - K8S and PVC backup. Free and open source by VMware 8. **MetalLB** - LoadBalancer for bare-metal k8s clusters 9. **tofu-controller** - Gitops for Terraform # GitOps :construction: GitOps is applied wherever possible using Flux2. CI/CD is done by bootstrapping flux into my cluster. Flux polls GitHub for changes and applies them automatically on my server. It is currently pretty stable. # Image updates Image updates are done via Renovate Bot :robot:. Renovate bot does periodic scans for new image versions and submits pull request for each change. # Accessing services ( istio, cert-manager ) Apps are currently exposed by Istio with Gateway API and have SSL certificates provided by cert-manager. A wildcard certificate is issued for my domain `*.sgenov.dev` and when the secret is created it is replicated in all namespace as `ingress` to be consumed by the ingress resources. This replication is needed because `Let's encrypt` rate limits certificate requests. ## :desktop_computer: Exposing Apps As a legacy approach I used to expose my apps via NodePort. This ability is removed but can be easily enabled by removing the commented out nodePort values in the Helm Charts, and I also try to add this functionality to future apps and services I install. # Control Plane Load Balancing I use DNS load balancing for the control plane. This is done by creating an A record for the control plane and pointing it to the IPs of the control plane nodes. This is done because I don't have a load balancer in my homelab and I don't want to expose the control plane on a single node. # Storage ( Longhorn ) Longhorn is a great replicated storage option with a great UI for better visualisation. It's fast and tailor made for k8s. Developed by the same people responsible for k3s/rancher and other great tools. [Official site](https://longhorn.io/) # Backup ( Velero ) Velero allows me to back up selected namespaces and ( with the help of restic ) ship the data to different sources. In my case I'm using the velero AWS plugin. The velero backup runs on a schedule every day during the evening hours and I pay around ~ $7 each month, mainly due to Wasabi pricing for 1TB as a minimum. Check the docs for more information about velero, but overall I try to backup everything. # Infrastructure as code `tofu-controller` is a tool by the team behind FluxCD2 and allows me to continuously reconcile a git repo and apply changes when a change or drift is detected. I'm not handling VM creation yet, as that has proven to be a nuisance with the Terraform provider. Security is the main focus of this. # What if I don't want to use Flux Well it's absolutely fine. You can go to `Helm/apps` and install any app you want ( e.g. `helm install media media -n media --create-namespace` ). However things like ingress, cert-management, longhorn are handled only via Flux. Information on the helm chart that is used can be found in the `helm-release.yaml` for the specific service. Let's look at an example: ~~~yaml --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: longhorn-system # What to call the deployment namespace: longhorn-system # Where to install the helm chart spec: interval: 10m # How often do we poll for changes install: createNamespace: true # Same as --create-namespace chart: spec: chart: longhorn # Which chart to use version: 1.2.4 # Which version of the chart interval: 10m # Where to find information for this chart ( in my case I have a HelmRepository defined in cluster/homelab/helm/longhorn-system sourceRef: kind: HelmRepository name: longhorn-system namespace: flux-system # Overwriting some values values: ingress: enabled: true host: longhorn.sgenov.dev ingressClassName: nginx tls: true tlsSecret: ingress service: ui: type: NodePort nodePort: 30030 ~~~ This would be the same as: 1. Creating a new file with the content: `values.yaml`: ~~~yaml ingress: enabled: true host: longhorn.sgenov.dev ingressClassName: nginx tls: true tlsSecret: ingress service: ui: type: NodePort nodePort: 30030 ~~~ 2. Running: `helm repo add longhorn https://charts.longhorn.io; helm repo update` to add the longhorn helm repo 3. Running: `helm install longhorn/longhorn --name longhorn --create-namespace -n longhorn-system -f values.yaml` ================================================ FILE: TODOS.md ================================================ # TODOs ## Fixes - [ ] Fix paperless-ngx redis:latest... broadcom... ## Security - [ ] Network Policies For External Services ## Infrastructure - [ ] Strip down the K3S Nodes of unused services and packages ## Service Specifics ## Upgrades - [ ] Migrate to newest postgresql - [ ] postgresql instances should be a statefulset ================================================ FILE: ansible/hosts/group_vars/master/k3s-config.yaml ================================================ --- k3s_control_node: true k3s_server: node-ip: "{{ ansible_default_ipv4.address }}" kubelet-arg: - "image-gc-high-threshold=75" - "image-gc-low-threshold=60" tls-san: - "{{ k3s_registration_address }}" docker: false disable: - traefik - local-storage - servicelb disable-network-policy: false disable-cloud-controller: true write-kubeconfig-mode: "644" cluster-cidr: "10.40.0.0/16" service-cidr: "10.96.0.0/16" etcd-expose-metrics: true ================================================ FILE: ansible/hosts/group_vars/workers/k3s-config.yaml ================================================ --- k3s_control_node: false k3s_agent: node-ip: "{{ ansible_default_ipv4.address }}" kubelet-arg: - "image-gc-high-threshold=75" - "image-gc-low-threshold=60" ================================================ FILE: ansible/hosts/inventory ================================================ [master] 192.168.1.78 192.168.1.83 192.168.1.242 [workers] 192.168.1.55 192.168.1.89 192.168.1.247 192.168.1.79 [extra] # 192.168.1.20 # 192.168.1.42 # 192.168.1.22 # This group has all the servers [all:children] master workers extra #Variables for all the servers [all:vars] ansible_connection=ssh ansible_user=stefan ansible_ssh_common_args='-o StrictHostKeyChecking=no' ================================================ FILE: ansible/playbooks/install/files/allContainerLogs ================================================ /var/logs/containers/*.log { rotate 2 copytruncate missingok notifempty compress maxsize 10M dateext dateformat -%Y%m%d-%s create 0644 root root } ================================================ FILE: ansible/playbooks/install/files/cleanUpOrphanedPods.py ================================================ import subprocess import select import re import shutil f = subprocess.Popen(['tail', '-F', '/var/log/syslog'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) p = select.poll() p.register(f.stdout) while True: if p.poll(1): line = f.stdout.readline().decode('utf-8') result = re.search('orphaned pod \\\\"([0-9a-zA-Z-]*)\\\\"', line) if result: toDelete = '/var/lib/kubelet/pods/' + result.group(1) try: shutil.rmtree(toDelete) print(toDelete + " was deleted") except: print(toDelete + " could not be deleted") ================================================ FILE: ansible/playbooks/install/files/cniLogs ================================================ /var/logs/calico/cni/*.log { rotate 2 copytruncate missingok notifempty compress maxsize 10M dateext dateformat -%Y%m%d-%s create 0644 root root } ================================================ FILE: ansible/playbooks/install/files/multipath.conf ================================================ blacklist { devnode "^sd[a-z0-9]+" } ================================================ FILE: ansible/playbooks/install/files/podLogs ================================================ /var/logs/pods/*/*/*.log { rotate 2 copytruncate missingok notifempty compress maxsize 10M dateext dateformat -%Y%m%d-%s create 0644 root root } ================================================ FILE: ansible/playbooks/install/main.yml ================================================ --- - hosts: all name: Setup sudoers gather_facts: false become: true tags: - preflight - preflight-sudoers vars_files: - "./vars/main.yml" tasks: - name: Show current Ansible user debug: var: ansible_user - name: Enable passwordless sudo for user copy: dest: "/etc/sudoers.d/10-{{ ansible_user }}" content: "{{ ansible_user }} ALL=(ALL) NOPASSWD:ALL" owner: root group: root mode: "0440" - hosts: all name: Setup Logs and log sizes gather_facts: false become: true tags: - preflight - preflight-logs vars_files: - "./vars/main.yml" tasks: - name: Logrotate copy: dest: "{{ item.dest }}" src: "{{ item.src }}" with_items: - dest: /etc/logrotate.d/allContainerLogs src: allContainerLogs - dest: /etc/logrotate.d/cniLogs src: cniLogs - dest: /etc/logrotate.d/podLogs src: podLogs - name: Check if logrotate is daily stat: path=/etc/cron.daily/logrotate register: logrotate_stat - name: Move logrotate to hourly if daily command: mv /etc/cron.daily/logrotate /etc/cron.hourly/logrotate when: logrotate_stat.stat.exists - name: Ensure persistent journal is enabled lineinfile: path: /etc/systemd/journald.conf regexp: "^#?SystemMaxUse=" line: "SystemMaxUse={{ journalctl_vaccum_size }}" state: present notify: restart systemd-journald - name: Reload systemd-journald configuration command: systemctl daemon-reload handlers: - name: restart systemd-journald service: name: systemd-journald state: restarted - hosts: all name: Setup limits gather_facts: false become: true tags: - preflight - preflight-limits vars_files: - "./vars/main.yml" tasks: - name: Set soft nofile limit for all users lineinfile: path: /etc/security/limits.conf insertafter: EOF line: "* soft nofile 65535" state: present - name: Set hard nofile limit for all users lineinfile: path: /etc/security/limits.conf insertafter: EOF line: "* hard nofile 65535" state: present - name: Ensure pam_limits is enabled lineinfile: path: /etc/pam.d/common-session regexp: "^#?session required pam_limits.so" line: "session required pam_limits.so" state: present - name: Reload the limits configuration shell: ulimit -n 65535 - hosts: all name: Setup Storage dependencies become: true gather_facts: false tags: - preflight - preflight-storage-dependencies vars_files: - "./vars/main.yml" tasks: - name: Ensure dependencies are installed apt: name: "{{ packages }}" state: present vars: packages: - open-iscsi - nfs-common - jq - hosts: - master - workers become: true any_errors_fatal: true tags: - setup - setup-k3s vars_files: - "./vars/main.yml" roles: - xanmanning.k3s - hosts: master name: Setup master k3s and fetch config become: true tags: - setup - setup-init-master vars_files: - "./vars/main.yml" tasks: - name: Setup k3s shell: "{{ item }}" with_items: - mkdir -p ~/.kube - cp /etc/rancher/k3s/k3s.yaml ~/.kube/config - name: Copy output to local files fetch: src: "{{ item.src }}" dest: "{{ item.dest }}" flat: true with_items: - src: /etc/rancher/k3s/k3s.yaml dest: "{{ output_dir }}/config" - name: Fix Config URL hosts: localhost connection: local gather_facts: false become: true tags: - setup - setup-fix-kubeconfig vars_files: - "./vars/main.yml" tasks: - replace: path: ./output/config regexp: "127.0.0.1" replace: "{{ k3s_registration_address }}" backup: true - hosts: all name: Fix Multipath become: true tags: - setup - setup-multipath tasks: - name: Make sure multipath conf file is missing file: path: /etc/multipath.conf state: absent - name: Copy Multipath File copy: src: ./files/multipath.conf dest: /etc/multipath.conf - name: Restart multipath service systemd: state: restarted name: multipathd - hosts: all name: Load Kernel Modules become: true tags: - setup - setup-kernel tasks: - name: Enable kernel modules now community.general.modprobe: name: "{{ item }}" state: present loop: [br_netfilter, ip_vs, ip_vs_rr] - name: Enable kernel modules on boot ansible.builtin.copy: mode: 0644 dest: "/etc/modules-load.d/{{ item }}.conf" content: "{{ item }}" loop: [br_netfilter, ip_vs, ip_vs_rr, dm_crypt] - hosts: all become: true tags: - unattended_upgrades systemctl roles: - role: hifis.toolkit.unattended_upgrades unattended_automatic_reboot: true - hosts: all become: true tags: - qemu tasks: - name: Install qemu-guest-agent apt: name: "{{ packages }}" state: present vars: packages: - qemu-guest-agent - name: Start and enable qemu-guest-agent systemd_service: name: qemu-guest-agent enabled: true state: started ================================================ FILE: ansible/playbooks/install/requirements.yml ================================================ --- collections: - name: kubernetes.core version: 6.3.0 - name: community.general version: 12.5.0 - name: hifis.toolkit version: 6.3.2 roles: - src: xanmanning.k3s ================================================ FILE: ansible/playbooks/install/vars/main.yml ================================================ --- arch: amd64 # architecture output_dir: ./output # Where to output files generated by the playbook journalctl_vaccum_size: 200M # After what size should journalctl logs be cleaned up k3s_release_version: "v1.34.1+k3s1" k3s_install_hard_links: true # For system-upgrader k3s_become: true k3s_debug: false k3s_etcd_datastore: true k3s_use_unsupported_config: true k3s_registration_address: 192.168.1.78 # Master node ip ================================================ FILE: cluster/homelab/age.agekey.public ================================================ age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn ================================================ FILE: cluster/homelab/apps/adminer/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: adminer labels: app.kubernetes.io/instance: adminer app.kubernetes.io/name: adminer spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: adminer app.kubernetes.io/name: adminer template: metadata: labels: app.kubernetes.io/instance: adminer app.kubernetes.io/name: adminer spec: containers: - name: adminer image: adminer:latest imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 resources: requests: cpu: 100m memory: 100Mi limits: cpu: 200m memory: 200Mi ================================================ FILE: cluster/homelab/apps/adminer/gateway-api.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: adminer-internal spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "adminer.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: adminer port: 80 ================================================ FILE: cluster/homelab/apps/adminer/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: adminer resources: - namespace.yaml - deployment.yaml - service.yaml - gateway-api.yaml ================================================ FILE: cluster/homelab/apps/adminer/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: adminer ================================================ FILE: cluster/homelab/apps/adminer/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: adminer spec: selector: app.kubernetes.io/instance: adminer app.kubernetes.io/name: adminer ports: - name: http protocol: TCP port: 80 targetPort: http ================================================ FILE: cluster/homelab/apps/bentopdf/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: bentopdf labels: app.kubernetes.io/instance: bentopdf app.kubernetes.io/name: bentopdf spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: bentopdf app.kubernetes.io/name: bentopdf template: metadata: labels: app.kubernetes.io/instance: bentopdf app.kubernetes.io/name: bentopdf spec: restartPolicy: Always containers: - name: bentopdf image: ghcr.io/alam00000/bentopdf:2.8.4 imagePullPolicy: IfNotPresent resources: limits: cpu: 512m memory: 512Mi ports: - name: web containerPort: 8080 securityContext: capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 tcpSocket: port: 8080 timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: 8080 ================================================ FILE: cluster/homelab/apps/bentopdf/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: bentopdf-internal annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: PDF Tools gethomepage.dev/group: Tools gethomepage.dev/icon: https://bentopdf.sgenov.dev/favicon.ico gethomepage.dev/name: BentoPDF spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "bentopdf.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: bentopdf port: 8080 ================================================ FILE: cluster/homelab/apps/bentopdf/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: bentopdf resources: - namespace.yaml - deployment.yaml - service.yaml - gateway-api.yaml ================================================ FILE: cluster/homelab/apps/bentopdf/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: bentopdf ================================================ FILE: cluster/homelab/apps/bentopdf/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: bentopdf spec: selector: app.kubernetes.io/instance: bentopdf app.kubernetes.io/name: bentopdf ports: - name: web protocol: TCP port: 8080 ================================================ FILE: cluster/homelab/apps/cert-manager/issuer.yaml ================================================ --- apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt namespace: cert-manager spec: acme: email: stefantigro@gmail.com server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: issuer-account-key solvers: - dns01: cloudflare: email: stefantigro@gmail.com apiTokenSecretRef: name: cloudflare key: apikey --- apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-staging namespace: cert-manager spec: acme: email: stefantigro@gmail.com server: https://acme-staging-v02.api.letsencrypt.org/directory privateKeySecretRef: name: issuer-account-key solvers: - dns01: cloudflare: email: stefantigro@gmail.com apiTokenSecretRef: name: cloudflare key: apikey ================================================ FILE: cluster/homelab/apps/cert-manager/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - issuer.yaml - wildcard-certificate.yaml ================================================ FILE: cluster/homelab/apps/cert-manager/wildcard-certificate.yaml ================================================ --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: ingress namespace: cert-manager spec: secretTemplate: annotations: reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" reflector.v1.k8s.emberstack.com/reflection-allowed: "true" secretName: ingress issuerRef: name: letsencrypt kind: ClusterIssuer commonName: "*.sgenov.dev" dnsNames: - "*.sgenov.dev" --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: adygenova-cert namespace: cert-manager spec: secretTemplate: annotations: reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" reflector.v1.k8s.emberstack.com/reflection-allowed: "true" secretName: adygenova-cert issuerRef: name: letsencrypt kind: ClusterIssuer commonName: "*.adygenova.com" dnsNames: - "*.adygenova.com" --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: replacedby-cert namespace: cert-manager spec: secretTemplate: annotations: reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true" reflector.v1.k8s.emberstack.com/reflection-allowed: "true" secretName: replacedby-cert issuerRef: name: letsencrypt kind: ClusterIssuer commonName: "*.replacedby.net" dnsNames: - "*.replacedby.net" ================================================ FILE: cluster/homelab/apps/changedetection/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: changedetection namespace: changedetection spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/changedetection reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: image: dgtlmoon/changedetection.io:0.55.3 ================================================ FILE: cluster/homelab/apps/changedetection/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/changedetection/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: changedetection ================================================ FILE: cluster/homelab/apps/cyberchef/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cyberchef namespace: cyberchef spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/cyberchef reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: cyberchef: image: mpepping/cyberchef:v10.24.0 ================================================ FILE: cluster/homelab/apps/cyberchef/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/cyberchef/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: cyberchef ================================================ FILE: cluster/homelab/apps/diagrams/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: diagrams namespace: diagrams spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/diagrams reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/diagrams/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/diagrams/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: diagrams ================================================ FILE: cluster/homelab/apps/firefly/cnpg.yaml ================================================ apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgres annotations: backup.velero.io/backup-volumes: pgdata spec: instances: 1 imageName: ghcr.io/cloudnative-pg/postgresql:18.1 storage: size: 10Gi podSecurityContext: runAsNonRoot: true securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL add: - NET_BIND_SERVICE - CHOWN - FOWNER privileged: false readOnlyRootFilesystem: true runAsNonRoot: true ================================================ FILE: cluster/homelab/apps/firefly/gateway-api.sensitive.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: firefly-internal annotations: gethomepage.dev/enabled: ENC[AES256_GCM,data:t+20kQ==,iv:p8Opyq1QUKUvAKSyU+qD1uUEoMBqXtlNJoajE2acRUo=,tag:Ue6njGAknFa4urpgXZnPmg==,type:str] gethomepage.dev/description: ENC[AES256_GCM,data:q/XSINQkdZQZWwduDQ==,iv:LGHKlrlyZxMy00Q/KSz3L54bMsxG4DLpIDUMKBqcY9s=,tag:XpwDkSMfKedBQ69DiqK2aQ==,type:str] gethomepage.dev/group: ENC[AES256_GCM,data:O75eHVHlgMs=,iv:5fdD2j9bKz3yh/qSE6El42LOg+XxFd9mdyMxu/H7B+o=,tag:ix2dZV5lVIgUDj192vCY2w==,type:str] gethomepage.dev/icon: ENC[AES256_GCM,data:178Nv5PrxA==,iv:l91hn6pM+xLZtCsKREP2davQ66mjXyDVyXsUMkOR/a0=,tag:2YXL3dUuAuyqh/A0qMHERg==,type:str] gethomepage.dev/name: ENC[AES256_GCM,data:ZUZi6zDny0vMSOc=,iv:9TtR1NcZ4osTVvJGQCK45fTD6W/WjPyycyPrD+tIPkY=,tag:uPJFwM2D0PcK3nJ0azTKuw==,type:str] gethomepage.dev/widget.type: ENC[AES256_GCM,data:Ms3+Oq/frQ==,iv:jSuKAhhGw1J8iseGw4fR2ZTCjvxFWLAfK7zwY/l+RQo=,tag:vO+KfSAYJZSPUVuYBB+oMQ==,type:str] gethomepage.dev/widget.url: ENC[AES256_GCM,data:xqqZ1Uz+xeB129mlwLMwPJv+8PU3kanHBg==,iv:WTcVvoYbwTRmxI+DgRn4QiL3Mpwjsx+OuW5v7B+XYM4=,tag:Y/04+cnaltjOyKVWCMqAWQ==,type:str] gethomepage.dev/widget.key: ENC[AES256_GCM,data:aQQ34DvJ3RHXbvnVMANchlXl68t1PMNlGpPP2jtrfFI23bOf972aQFqhcx7UHIPZxPmoEte25qkx8WbAxu1M0/rSBhUJ6SUsAzDEkak+pOdF68XnMEEr83uzmijrO0KJRawV4uyBDtaOW3EAOxGtbEUmi7F9EuqoNbR1n7UhCD2bcJL5A62E6XzoDAqDmgjWyhEV3R7thP8zzwvwDY8AFSMcS9WTMagGfqOh9ymCFpPrf4ESJDYukp0DUCMsd96u+xgDiTfZJVQ2vl32ixYVyWb8R4eOJFe3CYvw9LWB5XoWfds5AcCcVAyPOcim+6k3YCyXR3hKoW/ePhQl88YNXcpkoG8MU8Yg014EJhuvIHodWc1PLY0veNaGT0gJUU+nESOyqDqFFn/lcIAiG+KVDqAEjWmjYh1XRWCjG52Y3f9I3Lc8bjmoO8Y3eC35GY8mPjO0bNxL5/X1VHMogv260NINTLJMX1vBD4eQZ4V9dg9jqX1rs7HIdZmKsKsd7cCfI/BTx+S3Cd46nJFogpzmczm89kUvfwD4VZKnH0paHW0qD0sWgFUuN+pUAEl/0HmkNsjS9uYXD+e1fveoptP/RfQaWWSGzX78XZ8TYMzSQs5YV3vCOXrqFYgAJi9b7iSDWeVc1Q8lZ0bipOrJAzO7gKAfNoQ2dIx/+gduE4FZjug2SE1+pBfo7UEDneWT8mFtHAipgL4gg1do/ppmZ5CvXJ6dg996gDYaGsxprj6YRJVZR1DABrZfqomOEd8XlfTIhl55Dg57uWg0Cea+H9dK8m61NaqoES8EJ2Q74SWuPjjEBXoVhtltSm80f43FJT7f5mVIoE0bztiYMCWTr6Y3cqf1TdfBVT2vl0Omltqc6Q50C8bPzai0q1r0a51YDSzundSrOWxoKRilkn5cWEUTSonnjzwWrla0VMIwvbGLS5yYKP6s+CKFavEktCcq37o4x6Qa0wPmXeIQnHfVCzACy/vrTlrjwqbrwLj2dX3T5jdRtjtyOVj+pQYiOSVv3eYT2sqGnM7JT7CMD0sEtKii1W2pGWaXNtqLRhl8hZAAxN6lsBSMGjI27Gegdn5g77FecKOvg04/VtQySvREFKYqkzgR+dSsMxuZPXYJrxucOD0OqXJTl948FLznfl1NFKUoUFAz8EzuEkcbEweIanP6vRXGfAnFI5w3ecuClr/OIZN5B7cbffXAwIrVKUJuqySYwYmvyxaoWhgcCNVToL4Hf4NzTHrtf4OgvaCZmTjkZhlj+T7pKuVsBXHTlPFqSKKRv3w1TtsvdxBL+PfQAHWtbn2rRs6c4dpr,iv:qPV5l7n6VRzT9qmHIcERaLbwqFF7uvJKE61XriktbUU=,tag:FId4jYC6/ee1eOmrLFaz/Q==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRSVVWWE9CaFk3RncxTUpW UEkxblNraVlMdjVodzFiNzJ1K012TzhZNUY4CjVLSVVpbGhuRWFVcEdQV3QwSjgr MXlySHZNanlXMmF6TmMwSXQ5V2JaR3MKLS0tIDQzMUVNeDdjZk44anBzYTBNakUy OU5OV3FCOG9oUmkxanFOb1ROR2ZhMTAKAWjRBhvleX72BbS01DeDX+cQzE2U5lAd UmBCmNE6S5R4gP7cWO1WDSNRjYEGT0XMv5zr3whX2U2QQJvsxqCTeA== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-19T21:02:02Z" mac: ENC[AES256_GCM,data:DKD3lc5HNFyuUynHzwO6nco+jCovKuSdu7andnOi/atznqSQAPAGfdUswG81ZqP3vBEhBFnnbHBZZTpGe+PP+NKvTrhzAEQQ/R4UvUJ2KouDPYGTKL86I4suiq/xx3JezTnF7H32Tfer80UeaCLX37zeyTYaQ1eiU3Lfu9J/3cg=,iv:hxd1k9BVsQx39h6yHm/PdUTxzL4BVW2HIFrhfoEcYmU=,tag:pWUVZt9RQimRgyRlNxyvug==,type:str] encrypted_regex: ^(rules|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/firefly/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: firefly spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/firefly reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/firefly/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: firefly resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml - gateway-api.sensitive.yaml - cnpg.yaml ================================================ FILE: cluster/homelab/apps/firefly/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: firefly ================================================ FILE: cluster/homelab/apps/firefly/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: bot-env data: BOT_TOKEN: ENC[AES256_GCM,data:xuvnXdR1NZweB+BfkqWze92Vw81b2A055f7a7WszRyjVqm+GaPnDTr42XauyphIgbxbzhq26CZ6eDhFus75K0Q==,iv:5EOSLAZvQH4NfbY9pP5rExuB1i8YRomZk5BV3cZ0xGw=,tag:Un5a/PKYvGmTol0ISYNQog==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkR1hQTk9pWFZMYlQzKzNG WnlMcGYxZEhNOTB2TnEzOFhxTVY4SDhubVZBCmN6c1BLbmYxTU1zUHJOMTlIeDU2 T2tuT0M3ZXlxSW5pWTRtOUdBYjZlUFEKLS0tIFVBT3F4a1RwejJpdE9uWENLWWxE UHZSNFUzQ1ZvN3Q1ODJEWmRJMHRhNkUKI3gsgABTCJo6KKiimfT7W7xOFzwnjUwR 33TH2eoZhjsEKCnjiLfp7VES+DQXwNOyaH08BHhQx1zBvZZDDW9XGA== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-19T21:02:34Z" mac: ENC[AES256_GCM,data:xLm9Mks2x8EH9CT8PHiNG8RVpe7LdtplZKoWqzeYKNgrGckAyDgY1E65N8Y3rMAN9lDOGlfp3xzBHQOeEKwQzgiN29uJaa1QV8AGb73Osg54fEys0hy1o0FftGKnL9IzoU7i77tF2zrPdqY8zpd7CCS7kL+7dn1p1aWqoxW+wWQ=,iv:b7/We1YriVr1X0bsHq0Xfz3YJ+jT3pp35TcTDU7r79w=,tag:Xp9MmUCZgoheyPW3wsMadg==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 --- kind: Secret apiVersion: v1 type: Opaque metadata: name: app data: key: ENC[AES256_GCM,data:2SIGAGsK/RSNQcu3UR58bwKpc9cK7sJXOh2yMlZxNhOWuQSpCEBMT8N4tic=,iv:owyv8n8511tLV6C30N+Nj3RrwOaLvIgK+vYE9pf1YZc=,tag:bopeYUOEajH0C/LSGm+bKQ==,type:str] API_KEY: ENC[AES256_GCM,data:PtcrOqfl6stqDpsTham9hSX5vcJlHu4v7Px7Ko9hR16gCgHuWk+nSk2kud8J60FgtqLOQ6G23YBssQ3TEEPduHLv+XifafDX0TYjHh61+LSiQzpPpdyWGX5tqcULMKBBR+sUafTIBH9eUCj99LCe69P22rcI70b+sMte/dk3IGjCvswdObCLZeODodHghYscnGCDlxvWuh4Q8H8NZj8waALQ8DcudOA9+1dEZyfMT3vRK6+dyW1c1WC1lhI6ylhw81FcXVOs8Wju9vMNHQZ1JMdyNgbeFTiP9DhjALPyJBt8huUGhblzJw9N9Gefrd4u/X51pdgY66JT+Ny87cbeQMiHVDz6fclh9wc9GdM7dWbIUQjQq3ZsSb1bYZPnH1e0ggndUBptxjuGJcRLS/uhVKMTYjkb8V5UgMo9EFPAGQZv7uyffnP0Ztd/EUhCEoU2O1ctdmJ2aPbpd2Ig/QTcKKVec0dyhJ5LG+x3cOMGtxu15ROsb/LG8zDYVAwmRPy1+jc6equFxp50IJWQ0ZxmnMARVZPhLnap/ndyt6dOwefOGKnj9jw4lp01UUzEvwSA+jhFt57h6QLvSeGEM69L9P+HBYsOBqTwDE+nDvPbSKRgeRc7oR9A2RoNZElxVe1UMb1DwTyBXSoxgIWvzBgkTaHgS+G5lncEkIbtAxl7WvvZ3sN6UCE9n3WA373UPMA6CecIgmD+CkoAGOY9UqmGZ1SQXNlRbgPQEolk+WS/j237YwV4PwBNQNZ6EpYFmGZ6yQ7jurgAIwCOu0lpbzBs6MuUAbdbriMZWYyWK89ogp3vXYY9ymM6bwasy0DlYmlCz5IuKepruP+vN8nj+HhbA5i9ODZIiq+sA2L8h97hOovqL6JEQuLWOIC0WUesgFTcAZgpn6IyT8BKQNxNR6s4n07Y2B1bA+kdLx/tB+/A/utWRGJrs9gZayYAlJfJFMRPJQr3+I+YaZbX+UTuEJM/dVY/C8QsxWdSowQMkYyBisw8IHlIMYRcC34VtPWOB0o43Cy4Soc9YAwdMJPJWaLidoxDELfQ858fV/zmVYzeE79pCLRenzsjmH9arrn2q+Ok1VqqC63Qmlvxbu8Qw1JDBuvYbCbsjfIPQs8jeizf2psEl2hbyO+ZKclW6jnxvhRXwQLK7NA7y9cGBFunQi7uad0zscwQ8etNhYbBjrlVklb4saW2zwj7KL1E1o5hdUb2V4UtaIhYayY83sQiASeLLLfHTzGcYR0sZf4GQNXZ88sSO/fCvJGTCUoSCeiIGEyPCeTTXrLQyWZ4Jf/jmeaMd8n1nUk/L8NNGqaEnLgacjxxC+PJ7FGfsw4mlrOhlNkEmhvbTt7U6WJ1JICjV8ePin1Qb6tz6aIHtPOTWQCFirdZ2LFFwJhR1Et5cGvjrmaLtCNL1dNVPruAnLfDh81TRV0mIOvb6lw89wRM8OqDjRVMJ3KCSshC1aDOOEi5wZLBNzwtkOvzJdZvwtsLYWHYa50pE6fV9IFe5v62i2R5mbdUPsglhPJjwsQpZjoBUC4ktWpLjbFOe8+27dpSEzBm+Ht8KrcZvvRjIl2ERgtrhjoOrdwZZ/h87qDDoU8dyqVBAQJjkVFBKnXEcOkftvdTd2+XvdlZEejq1eqwOmpMBpvC1KK1d+bK6qbZXGgmdXxyy0NRuUftXB/kb24qCWqg1ev5Qu1wayHdEvWG4T4WWCHCKD15iTK9tAQd2ymnGjE+2nlQLvuATgZLxLMI,iv:4r3cUqQtQam0l5SUgtDUgSpdY1Rd8kbqNU9oclSMHl4=,tag:iM4TNQTpzgpsQkkc++YVGg==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkR1hQTk9pWFZMYlQzKzNG WnlMcGYxZEhNOTB2TnEzOFhxTVY4SDhubVZBCmN6c1BLbmYxTU1zUHJOMTlIeDU2 T2tuT0M3ZXlxSW5pWTRtOUdBYjZlUFEKLS0tIFVBT3F4a1RwejJpdE9uWENLWWxE UHZSNFUzQ1ZvN3Q1ODJEWmRJMHRhNkUKI3gsgABTCJo6KKiimfT7W7xOFzwnjUwR 33TH2eoZhjsEKCnjiLfp7VES+DQXwNOyaH08BHhQx1zBvZZDDW9XGA== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-19T21:02:34Z" mac: ENC[AES256_GCM,data:xLm9Mks2x8EH9CT8PHiNG8RVpe7LdtplZKoWqzeYKNgrGckAyDgY1E65N8Y3rMAN9lDOGlfp3xzBHQOeEKwQzgiN29uJaa1QV8AGb73Osg54fEys0hy1o0FftGKnL9IzoU7i77tF2zrPdqY8zpd7CCS7kL+7dn1p1aWqoxW+wWQ=,iv:b7/We1YriVr1X0bsHq0Xfz3YJ+jT3pp35TcTDU7r79w=,tag:Xp9MmUCZgoheyPW3wsMadg==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/foldingathome/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: foldingathome namespace: foldingathome spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/foldingathome reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/foldingathome/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml - helm-release.yaml - secret.sops.yaml ================================================ FILE: cluster/homelab/apps/foldingathome/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: foldingathome ================================================ FILE: cluster/homelab/apps/foldingathome/secret.sops.yaml ================================================ apiVersion: v1 kind: Secret type: Opaque metadata: name: app namespace: foldingathome data: ACCOUNT_TOKEN: ENC[AES256_GCM,data:LcKIHKwY1R5a8caYEKOuWQqdQ5Eind01SB7JQ++u7aiZzMGKbnh10d5LKj7MuNYYtAgravRRX72i+RlE,iv:QHRc+xJOtsDXAgGNKKD7boYK58tubA9k52uItz7y1cQ=,tag:uLZOK1mAaRzRK/pnI+oIJg==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5aXJGYTRXQ0FWSTFIbzdM ckJvbTlsbUkzMHRxNFhZRG1ZTjcrb2VTMlZRCldrZVMvaGdBa0psZTN3cEJIYUdo MTVYMEl2bTNLUXIwQ3cxSlByWnRMejgKLS0tIERQOHBDUlN4c1AvbmxiaTlvVkJl L2E4aHBKdWNzODFFVmZ5SWRCSTZLUUUKmNROIHloB2wL/WV2ef+4Zccjrxoq6AOr 2oZav4A65XSSWkx7rOCJb+M9L017I0l3C4yLXup3fK5fTM0sC6oMNw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-14T10:03:19Z" mac: ENC[AES256_GCM,data:QAKqLDW8xT/M3IgXAZM5K5unKn+0VwVPwtmHzh9+oTPqjosPrq+6jFLLMhxIPtMyafM1bz+2hfzQ2V7+atpT4ZZc7pj/iRgG4Q+uu7cpIZ1bnwzG8+yancJfJoRywL3a9CG3YBP0K7JMYqU9/WkOkGIZMe+7ENxoeYr0c6phsrM=,iv:YzRQxBzMEngdrGzaBodP16KNnf4xtd1bjhK4+nLUTk0=,tag:EEG53rEB1VUYvU7DEWThcw==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/freshrss/cnpg.yaml ================================================ apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgres annotations: backup.velero.io/backup-volumes: pgdata spec: instances: 1 imageName: ghcr.io/cloudnative-pg/postgresql:18.1 storage: size: 10Gi podSecurityContext: runAsNonRoot: true securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL add: - NET_BIND_SERVICE - CHOWN - FOWNER privileged: false readOnlyRootFilesystem: true runAsNonRoot: true ================================================ FILE: cluster/homelab/apps/freshrss/gateway-api.sops.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: freshrss-internal annotations: gethomepage.dev/enabled: ENC[AES256_GCM,data:gCd/qg==,iv:PrIwNYNYihjU1sxKguhm4Of2EJ5RV+rFXm7c7C9lPCo=,tag:quSplKJRnCtYMgaJQckoaA==,type:str] gethomepage.dev/description: ENC[AES256_GCM,data:rxXU1oRTZiLDnA==,iv:qoKeesKlrezQ1hqNmKeumpZuWFJPBp9Vk8CEne/gRJs=,tag:vyLyCia/wUgF2Oakm+APdA==,type:str] gethomepage.dev/group: ENC[AES256_GCM,data:sidRrC3PVkr9,iv:U+8XzY0udoXlr2L/DT/QtzVCSk+YgCoA9jvHUw8elDQ=,tag:84+WOUIXdhTB9KvCH/QPzA==,type:str] gethomepage.dev/icon: ENC[AES256_GCM,data:8S0y5kyMb9I=,iv:3xptRnbFzc1+cyYKS/MQcP+CN8becz2F5zvXC6mPCuc=,tag:4+qbmrqZ8BmvENX9ZuxToA==,type:str] gethomepage.dev/name: ENC[AES256_GCM,data:YmFMnEQpOrLQ,iv:AiwUeoeqoXdfTLGjRzYkPzMITN2bX+RJ4PsDd0zl8uk=,tag:EPR16Pr7fFAUwMqj0iokeg==,type:str] gethomepage.dev/widget.type: ENC[AES256_GCM,data:bXt+imc9Hjo=,iv:nltD3/EI1UGaHN3P7VUkIVyWC3jGybGsN/4IWirEWAM=,tag:t+jwIrzlMMRso3hd6s4O6A==,type:str] gethomepage.dev/widget.url: ENC[AES256_GCM,data:KFnW5e895Wt29jBPdqJVrrM/VdevCyfoNx5Z,iv:3yr7y+GvAutZY0N8eOmQE2ioXIVEKWn/cLVU2Yl4qKw=,tag:xBfMUIjB0CJl9cMTU2Snsw==,type:str] gethomepage.dev/widget.username: ENC[AES256_GCM,data:V9bKaz6Q,iv:Xdnft/QvqqM++LO5GSOGiUc6wQ1TMfO5AnDAmGbsE0o=,tag:c8hofYDlKUja/NRY1HMbGw==,type:str] gethomepage.dev/widget.password: ENC[AES256_GCM,data:yMhsd5gilYq0kAxsgGADfPPJ3A==,iv:NRram8s+gVjelwuM0CGI1mOHnO3r7sepop5BPeHEUYg=,tag:i9xqK4Vpoc/nN6NcDS1/RA==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArL0VRWkF2YmtVQU1JaXBT YlRrOUMyRVJoVkIxMTNUT0Q1dkd6cnV5VlhrCkl2U0VqZW9aZnlqeExpanEra09R MmpOVGVpQW00czVTTENrVGt1TXJta0kKLS0tIGtrUHg1ekVqczJoNWp6NEVVTWFM S3JjZ3Evc3MwbzQreGp4S0pkSnlMSm8K0q8CXCy/wrUXoZeC6aA90D/n36JDaXda cZrooeCRbadIFwWGV+fyvpcN/WKCLupSlJ4IOhDn62zZzBOx6Nb6Pg== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-19T17:43:05Z" mac: ENC[AES256_GCM,data:l4q97MmKjDtpMv0VIOB2p71FjlQ8iYk5aKQVyG2UohySS6EUsYWomajZLyrotX1EtX9dwN9XQgMhA0JAC0TYOfQ6wf6bfa203++Z0Z3L00Ba0fEQjEQuFmdtkMglochuYZyRxyP/YPppdCRX6CZnNZsf6FXTzBTfKHKQC6fX6Bo=,iv:Wox9C2HYSsq3J+JTCZ3rVWCSqJ9mOHte9ldpsmG2qcQ=,tag:fTGHRcvoggHiEbAYaDrFDA==,type:str] encrypted_regex: ^(rules|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/freshrss/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: freshrss spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/freshrss reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/freshrss/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: freshrss resources: - namespace.yaml - helm-release.yaml - gateway-api.sops.yaml - cnpg.yaml ================================================ FILE: cluster/homelab/apps/freshrss/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: freshrss ================================================ FILE: cluster/homelab/apps/garden/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: garden labels: app.kubernetes.io/instance: garden app.kubernetes.io/name: garden spec: replicas: 3 selector: matchLabels: app.kubernetes.io/instance: garden app.kubernetes.io/name: garden template: metadata: labels: app.kubernetes.io/instance: garden app.kubernetes.io/name: garden spec: restartPolicy: Always priorityClassName: critical-priority affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/instance: garden app.kubernetes.io/name: garden topologyKey: kubernetes.io/hostname weight: 1 containers: - name: garden image: ghcr.io/michaelpalacce/garden:v4.1.1769964525 imagePullPolicy: IfNotPresent resources: # Initial run requires a few more resources limits: cpu: 500m memory: 51Mi ports: - name: web containerPort: 80 securityContext: capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" livenessProbe: failureThreshold: 10 initialDelaySeconds: 10 tcpSocket: port: 80 timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: 80 ================================================ FILE: cluster/homelab/apps/garden/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: garden-external spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "garden.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: garden port: 80 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: garden-internal annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Personal Gaden / Second Brain / Blog gethomepage.dev/group: Personal gethomepage.dev/name: Garden spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "garden.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: garden port: 80 ================================================ FILE: cluster/homelab/apps/garden/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: garden resources: - namespace.yaml - deployment.yaml - service.yaml - gateway-api.yaml - pdb.yaml ================================================ FILE: cluster/homelab/apps/garden/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: garden ================================================ FILE: cluster/homelab/apps/garden/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: garden spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: garden app.kubernetes.io/name: garden ================================================ FILE: cluster/homelab/apps/garden/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: garden spec: selector: app.kubernetes.io/instance: garden app.kubernetes.io/name: garden ports: - name: garden protocol: TCP port: 80 ================================================ FILE: cluster/homelab/apps/go-ddns-controller/configMaps.sops.yaml ================================================ kind: ConfigMap apiVersion: v1 metadata: name: cloudflare-config namespace: go-ddns-controller-system data: config: ENC[AES256_GCM,data:ByjuPiSK+tPXtb+UqYPt/BNh0JX6MkOzEFpxKH3ujW0gqLECWvwSqUflV5ovB3g26E5GoWSi5ni3ZGwfZ1nLffj6ITZ3qPm8oEpT/BygRct6PS0l7CBP5NeHQLYhrZYydOZ5t0lTwBp1XiQO194O2HY2KmMiNDReG4cS1zIhDBWXK3dgce5Uw/LEHC9+Kuh0u99cRuHr64xWrE6aCFKOr9Za2BMk7Gd0oMTUVQ3HLltWYMo9nT7ioNoVcLSdblwPVmC+hui+fWKUKm8Ty0xPNOVCStdYo7MdeiCC3s8yr1wuju4cnp37NixRCsN9f62atJ9cLbw69cYNNln+vFP5mkgUTwndxAXt6iERBhe+xpAZRCIhrCH3rAkGehNCZOwNvoDIYnAOjNBtY4i8CeP5FIIrWKoJmWTvC1dy/CJ6hPkFBTs7H0D38+jatFaij0HgI/+nfeJWa+3RvtlfwMTnSYTrbqqdiD6LEhLeHednJfZAgZdrnc5RYhEHgNbEqZdEQfxl0UfKeu8YC7xgXThWUVDbxuaVdEk533LW2RGobymcAIsNjk1gDFA9w8opAbg8z/ax/HdEQJd5COLGbeCXRkS+8cgY7SxXsAgpuUbS5XSZhWtcsr8HubwV4FkyTg8nTe1WPxIpl6llCTzDjPOCN5iCFbDDtdi9JMn5ysDMkRAx71Axj6+cSjRFT5mVCczyb2IZbec/0IKN17sYcRf3ZaXGS3J18QUkgIolhBK/myazTCNjuAEYo13UP9UmF9fLV0HfKadOHRe9iymGcTYfrpP4BiQRa9c/5TbyyqnbUfUUVwj7TCcBHDzqs8qQwuLhE7iuxGQtHYFbTJrt6G3uvoL+bXRHfxcArwoJT5aW6I7DgvmFsNSemtPrVTDTNXMcuJ7ULPJhrGXEVNgDyDNml3r0jZAZNiE6SwvMoofw+Vt3HvboRcPfqUBu5K0z7tKTUQM38Y3AD7sb0xlIws/xXEmmD31lBC7hzySROmHciZHMfX6nHT54Ne66/jp48cpf8gsW1eaeg6cG9FMwE2HqqPtkAWp+c9JHKa3dPYgvzU+FIE3v7BUPM6F3FoL/bq8sCONF4QH8TF9LyIeScUVEZToKy6tmEGbT6oHokRXQSf9mc3ZUEzVsaWzkTkn2XlzDfmuYdgecvFLqy7cQj0TKi8Tn1+PduuUolpB1wPMyuKniYc6/YEb1BR//F51EburURGITW4gTVclEvfDXjucUySzAe+tahQJVoBfq5M/wOVZgxOgT60mil06cVj78jIPNkeYbH57n5sPZHdGIwZZBAdhL5c0CHre9kOUpxNtYlNlFNsjyI16rQ/kS1YykgIY6AmBHwqqb39FKeDl/EisCNrLMDbVBfu0O7HmJAM78xxRscXGjZwVsr0JmGeNjS8Ndb3VcaSJTOkPE38f0C0Y5Z2rSkMDfYMHt7HDzQ4BD8cvFN3hZVIy+EoGLHOxleh4gtQvuS8TpbfDrNg94UwwY0KWgSZJ/ZTc0QdqAIq1+D3mSuWXd+Tq3IYX9aLdry7LtXDrA1LOuAZI44uFsP4Vv1ogMbXWqzCsnhaKoL+zbGUbTmsS7TEwK7aElKzzfvW/9miFNwQqtYqCvzuzHkhLtHN8mdznbQ6acpcg3pEyDlToMH1cAQ0Ma3wwk45R64Y6AJASs,iv:c+YDZfQnJqdEmVJo8ocfmz9qSAUGJIiCgR6rrPhkDlM=,tag:0/e2HSxSwQxMdi+2Dyx9rw==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwbVAxOU9EekpINmVDbmg4 aGM4aGlpbkVzNVp3akFwdGtCVllvbzNVOFNzCmVmUG85OTBiMFY3b05kNzFrd0kv UWJNLzlpWmQ5enNBa1dHVXo3dTdQZk0KLS0tIHVoWTF1cm1oUXRhRWZiQmtqYnc1 WU50WnI0K0oyeDJTek9JY2ozZVR6aHcKhO6jXhMH04+g97aVYqGhpNW/0aMnfP84 F9ibzn8HSYA4pzaMth16BhE6SSXZzGq8wYiyOYRasawS6EfaaT+LuA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-24T17:08:07Z" mac: ENC[AES256_GCM,data:A4V58CbIin6h7K87gu8d5XFrhgE1+VNkGsbZw73Ok080Vd4jp1qInuBL47SIwO+KK9bne50GeAi5ECtnn+qmBRV24s4oEn1qblj5WAjarpim/Uj4171yj0i7GoHkhy43cSXF4tKl5DS6kCQHK0UlFJCgCkCnLcK7NqgdEVV+gaU=,iv:0RFXBrK6hnAcUONyTypZ/gSzhu2f1LsMVXV6xTdkd38=,tag:oKfvTpmjdznBV8V5xiMdYg==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 --- kind: ConfigMap apiVersion: v1 metadata: name: webhook-config namespace: go-ddns-controller-system data: config: "" sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwbVAxOU9EekpINmVDbmg4 aGM4aGlpbkVzNVp3akFwdGtCVllvbzNVOFNzCmVmUG85OTBiMFY3b05kNzFrd0kv UWJNLzlpWmQ5enNBa1dHVXo3dTdQZk0KLS0tIHVoWTF1cm1oUXRhRWZiQmtqYnc1 WU50WnI0K0oyeDJTek9JY2ozZVR6aHcKhO6jXhMH04+g97aVYqGhpNW/0aMnfP84 F9ibzn8HSYA4pzaMth16BhE6SSXZzGq8wYiyOYRasawS6EfaaT+LuA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-24T17:08:07Z" mac: ENC[AES256_GCM,data:A4V58CbIin6h7K87gu8d5XFrhgE1+VNkGsbZw73Ok080Vd4jp1qInuBL47SIwO+KK9bne50GeAi5ECtnn+qmBRV24s4oEn1qblj5WAjarpim/Uj4171yj0i7GoHkhy43cSXF4tKl5DS6kCQHK0UlFJCgCkCnLcK7NqgdEVV+gaU=,iv:0RFXBrK6hnAcUONyTypZ/gSzhu2f1LsMVXV6xTdkd38=,tag:oKfvTpmjdznBV8V5xiMdYg==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/go-ddns-controller/git-repo-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: go-ddns-controller namespace: go-ddns-controller-system spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: ./charts/go-ddns-controller reconcileStrategy: Revision sourceRef: kind: GitRepository name: go-ddns-controller namespace: flux-system values: image: repository: ghcr.io/michaelpalacce/go-ddns-controller tag: v1.1.3 controller: replicas: 3 resources: limits: cpu: 100m memory: 512Mi requests: cpu: 10m memory: 64Mi ================================================ FILE: cluster/homelab/apps/go-ddns-controller/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: go-ddns-controller-system resources: - namespace.yaml - git-repo-release.yaml - secret.sops.yaml - configMaps.sops.yaml - notifier.yaml - provider.yaml ================================================ FILE: cluster/homelab/apps/go-ddns-controller/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: go-ddns-controller-system ================================================ FILE: cluster/homelab/apps/go-ddns-controller/notifier.yaml ================================================ apiVersion: ddns.stefangenov.site/v1alpha1 kind: Notifier metadata: labels: app.kubernetes.io/name: go-ddns-controller app.kubernetes.io/managed-by: kustomize name: webhook-notifier namespace: go-ddns-controller-system spec: name: Webhook secretName: webhook configMap: webhook-config ================================================ FILE: cluster/homelab/apps/go-ddns-controller/provider.yaml ================================================ apiVersion: ddns.stefangenov.site/v1alpha1 kind: Provider metadata: labels: app.kubernetes.io/name: go-ddns-controller app.kubernetes.io/managed-by: kustomize name: cloudflare-provider namespace: go-ddns-controller-system spec: name: Cloudflare secretName: cloudflare configMap: cloudflare-config notifierRefs: - name: webhook-notifier ================================================ FILE: cluster/homelab/apps/go-ddns-controller/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: webhook namespace: go-ddns-controller-system stringData: url: https://discord.com/api/webhooks/1175178233185046619/nHQnEuID5QxLD2uqRatDpyT0TD9GhBJfAOQS548S6HW2hrCMyQw0P6smN34-dB9WVdY2 --- kind: Secret apiVersion: v1 type: Opaque metadata: name: cloudflare namespace: go-ddns-controller-system stringData: apiToken: i6goSPMYlroTEdJoPhn2VyjPSxiInQg1hh-UpNOL ================================================ FILE: cluster/homelab/apps/gotenberg/helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: gotenberg namespace: gotenberg spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: gotenberg version: 1.21.0 interval: 10m sourceRef: kind: HelmRepository name: maikumori namespace: flux-system values: image: repository: gotenberg/gotenberg tag: 8.32.0 ================================================ FILE: cluster/homelab/apps/gotenberg/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml - helm-release.yaml ================================================ FILE: cluster/homelab/apps/gotenberg/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: gotenberg ================================================ FILE: cluster/homelab/apps/homebox/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: homebox namespace: homebox spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: ./Helm/apps/homebox reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/homebox/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/homebox/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: homebox ================================================ FILE: cluster/homelab/apps/homepage/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: homepage-internal namespace: homepage spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "homepage.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: homepage port: 3000 ================================================ FILE: cluster/homelab/apps/homepage/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: homepage namespace: homepage spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: homepage version: 2.1.0 interval: 10m sourceRef: kind: HelmRepository name: homepage namespace: flux-system values: image: repository: ghcr.io/gethomepage/homepage tag: v1.12.3 # Enable RBAC. RBAC is necessary to use Kubernetes integration enableRbac: true serviceAccount: # Specify a different service account name name: homepage # Create service account. Needed when RBAC is enabled. create: true service: main: ports: http: port: 3000 controller: strategy: RollingUpdate rollingUpdate: maxSurge: 25% maxUnavailable: 25% # Enable the ingress to expose Homepage to the network. ingress: main: enabled: false # All the config files for Homepage can be specified under their relevant config block. config: # To use an existing ConfigMap uncomment this line and specify the name useExistingConfigMap: homepage-config persistence: logs: enabled: true type: emptyDir mountPath: /app/config/logs env: - name: HOMEPAGE_ALLOWED_HOSTS # This value must be set # ref: https://gethomepage.dev/installation/#homepage_allowed_hosts value: homepage.sgenov.dev # resources: # requests: # memory: 10Mi # cpu: 10m # limits: # memory: 200Mi # cpu: 500m ================================================ FILE: cluster/homelab/apps/homepage/homepage-config.sops.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: homepage-config namespace: homepage data: kubernetes.yaml: ENC[AES256_GCM,data:mBALaNiFgQE3ZplU8GbWaelfUUIbE3x3dzEmqw==,iv:BBF8cTL0h2J8bC1GiCVP/SKkEhg6gU1FsSesqQxtPLc=,tag:SYWPS5po3G8G8roc8YqYHQ==,type:str] settings.yaml: ENC[AES256_GCM,data:gizV0E2Z3BDVpXXw/m2xcdqb4bkxpdE0y/p5FkjdRzwh7KFWchRhqelLvEZCYzGXsArSK2qm9Ts19RIZ0XHTDrdvN1+FnEupQKm13pvMRe0MDqVAv2+WNOvQ5+jFVxMjQcdRetF4xfx/Qk66xFh0Y9FbufgH5eLrCTKeoM9m5L8L7wcgToWOk/iGlAqG3cfGmSSx7MnmkwEw8smARCPRqCu++P8Shke/WC2ssI8H+faKhCUDoYrPrnwdT77kzR7z5YktdmBDq0D6nJSD2VIrk5wdQ2hJEecl6/bYv8l5UdH60d/H2+ic4/9TlYdH9SqZAE8a4DPR7qQavbognRbraikWWSv24YV/U+BhMQb/bPy0Snzt7DmtdrRutgAIvPZtg20Rmbyj6r8hWiVJ4bBn2OoGP7YLrCgGWIDtE3jQFSFp8XXkZfShxkxXK65efRRYo3LgjVGPokNvDzGPU6vgkZnNV3uTgvIy5OxB0wlpKR6jMVPCfdugQPKeod4bBFgtx9ut9/m+rDas8gxdlyRFyLIStY6+zLVh28Fj+UPb5++WCW7h3fFavAETwKqxLTeQCz4oYVu1+G0InXXQxx2w0/PHGKGMDd8V8eLsS2brf5+ucqU9xWbKE9ywAgYIcFjS+XPATUxyMOrL1014rPKeWbZ4I3W1aA8LPemFmo+IfsO8Rn7OilV7LkYRrRBvVY3fMbRVjVqzpCnfpZ+jOIc++l9VUdynRl/9rTFJwiE5yoU+UxUlRa3pG2bejuPV2m1KFMspZE451OXVv8blkY0MDQp21xx4o5WAi0XLBamX/GGGwpHnPHxL8r6l194=,iv:yiwZ+MzaBOqAtJicwyeOThNBOvgo5Au8SQv4/nbhrP4=,tag:RxjtSq2Ir6EZh2H+Ajqi1g==,type:str] bookmarks.yaml: ENC[AES256_GCM,data:ync13dJ+NIiLPX18exnzaaFW4Ff5dbC7v2PmWalXevunnPM7OI43/V4HPgqu2XEHXe2fS6M5AYUVyngLRiJ40GI/+xfL2PXRr/QCxt0xU1REcjZCEl63CQiZysGIDclVX+EEGY0yWTTNsaI4MxTOW5ioYen0znT6F+vx7E0IjkoGARpfxE9yLfxI2rr1NeLiufVEcfX1mo1gfHyFiTEUKT0T6P88iKMKFRowTm1Ra6wAwMlhGoxc1ufKUn2dOHpYAmCFiy6vZTXeHn42YttvBEMhINsBRE4ZFVzDm+jMLwQoeVLevkLqCMligGV+0WFUdqfqrxMH26+eGEyTH+Yrd9vGKLztUM5H2uqbOSAec+AyTxSBd70ISabYyIsaaANZufIGMC/XsTRz0+hCLq2xFTR1LR2/Rc1IUOIWD8xf/YxADyBjgcRhQF6032naXrdaeFcVqu9vjRtoCAlgpENFJw==,iv:gw9AgZgimjkE3ZLXXugM+L0od6HykTtNjwTk8NGkcK4=,tag:V0IA1i+QVkKVbmWh/Rx+qA==,type:str] services.yaml: ENC[AES256_GCM,data:86Wok2ueEIvi0j6xV3JRN+65uuoQcQWmRvKORi3CKGGbNrgpfszCu6hdkHHEB+c8yTZnrbylII5MGfifWX+H24ZUTZXGM3IzbbaWRfvqn3BWbbYrnUfLnqVYP4ZGOCYtr3FfUPwbRj3R0bZAzq1BKy5nKtVEf94Ot7L5yabu4/h5vKumy2Mg6oTAfcwqJ/GB/2WqCmUu+zSXg4Crb4VPbowFyh2+fN82CA3xvmtYPdEgP0joieVsoarV4yAHfAWMvMGoMlHZq+wJXMKAdaxZm5velvw2zFKh6WCl3OXe5OdbYsJ7QJJDUJb/QqZ7W0xLQuwnP+/g+P0j3gKiSKATdDlCsnIgMoi5dOjsSrWMFnMkfYG6NN5JRXaKUOqvcMuNvZP4QqTrpKIukORXi5Mlrimk+ZAroEel+ZrMmi41mrK0E29T6ZZJA000rvkAu6Bf+hbss/UET3FqJcMbgAf/rlSBwGbsBBag1doUEUlElDZDb+QawtitsekF4DCZb2hw8m8y/cr6qtpWbrCbjQ2nLOnG9DdAS2lv5l+thmbmr/9MgiN5lcIj7aP6DP2QwCfIGrRNXFGoUJkICAjpDqaP5KVhtk5VgORZ87ZQQzA0VeF67Yb5d1IpCVvtUFCYQssUD+Ow45vOTjgbQEJRi9diqieGSDzdAdkHvN5YE0UqmiipEiSMP6WTyCuag41JZtaKyP+vD3pLabhI/UY3jGHuNCBL+2dxxgSLI2B2iVopFXtHqdX53uL/U7ycWi/GLVCWyaatKj5CszNeTVnJJ3oUejmwUzsgOpvMsdpbv94A18wmVS/kB/YushewwALkF0qnJz4rfBzumr8a/kazHssdBaqu73zGAeMfLxbGQ1eY8UasBNhkwgT20l8MB/8YhqFZwDpTS3804c1ILs6krgGu+R0WvFKzjGQ55LoKxDBRVrr8wQruouP8VQjLq+9IIg2Vz0iOZwUoGHrdaHRLXVrksuP4pJJIduRYhWeef5MGtBj5VsSN285ehFoywKnP7ZuqqX6h4jAEHahJRtFZ42q2ivRSF3WOfjW7f6ujfp9atlQ54ZVYU/4L1M7vOwthVgF/Ynsw3Cf7Ahu5httz5uTKiipGh8oiMmjlqwesb/vyMP0ehtY1z9uJDRzgaNIbgKcGs5eJwCuG/X4rU/2c2FUEKd7NSc5ckMkNyJU3Lk3kySJCJsTYmDy+CXuo0foJV/7bxekrr/1QphDN6+JVEeqsA57zI2lxnik3W1la1YgbuwfGJ0o2EVZZTpOHHgaNH/YQ/gWYAkZlITEFAroR6UVaYSL+iZeYH2g/IUaPL5lXTnmKa15gyeiX0FTCnFzJzkLzYzuMuWNagnXzr1OYNOnn4YLhV5DquAlBZxXBdIKYRX6gDzWHIzoqF85OYUTkKipWp37KR8FE1pQomPaIuoC+oaUG+H5+Ex7cCin6RMAsr6uu4NIAWlQlpl/Z8CqT3Rm4EUScGv6C+v3gcHh09dIIDYNGyqpIBRBed+kGRI1TnB19ii68FFetbIQ3D7r5L/Gs9LvN57NDr9LnmV/kB6D3bcIgopYb3qFzvtv33fnWs/SxCZDmYQ8KgLUt06NKuSk+p3Joipgma2z9B+mHAxbgJ6b9K4leRabSSBOGp5Ye5HdpdlrtZBTSu3j204SVgyhqR+hqNsdTxpajTCHVfw3yKqRd7IYcgHWdVECEFevWlgo1tq4zyEbwjprbNCGzBBYlLU2z+2E7/mLZpNhTGHblPBEqGxAMJF2l2FFkr4rtcxDRTEprMawRYV67sHN5smgUhrkMsQCTyb/c4zLZUL2CMrYZVVny7bjjx34DiSzrGex1GfAPjEOJ5e8hGG7qg0cQqGcg5s92mEHXw1crg6ITrB4WIs2Fq8BD7m/swokbF+p/YlEsU0W9mmHjh/Ib5tOS/bhYN7mlY3ZcUBAwcd+JSz6AyXp9+BJf5H9GQCWe3qE98mS3+MZeu77BmpMnidozSnFiUd46UVw=,iv:pSUJPZTjVHBwUXIkBOn0tD8L9WWjO22JxG56SEiQoRI=,tag:UejsdYL0BqKziAjf+wPv7g==,type:str] widgets.yaml: ENC[AES256_GCM,data:V0SXnKIrqHizOI4ZcUOnE69fqLurqxKLgQ6/r/ldnhbE18PJQT3hMfEuV9FG3K1nSlv0zkWczSWTQEd2hevt6/+oXKLf82JJ/B1CoaeIkxkUDIKYFo4C0vlmwmblSHYL/uP6IJzf7D+kfXshbEcYubfzqGPnp3YXY11MwgrHMIUnspdml0GsygxHgtSODeM3rTKwacF5desH4GH371+s2XnJ39iuAbUNU70Op0qs4eF7cDqagGyhMlVD9jxZ3wfSFadFva2VcX8qz0GpBdZjNNElavz95JNVdT+NXvSbXbxbmDM0NUI8SbtRW8cKSwJW4z/urO3r0wbhP0TdPrDfDP6yXZCd8HzDPXmKnt3UdK9LQ8kDZKBQiRuhC8UGS6s84D7GMJRvSZajDT5pWSCTfltVK8O0rbS6zNpVp1anwYJf9Ec+vAH1eGBsN0Cbqak38vm5Dyp5vlfcvMF2rhes8xghFwsP0DDe4Gz36mBMH7JMOMS7Lw0XrREHFBGSykB8g176Py6WTSqzWA95OMLcC3udxMeArf4ItdAiBhYkd1+P4l+kgyWPQlcu1MOwJrHxbdqjKWN96p0tQ0NSWFpz5V7aNmVWSmGUasK3gmnvyeDCBfjXW5e8/VMZLjMn0lI/c6MVcOiOVDwlT0kkVVIX1mSeg+T2T+uaT+IB73UZNZyK45LWBt11yjl1LMsuUbBQyZrAu2+MPeWxfk1akJspiC8uaPib1sjAvTr2efjzjvCwoscYdVwHsoCIRJmOwW2Ij21czlLNlHvUPCNcLc0TwNVHo7zX/XhBA126PboTNXYE38l8EWAYTLrGikm0HZXcUnGnv2IxJdFYpGYIIJfp13g2VJigRTI//AEL/oV8Ca0ohEEHxbAjXFgLmO8FZecqom6pcqfo/B0ksY5fd3srFgvZHKLFiDBcAFpqL9+7HGPyuddQGXLDoODkJwohhKXoO/7F7FXgUa0X2RQPrOLO3r9+wAqM+aqL6DVmzx0gRdAJmY7CCsclzlT8jb7VyB8Ok287fE9kLhQ/mSJgn0jmbZ6Eo6UX6AbvNUTYM+yXRF9jkKDVjdXT2RDNNEcfpDzo2i3w05XXHx4azq6eF0pp24BoY1bpMsuFAIDIL8p/j+x444BDlq2I/YjitGjYeT25/M9d1Rtk+BrLZQzKbIZeaKGCkLMgzaQUyk3ONp4VtjuxFz1ZtxHZvoIDyfhG7qdNRmrBgRczFMIaRpOu7uKd+nAOuD2Xz8mpNk9SjFyG/cntketSYsl+DtXyTGXXBZKr+df52TyJo2F7YMXVY3WRkk217s0zigwxQqUb+LK0++JN6fvQ0iTqAiFFztSsIkiDCbPZK30A1Jr8canmgKW3NEhqhEnjmiMAugGQkphixEM3pTRVmpIydnLx3jzqOnwQ2hJBgPGf48GQub5A4VlrvmpKs9e/JRrouDEwKpS8rG+IYycrmAOFI91D3YwJW8zPnVvMC+Po0q9OMPdJYsbDnTbPA1VE/+6c+iRmSM33e196tSGSUO2cgcPpel6Fe0rHzxLq6u/H2fW1vg==,iv:kxNQUSSQsZgvBi7dDFE87I3msWHoXdss3QySzMABW/k=,tag:JQcn+FkkIeGy+ZneapreUw==,type:str] docker.yaml: "" sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzRk5DeUNab0F4QThlYnJ1 OGRDRkVRQTdTNWZKbnBNWVNoSCtuT2dBOG5NCmVzVlR5VWF3aUxQREZ2ZGtZVmha NzFscExCbFg5eXNnRG1kVWF4S25vcDAKLS0tIG4zVjMzTG43K1dMc2V1V3EzTmJE bGdpbDdPQk9ZTWZOOWNPOTJTeFBsWHcKdnvn4//LIMPtpU7QsPxe+Ui457PV5mam AUr8KWITUXCWwwzD3S4kHedWuSP84cKhIwb7dZNH2ArpIaDfJvLZrQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-02T07:58:59Z" mac: ENC[AES256_GCM,data:rprg+YNFIuU+97n6hpzJdGSN4skmTAyb6vNGTsGPeeO7hAeexswXqHFIdYpkOqaSpDNQoaI3I8sBLD7nGf38d2hV3A940Bs41OO6JUsKvu7JpiR78XzUCTCcXqtI+SR+dS4k4WG8m7s4BXTbAbIdQHf0DdjZgM4eOxQbQwKuhYE=,iv:lmjKnae4IurmaNgGQIX9wG6jcxbA51BS/Be85KU/N98=,tag:Z9epc5M8OUoksEuvtZhJhQ==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/homepage/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml - homepage-config.sops.yaml - helm-release.yaml - gateway-api.yaml ================================================ FILE: cluster/homelab/apps/homepage/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: homepage ================================================ FILE: cluster/homelab/apps/it-tools/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: it-tools namespace: it-tools spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/it-tools reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: ittools: replicas: 3 ================================================ FILE: cluster/homelab/apps/it-tools/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/it-tools/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: it-tools ================================================ FILE: cluster/homelab/apps/koffan/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: koffan labels: app.kubernetes.io/instance: koffan app.kubernetes.io/name: koffan spec: replicas: 1 # Uses SqLite, so only one strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: koffan app.kubernetes.io/name: koffan template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app.kubernetes.io/instance: koffan app.kubernetes.io/name: koffan spec: restartPolicy: Always containers: - name: koffan image: ghcr.io/pansalut/koffan:v2.10.0 imagePullPolicy: IfNotPresent resources: requests: cpu: 128m memory: 128Mi limits: cpu: 512m memory: 512Mi ports: - name: web containerPort: 80 volumeMounts: - name: data mountPath: /data securityContext: capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" - name: APP_ENV value: "production" - name: PORT value: "80" - name: DB_PATH value: "/data/shopping.db" envFrom: - secretRef: name: app startupProbe: exec: command: - wget - --no-verbose - --tries=1 - --spider - http://127.0.0.1:80/login initialDelaySeconds: 5 failureThreshold: 30 periodSeconds: 10 livenessProbe: exec: command: - wget - --no-verbose - --tries=1 - --spider - http://127.0.0.1:80/login initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: exec: command: - wget - --no-verbose - --tries=1 - --spider - http://127.0.0.1:80/login initialDelaySeconds: 5 periodSeconds: 10 volumes: - name: data persistentVolumeClaim: claimName: koffan-data ================================================ FILE: cluster/homelab/apps/koffan/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: koffan-external spec: parentRefs: - name: external namespace: istio-gateway hostnames: - "koffan.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: web port: 80 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: koffan-internal annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Shopping List gethomepage.dev/group: Personal gethomepage.dev/name: Koffan spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "koffan.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: koffan port: 80 ================================================ FILE: cluster/homelab/apps/koffan/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: koffan resources: - namespace.yaml - deployment.yaml - service.yaml - gateway-api.yaml - secret.sops.yaml - storage.yaml ================================================ FILE: cluster/homelab/apps/koffan/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: koffan ================================================ FILE: cluster/homelab/apps/koffan/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: app data: APP_PASSWORD: ENC[AES256_GCM,data:F6auiB0LASmPXwp4dIRuV1QMbKDGI1cAKzOuito/obH0NGkr18ejhKacuH6Knssr,iv:b30R/IGlh1c5Ntrf3JtVFlQwOmHdVdkfnV1JWhOgFDk=,tag:I1X/eFaD8WX6HytsHGN8og==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0dGZoVVMzVXFOd282K0NQ TTdjdnczMW5kMGZHVzNwS1VnYUl4RWUvakdJCkZDQ0V3YTIzRW9CTzl6dW5JTWM3 YzR1K2UwNGFSalhUWGJzcXUxRlVxdjAKLS0tIGU3TkhvNUxYT2VBcVdNR1lNRXFj STlmT1pDeCsvWkl4QmVPd3U2YUpwNHcKLZh9be/LzmsO+ymI2HVwkHL2AnnvITo3 H0r/qlXZEiblgjyWQGt8LoEid9SMl0wJsxzNGWAemnuGmJpMUnIiQQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-30T08:03:56Z" mac: ENC[AES256_GCM,data:3d/7Yl99wez6a5fx01g09V2B/3v3UkzCOld7hV6s3VAyPY/w6PxD+TB1aj2wOblHlTJ8eQemw2djHZHstH0Na4CMJ1VIG5U3CP+jbcIiQPoFikVltRrruG+f2FcHHUKSqHcMPya2JbRH2knsikMEh0NoeS+PVdOu8hZ6KX5Qlvc=,iv:t8OWfyNl9uxMPX9ST+zJ44vDHYdIv/8x7ntDePB7Loo=,tag:+gIFW8byRpG2VOc4KQCzBg==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/koffan/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: koffan spec: selector: app.kubernetes.io/instance: koffan app.kubernetes.io/name: koffan ports: - name: web protocol: TCP port: 80 ================================================ FILE: cluster/homelab/apps/koffan/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: koffan-data spec: accessModes: - ReadWriteOnce # It's Sqlite, so not a good idea to be many! storageClassName: longhorn resources: requests: storage: 1Gi ================================================ FILE: cluster/homelab/apps/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - adminer - bentopdf - cert-manager - changedetection - cyberchef - diagrams - firefly - freshrss - foldingathome - garden - go-ddns-controller - gotenberg - homepage - it-tools - mazanoke - mealie - media - n8n - nodered - openbooks - linkwarden - observeability - paperless-ngx - reactiveresume - replacedby - koffan - storage - tika - uptimekuma - vikunja - website - homebox - networking-toolbox # - wallabag ================================================ FILE: cluster/homelab/apps/linkwarden/cnpg.yaml ================================================ apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgres annotations: backup.velero.io/backup-volumes: pgdata spec: instances: 3 imageName: ghcr.io/cloudnative-pg/postgresql:18.1 storage: size: 10Gi podSecurityContext: runAsNonRoot: true securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL add: - NET_BIND_SERVICE - CHOWN - FOWNER privileged: false readOnlyRootFilesystem: true runAsNonRoot: true ================================================ FILE: cluster/homelab/apps/linkwarden/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: linkwarden spec: interval: 5m install: createNamespace: true chart: spec: chart: ./Helm/apps/linkwarden reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: linkwarden: replicas: 3 ================================================ FILE: cluster/homelab/apps/linkwarden/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: linkwarden resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml - cnpg.yaml ================================================ FILE: cluster/homelab/apps/linkwarden/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: linkwarden ================================================ FILE: cluster/homelab/apps/linkwarden/secret.sops.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: app namespace: linkwarden data: NEXTAUTH_SECRET: ENC[AES256_GCM,data:/k2eA3k1yEqHvFsGHFuundeRLR8SUwcpcEvetEDK0TUSpJEO78lqq4j/bgk=,iv:bMGuh6IL+8bEqxPLS4qwmGpYllNfkOCt9uriumVPJOA=,tag:w/VkMIi++RTMItODLMix2w==,type:str] NEXTAUTH_URL: ENC[AES256_GCM,data:oKC9Gq7Ji8QIo5EU1V6rxg/qiLE+YbzrsJD3pX0l1Kau3Zm5y3q82yT+MUtNGZLoSsr7j4uQiNWeUtK+XsOhVA==,iv:f63jEvj5tOaG9eiDOR8UBXNHTc+INe2YohuEQ+THKww=,tag:wxaIe2H2HdOYqW0rh2/e1g==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXaDdBeCs0WERaVjFjcEl5 bjRGdDZNQmZaSy9UU0VvSmlCcURUU3FCcTNBCklJdW1yYlVOYkNMWGpNMUkyWDZD cVZjUGxPM2hCM0lRRURDOVgySkxGQ2sKLS0tIHdPQ0xQMzRpRC9DYVd5UEVUV0Vn SnI5c3ZWZXdzR2xPdGRtRmYvekVVVncK/8lqfCwGw4058wMGPj8jiFeOW1bt+Da9 gckT/pu7STTMPIqHPCzNzMRZUNQbuLjqepwGLv0+qzwi/nfhObO+nQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-19T17:23:38Z" mac: ENC[AES256_GCM,data:+zznqsa5tQd0j4voUsq0eqLAtSa4xoSTrH5e9QKOK+BKRLGm9WRixeJz3kp9TBLqNf0KxfreUMDj/HwlgsGfrDkeGa47wxv0CCurX2wK3nmbjq9dGeL1XQEDdSDSWIhilWHsYz+T8PXrTn96JCwdDBs9nv9Cm0VtgMEdtyOnscc=,iv:IGHcUrKb/3MyeRcGzSULCNOqok3ukeJmDOBT116vRVE=,tag:CEuxbRr6obobVBmXugcBrQ==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/mazanoke/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: mazanoke namespace: mazanoke spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/mazanoke reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/mazanoke/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/mazanoke/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: mazanoke ================================================ FILE: cluster/homelab/apps/mealie/gateway-api.sops.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: mealie-internal namespace: mealie annotations: nginx.ingress.kubernetes.io/proxy-body-size: "0" gethomepage.dev/enabled: "true" gethomepage.dev/description: Self-hosted Recipes! gethomepage.dev/group: Knowledge gethomepage.dev/icon: mealie gethomepage.dev/name: Mealie gethomepage.dev/widget.type: mealie gethomepage.dev/widget.url: https://mealie.sgenov.dev gethomepage.dev/widget.key: ENC[AES256_GCM,data:6NLdB8Rv5Odp4eZ2osXaxoUJ5MRta3JcPEI5F8vmTVx480PVBiQ5E19Hqsmg/k1BDueZsl7B5EpjaqfikoNcw0nXEwGVh/LGnJk+2w/HI4/MtgIROg7UTn6DkVLbcCAhpXVRm7a0NpBNau+sQnf+HB5TPeMmxp1e7nJvgg922eiMH0kQq2urJszY+FqHaHQltw2W4NuoTxEaT9/UBc/IBTj000N2A8rW0BrWXKuyUhzIECF7BbJy/DNRSRwJDVuOuWsMO/UwUoC/fKG2cJdfYLPWZuF1CgoYS6DJ0SNsFx+5C7A3GijvZKwwOTxa+ZGigBueVeVGmNs=,iv:GnCnhG7VL/mneIpAsBqBXStRBFSgS2ickNicG6pZa64=,tag:7b7GIEAGmWdkIfb4ueqoiQ==,type:str] gethomepage.dev/widget.version: "2" sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtSmwrR2Z1L2JXd28xUEpq K1lhSWo1dEdaUHF2bjdpYjBHMWlySEExTXpjCkkremhKaC82b2RGYi9wcW04WTR6 L3BxVmxPaXdBVXh1NHc0WFFsWUZQWDQKLS0tIDFwR1hnTUovOTFyVUpacmxJSkRu YllZRVlETlhSL0c1T3ZWMDA1RHIrbjgK8AJi7u+479LRLnBz4CWntoODZn6Vn9sN s5ry2zh8P38/wSrCvGwCY3ULg5k9NK3iZH+eKqPEkPOKJpK7XcSrPQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T14:07:24Z" mac: ENC[AES256_GCM,data:OUc0vT0MrWjsqrAXu06Gf7nnXWPiqWe1a1J5OR71G3i51JG1IY2IgBmL2xbTQIY61qqOehlTK9PdwvYC0aAnH24LGxrflRcYbzMZNHo94gM1su5lf6bOMw+M1otN96mOeZK53gD0WSSoi5uCLKjxBBSR8OcuzfTPDvREp3Tm+78=,iv:9RYie7V5HRCVmWz9Ys8jojLTnXIMse9Y4NAKjK0JGO8=,tag:0L2L76aHDbqsqQFBncwl0w==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 ================================================ FILE: cluster/homelab/apps/mealie/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: mealie namespace: mealie spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/mealie reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: mealie: replicas: 3 ================================================ FILE: cluster/homelab/apps/mealie/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - gateway-api.sops.yaml ================================================ FILE: cluster/homelab/apps/mealie/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: mealie ================================================ FILE: cluster/homelab/apps/media/gateway-api.sops.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: sonarr-internal namespace: media annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Shows Downloader gethomepage.dev/group: Torrents gethomepage.dev/icon: sonarr gethomepage.dev/name: Sonarr gethomepage.dev/widget.type: sonarr gethomepage.dev/widget.url: https://sonarr.sgenov.dev gethomepage.dev/widget.key: ENC[AES256_GCM,data:bfeU3jlvlGBqdw1MLCMsZQJOjTxUumteaSRA5e8U9Y0=,iv:6ufc5sNocrleBXVzHWTtTkcf51pBZR5sDp1dUwXpMGw=,tag:JreJG5LgDQgpF25paa35yA==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL1FSdG9yL2VFVFcwQURk ZVJCV0JDQXlCSTQvdXFtOS9sWE9tM0JRTmlvCktKVHNBVnAvM1R0SXArRFVjOXM1 cFpOdytCZGI5akRRR2hPL2tnRUF5VUkKLS0tIDRSSFJxbFIyMGtDNjBPcnhHbzcz UFFvWXhRZjQvdmlSZVNXWHBPQWlLTlEKqGbJ34MVRiQqJe9eAFdWki0fUd5TORNH govtKf9SiYLuts+hoA2R9PkO83wUhPkBf09+6fJh9R/6xumAS1Rarw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T15:25:41Z" mac: ENC[AES256_GCM,data:0VSodsbV0RiQZa7xasf/OwywYDujDai0+/U4TfrG5BL1WxzvDDKkxt3BQ4T++Q0jTZKbFo1WTaZm3LYHLEEA6zEvU70FiMbiz6GL7DV/0LxK3tWjwADmDxsGQ/RDk89xIo7hWH7+4BT34px8gEXqc0fc0bU6yHhsIRtCJ4diJHs=,iv:ns+7lEJqUxICiLiXnXYBjeUqgK7DHbszeamivD7h/Tk=,tag:m1BatitxoO9LjjVvpWBWKg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: kavita-internal namespace: media annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Book Reader And Tracker gethomepage.dev/group: Media gethomepage.dev/icon: kavita gethomepage.dev/name: Kavita gethomepage.dev/widget.type: kavita gethomepage.dev/widget.url: https://kavita.sgenov.dev gethomepage.dev/widget.username: stefan gethomepage.dev/widget.password: ENC[AES256_GCM,data:yFIFFGLiDf9+CUdPuYxbBCr1uVLmz0pdvLlaW5DarjPhc2WsNOl0IGsF,iv:dcIoXceoga3mDqZKjqGXDqL7Hwd9Ba+m2uHFKcI1m1s=,tag:HLRuyfEXHvW2xFoiFXzWPA==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL1FSdG9yL2VFVFcwQURk ZVJCV0JDQXlCSTQvdXFtOS9sWE9tM0JRTmlvCktKVHNBVnAvM1R0SXArRFVjOXM1 cFpOdytCZGI5akRRR2hPL2tnRUF5VUkKLS0tIDRSSFJxbFIyMGtDNjBPcnhHbzcz UFFvWXhRZjQvdmlSZVNXWHBPQWlLTlEKqGbJ34MVRiQqJe9eAFdWki0fUd5TORNH govtKf9SiYLuts+hoA2R9PkO83wUhPkBf09+6fJh9R/6xumAS1Rarw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T15:25:41Z" mac: ENC[AES256_GCM,data:0VSodsbV0RiQZa7xasf/OwywYDujDai0+/U4TfrG5BL1WxzvDDKkxt3BQ4T++Q0jTZKbFo1WTaZm3LYHLEEA6zEvU70FiMbiz6GL7DV/0LxK3tWjwADmDxsGQ/RDk89xIo7hWH7+4BT34px8gEXqc0fc0bU6yHhsIRtCJ4diJHs=,iv:ns+7lEJqUxICiLiXnXYBjeUqgK7DHbszeamivD7h/Tk=,tag:m1BatitxoO9LjjVvpWBWKg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: prowlarr-internal namespace: media annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Torrent indexer gethomepage.dev/group: Torrents gethomepage.dev/icon: prowlarr gethomepage.dev/name: Prowlarr gethomepage.dev/widget.type: prowlarr gethomepage.dev/widget.url: https://prowlarr.sgenov.dev gethomepage.dev/widget.key: ENC[AES256_GCM,data:kzoEUfFLJiGJDIfhK6PxzjsARStbmjYsM4/quTEnAN0=,iv:TzD2xe4/aHqYRIX6asXnFak9eiJ+pkw14VuCHx+1lX4=,tag:Sr/I7eJLVdYTKaSMlAzYQw==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL1FSdG9yL2VFVFcwQURk ZVJCV0JDQXlCSTQvdXFtOS9sWE9tM0JRTmlvCktKVHNBVnAvM1R0SXArRFVjOXM1 cFpOdytCZGI5akRRR2hPL2tnRUF5VUkKLS0tIDRSSFJxbFIyMGtDNjBPcnhHbzcz UFFvWXhRZjQvdmlSZVNXWHBPQWlLTlEKqGbJ34MVRiQqJe9eAFdWki0fUd5TORNH govtKf9SiYLuts+hoA2R9PkO83wUhPkBf09+6fJh9R/6xumAS1Rarw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T15:25:41Z" mac: ENC[AES256_GCM,data:0VSodsbV0RiQZa7xasf/OwywYDujDai0+/U4TfrG5BL1WxzvDDKkxt3BQ4T++Q0jTZKbFo1WTaZm3LYHLEEA6zEvU70FiMbiz6GL7DV/0LxK3tWjwADmDxsGQ/RDk89xIo7hWH7+4BT34px8gEXqc0fc0bU6yHhsIRtCJ4diJHs=,iv:ns+7lEJqUxICiLiXnXYBjeUqgK7DHbszeamivD7h/Tk=,tag:m1BatitxoO9LjjVvpWBWKg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: radarr-internal namespace: media annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Movies Downloader gethomepage.dev/group: Torrents gethomepage.dev/icon: radarr gethomepage.dev/name: Radarr gethomepage.dev/widget.type: radarr gethomepage.dev/widget.url: https://radarr.sgenov.dev gethomepage.dev/widget.key: ENC[AES256_GCM,data:3iEFMaCr8U1v4lBK96oTTcImID5PpHQ//2R2xcyYBgo=,iv:ruU1zFTrnaIKX4lFePwj8cOEjjDpK+cgsdG0R1BXGVY=,tag:9bywyp9yOU+gAIHwWBtMuQ==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL1FSdG9yL2VFVFcwQURk ZVJCV0JDQXlCSTQvdXFtOS9sWE9tM0JRTmlvCktKVHNBVnAvM1R0SXArRFVjOXM1 cFpOdytCZGI5akRRR2hPL2tnRUF5VUkKLS0tIDRSSFJxbFIyMGtDNjBPcnhHbzcz UFFvWXhRZjQvdmlSZVNXWHBPQWlLTlEKqGbJ34MVRiQqJe9eAFdWki0fUd5TORNH govtKf9SiYLuts+hoA2R9PkO83wUhPkBf09+6fJh9R/6xumAS1Rarw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T15:25:41Z" mac: ENC[AES256_GCM,data:0VSodsbV0RiQZa7xasf/OwywYDujDai0+/U4TfrG5BL1WxzvDDKkxt3BQ4T++Q0jTZKbFo1WTaZm3LYHLEEA6zEvU70FiMbiz6GL7DV/0LxK3tWjwADmDxsGQ/RDk89xIo7hWH7+4BT34px8gEXqc0fc0bU6yHhsIRtCJ4diJHs=,iv:ns+7lEJqUxICiLiXnXYBjeUqgK7DHbszeamivD7h/Tk=,tag:m1BatitxoO9LjjVvpWBWKg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: overseerr-internal namespace: media annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Media Requests gethomepage.dev/group: Media gethomepage.dev/icon: overseerr gethomepage.dev/name: Overseerr gethomepage.dev/widget.type: overseerr gethomepage.dev/widget.url: https://overseerr.sgenov.dev gethomepage.dev/widget.key: ENC[AES256_GCM,data:q1Mwyvee4pxLpc5QkIM/CuQN96X1FMxGQildNhMituLCSyuJYpnTZDE+mIPnIxK0SrujC0bwHdHtaqMU299q1lGIkyM=,iv:iKpFg5XZfTvL/n8ti7BgvbVSuDWbLvkWp3Ay85O2aoQ=,tag:cGLDf1NuOpdWAqnGcmGjZg==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL1FSdG9yL2VFVFcwQURk ZVJCV0JDQXlCSTQvdXFtOS9sWE9tM0JRTmlvCktKVHNBVnAvM1R0SXArRFVjOXM1 cFpOdytCZGI5akRRR2hPL2tnRUF5VUkKLS0tIDRSSFJxbFIyMGtDNjBPcnhHbzcz UFFvWXhRZjQvdmlSZVNXWHBPQWlLTlEKqGbJ34MVRiQqJe9eAFdWki0fUd5TORNH govtKf9SiYLuts+hoA2R9PkO83wUhPkBf09+6fJh9R/6xumAS1Rarw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T15:25:41Z" mac: ENC[AES256_GCM,data:0VSodsbV0RiQZa7xasf/OwywYDujDai0+/U4TfrG5BL1WxzvDDKkxt3BQ4T++Q0jTZKbFo1WTaZm3LYHLEEA6zEvU70FiMbiz6GL7DV/0LxK3tWjwADmDxsGQ/RDk89xIo7hWH7+4BT34px8gEXqc0fc0bU6yHhsIRtCJ4diJHs=,iv:ns+7lEJqUxICiLiXnXYBjeUqgK7DHbszeamivD7h/Tk=,tag:m1BatitxoO9LjjVvpWBWKg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: transmission-internal namespace: media annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Torrent Handler gethomepage.dev/group: Torrents gethomepage.dev/icon: transmission gethomepage.dev/name: Transmission gethomepage.dev/widget.type: transmission gethomepage.dev/widget.url: https://transmission.sgenov.dev gethomepage.dev/widget.username: username gethomepage.dev/widget.password: ENC[AES256_GCM,data:GxMPFslgFxA=,iv:ZqAxDXcnkMo/EaCEL0DacDmGWXf+duVGJ4HcMTwsLeA=,tag:EeSOa86hS4qUlJofcBYC+g==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxL1FSdG9yL2VFVFcwQURk ZVJCV0JDQXlCSTQvdXFtOS9sWE9tM0JRTmlvCktKVHNBVnAvM1R0SXArRFVjOXM1 cFpOdytCZGI5akRRR2hPL2tnRUF5VUkKLS0tIDRSSFJxbFIyMGtDNjBPcnhHbzcz UFFvWXhRZjQvdmlSZVNXWHBPQWlLTlEKqGbJ34MVRiQqJe9eAFdWki0fUd5TORNH govtKf9SiYLuts+hoA2R9PkO83wUhPkBf09+6fJh9R/6xumAS1Rarw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T15:25:41Z" mac: ENC[AES256_GCM,data:0VSodsbV0RiQZa7xasf/OwywYDujDai0+/U4TfrG5BL1WxzvDDKkxt3BQ4T++Q0jTZKbFo1WTaZm3LYHLEEA6zEvU70FiMbiz6GL7DV/0LxK3tWjwADmDxsGQ/RDk89xIo7hWH7+4BT34px8gEXqc0fc0bU6yHhsIRtCJ4diJHs=,iv:ns+7lEJqUxICiLiXnXYBjeUqgK7DHbszeamivD7h/Tk=,tag:m1BatitxoO9LjjVvpWBWKg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 ================================================ FILE: cluster/homelab/apps/media/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: media namespace: media spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/media reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/media/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - gateway-api.sops.yaml - ./shelfmark/ ================================================ FILE: cluster/homelab/apps/media/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: media ================================================ FILE: cluster/homelab/apps/media/shelfmark/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: shelfmark labels: app.kubernetes.io/instance: shelfmark app.kubernetes.io/name: shelfmark spec: replicas: 1 # Uses SqLite, so only one strategy: type: Recreate selector: matchLabels: app.kubernetes.io/instance: shelfmark app.kubernetes.io/name: shelfmark template: metadata: annotations: backup.velero.io/backup-volumes: data labels: app.kubernetes.io/instance: shelfmark app.kubernetes.io/name: shelfmark spec: restartPolicy: Always containers: - name: shelfmark image: ghcr.io/calibrain/shelfmark:v1.2.3 imagePullPolicy: IfNotPresent resources: requests: cpu: 128m memory: 128Mi limits: cpu: 1 memory: 1Gi ports: - name: web containerPort: 8084 env: - name: PUID value: "1000" - name: PGID value: "1000" - name: TZ value: "Europe/Sofia" - name: CWA_DB_PATH value: "/config/app.db" - name: INGEST_DIR value: "/books/Other" securityContext: capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID livenessProbe: failureThreshold: 5 initialDelaySeconds: 30 timeoutSeconds: 2 tcpSocket: port: 8084 startupProbe: failureThreshold: 10 timeoutSeconds: 2 tcpSocket: port: 8084 volumeMounts: - name: books-data-nfs mountPath: /books # This is where the books will be downloaded and ingested by your book management application - name: config mountPath: /config - name: downloads-data mountPath: /downloads volumes: - name: config persistentVolumeClaim: claimName: shelfmark-config - name: downloads-data nfs: path: "/volume1/k3s/media/downloads" server: "192.168.1.39" - name: books-data-nfs nfs: path: "/volume1/k3s/media/books" server: "192.168.1.39" ================================================ FILE: cluster/homelab/apps/media/shelfmark/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: shelfmark-internal annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Books and Audiobooks Downloader gethomepage.dev/group: Torrents gethomepage.dev/icon: favicon gethomepage.dev/name: Shelfmark spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "shelfmark.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: shelfmark port: 8084 ================================================ FILE: cluster/homelab/apps/media/shelfmark/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: media resources: - deployment.yaml - service.yaml - gateway-api.yaml - storage.yaml ================================================ FILE: cluster/homelab/apps/media/shelfmark/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: shelfmark spec: selector: app.kubernetes.io/instance: shelfmark app.kubernetes.io/name: shelfmark ports: - name: web protocol: TCP port: 8084 ================================================ FILE: cluster/homelab/apps/media/shelfmark/storage.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: shelfmark-config spec: accessModes: - ReadWriteOnce # It's Sqlite, so not a good idea to be many! storageClassName: longhorn resources: requests: storage: 1Gi ================================================ FILE: cluster/homelab/apps/n8n/cnpg.yaml ================================================ apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgres annotations: backup.velero.io/backup-volumes: pgdata spec: instances: 1 imageName: ghcr.io/cloudnative-pg/postgresql:18.1 storage: size: 10Gi podSecurityContext: runAsNonRoot: true securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL add: - NET_BIND_SERVICE - CHOWN - FOWNER privileged: false readOnlyRootFilesystem: true runAsNonRoot: true ================================================ FILE: cluster/homelab/apps/n8n/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: n8n spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/n8n reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: n8n: replicas: 1 ================================================ FILE: cluster/homelab/apps/n8n/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: n8n resources: - helm-release.yaml - secret.sops.yaml - namespace.yaml - cnpg.yaml ================================================ FILE: cluster/homelab/apps/n8n/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: n8n ================================================ FILE: cluster/homelab/apps/n8n/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: app data: username: ENC[AES256_GCM,data:J5v0auXQKy8=,iv:cPS0FnTR9RmUFn8mNOD1vJZFjOQy1R5Cn1Rf7mcdyr0=,tag:pDwNONHnnXZE1aqadI3Pcg==,type:str] password: ENC[AES256_GCM,data:naJ50Z5z4aM=,iv:+gAKRlfLvuf9yInTV7qVuKsVdNGCsZAmhgpEeO1fnmU=,tag:q2A+YG1SK9GKnjW8mx7tZg==,type:str] encryption_key: ENC[AES256_GCM,data:2UsEOImit7ahSSeq64wjkQ==,iv:Fia1/5E1mfhlEJJpdhLQXi0qIQlP0sNDCOTFkwPfrKw=,tag:VwtqBnw55iesY/DWrHVUzw==,type:str] maxFileSizeMb: ENC[AES256_GCM,data:kh0DFA==,iv:H0yvXfwUWXj8kDcks6uwVr8UdtdZ8K36OM4D9Ygyylw=,tag:9UJSpTYCXicdCNZDvZQYpQ==,type:str] type: ENC[AES256_GCM,data:y+z8y0xkHcsbofXTvUhpnA==,iv:nWEU6WIR6bNWd0bww5c9sGfGAfTSN08D3bnlJdTUrHg=,tag:Q4VOKDeW2VRSNSzfR3ZB4Q==,type:str] host: ENC[AES256_GCM,data:HuF7TW87812O4JV8whD8fQ==,iv:NgkAjb5G38svEDdZkkhwo3FXgv9bDC3I5VdVR1ti89U=,tag:Aqv1GFG11fl5xKhqYDR1gA==,type:str] port: ENC[AES256_GCM,data:i8fqnkYu7eY=,iv:KZHINX2pdNkT+DybWTcoZUEb7HPWQ2zQGnmpw2+f9dI=,tag:jpn/MMDIP3KyGM+P/VpWZQ==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxVUdSeDN5ZThGRWhURXdB NGZkNnlzeDJpUXdHcW04U1IzdENKSHY3L2drClpyRnhIcExFWXpLYnNLU0lmcWRJ dEF1eWtLTm10OHZJcUloTHc2M3NZZWMKLS0tIHFUT2tmZURJZ2hiNjBjRUw0czJ6 SHhERGFkZHhkTSs4SEFEZUFSdFRNbk0KApOph5mFVaxVSrsK7s5anOuQ4XcHdjXX tG/ROAVjiTuOihQoOHE3cjc4CaYPIVqw3oSR6te/gP8EdEjCJ3kDag== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-18T19:42:18Z" mac: ENC[AES256_GCM,data:9noguTP8TDOmRh/09zMWLAlRzc0opftrfKXmTSQWbRnOhINC1wQktdziNlH0C8lWlCJ5TVxj5b+P85UWsvXbQLvScxZeiLlZb0iUAUdAu/VIDA4NAdbPcpUpnzSXeIqe7NUtT8CLpi1qTj+NYIkr6dLvf4CN4+2lnNhw30j6SPk=,iv:BWRV+UNd/OGWQP3zy0+Faxkk+BqWX04PGKAwhNxmiF0=,tag:YXFKEedjk+PO+76JKvorlw==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/networking-toolbox/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: networkingtoolbox labels: app.kubernetes.io/instance: networkingtoolbox app.kubernetes.io/name: networkingtoolbox spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: networkingtoolbox app.kubernetes.io/name: networkingtoolbox template: metadata: labels: app.kubernetes.io/instance: networkingtoolbox app.kubernetes.io/name: networkingtoolbox spec: containers: - name: networkingtoolbox image: ghcr.io/lissy93/networking-toolbox:1.6.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 3000 env: - name: NODE_ENV value: "production" - name: PORT value: "3000" - name: HOST value: "0.0.0.0" resources: requests: cpu: 100m memory: 100Mi limits: cpu: 200m memory: 200Mi livenessProbe: exec: command: - wget - -qO- - http://127.0.0.1:3000/health initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: exec: command: - wget - -qO- - http://127.0.0.1:3000/health initialDelaySeconds: 5 periodSeconds: 10 ================================================ FILE: cluster/homelab/apps/networking-toolbox/gateway-api.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: networkingtoolbox-internal spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - "networkingtoolbox.sgenov.dev" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: networkingtoolbox port: 3000 ================================================ FILE: cluster/homelab/apps/networking-toolbox/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: networkingtoolbox resources: - namespace.yaml - deployment.yaml - service.yaml - gateway-api.yaml ================================================ FILE: cluster/homelab/apps/networking-toolbox/namespace.yaml ================================================ apiVersion: v1 kind: Namespace metadata: name: networkingtoolbox ================================================ FILE: cluster/homelab/apps/networking-toolbox/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: networkingtoolbox spec: selector: app.kubernetes.io/instance: networkingtoolbox app.kubernetes.io/name: networkingtoolbox ports: - name: http protocol: TCP port: 3000 targetPort: http ================================================ FILE: cluster/homelab/apps/nodered/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: nodered namespace: nodered spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/nodered reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/nodered/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/nodered/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: nodered ================================================ FILE: cluster/homelab/apps/observeability/helm-release.sensitive.sops.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: observeability namespace: observeability spec: interval: 10m install: createNamespace: true chart: spec: chart: kube-prometheus-stack version: 82.18.0 interval: 10m sourceRef: kind: HelmRepository name: kube-prometheus-stack namespace: flux-system values: defaultRules: create: true rules: alertmanager: true etcd: true configReloaders: true general: true k8sContainerCpuUsageSecondsTotal: true k8sContainerMemoryCache: true k8sContainerMemoryRss: true k8sContainerMemorySwap: true k8sContainerResource: true k8sContainerMemoryWorkingSetBytes: true k8sPodOwner: true kubeApiserverAvailability: true kubeApiserverBurnrate: true kubeApiserverHistogram: true kubeApiserverSlos: true kubeControllerManager: false kubelet: true kubeProxy: false kubePrometheusGeneral: true kubePrometheusNodeRecording: true kubernetesApps: true kubernetesResources: true kubernetesStorage: true kubernetesSystem: true kubeSchedulerAlerting: false kubeSchedulerRecording: false kubeStateMetrics: true network: true node: true nodeExporterAlerting: true nodeExporterRecording: true prometheus: true prometheusOperator: true windows: false prometheus-node-exporter: containerSecurityContext: readOnlyRootFilesystem: true capabilities: drop: - ALL prometheus: prometheusSpec: scrapeInterval: 60s scrapeTimeout: 30s retention: 30d retentionSize: 10GiB storageSpec: volumeClaimTemplate: spec: storageClassName: longhorn accessModes: - ReadWriteOnce resources: requests: storage: 15Gi serviceMonitorNamespaceSelector: matchLabels: monitoring.coreos.com/serviceMonitor: "true" route: main: # -- Enables or disables the route enabled: true apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Metrics Aggregator. gethomepage.dev/group: Monitoring gethomepage.dev/icon: prometheus gethomepage.dev/name: Prometheus hostnames: - prometheus.sgenov.dev parentRefs: - name: internal namespace: istio-gateway matches: - path: type: PathPrefix value: / alertmanager: config: global: resolve_timeout: 5m inhibit_rules: - source_matchers: - severity = critical target_matchers: - severity =~ warning|info equal: - namespace - alertname - source_matchers: - severity = warning target_matchers: - severity = info equal: - namespace - alertname - source_matchers: - alertname = InfoInhibitor target_matchers: - severity = info equal: - namespace - target_matchers: - alertname = InfoInhibitor route: group_by: - alertname - namespace group_wait: 30s group_interval: 5m repeat_interval: 12h receiver: discord routes: - receiver: "null" matchers: - alertname="PrometheusDuplicateTimestamps" continue: false - receiver: "null" matchers: - alertname="Watchdog" continue: false - receiver: "null" matchers: - alertname="InfoInhibitor" continue: false # Match everything else - receiver: discord receivers: - name: "null" - name: discord discord_configs: - webhook_url: ENC[AES256_GCM,data:X3JPxmLya1DAXOcF2Wye04dWuT0d5mnwarj04DL1OE5yZFCojauRzcQIF2JNV5Z4lJBWZD5LQuTQ991OS/RBCKBa3zNjoZAP1xFifGfDxTGUxEfszmNpey6porPa7jK+1bRVS7dZX7ZUIEY4Cyg8wfE9TPFDz1jKCQ==,iv:FUy+psbXPk7/m60Ui4p1ERn/mdadI+kRTatdKLAAHEE=,tag:hkUPZmQyDJ1QuRZOrBeiog==,type:str] send_resolved: true templates: - /etc/alertmanager/config/*.tmpl alertmanagerSpec: alertmanagerConfigSelector: matchLabels: # This is so we can create AlertManager configs targeting `default` alertmanagerConfig: default storage: volumeClaimTemplate: spec: storageClassName: longhorn accessModes: - ReadWriteOnce resources: requests: storage: 5Gi route: main: # -- Enables or disables the route enabled: true apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Handles Prometheus Alerts gethomepage.dev/group: Monitoring gethomepage.dev/icon: alertmanager gethomepage.dev/name: Alertmanager hostnames: - alertmanager.sgenov.dev parentRefs: - name: internal namespace: istio-gateway matches: - path: type: PathPrefix value: / grafana: adminUser: admin adminPassword: ENC[AES256_GCM,data:W9cc+RM2pJtf/ce61cziwq0pNM4Aro8O240P11xu4MRXNwcAyywK9n0EyBtQGHauZM+t7g==,iv:xZEhDmF+9p5ILOgCUH9yA7uVxFucsjbAnJajTBdlxE8=,tag:dDAMCmNwX2oSzHAVliHjnA==,type:str] persistence: enabled: true type: sts storageClassName: longhorn accessModes: - ReadWriteOnce size: 2Gi finalizers: - kubernetes.io/pvc-protection route: main: # -- Enables or disables the route enabled: true apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute annotations: null gethomepage.dev/enabled: "true" gethomepage.dev/description: Nice observeability graphs. gethomepage.dev/group: Monitoring gethomepage.dev/icon: grafana gethomepage.dev/name: Grafana gethomepage.dev/widget.type: grafana gethomepage.dev/widget.url: https://grafana.sgenov.dev gethomepage.dev/widget.version: "2" gethomepage.dev/widget.alerts: alertmanager gethomepage.dev/widget.username: admin gethomepage.dev/widget.password: ENC[AES256_GCM,data:/h9MONsjnnynnvz6uTHbgS2s20R09kfhbTUj6CZsCz/Daq00ZnLTRb5ZmDfqFe4Yu+xsXQ==,iv:EkzGmmbeIP9SuB+RbBsypNPEg0xQb3kSpNvdXXdavBo=,tag:tPN9Rahh1fOQiG26YOUuuw==,type:str] hostnames: - grafana.sgenov.dev parentRefs: - name: internal namespace: istio-gateway matches: - path: type: PathPrefix value: / crds: enabled: true ## The CRD upgrade job mitigates the limitation of helm not being able to upgrade CRDs. ## The job will apply the CRDs to the cluster before the operator is deployed, using helm hooks. ## It deploy a corresponding clusterrole, clusterrolebinding and serviceaccount to apply the CRDs. ## This feature is in preview, off by default and may change in the future. upgradeJob: enabled: true forceConflicts: true image: busybox: registry: docker.io repository: busybox tag: "1.37" sha: "" pullPolicy: IfNotPresent kubectl: registry: registry.k8s.io repository: kubectl # defaults to the Kubernetes version tag: "" sha: "" pullPolicy: IfNotPresent sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvd2dkWC9RbjRTTzVCcjR5 R3h0S3kvSHA1K3VjaDhjY3BoSzlnV2Y5RTFvCkJER095MVB6VEhDMVBoNUM1TkZN SEFhN3k1WkRsTFUwVmhrTEhGc0g1ZlkKLS0tIEp4MFNZbkxaZGZDNTlWL0ZYMjVP MnZTaUoxakkzSS9yd2hxL1NrSXVoZjQKq8DBQpSfBIe+49H9T4eFXYdUi7ZRtjMd 1St9o6vw0RmzNqGTtczmKZs42K2Cf3gE09b40TnFWzh/1AkhtkQuNQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-14T23:32:11Z" mac: ENC[AES256_GCM,data:RSneOamRAdxSkyLVxpZPzfmKJAQwXoFtq4ka2X1hi6TUW5CwieVxzrWScYRbYQxoySD5RoJlnsugmMHSI96TXFDtqHZAA6DYek20ettwO2vuFq8Yp9QvwGJ0ht+f042yJOWilBAdK6hnCGB07xXuS9b4L5E6UcZKBKze+9XlFZM=,iv:iAFeVBOKojgRiEvX7yh/REIYQs22ixGaMdNdzTfKeKA=,tag:tl6t6t5ijhy0bcoZ8aNYZg==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 ================================================ FILE: cluster/homelab/apps/observeability/kubernetes-server-metrics.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: kubernetes-server-metrics namespace: observeability labels: grafana_dashboard: "1" data: new-dashboard.json: | { "annotations": { "list": [ { "$$hashKey": "object:1058", "builtIn": 1, "datasource": { "type": "prometheus", "uid": "prometheus" }, "enable": true, "hide": false, "iconColor": "rgba(0, 211, 255, 1)", "limit": 100, "name": "Annotations & Alerts", "showIn": 0, "type": "dashboard" } ] }, "description": "If NHD is present in the name of a metric or row that means it is Not Host Dependent", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": 31, "links": [], "panels": [ { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 6, "w": 3, "x": 0, "y": 0 }, "id": 381, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "
\n \n

$k8s_version

\n
", "mode": "html" }, "pluginVersion": "12.1.1", "title": "", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [ { "options": { "match": "null", "result": { "text": "N/A" } }, "type": "special" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 6, "w": 3, "x": 3, "y": 0 }, "id": 407, "maxDataPoints": 100, "options": { "colorMode": "none", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_info)", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "Nodes", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [ { "options": { "match": "null", "result": { "color": "#299c46", "text": "0" } }, "type": "special" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "#299c46", "value": 0 }, { "color": "rgba(237, 129, 40, 0.89)", "value": 1 }, { "color": "#d44a3a" } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 3, "w": 4, "x": 6, "y": 0 }, "id": 409, "maxDataPoints": 100, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_status_condition{condition=\"DiskPressure\", node=~\"$Node\", status!=\"false\"})", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "Disk Pressure", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [ { "options": { "match": "null", "result": { "color": "#299c46", "text": "0" } }, "type": "special" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "#299c46", "value": 0 }, { "color": "rgba(237, 129, 40, 0.89)", "value": 1 }, { "color": "#d44a3a" } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 3, "w": 4, "x": 10, "y": 0 }, "id": 413, "maxDataPoints": 100, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_status_condition{condition=\"PIDPressure\", node=~\"$Node\", status!=\"false\"})", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "PID Pressure", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [ { "options": { "match": "null", "result": { "color": "#299c46", "text": "0" } }, "type": "special" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "#299c46", "value": 0 }, { "color": "rgba(237, 129, 40, 0.89)", "value": 1 }, { "color": "#d44a3a" } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 3, "w": 4, "x": 14, "y": 0 }, "id": 411, "maxDataPoints": 100, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_status_condition{condition=\"MemoryPressure\", node=~\"$Node\", status!=\"false\"})", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "Memory Pressure", "type": "stat" }, { "datasource": {}, "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd" }, "mappings": [], "max": 1, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 3, "w": 6, "x": 18, "y": 0 }, "id": 419, "options": { "displayMode": "lcd", "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "maxVizHeight": 300, "minVizHeight": 10, "minVizWidth": 0, "namePlacement": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true, "sizing": "auto", "valueMode": "color" }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": true, "expr": "avg(1-rate(node_cpu_seconds_total{mode=\"idle\"}[5m]))", "interval": "", "legendFormat": "Real", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_pod_container_resource_requests{unit=\"core\"}) / sum(machine_cpu_cores)", "hide": false, "legendFormat": "Requests", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_pod_container_resource_limits{unit=\"core\"}) / sum(machine_cpu_cores)", "hide": false, "legendFormat": "Limits", "range": true, "refId": "C" } ], "title": "Global CPU Usage", "type": "bargauge" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "#299c46", "value": 0 }, { "color": "rgba(237, 129, 40, 0.89)", "value": 1 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 3, "w": 4, "x": 6, "y": 3 }, "id": 417, "maxDataPoints": 100, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_status_condition{condition=\"OutOfDisk\", node=~\"$Node\", status=\"true\"})", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "Out of Disk", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [ { "options": { "match": "null", "result": { "color": "#299c46", "text": "0" } }, "type": "special" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "#299c46", "value": 0 }, { "color": "rgba(237, 129, 40, 0.89)", "value": 1 }, { "color": "#d44a3a" } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 3, "w": 4, "x": 10, "y": 3 }, "id": 415, "maxDataPoints": 100, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_status_condition{condition=\"NetworkUnavailable\", node=~\"$Node\", status!=\"false\"})", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "Network Unavailable", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [ { "options": { "match": "null", "result": { "text": "N/A" } }, "type": "special" } ], "thresholds": { "mode": "absolute", "steps": [ { "color": "#299c46", "value": 0 }, { "color": "dark-red", "value": 1 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 3, "w": 4, "x": 14, "y": 3 }, "id": 405, "maxDataPoints": 100, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "horizontal", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_spec_unschedulable)", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "title": "Nodes Unschedulable", "type": "stat" }, { "datasource": {}, "fieldConfig": { "defaults": { "color": { "mode": "continuous-GrYlRd" }, "mappings": [], "max": 1, "min": 0, "thresholds": { "mode": "percentage", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 3, "w": 6, "x": 18, "y": 3 }, "id": 421, "options": { "displayMode": "lcd", "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": false }, "maxVizHeight": 300, "minVizHeight": 10, "minVizWidth": 0, "namePlacement": "auto", "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true, "sizing": "auto", "text": {}, "valueMode": "color" }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": true, "expr": "sum(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / sum(node_memory_MemTotal_bytes)", "interval": "", "legendFormat": "Real", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_pod_container_resource_requests{unit=\"byte\"}) / sum(machine_memory_bytes)", "hide": false, "legendFormat": "Requests", "range": true, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_pod_container_resource_limits{unit=\"byte\"}) / sum(machine_memory_bytes)", "hide": false, "legendFormat": "Limits", "range": true, "refId": "C" } ], "title": "Global RAM Usage", "type": "bargauge" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "percentage", "steps": [ { "color": "green", "value": 0 }, { "color": "#EAB839", "value": 75 }, { "color": "red", "value": 90 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 7, "w": 3, "x": 0, "y": 6 }, "id": 423, "options": { "minVizHeight": 75, "minVizWidth": 75, "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "/^requested$/", "values": false }, "showThresholdLabels": true, "showThresholdMarkers": true, "sizing": "auto", "text": {} }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_node_status_allocatable{resource=\"pods\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "allocatable", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_pod_info)", "format": "time_series", "intervalFactor": 1, "legendFormat": "requested", "refId": "C" } ], "title": "Cluster Pod Capacity", "type": "gauge" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "blue", "value": 0 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 7, "w": 3, "x": 3, "y": 6 }, "id": 439, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_node_status_allocatable{resource=\"pods\"})", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Max Containers", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "percentage", "steps": [ { "color": "green", "value": 0 }, { "color": "#EAB839", "value": 80 }, { "color": "red", "value": 90 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 7, "w": 3, "x": 6, "y": 6 }, "id": 425, "options": { "minVizHeight": 75, "minVizWidth": 75, "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "/^requested$/", "values": false }, "showThresholdLabels": true, "showThresholdMarkers": true, "sizing": "auto" }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_node_status_capacity{resource=\"cpu\",unit=\"core\"})", "format": "time_series", "hide": false, "intervalFactor": 1, "legendFormat": "allocatable", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_pod_container_resource_requests{resource=\"cpu\",unit=\"core\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "requested", "refId": "C" } ], "title": "Cluster CPU Capacity", "type": "gauge" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "blue", "value": 0 } ] }, "unit": "none" }, "overrides": [] }, "gridPos": { "h": 7, "w": 3, "x": 9, "y": 6 }, "id": 437, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_node_status_capacity{resource=\"cpu\",unit=\"core\"})", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Total CPUs", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "percentage", "steps": [ { "color": "green", "value": 0 }, { "color": "#EAB839", "value": 75 }, { "color": "semi-dark-red", "value": 90 } ] }, "unit": "decbytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "allocatable" }, "properties": [ { "id": "unit", "value": "bytes" } ] } ] }, "gridPos": { "h": 7, "w": 3, "x": 12, "y": 6 }, "id": 427, "options": { "minVizHeight": 75, "minVizWidth": 75, "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "/^requested$/", "values": false }, "showThresholdLabels": true, "showThresholdMarkers": true, "sizing": "auto" }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(kube_node_status_allocatable{unit=\"byte\",resource=\"memory\"})", "format": "time_series", "instant": false, "interval": "", "intervalFactor": 1, "legendFormat": "allocatable", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum(kube_pod_container_resource_requests{unit=\"byte\",resource=\"memory\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "requested", "refId": "C" } ], "title": "Cluster Mem Capacity", "type": "gauge" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "mappings": [], "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "blue", "value": 0 } ] }, "unit": "bytes" }, "overrides": [] }, "gridPos": { "h": 7, "w": 3, "x": 15, "y": 6 }, "id": 435, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showPercentChange": false, "textMode": "auto", "wideLayout": true }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(kube_node_status_allocatable{unit=\"byte\",resource=\"memory\"})", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Total memory", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "line+area" } }, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "#EAB839", "value": 50 }, { "color": "orange", "value": 75 }, { "color": "red", "value": 90 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 7, "w": 6, "x": 18, "y": 6 }, "id": 367, "options": { "legend": { "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "exemplar": true, "expr": "100 - ((node_filesystem_avail_bytes{job=\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"} * 100) / node_filesystem_size_bytes{job=\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"})", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "title": "Disk Capacity", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "Percentage", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 6, "scaleDistribution": { "type": "linear" }, "showPoints": "always", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "line+area" } }, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "transparent", "value": 0 }, { "color": "orange", "value": 75 }, { "color": "red", "value": 90 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 13 }, "id": 363, "options": { "legend": { "calcs": [ "mean", "lastNotNull" ], "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "exemplar": true, "expr": "sum(irate(node_cpu_seconds_total{mode!='idle'}[5m])) by (instance) / sum(irate(node_cpu_seconds_total[5m])) by (instance) * 100", "format": "time_series", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "title": "CPU Busy ( 5m )", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "Percentage", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "stepAfter", "lineWidth": 1, "pointSize": 6, "scaleDistribution": { "type": "linear" }, "showPoints": "always", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "line+area" } }, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "transparent", "value": 0 }, { "color": "orange", "value": 75 }, { "color": "red", "value": 90 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 13 }, "id": 365, "options": { "legend": { "calcs": [ "mean", "lastNotNull" ], "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "exemplar": true, "expr": "100 - ((node_memory_MemAvailable_bytes{job=\"$job\"} * 100) / node_memory_MemTotal_bytes{job=\"$job\"})", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "title": "Ram used % ", "type": "timeseries" }, { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 22 }, "id": 375, "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 3, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 30 }, "id": 373, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Mean", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "exemplar": true, "expr": "sum (rate (container_cpu_usage_seconds_total{namespace!=\"\",node=~\"^$Node$\",namespace=~\"$Namespace\"}[5m])) by (namespace)", "format": "time_series", "interval": "10s", "intervalFactor": 4, "legendFormat": "{{ namespace}}", "metric": "network", "refId": "A", "step": 10 } ], "title": "CPU usage by namespace", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 30, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 3, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "Bps" }, "overrides": [] }, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 30 }, "id": 377, "options": { "legend": { "calcs": [ "mean", "lastNotNull" ], "displayMode": "list", "placement": "bottom", "showLegend": false }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum (rate (container_network_receive_bytes_total{node=~\"^$Node$\"}[5m]))", "format": "time_series", "interval": "10s", "intervalFactor": 4, "legendFormat": "Received", "metric": "network", "refId": "A", "step": 10 }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "- sum (rate (container_network_transmit_bytes_total{node=~\"^$Node$\"}[5m]))", "format": "time_series", "interval": "10s", "intervalFactor": 4, "legendFormat": "Sent", "metric": "network", "refId": "B", "step": 10 } ], "title": "Network I/O pressure", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 3, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "decbytes" }, "overrides": [] }, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 30 }, "id": 379, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Mean", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "exemplar": true, "expr": "sum (container_memory_working_set_bytes{namespace!=\"\",node=~\"^$Node$\",namespace=~\"$Namespace\"}) by (namespace)", "format": "time_series", "interval": "10s", "intervalFactor": 4, "legendFormat": "{{ namespace}}", "metric": "network", "refId": "A", "step": 10 } ], "title": "Memory use by namespace", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 89 }, "id": 371, "options": { "legend": { "calcs": [ "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Last *", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "100 * (kubelet_volume_stats_used_bytes{kubernetes_io_hostname=~\"^$Node$\"} / kubelet_volume_stats_capacity_bytes{kubernetes_io_hostname=~\"^$Node$\"})", "format": "time_series", "intervalFactor": 2, "legendFormat": "{{ persistentvolumeclaim }} | {{ kubernetes_io_hostname }}", "refId": "A", "step": 120 } ], "title": "Disk Usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "cores", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 3, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "decimals": 3, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 98 }, "id": 395, "options": { "legend": { "calcs": [ "mean", "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Mean", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "exemplar": true, "expr": "sum (rate (container_cpu_usage_seconds_total{pod!=\"\",node=~\"^$Node$\",namespace=~\"$Namespace\"}[5m])) by (pod)", "format": "time_series", "interval": "10s", "intervalFactor": 5, "legendFormat": "{{ pod }}", "metric": "container_cpu", "refId": "A", "step": 10 } ], "title": "Pods CPU usage (5m avg)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 3, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": true, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 80 } ] }, "unit": "bytes" }, "overrides": [] }, "gridPos": { "h": 7, "w": 24, "x": 0, "y": 105 }, "id": 401, "options": { "legend": { "calcs": [ "mean", "lastNotNull" ], "displayMode": "table", "placement": "right", "showLegend": true, "sortBy": "Mean", "sortDesc": true }, "tooltip": { "hideZeros": false, "mode": "multi", "sort": "desc" } }, "pluginVersion": "12.1.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "exemplar": true, "expr": "sum (container_memory_working_set_bytes{pod!=\"\",node=~\"^$Node$\",namespace=~\"$Namespace\"}) by (pod)", "format": "time_series", "interval": "10s", "intervalFactor": 5, "legendFormat": "{{ pod }}", "metric": "container_memory_usage:sort_desc", "refId": "A", "step": 10 } ], "title": "Pods memory usage", "type": "timeseries" } ], "title": "Usage", "type": "row" } ], "preload": false, "refresh": "30s", "schemaVersion": 41, "tags": [ "linux", "node-exporter" ], "templating": { "list": [ { "current": { "text": "kubernetes-pods", "value": "kubernetes-pods" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(node_uname_info, job)", "includeAll": false, "label": "Job", "name": "job", "options": [], "query": { "query": "label_values(node_uname_info, job)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "allValue": ".*", "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(kubernetes_io_hostname)", "includeAll": true, "label": "Node", "name": "Node", "options": [], "query": { "query": "label_values(kubernetes_io_hostname)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "sort": 1, "type": "query" }, { "allValue": ".*", "current": { "text": "All", "value": [ "$__all" ] }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(namespace)", "description": "", "includeAll": true, "multi": true, "name": "Namespace", "options": [], "query": { "query": "label_values(namespace)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "current": { "text": "v1.33.2+k3s1", "value": "v1.33.2+k3s1" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(kubernetes_build_info, git_version)", "hide": 2, "includeAll": false, "name": "k8s_version", "options": [], "query": { "query": "label_values(kubernetes_build_info, git_version)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "allValue": ".*", "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(nginx_ingress_controller_config_hash{namespace=~\"$namespace\"}, controller_class)", "hide": 2, "includeAll": true, "label": "Controller Class", "name": "controller_class", "options": [], "query": { "query": "label_values(nginx_ingress_controller_config_hash{namespace=~\"$namespace\"}, controller_class)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "allValue": ".*", "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(nginx_ingress_controller_config_hash{namespace=~\"$namespace\",controller_class=~\"$controller_class\"}, controller_pod) ", "hide": 2, "includeAll": true, "label": "Controller", "name": "controller", "options": [], "query": { "query": "label_values(nginx_ingress_controller_config_hash{namespace=~\"$namespace\",controller_class=~\"$controller_class\"}, controller_pod) ", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "allValue": ".*", "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(nginx_ingress_controller_requests{namespace=~\"$namespace\",controller_class=~\"$controller_class\",controller=~\"$controller\"}, ingress) ", "includeAll": true, "label": "Ingress", "name": "ingress", "options": [], "query": { "query": "label_values(nginx_ingress_controller_requests{namespace=~\"$namespace\",controller_class=~\"$controller_class\",controller=~\"$controller\"}, ingress) ", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "allValue": ".*", "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(nginx_ingress_controller_config_hash, controller_namespace)", "includeAll": true, "label": "namespace", "name": "namespace", "options": [], "query": { "query": "label_values(nginx_ingress_controller_config_hash, controller_namespace)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "current": { "text": "speedtest.monitoring:9798", "value": "speedtest.monitoring:9798" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(speedtest_up, instance)", "hide": 2, "includeAll": false, "label": "speedtestinstance", "name": "speedtestinstance", "options": [], "query": { "query": "label_values(speedtest_up, instance)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" }, { "current": { "text": "speedtest-exporter", "value": "speedtest-exporter" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(speedtest_up, job)", "hide": 2, "includeAll": false, "label": "speedtestjob", "name": "speedtestjob", "options": [], "query": { "query": "label_values(speedtest_up, job)", "refId": "StandardVariableQuery" }, "refresh": 1, "regex": "", "type": "query" } ] }, "time": { "from": "now-24h", "to": "now-0m" }, "timepicker": { "nowDelay": "0m" }, "timezone": "browser", "title": "Kubernetes Server Metrics", "uid": "35xtB4Anz", "version": 1 } ================================================ FILE: cluster/homelab/apps/observeability/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.sensitive.sops.yaml - loki-helm-release.yaml - namespace.yaml # Dashboards - kubernetes-server-metrics.yaml - trivy.yaml ================================================ FILE: cluster/homelab/apps/observeability/loki-helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: observeability-loki namespace: observeability spec: interval: 10m install: createNamespace: true chart: spec: chart: loki-stack version: 2.10.3 interval: 10m sourceRef: kind: HelmRepository name: grafana namespace: flux-system values: test_pod: enabled: false loki: enabled: true isDefault: false image: tag: "2.9.3" containerSecurityContext: readOnlyRootFilesystem: true capabilities: drop: - ALL promtail: enabled: true ================================================ FILE: cluster/homelab/apps/observeability/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: observeability labels: monitoring.coreos.com/serviceMonitor: "true" ================================================ FILE: cluster/homelab/apps/observeability/trivy.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: trivy-dashboard namespace: observeability labels: grafana_dashboard: "1" data: trivy.json: | { "__inputs": [ { "name": "DS_PROMETHEUS", "label": "Prometheus", "description": "", "type": "datasource", "pluginId": "prometheus", "pluginName": "Prometheus" } ], "__elements": {}, "__requires": [ { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "9.3.1" }, { "type": "datasource", "id": "prometheus", "name": "Prometheus", "version": "1.0.0" }, { "type": "panel", "id": "stat", "name": "Stat", "version": "" }, { "type": "panel", "id": "table", "name": "Table", "version": "" }, { "type": "panel", "id": "timeseries", "name": "Time series", "version": "" } ], "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana", "uid": "-- Grafana --" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "target": { "limit": 100, "matchAny": false, "tags": [], "type": "dashboard" }, "type": "dashboard" } ] }, "description": "This Dashboard is used to visualise the metrics from the security reports of the Trivy Operator", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": null, "links": [], "liveNow": false, "panels": [ { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 12, "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "Total number by type of security issues identified in the cluster", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 1 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Critical" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "High" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Medium" }, "properties": [ { "id": "color", "value": { "fixedColor": "dark-yellow", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Low" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Unknown" }, "properties": [ { "id": "color", "value": { "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 1 }, "id": 21, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities)", "instant": true, "legendFormat": "Vulnerabilities", "range": false, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_resource_configaudits)", "hide": false, "instant": true, "legendFormat": "Misconfiguration", "range": false, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_exposedsecrets)", "hide": false, "instant": true, "legendFormat": "Exposed Secrets", "range": false, "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_clusterrole_clusterrbacassessments)", "hide": false, "instant": true, "legendFormat": "RBAC Assessment", "range": false, "refId": "D" } ], "title": "Number and Type of Security Issues", "type": "stat" } ], "title": "Quick Overview", "type": "row" }, { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 1 }, "id": 2, "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Critical" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "High" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Medium" }, "properties": [ { "id": "color", "value": { "fixedColor": "dark-yellow", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Low" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Unknown" }, "properties": [ { "id": "color", "value": { "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 2 }, "id": 19, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Critical\"})", "instant": true, "legendFormat": "Critical", "range": false, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"High\"})", "hide": false, "instant": true, "legendFormat": "High", "range": false, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Medium\"})", "hide": false, "instant": true, "legendFormat": "Medium", "range": false, "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Low\"})", "hide": false, "instant": true, "legendFormat": "Low", "range": false, "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Unknown\"})", "hide": false, "instant": true, "legendFormat": "Unknown", "range": false, "refId": "E" } ], "title": "Severity Breakdown of all Vulnerabilities", "type": "stat" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 3, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 1 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 11 }, "id": 27, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(trivy_image_vulnerabilities) by (namespace)", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Number of Vulnerabilities by namespace", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": "left", "displayMode": "color-text", "filterable": true, "inspect": false }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "super-light-yellow", "value": 1 }, { "color": "orange", "value": 100 }, { "color": "red", "value": 500 } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "Image" }, "properties": [ { "id": "custom.displayMode", "value": "json-view" }, { "id": "custom.width", "value": 350 } ] }, { "matcher": { "id": "byName", "options": "image_tag" }, "properties": [ { "id": "custom.displayMode", "value": "json-view" } ] } ] }, "gridPos": { "h": 14, "w": 24, "x": 0, "y": 19 }, "id": 23, "options": { "footer": { "enablePagination": true, "fields": "", "reducer": [ "sum" ], "show": false }, "frameIndex": 1, "showHeader": true, "sortBy": [] }, "pluginVersion": "9.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Critical\"}) by (image_repository,image_tag)", "format": "table", "instant": true, "range": false, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"High\"}) by (image_repository,image_tag)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Medium\"}) by (image_repository,image_tag)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Low\"}) by (image_repository,image_tag)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_image_vulnerabilities{severity=\"Unknown\"}) by (image_repository,image_tag)", "format": "table", "hide": false, "instant": true, "range": false, "refId": "E" } ], "title": "Vulnerability by Image", "transformations": [ { "id": "filterFieldsByName", "options": { "include": { "names": [ "image_repository", "image_tag", "Value #A", "Value #B", "Value #C", "Value #D", "Value #E" ] } } }, { "id": "seriesToColumns", "options": { "byField": "image_repository" } }, { "id": "filterFieldsByName", "options": { "include": { "names": [ "image_repository", "Value #A", "Value #B", "Value #C", "Value #D", "Value #E", "image_tag 1" ] } } }, { "id": "organize", "options": { "excludeByName": { "image_tag": false }, "indexByName": {}, "renameByName": { "Value #A": "Critical", "Value #B": "High", "Value #C": "Medium", "Value #D": "Low", "Value #E": "Unknown", "image_repository": "Image", "image_tag": "Tag" } } } ], "type": "table" } ], "title": "Vulnerabilities", "type": "row" }, { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 2 }, "id": 4, "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Critical" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "High" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Medium" }, "properties": [ { "id": "color", "value": { "fixedColor": "dark-yellow", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Low" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Unknown" }, "properties": [ { "id": "color", "value": { "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 3 }, "id": 28, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_resource_configaudits{severity=\"Critical\"})", "instant": true, "legendFormat": "Critical", "range": false, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_resource_configaudits{severity=\"High\"})", "hide": false, "instant": true, "legendFormat": "High", "range": false, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_resource_configaudits{severity=\"Medium\"})", "hide": false, "instant": true, "legendFormat": "Medium", "range": false, "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_resource_configaudits{severity=\"Low\"})", "hide": false, "instant": true, "legendFormat": "Low", "range": false, "refId": "D" } ], "title": "Severity Breakdown of all Misconfiguration", "type": "stat" } ], "title": "Misconfiguration", "type": "row" }, { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 3 }, "id": 8, "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] }, "unit": "none" }, "overrides": [ { "matcher": { "id": "byName", "options": "Critical" }, "properties": [ { "id": "color", "value": { "fixedColor": "red", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "High" }, "properties": [ { "id": "color", "value": { "fixedColor": "orange", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Medium" }, "properties": [ { "id": "color", "value": { "fixedColor": "dark-yellow", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Low" }, "properties": [ { "id": "color", "value": { "fixedColor": "green", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Unknown" }, "properties": [ { "id": "color", "value": { "mode": "fixed" } } ] } ] }, "gridPos": { "h": 9, "w": 24, "x": 0, "y": 4 }, "id": 29, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "center", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "pluginVersion": "9.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_role_rbacassessments{severity=\"Critical\"})", "instant": true, "legendFormat": "Critical", "range": false, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_role_rbacassessments{severity=\"High\"})", "hide": false, "instant": true, "legendFormat": "High", "range": false, "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_role_rbacassessments{severity=\"Medium\"})", "hide": false, "instant": true, "legendFormat": "Medium", "range": false, "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_role_rbacassessments{severity=\"Low\"})", "hide": false, "instant": true, "legendFormat": "Low", "range": false, "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "exemplar": false, "expr": "sum(trivy_role_rbacassessments{severity=\"UNKNOWN\"})", "hide": false, "instant": true, "legendFormat": "Unknown", "range": false, "refId": "E" } ], "title": "Severity Breakdown of RBAC Security Issues", "type": "stat" } ], "title": "RBAC Assessment", "type": "row" }, { "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 4 }, "id": 6, "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "description": "", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "lineInterpolation": "linear", "lineWidth": 3, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 1 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 }, "id": 30, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "editorMode": "code", "expr": "sum(trivy_image_exposedsecrets) by (namespace)", "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Exposed Secrets per namespace", "type": "timeseries" } ], "title": "Exposed Secrets", "type": "row" } ], "refresh": false, "schemaVersion": 37, "style": "dark", "tags": [ "trivy", "trivy operator", "security", "security scanning", "vulnerabilities", "exposed secrets", "misconfiguration" ], "templating": { "list": [ { "current": { "selected": true, "text": "Prometheus", "value": "Prometheus" }, "hide": 0, "includeAll": false, "label": "datasource", "multi": false, "name": "DS_PROMETHEUS", "options": [], "query": "prometheus", "queryValue": "", "refresh": 1, "regex": "", "skipUrlSync": false, "type": "datasource" } ] }, "time": { "from": "now-2d", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Trivy Operator Dashboard", "uid": "ycwPj724k", "version": 12, "weekStart": "", "gnetId": 17813 } ================================================ FILE: cluster/homelab/apps/openbooks/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: openbooks namespace: openbooks spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/openbooks reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/openbooks/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/openbooks/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: openbooks ================================================ FILE: cluster/homelab/apps/paperless-ngx/gateway-api.sensitive.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: paperless-ngx-external namespace: paperless-ngx spec: parentRefs: - name: external namespace: istio-gateway hostnames: - paperless.sgenov.dev rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: paperless-ngx port: 80 sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArQ1QzVGpzYzVaWnU5bHQ2 K25JZG9JNjRnZE1ERkZINTY0U0pidGdNN0NBCnJ4eEVya29tTEdoQllaSW1Ja3V3 YWxqWjZxODdMNUVEUlhzUnZXeW1OckEKLS0tIC9sYkRRNDh4eWNJaWlaamJqVmtM MmdKRmVRQzVWNzVrZHp2U2dmZllnK00KzJ8nbGiRMtzzxRwBY3ixXOiZ3DIl+Idh OEMEBvdYpjVkxL6pXnFmcw1qzvq5ddeGe8m6uuy8u5NO9yxShqrKBA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T14:23:48Z" mac: ENC[AES256_GCM,data:XNuJvx7uQPkB+kJCDopO36GZ44to6sEMU0FpF8nJw+CFqdGdoFzqwDq7ThNXDPGM8rSKU+i8quXl1WVO/WvVcvUf/3+5Qp5s4D0QJBNT2csEbqTI0x0sLSADzyuqs38zFR50OBr23J1feHHiE2jMi4kUniMCmv/NoRrHIeVsihA=,iv:tabpzBbjgqhm9WS0Vv9CDTLzgeKUFUn0MzSJsLbQX9M=,tag:eU3ta9koDdIKLPy9zockZA==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: paperless-ngx-internal namespace: paperless-ngx annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Document Management System gethomepage.dev/group: Knowledge gethomepage.dev/icon: paperless-ngx gethomepage.dev/name: Paperless-NGX gethomepage.dev/widget.type: paperlessngx gethomepage.dev/widget.url: https://paperless.sgenov.dev gethomepage.dev/widget.key: ENC[AES256_GCM,data:Rnzez6tBbfRuqOsJ9hDf9hq1x+bg3uGfokqt1vRhVwP1btqFpOqk472WgPp5njB+vIRq6JwntwFarp93ZaLTdejla7Tn1pzLlvqgnmZms/g/6V4R7hGejklHpF4FBP7l8hTVPKqqYFGrJ4h2dlLORnpmaFRGB+pkQy6hP4XFkszgfOkeehflpoQSNMcLIew3tMRDGGR2sKJ23WN5F9mOSwn0mw==,iv:jwRN7MVVzwvJ1A1WAYlNnzBbLEW6fwiGPf4bSlEDKMo=,tag:2B/jfk+a7V9FTSqmtMdyBw==,type:str] spec: parentRefs: - name: internal namespace: istio-gateway hostnames: - paperless.sgenov.dev rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: paperless-ngx port: 80 sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArQ1QzVGpzYzVaWnU5bHQ2 K25JZG9JNjRnZE1ERkZINTY0U0pidGdNN0NBCnJ4eEVya29tTEdoQllaSW1Ja3V3 YWxqWjZxODdMNUVEUlhzUnZXeW1OckEKLS0tIC9sYkRRNDh4eWNJaWlaamJqVmtM MmdKRmVRQzVWNzVrZHp2U2dmZllnK00KzJ8nbGiRMtzzxRwBY3ixXOiZ3DIl+Idh OEMEBvdYpjVkxL6pXnFmcw1qzvq5ddeGe8m6uuy8u5NO9yxShqrKBA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-11-16T14:23:48Z" mac: ENC[AES256_GCM,data:XNuJvx7uQPkB+kJCDopO36GZ44to6sEMU0FpF8nJw+CFqdGdoFzqwDq7ThNXDPGM8rSKU+i8quXl1WVO/WvVcvUf/3+5Qp5s4D0QJBNT2csEbqTI0x0sLSADzyuqs38zFR50OBr23J1feHHiE2jMi4kUniMCmv/NoRrHIeVsihA=,iv:tabpzBbjgqhm9WS0Vv9CDTLzgeKUFUn0MzSJsLbQX9M=,tag:eU3ta9koDdIKLPy9zockZA==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 ================================================ FILE: cluster/homelab/apps/paperless-ngx/helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: paperless-ngx namespace: paperless-ngx spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: paperless-ngx version: 0.24.1 interval: 10m sourceRef: kind: HelmRepository name: gabe565 namespace: flux-system values: env: PAPERLESS_OCR_LANGUAGES: eng bul PAPERLESS_TIKA_ENABLED: "true" PAPERLESS_TIKA_ENDPOINT: http://tika.tika:9998 PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg.gotenberg:80 PAPERLESS_URL: https://paperless.sgenov.dev podAnnotations: backup.velero.io/backup-volumes: data,media,export,consume redis: image: tag: latest service: main: ports: http: port: 80 image: # -- Image repository repository: ghcr.io/paperless-ngx/paperless-ngx # -- Image pull policy pullPolicy: IfNotPresent # -- Image tag tag: 2.20.15 persistence: data: enabled: true storageClass: longhorn accessMode: ReadWriteOnce size: 10Gi media: enabled: true storageClass: longhorn accessMode: ReadWriteOnce size: 100Gi export: enabled: true storageClass: longhorn accessMode: ReadWriteOnce size: 1Gi consume: enabled: true storageClass: longhorn accessMode: ReadWriteOnce size: 4Gi ================================================ FILE: cluster/homelab/apps/paperless-ngx/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - gateway-api.sensitive.yaml ================================================ FILE: cluster/homelab/apps/reactiveresume/cnpg.yaml ================================================ apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgres annotations: backup.velero.io/backup-volumes: pgdata spec: instances: 1 imageName: ghcr.io/cloudnative-pg/postgresql:18.1 storage: size: 10Gi podSecurityContext: runAsNonRoot: true securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL add: - NET_BIND_SERVICE - CHOWN - FOWNER privileged: false readOnlyRootFilesystem: true runAsNonRoot: true ================================================ FILE: cluster/homelab/apps/reactiveresume/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: reactiveresume spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/reactiveresume reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/reactiveresume/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: reactiveresume resources: - namespace.yaml - secret.sops.yaml - helm-release.yaml - cnpg.yaml ================================================ FILE: cluster/homelab/apps/reactiveresume/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: reactiveresume ================================================ FILE: cluster/homelab/apps/reactiveresume/secret.sops.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: app type: Opaque data: JWT_EXPIRY_TIME: ENC[AES256_GCM,data:P9MdruOYpu8=,iv:33A+J63wTvd4BWKWTtf+DfPMcFaAAhklBA6xUotbBsc=,tag:piTHrEpXxv7f37+u9ie4BA==,type:str] JWT_SECRET: ENC[AES256_GCM,data:KFp2KPjG+E1+mG8sAXUyhP6xVfM=,iv:/7hEcfytngg+vCbjk3YV0LGeDYXvKYUHVCqH16AbXiQ=,tag:qeaOthDLZRIWsHnz1RzZLA==,type:str] PUBLIC_SERVER_URL: ENC[AES256_GCM,data:OkH4qasBiIhuplM6RQl7SLHZ1Qr3SjMWWKcM/1g5aa0fN6oJbbz2Mg==,iv:MAeGwn0Y4daJ4DywSWrC29F+SnV1qBpww2zVwO6uZtg=,tag:CGsvdEEJQpd1sWEi3lrE+g==,type:str] PUBLIC_URL: ENC[AES256_GCM,data:gqkph/fPsb+4soHrtzko4AdY2sTHoce4WYk9LQ+2Ixl9LGZq,iv:1oQaQV9Vnf7goq6+A8rGmy4glpi7maBFB2xG3LB9TM0=,tag:nWqzOgo8fCBRtuLknbXWdg==,type:str] SECRET_KEY: ENC[AES256_GCM,data:/zhSKEVPyMQSkKGX6jrhR1Gqnic=,iv:BHiVg4PXboyHhhrnCn6xKWvDT1PCmkyNFVS3GSWGqHM=,tag:VLFuW7thQK7TvWsgGT3LBw==,type:str] STORAGE_S3_ENABLED: ENC[AES256_GCM,data:WHJ568szLpQ=,iv:CtRhSbcb51Ofw7KhEBeGmaB6Wm6C4Zub26C3C1ez/oI=,tag:OM/MmjEzjCGsu+C8xsLcYg==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSRDV3cXpjaGF5N0J6WURE a2duMXA5b3BPQVpLbnZMUVkrRUtjV1pzbjI4CnZzRUtJL213S1JZRC9WVm9MV0Zy T2UwK1NaZjlGcGJQemdpWEsrczlTNVUKLS0tIFdlYkErRjhoMW5IZVJpUG5BUnFq K1pIRTh5YWdneGFkNVBOaFZyYk1yTzQK0bp8VvFMi86o3wqzvfa00AhEBn8l9+rv Zju2NZNZFYtoY59zqA45f4BxbGW2dZTFiJC3u6JY84qZmzLCJBC+OQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-18T20:05:40Z" mac: ENC[AES256_GCM,data:/+SeOCEhLh4xFeZZnW13dRkf3EVKabhgPpvHH5hNLcGiOZwm3UMs+8spxeU0mAg93lATbexIjANp/RMUPmS/3ANdg4SgxY0ZHNakvhmU/KfOfgD21BLDQocnPMv8TlbcGi3y6Bg2geh4sYCMnfoRUMH9S8X4hQg4B9mQUEtp+jU=,iv:t4R5EbS0pSEk5kh2sDNhzuF3qQy9D6H/zNwSpURoLj0=,tag:ugzOATJ6lvZHJ2FUFjxyMQ==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/replacedby/database.yaml ================================================ apiVersion: k8s.mariadb.com/v1alpha1 kind: MariaDB metadata: name: mariadb spec: inheritMetadata: annotations: backup.velero.io/backup-volumes: storage storage: size: 15Gi replicas: 3 replication: enabled: true primary: # Whether the operator should automatically perform primary failover. autoFailover: true # Duration before performing primary failover. autoFailoverDelay: 0s # Trigger a switchover by declaring the desired primary index. # podIndex: 0 tls: enabled: false --- apiVersion: k8s.mariadb.com/v1alpha1 kind: Database metadata: name: app spec: mariaDbRef: name: mariadb characterSet: utf8 collate: utf8_general_ci cleanupPolicy: Delete requeueInterval: 10h retryInterval: 30s ================================================ FILE: cluster/homelab/apps/replacedby/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: replacedby labels: app.kubernetes.io/instance: replacedby app.kubernetes.io/name: replacedby spec: replicas: 3 strategy: rollingUpdate: maxUnavailable: 1 selector: matchLabels: app.kubernetes.io/instance: replacedby app.kubernetes.io/name: replacedby template: metadata: labels: app.kubernetes.io/instance: replacedby app.kubernetes.io/name: replacedby spec: restartPolicy: Always containers: - name: replacedby image: ghcr.io/michaelpalacce/replacedby:0.1.1769382806 imagePullPolicy: IfNotPresent resources: requests: cpu: 1 memory: 1Gi limits: cpu: 1 memory: 1Gi ports: - name: web containerPort: 8080 securityContext: capabilities: drop: - "ALL" add: - CHOWN - SETUID - SETGID env: - name: PORT value: ":8080" - name: ENV value: "prod" - name: GIN_MODE value: "release" - name: MYSQL_PORT value: "3306" - name: MYSQL_HOSTNAME value: "mariadb-primary" - name: MYSQL_DATABASE value: "app" - name: MYSQL_ROOT_PASSWORD #unused... need to fix in app.. w/e valueFrom: secretKeyRef: name: mariadb-root key: password - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mariadb-root key: password - name: MYSQL_USER value: "root" livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 tcpSocket: port: 8080 timeoutSeconds: 2 startupProbe: failureThreshold: 20 timeoutSeconds: 2 tcpSocket: port: 8080 ================================================ FILE: cluster/homelab/apps/replacedby/gateway-api.yaml ================================================ --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: replacedby-external spec: parentRefs: - name: external-replacedby namespace: istio-gateway hostnames: - "replacedby.net" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: replacedby port: 8080 ================================================ FILE: cluster/homelab/apps/replacedby/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: replacedby resources: - namespace.yaml - deployment.yaml - service.yaml - gateway-api.yaml - database.yaml ================================================ FILE: cluster/homelab/apps/replacedby/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: replacedby ================================================ FILE: cluster/homelab/apps/replacedby/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: replacedby spec: selector: app.kubernetes.io/instance: replacedby app.kubernetes.io/name: replacedby ports: - name: web protocol: TCP port: 8080 ================================================ FILE: cluster/homelab/apps/storage/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: storage namespace: storage spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/storage reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/storage/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/storage/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: storage ================================================ FILE: cluster/homelab/apps/tika/helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: tika namespace: tika spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: tika version: 3.2.2 interval: 10m sourceRef: kind: HelmRepository name: tika namespace: flux-system values: image: repository: apache/tika tag: 3.3.0.0-full securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 35002 runAsGroup: 35002 resources: limits: cpu: "1" memory: 1000Mi requests: cpu: 500m memory: 500Mi config: base_url: "https://tika.sgenov.dev" # ingress: # ingressClassName: nginx # enabled: true # annotations: # hosts: # - host: tika.sgenov.dev # paths: # - path: / # tls: # - secretName: ingress # hosts: # - '*.sgenov.dev' ================================================ FILE: cluster/homelab/apps/tika/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml - helm-release.yaml ================================================ FILE: cluster/homelab/apps/tika/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: tika ================================================ FILE: cluster/homelab/apps/uptimekuma/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: uptimekuma namespace: uptimekuma spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/uptimekuma reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: uptimekuma: replicas: 1 ================================================ FILE: cluster/homelab/apps/uptimekuma/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/apps/uptimekuma/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: uptimekuma ================================================ FILE: cluster/homelab/apps/vikunja/cnpg.yaml ================================================ apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-postgres annotations: backup.velero.io/backup-volumes: pgdata spec: instances: 1 imageName: ghcr.io/cloudnative-pg/postgresql:18.1 storage: size: 10Gi podSecurityContext: runAsNonRoot: true securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL add: - NET_BIND_SERVICE - CHOWN - FOWNER privileged: false readOnlyRootFilesystem: true runAsNonRoot: true ================================================ FILE: cluster/homelab/apps/vikunja/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: vikunja spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/vikunja reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/vikunja/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: vikunja resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml - cnpg.yaml ================================================ FILE: cluster/homelab/apps/vikunja/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: vikunja ================================================ FILE: cluster/homelab/apps/vikunja/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: app data: JWT_SECRET: ENC[AES256_GCM,data:HV8lEczdf0r5M86z55Sg1ayJiuZw4QF3zFfBwg==,iv:hQR416W0+cXl0g2AW1xnMdz8RtJKU8SMl2p4dZHTFJM=,tag:mhewMNefOsOknkqTbPy9Lg==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPbDQ1S1gwVXNhZHdWQ2k4 TllvK3owU0hWbjA1NFd2eW01cG5RdTcwY21ZCjdkWVdPNGt6bmwrWERiQlJ4d1h0 WUlxUmE2WDlIVTJ6SjNkWE56UlFwQ2sKLS0tIEsyRUNmYldwblBzelBDR0JuQkNT cjJiUFNvV1FxUktJNE95NlNUdDNMdDgKmkERB0veEzIccXbBf6iuggkuPI4TnXMj XOU0EkCIOIKorc5Ww6mc/nrPJwltL6zCEn4m9oxQ7JhpxWJkAD96lQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-19T20:21:59Z" mac: ENC[AES256_GCM,data:F1PI6Lbkf3QpBpy72aCRAZevbElX2TQzUN+32zidvfXPWYOkSz5Du7YflzscoX9bD0iTV5Z9zJQ0YjXiOtfFEjpT5rUPsJ69kPqpBVoUcoqe9lejX2++noUvHMP+ZrgKP8xDQiAuRoilfSnOERr3UDsQ8WFNkb/o/dP4Ls8QTqM=,iv:R2MAWCXdMIaLwJzZUwGyw1YqRA78fuWlnlxJzRldFS0=,tag:Si07xwoL1gAz38quo7gLIA==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/apps/wallabag/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: wallabag namespace: wallabag spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/wallabag reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system values: wallabag: replicas: 1 ================================================ FILE: cluster/homelab/apps/wallabag/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml ================================================ FILE: cluster/homelab/apps/wallabag/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: wallabag ================================================ FILE: cluster/homelab/apps/wallabag/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: app namespace: wallabag data: SYMFONY__ENV__DATABASE_DRIVER: ENC[AES256_GCM,data:cVVf28Vlw0yQE2PE,iv:Won29sNJKeVSLZW49yDGU0pd4w3FSDPl7SjB9KSiyEc=,tag:Lg+EIspPQehp/Aa97bbL+w==,type:str] SYMFONY__ENV__DATABASE_PORT: ENC[AES256_GCM,data:qujqBhKN870=,iv:wFoLBtAf/yKpToxGBpZNMMHVrHvKClgnWLwGNsLOZFo=,tag:Rm+KizBSIGyKOAn5UsXMFw==,type:str] SYMFONY__ENV__DATABASE_NAME: ENC[AES256_GCM,data:rWlpmX77nYhpCLtr,iv:8vnXRHptGLk5alkd6ZXO/XZjlNGsxjMKVtE8JTguY8U=,tag:k92wlKm8pl/zlmfr/Le3mw==,type:str] SYMFONY__ENV__DATABASE_USER: ENC[AES256_GCM,data:28ytQy20OTreqb59,iv:Q8HvVHQTvoNEWagMmUjFa2n5UceHB0GQe2dNmyqQF2Y=,tag:Va3xsMcFEOjOueaapG6kAQ==,type:str] SYMFONY__ENV__DATABASE_PASSWORD: ENC[AES256_GCM,data:AV+ELghahKDaN/Wz,iv:d9GssB8dgIIOIGYXz8eNiz/EIOf38HYBLVJgBCKRsLY=,tag:qU0LRMhtgWv4VWI0qJOvdQ==,type:str] SYMFONY__ENV__DATABASE_HOST: ENC[AES256_GCM,data:0uRbZTTzUv3JoE8lC7mcQITxLsm5ND1i,iv:wJVcokt0NA8T6t8c87PiDbATFxkQVYp1DsRDcoZR2bY=,tag:d6BZn1baCnD9ZAdIgpjq/w==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSRTc1M0ExK2JtK0dBR1Uy LzhEbXJDdkxSajVjODNiZHJPQlR4d2gzeW5jCnVQSFgxRUxtbkhtOXoySzl1ZU1v L1JnRUk0TlpENG42dTVaSFMwZVFSNEEKLS0tIE1QeHpxNkg2TU8zY0JtWE5tOWlX QU1LcU05dE10ZjJ1UWxKUy9YNTVYbFUKFPfOI/37nSoRj0/LOmhzgJ63k69+lHl7 apC4Ycq3es3ner5NyGLnKeq2lTFpZXlsd8m8UYidGORE2ndpN9mihA== -----END AGE ENCRYPTED FILE----- lastmodified: "2024-08-03T18:13:49Z" mac: ENC[AES256_GCM,data:8Izus6Qvc0NBCfNI3cim96Elw8agrf0l3O3DVaYh/ApyAZuf41/PyctTnY64gWMB5Yt/LonyuWRYnYZ5un1bWTMWmjY0H+GJVLUNG+QFW+RssR8L2voZvI8/+1hFC1PjyVrCrvbZem+achri/tuCMBpdjjh4Xlirsy1Gx5kRkMo=,iv:DnyV9ksKEGiZE/zKqkhk1ReHYwNyUmsSqev2e7aCVAQ=,tag:KpTHnsamxyv1JbtpKG+8Qg==,type:str] pgp: [] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.8.1 --- kind: Secret apiVersion: v1 type: Opaque metadata: name: db namespace: wallabag data: POSTGRES_USER: ENC[AES256_GCM,data:cnsgtR213+9PMrZo,iv:rRfDZm+n9hiQb2J3ljwCtM1UmmnYNu/9ETxRQUz2As4=,tag:jJ9tCfhokr55omhpWxPXVg==,type:str] POSTGRES_DB: ENC[AES256_GCM,data:0ssrdd8l2Hr6u1mq,iv:mIUmLRfo8A2fIbzKDWk5eQUAfvpLuxuavYFQ1Ch7QQM=,tag:N+s8D1QW7YcFMMKOM+GQBQ==,type:str] POSTGRES_PASSWORD: ENC[AES256_GCM,data:SiHbaUDGFYcD8pWL,iv:U8m08t8dzUjBIW7jXfD7P+xDltx+Eiybese3g1n2CsA=,tag:ZIrEFT41w4tHh4AVKRwDQQ==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSRTc1M0ExK2JtK0dBR1Uy LzhEbXJDdkxSajVjODNiZHJPQlR4d2gzeW5jCnVQSFgxRUxtbkhtOXoySzl1ZU1v L1JnRUk0TlpENG42dTVaSFMwZVFSNEEKLS0tIE1QeHpxNkg2TU8zY0JtWE5tOWlX QU1LcU05dE10ZjJ1UWxKUy9YNTVYbFUKFPfOI/37nSoRj0/LOmhzgJ63k69+lHl7 apC4Ycq3es3ner5NyGLnKeq2lTFpZXlsd8m8UYidGORE2ndpN9mihA== -----END AGE ENCRYPTED FILE----- lastmodified: "2024-08-03T18:13:49Z" mac: ENC[AES256_GCM,data:8Izus6Qvc0NBCfNI3cim96Elw8agrf0l3O3DVaYh/ApyAZuf41/PyctTnY64gWMB5Yt/LonyuWRYnYZ5un1bWTMWmjY0H+GJVLUNG+QFW+RssR8L2voZvI8/+1hFC1PjyVrCrvbZem+achri/tuCMBpdjjh4Xlirsy1Gx5kRkMo=,iv:DnyV9ksKEGiZE/zKqkhk1ReHYwNyUmsSqev2e7aCVAQ=,tag:KpTHnsamxyv1JbtpKG+8Qg==,type:str] pgp: [] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.8.1 ================================================ FILE: cluster/homelab/apps/website/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: website spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/website reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/apps/website/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: website resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml ================================================ FILE: cluster/homelab/apps/website/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: website ================================================ FILE: cluster/homelab/apps/website/secret.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: website data: REQUEST_TIMEOUT: ENC[AES256_GCM,data:iEBil+HGF8s=,iv:72dkrYUQAD1wnEEKKxgHnM5v1Pw01wJ3ZVWP+LxNvMo=,tag:3OFJBFgVdhj9zGXzs9xUhA==,type:str] ENV: ENC[AES256_GCM,data:+WiSwEFzDw5pP5A1hxOKJQ==,iv:QGlRfBVPsV++S21QTYL1HN44AV+i4pCtJwj7PGGSs/E=,tag:ONGlpovBj0Qw3zpFQ87ViQ==,type:str] USER: ENC[AES256_GCM,data:DIL062NtREM=,iv:FzgDHteBjfeEhXOcFhXOUVM16p/p5yv82aU6tHOcLBw=,tag:G8hd54vIfkF6OzStcH49cA==,type:str] PASS: ENC[AES256_GCM,data:bGjFSvpPxb3TVmT9T344Jzxbh64=,iv:xAoeJCYz9j9ZNi36e0QxxJ7sExmePa2gXL0u3lfYsWc=,tag:hcMXhgEopo8ZruW6hAiXUw==,type:str] PM2_PUBLIC_KEY: ENC[AES256_GCM,data:3Z0Lte5GeVP98K+Fov1aplVNzhc=,iv:k9RpIXhIoiQcLzh9w6LAPqius8hByvHNZzpRBPFDFHA=,tag:5o1FjymZJfMzd2D8pO5FaA==,type:str] PM2_SECRET_KEY: ENC[AES256_GCM,data:nd4N9dKztdXlCGBkZGywUNgPpdg=,iv:PpUxf9yZ6bHuWKjPiPQeQaPlR+spFvySQ6Y2TqLqovM=,tag:QKRVEPWpCvfCPNm4muhGJw==,type:str] DATA_PATH: ENC[AES256_GCM,data:SwwjHMBdICU=,iv:nXsiSlz0jy0qF6WWXYRAeJtbip89OhwDvTs8hHYB7h8=,tag:VbqSBgo9TPLzm30OxonbbQ==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2bmg1VGE1dkdLZTREVndZ WkRXN1RLYzJjSS9RZWl1TTZ0WTNsWG4zMDBjCktjelZ3VE9KZ0VEZGExQUZhcXFu R1pKanNOUVN2ampGV1JEOTdjV0J0aDgKLS0tIEpRYmxsOGhkbDdRTm8zR3dYZ3NI RWg3NU5DZkMvTHRxSzZmVHpXNlpvLzAKv1QZr1vuxP0aNdLM/4d8uYBptxs4KzoP Uxxvseg5Eo6OGvMnUHTnK33OHodmmEbL7KLGrBPUpSHo1P6i/Lpnow== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-10-24T18:58:53Z" mac: ENC[AES256_GCM,data:TIUnPV9grmOUV79MZvAx5yTGuxQH8PnZX4Yg3uQ9CPRaQfpq6vCp4riik5ZstVpwqV9NYVIu7XT1hjbfDVGmYIWt0RJGYwyBjywuhZ04beJcWTrI+ms9TKhw9LwQLzsAOQ7FtWzGGGwrb0l886wQdOdjoWKyCh77j/RVsY22jBs=,iv:W+mZanSpI+HmzHT7V7QFMS+eSObisDVyJ3lyNcrSrTI=,tag:nJ5zcDUHWFAkMF5pr4O4ow==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/base/.sops.yaml ================================================ creation_rules: # Secrets - path_regex: .*/*secret.sops.yaml encrypted_regex: ^(data|stringData|annotations|)$ pgp: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn # Config Maps - path_regex: .*/*config.sops.yaml encrypted_regex: ^(data|stringData|annotations|)$ pgp: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn # Ingress Hosts - path_regex: .*/*gateway-api.sops.yaml encrypted_regex: ^(rules|annotations|)$ pgp: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn # helm-release - path_regex: .*/*helm-release.sops.yaml encrypted_regex: ^(values)$ pgp: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn # alertmanager alert - path_regex: .*/*alert.sops.yaml encrypted_regex: ^(receivers)$ pgp: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn # sensitive... just general stuff I don't want to be seen - path_regex: .*/*sensitive.sops.yaml encrypted_regex: (?i)password|webhook_url|token|key pgp: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn ================================================ FILE: cluster/homelab/base/apps.yaml ================================================ --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: apps namespace: flux-system spec: interval: 10m dependsOn: - name: core path: ./cluster/homelab/apps prune: true decryption: provider: sops secretRef: name: sops-age sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/base/configs.yaml ================================================ --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: configs namespace: flux-system spec: interval: 10m dependsOn: - name: core path: ./cluster/homelab/configs prune: true decryption: provider: sops secretRef: name: sops-age sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/base/core.yaml ================================================ --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: core namespace: flux-system spec: interval: 10m dependsOn: - name: helm - name: crds path: ./cluster/homelab/core prune: true decryption: provider: sops secretRef: name: sops-age sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/base/crds.yaml ================================================ --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: crds namespace: flux-system spec: interval: 10m path: ./cluster/homelab/crds prune: true decryption: provider: sops secretRef: name: sops-age sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/base/flux-system/gotk-components.yaml ================================================ --- # This manifest was generated by flux. DO NOT EDIT. # Flux Version: v2.7.5 # Components: source-controller,kustomize-controller,helm-controller,notification-controller apiVersion: v1 kind: Namespace metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: latest name: flux-system --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: allow-egress namespace: flux-system spec: egress: - {} ingress: - from: - podSelector: {} podSelector: {} policyTypes: - Ingress - Egress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: allow-scraping namespace: flux-system spec: ingress: - from: - namespaceSelector: {} ports: - port: 8080 protocol: TCP podSelector: {} policyTypes: - Ingress --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: allow-webhooks namespace: flux-system spec: ingress: - from: - namespaceSelector: {} podSelector: matchLabels: app: notification-controller policyTypes: - Ingress --- apiVersion: v1 kind: ResourceQuota metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: critical-pods-flux-system namespace: flux-system spec: hard: pods: "1000" scopeSelector: matchExpressions: - operator: In scopeName: PriorityClass values: - system-node-critical - system-cluster-critical --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: crd-controller-flux-system rules: - apiGroups: - source.toolkit.fluxcd.io resources: - '*' verbs: - '*' - apiGroups: - kustomize.toolkit.fluxcd.io resources: - '*' verbs: - '*' - apiGroups: - helm.toolkit.fluxcd.io resources: - '*' verbs: - '*' - apiGroups: - notification.toolkit.fluxcd.io resources: - '*' verbs: - '*' - apiGroups: - image.toolkit.fluxcd.io resources: - '*' verbs: - '*' - apiGroups: - source.extensions.fluxcd.io resources: - '*' verbs: - '*' - apiGroups: - "" resources: - namespaces - secrets - configmaps - serviceaccounts verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - "" resources: - configmaps verbs: - get - list - watch - create - update - patch - delete - apiGroups: - "" resources: - configmaps/status verbs: - get - update - patch - apiGroups: - coordination.k8s.io resources: - leases verbs: - get - list - watch - create - update - patch - delete - apiGroups: - "" resources: - serviceaccounts/token verbs: - create - nonResourceURLs: - /livez/ping verbs: - head --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" name: flux-edit-flux-system rules: - apiGroups: - notification.toolkit.fluxcd.io - source.toolkit.fluxcd.io - source.extensions.fluxcd.io - helm.toolkit.fluxcd.io - image.toolkit.fluxcd.io - kustomize.toolkit.fluxcd.io resources: - '*' verbs: - create - delete - deletecollection - patch - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 rbac.authorization.k8s.io/aggregate-to-admin: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-view: "true" name: flux-view-flux-system rules: - apiGroups: - notification.toolkit.fluxcd.io - source.toolkit.fluxcd.io - source.extensions.fluxcd.io - helm.toolkit.fluxcd.io - image.toolkit.fluxcd.io - kustomize.toolkit.fluxcd.io resources: - '*' verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: cluster-reconciler-flux-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kustomize-controller namespace: flux-system - kind: ServiceAccount name: helm-controller namespace: flux-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: crd-controller-flux-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: crd-controller-flux-system subjects: - kind: ServiceAccount name: kustomize-controller namespace: flux-system - kind: ServiceAccount name: helm-controller namespace: flux-system - kind: ServiceAccount name: source-controller namespace: flux-system - kind: ServiceAccount name: notification-controller namespace: flux-system - kind: ServiceAccount name: image-reflector-controller namespace: flux-system - kind: ServiceAccount name: image-automation-controller namespace: flux-system - kind: ServiceAccount name: source-watcher namespace: flux-system --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: buckets.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io names: kind: Bucket listKind: BucketList plural: buckets singular: bucket scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.endpoint name: Endpoint type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v1 schema: openAPIV3Schema: description: Bucket is the Schema for the buckets API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- BucketSpec specifies the required configuration to produce an Artifact for an object storage bucket. properties: bucketName: description: BucketName is the name of the object storage bucket. type: string certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the bucket. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. This field is only supported for the `generic` provider. properties: name: description: Name of the referent. type: string required: - name type: object endpoint: description: Endpoint is the object storage address the BucketName is located at. type: string ignore: description: |- Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are. type: string insecure: description: Insecure allows connecting to a non-TLS HTTP Endpoint. type: boolean interval: description: |- Interval at which the Bucket Endpoint is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string prefix: description: Prefix to use for server-side filtering of files in the Bucket. type: string provider: default: generic description: |- Provider of the object storage bucket. Defaults to 'generic', which expects an S3 (API) compatible object storage. enum: - generic - aws - gcp - azure type: string proxySecretRef: description: |- ProxySecretRef specifies the Secret containing the proxy configuration to use while communicating with the Bucket server. properties: name: description: Name of the referent. type: string required: - name type: object region: description: Region of the Endpoint where the BucketName is located in. type: string secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the Bucket. properties: name: description: Name of the referent. type: string required: - name type: object serviceAccountName: description: |- ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate the bucket. This field is only supported for the 'gcp' and 'aws' providers. For more information about workload identity: https://fluxcd.io/flux/components/source/buckets/#workload-identity type: string sts: description: |- STS specifies the required configuration to use a Security Token Service for fetching temporary credentials to authenticate in a Bucket provider. This field is only supported for the `aws` and `generic` providers. properties: certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the STS endpoint. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. This field is only supported for the `ldap` provider. properties: name: description: Name of the referent. type: string required: - name type: object endpoint: description: |- Endpoint is the HTTP/S endpoint of the Security Token Service from where temporary credentials will be fetched. pattern: ^(http|https)://.*$ type: string provider: description: Provider of the Security Token Service. enum: - aws - ldap type: string secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the STS endpoint. This Secret must contain the fields `username` and `password` and is supported only for the `ldap` provider. properties: name: description: Name of the referent. type: string required: - name type: object required: - endpoint - provider type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this Bucket. type: boolean timeout: default: 60s description: Timeout for fetch operations, defaults to 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string required: - bucketName - endpoint - interval type: object x-kubernetes-validations: - message: STS configuration is only supported for the 'aws' and 'generic' Bucket providers rule: self.provider == 'aws' || self.provider == 'generic' || !has(self.sts) - message: '''aws'' is the only supported STS provider for the ''aws'' Bucket provider' rule: self.provider != 'aws' || !has(self.sts) || self.sts.provider == 'aws' - message: '''ldap'' is the only supported STS provider for the ''generic'' Bucket provider' rule: self.provider != 'generic' || !has(self.sts) || self.sts.provider == 'ldap' - message: spec.sts.secretRef is not required for the 'aws' STS provider rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.secretRef)' - message: spec.sts.certSecretRef is not required for the 'aws' STS provider rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.certSecretRef)' - message: ServiceAccountName is not supported for the 'generic' Bucket provider rule: self.provider != 'generic' || !has(self.serviceAccountName) - message: cannot set both .spec.secretRef and .spec.serviceAccountName rule: '!has(self.secretRef) || !has(self.serviceAccountName)' status: default: observedGeneration: -1 description: BucketStatus records the observed state of a Bucket. properties: artifact: description: Artifact represents the last successful Bucket reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the Bucket. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation of the Bucket object. format: int64 type: integer observedIgnore: description: |- ObservedIgnore is the observed exclusion patterns used for constructing the source artifact. type: string url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact data is recommended. type: string type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.endpoint name: Endpoint type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 Bucket is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: Bucket is the Schema for the buckets API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- BucketSpec specifies the required configuration to produce an Artifact for an object storage bucket. properties: accessFrom: description: |- AccessFrom specifies an Access Control List for allowing cross-namespace references to this object. NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 properties: namespaceSelectors: description: |- NamespaceSelectors is the list of namespace selectors to which this ACL applies. Items in this list are evaluated using a logical OR operation. items: description: |- NamespaceSelector selects the namespaces to which this ACL applies. An empty map of MatchLabels matches all namespaces in a cluster. properties: matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object type: array required: - namespaceSelectors type: object bucketName: description: BucketName is the name of the object storage bucket. type: string certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the bucket. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. This field is only supported for the `generic` provider. properties: name: description: Name of the referent. type: string required: - name type: object endpoint: description: Endpoint is the object storage address the BucketName is located at. type: string ignore: description: |- Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are. type: string insecure: description: Insecure allows connecting to a non-TLS HTTP Endpoint. type: boolean interval: description: |- Interval at which the Bucket Endpoint is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string prefix: description: Prefix to use for server-side filtering of files in the Bucket. type: string provider: default: generic description: |- Provider of the object storage bucket. Defaults to 'generic', which expects an S3 (API) compatible object storage. enum: - generic - aws - gcp - azure type: string proxySecretRef: description: |- ProxySecretRef specifies the Secret containing the proxy configuration to use while communicating with the Bucket server. properties: name: description: Name of the referent. type: string required: - name type: object region: description: Region of the Endpoint where the BucketName is located in. type: string secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the Bucket. properties: name: description: Name of the referent. type: string required: - name type: object sts: description: |- STS specifies the required configuration to use a Security Token Service for fetching temporary credentials to authenticate in a Bucket provider. This field is only supported for the `aws` and `generic` providers. properties: certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the STS endpoint. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. This field is only supported for the `ldap` provider. properties: name: description: Name of the referent. type: string required: - name type: object endpoint: description: |- Endpoint is the HTTP/S endpoint of the Security Token Service from where temporary credentials will be fetched. pattern: ^(http|https)://.*$ type: string provider: description: Provider of the Security Token Service. enum: - aws - ldap type: string secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the STS endpoint. This Secret must contain the fields `username` and `password` and is supported only for the `ldap` provider. properties: name: description: Name of the referent. type: string required: - name type: object required: - endpoint - provider type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this Bucket. type: boolean timeout: default: 60s description: Timeout for fetch operations, defaults to 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string required: - bucketName - endpoint - interval type: object x-kubernetes-validations: - message: STS configuration is only supported for the 'aws' and 'generic' Bucket providers rule: self.provider == 'aws' || self.provider == 'generic' || !has(self.sts) - message: '''aws'' is the only supported STS provider for the ''aws'' Bucket provider' rule: self.provider != 'aws' || !has(self.sts) || self.sts.provider == 'aws' - message: '''ldap'' is the only supported STS provider for the ''generic'' Bucket provider' rule: self.provider != 'generic' || !has(self.sts) || self.sts.provider == 'ldap' - message: spec.sts.secretRef is not required for the 'aws' STS provider rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.secretRef)' - message: spec.sts.certSecretRef is not required for the 'aws' STS provider rule: '!has(self.sts) || self.sts.provider != ''aws'' || !has(self.sts.certSecretRef)' status: default: observedGeneration: -1 description: BucketStatus records the observed state of a Bucket. properties: artifact: description: Artifact represents the last successful Bucket reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the Bucket. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation of the Bucket object. format: int64 type: integer observedIgnore: description: |- ObservedIgnore is the observed exclusion patterns used for constructing the source artifact. type: string url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact data is recommended. type: string type: object type: object served: true storage: false subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: externalartifacts.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io names: kind: ExternalArtifact listKind: ExternalArtifactList plural: externalartifacts singular: externalartifact scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string - jsonPath: .spec.sourceRef.name name: Source type: string name: v1 schema: openAPIV3Schema: description: ExternalArtifact is the Schema for the external artifacts API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: ExternalArtifactSpec defines the desired state of ExternalArtifact properties: sourceRef: description: |- SourceRef points to the Kubernetes custom resource for which the artifact is generated. properties: apiVersion: description: API version of the referent, if not specified the Kubernetes preferred version will be used. type: string kind: description: Kind of the referent. type: string name: description: Name of the referent. type: string namespace: description: Namespace of the referent, when not specified it acts as LocalObjectReference. type: string required: - kind - name type: object type: object status: description: ExternalArtifactStatus defines the observed state of ExternalArtifact properties: artifact: description: Artifact represents the output of an ExternalArtifact reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the ExternalArtifact. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array type: object type: object served: true storage: true subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: gitrepositories.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io names: kind: GitRepository listKind: GitRepositoryList plural: gitrepositories shortNames: - gitrepo singular: gitrepository scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.url name: URL type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v1 schema: openAPIV3Schema: description: GitRepository is the Schema for the gitrepositories API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- GitRepositorySpec specifies the required configuration to produce an Artifact for a Git repository. properties: ignore: description: |- Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are. type: string include: description: |- Include specifies a list of GitRepository resources which Artifacts should be included in the Artifact produced for this GitRepository. items: description: |- GitRepositoryInclude specifies a local reference to a GitRepository which Artifact (sub-)contents must be included, and where they should be placed. properties: fromPath: description: |- FromPath specifies the path to copy contents from, defaults to the root of the Artifact. type: string repository: description: |- GitRepositoryRef specifies the GitRepository which Artifact contents must be included. properties: name: description: Name of the referent. type: string required: - name type: object toPath: description: |- ToPath specifies the path to copy contents to, defaults to the name of the GitRepositoryRef. type: string required: - repository type: object type: array interval: description: |- Interval at which the GitRepository URL is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string provider: description: |- Provider used for authentication, can be 'azure', 'github', 'generic'. When not specified, defaults to 'generic'. enum: - generic - azure - github type: string proxySecretRef: description: |- ProxySecretRef specifies the Secret containing the proxy configuration to use while communicating with the Git server. properties: name: description: Name of the referent. type: string required: - name type: object recurseSubmodules: description: |- RecurseSubmodules enables the initialization of all submodules within the GitRepository as cloned from the URL, using their default settings. type: boolean ref: description: |- Reference specifies the Git reference to resolve and monitor for changes, defaults to the 'master' branch. properties: branch: description: Branch to check out, defaults to 'master' if no other field is defined. type: string commit: description: |- Commit SHA to check out, takes precedence over all reference fields. This can be combined with Branch to shallow clone the branch, in which the commit is expected to exist. type: string name: description: |- Name of the reference to check out; takes precedence over Branch, Tag and SemVer. It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head" type: string semver: description: SemVer tag expression to check out, takes precedence over Tag. type: string tag: description: Tag to check out, takes precedence over Branch. type: string type: object secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the GitRepository. For HTTPS repositories the Secret must contain 'username' and 'password' fields for basic auth or 'bearerToken' field for token auth. For SSH repositories the Secret must contain 'identity' and 'known_hosts' fields. properties: name: description: Name of the referent. type: string required: - name type: object serviceAccountName: description: |- ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate to the GitRepository. This field is only supported for 'azure' provider. type: string sparseCheckout: description: |- SparseCheckout specifies a list of directories to checkout when cloning the repository. If specified, only these directories are included in the Artifact produced for this GitRepository. items: type: string type: array suspend: description: |- Suspend tells the controller to suspend the reconciliation of this GitRepository. type: boolean timeout: default: 60s description: Timeout for Git operations like cloning, defaults to 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string url: description: URL specifies the Git repository URL, it can be an HTTP/S or SSH address. pattern: ^(http|https|ssh)://.*$ type: string verify: description: |- Verification specifies the configuration to verify the Git commit signature(s). properties: mode: default: HEAD description: |- Mode specifies which Git object(s) should be verified. The variants "head" and "HEAD" both imply the same thing, i.e. verify the commit that the HEAD of the Git repository points to. The variant "head" solely exists to ensure backwards compatibility. enum: - head - HEAD - Tag - TagAndHEAD type: string secretRef: description: |- SecretRef specifies the Secret containing the public keys of trusted Git authors. properties: name: description: Name of the referent. type: string required: - name type: object required: - secretRef type: object required: - interval - url type: object x-kubernetes-validations: - message: serviceAccountName can only be set when provider is 'azure' rule: '!has(self.serviceAccountName) || (has(self.provider) && self.provider == ''azure'')' status: default: observedGeneration: -1 description: GitRepositoryStatus records the observed state of a Git repository. properties: artifact: description: Artifact represents the last successful GitRepository reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the GitRepository. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array includedArtifacts: description: |- IncludedArtifacts contains a list of the last successfully included Artifacts as instructed by GitRepositorySpec.Include. items: description: Artifact represents the output of a Source reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: |- ObservedGeneration is the last observed generation of the GitRepository object. format: int64 type: integer observedIgnore: description: |- ObservedIgnore is the observed exclusion patterns used for constructing the source artifact. type: string observedInclude: description: |- ObservedInclude is the observed list of GitRepository resources used to produce the current Artifact. items: description: |- GitRepositoryInclude specifies a local reference to a GitRepository which Artifact (sub-)contents must be included, and where they should be placed. properties: fromPath: description: |- FromPath specifies the path to copy contents from, defaults to the root of the Artifact. type: string repository: description: |- GitRepositoryRef specifies the GitRepository which Artifact contents must be included. properties: name: description: Name of the referent. type: string required: - name type: object toPath: description: |- ToPath specifies the path to copy contents to, defaults to the name of the GitRepositoryRef. type: string required: - repository type: object type: array observedRecurseSubmodules: description: |- ObservedRecurseSubmodules is the observed resource submodules configuration used to produce the current Artifact. type: boolean observedSparseCheckout: description: |- ObservedSparseCheckout is the observed list of directories used to produce the current Artifact. items: type: string type: array sourceVerificationMode: description: |- SourceVerificationMode is the last used verification mode indicating which Git object(s) have been verified. type: string type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.url name: URL type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 GitRepository is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: GitRepository is the Schema for the gitrepositories API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- GitRepositorySpec specifies the required configuration to produce an Artifact for a Git repository. properties: accessFrom: description: |- AccessFrom specifies an Access Control List for allowing cross-namespace references to this object. NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 properties: namespaceSelectors: description: |- NamespaceSelectors is the list of namespace selectors to which this ACL applies. Items in this list are evaluated using a logical OR operation. items: description: |- NamespaceSelector selects the namespaces to which this ACL applies. An empty map of MatchLabels matches all namespaces in a cluster. properties: matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object type: array required: - namespaceSelectors type: object gitImplementation: default: go-git description: |- GitImplementation specifies which Git client library implementation to use. Defaults to 'go-git', valid values are ('go-git', 'libgit2'). Deprecated: gitImplementation is deprecated now that 'go-git' is the only supported implementation. enum: - go-git - libgit2 type: string ignore: description: |- Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are. type: string include: description: |- Include specifies a list of GitRepository resources which Artifacts should be included in the Artifact produced for this GitRepository. items: description: |- GitRepositoryInclude specifies a local reference to a GitRepository which Artifact (sub-)contents must be included, and where they should be placed. properties: fromPath: description: |- FromPath specifies the path to copy contents from, defaults to the root of the Artifact. type: string repository: description: |- GitRepositoryRef specifies the GitRepository which Artifact contents must be included. properties: name: description: Name of the referent. type: string required: - name type: object toPath: description: |- ToPath specifies the path to copy contents to, defaults to the name of the GitRepositoryRef. type: string required: - repository type: object type: array interval: description: Interval at which to check the GitRepository for updates. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string recurseSubmodules: description: |- RecurseSubmodules enables the initialization of all submodules within the GitRepository as cloned from the URL, using their default settings. type: boolean ref: description: |- Reference specifies the Git reference to resolve and monitor for changes, defaults to the 'master' branch. properties: branch: description: Branch to check out, defaults to 'master' if no other field is defined. type: string commit: description: |- Commit SHA to check out, takes precedence over all reference fields. This can be combined with Branch to shallow clone the branch, in which the commit is expected to exist. type: string name: description: |- Name of the reference to check out; takes precedence over Branch, Tag and SemVer. It must be a valid Git reference: https://git-scm.com/docs/git-check-ref-format#_description Examples: "refs/heads/main", "refs/tags/v0.1.0", "refs/pull/420/head", "refs/merge-requests/1/head" type: string semver: description: SemVer tag expression to check out, takes precedence over Tag. type: string tag: description: Tag to check out, takes precedence over Branch. type: string type: object secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the GitRepository. For HTTPS repositories the Secret must contain 'username' and 'password' fields for basic auth or 'bearerToken' field for token auth. For SSH repositories the Secret must contain 'identity' and 'known_hosts' fields. properties: name: description: Name of the referent. type: string required: - name type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this GitRepository. type: boolean timeout: default: 60s description: Timeout for Git operations like cloning, defaults to 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string url: description: URL specifies the Git repository URL, it can be an HTTP/S or SSH address. pattern: ^(http|https|ssh)://.*$ type: string verify: description: |- Verification specifies the configuration to verify the Git commit signature(s). properties: mode: description: Mode specifies what Git object should be verified, currently ('head'). enum: - head type: string secretRef: description: |- SecretRef specifies the Secret containing the public keys of trusted Git authors. properties: name: description: Name of the referent. type: string required: - name type: object required: - mode - secretRef type: object required: - interval - url type: object status: default: observedGeneration: -1 description: GitRepositoryStatus records the observed state of a Git repository. properties: artifact: description: Artifact represents the last successful GitRepository reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the GitRepository. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array contentConfigChecksum: description: |- ContentConfigChecksum is a checksum of all the configurations related to the content of the source artifact: - .spec.ignore - .spec.recurseSubmodules - .spec.included and the checksum of the included artifacts observed in .status.observedGeneration version of the object. This can be used to determine if the content of the included repository has changed. It has the format of `:`, for example: `sha256:`. Deprecated: Replaced with explicit fields for observed artifact content config in the status. type: string includedArtifacts: description: |- IncludedArtifacts contains a list of the last successfully included Artifacts as instructed by GitRepositorySpec.Include. items: description: Artifact represents the output of a Source reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: |- ObservedGeneration is the last observed generation of the GitRepository object. format: int64 type: integer observedIgnore: description: |- ObservedIgnore is the observed exclusion patterns used for constructing the source artifact. type: string observedInclude: description: |- ObservedInclude is the observed list of GitRepository resources used to to produce the current Artifact. items: description: |- GitRepositoryInclude specifies a local reference to a GitRepository which Artifact (sub-)contents must be included, and where they should be placed. properties: fromPath: description: |- FromPath specifies the path to copy contents from, defaults to the root of the Artifact. type: string repository: description: |- GitRepositoryRef specifies the GitRepository which Artifact contents must be included. properties: name: description: Name of the referent. type: string required: - name type: object toPath: description: |- ToPath specifies the path to copy contents to, defaults to the name of the GitRepositoryRef. type: string required: - repository type: object type: array observedRecurseSubmodules: description: |- ObservedRecurseSubmodules is the observed resource submodules configuration used to produce the current Artifact. type: boolean url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise GitRepositoryStatus.Artifact data is recommended. type: string type: object type: object served: true storage: false subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: helmcharts.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io names: kind: HelmChart listKind: HelmChartList plural: helmcharts shortNames: - hc singular: helmchart scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.chart name: Chart type: string - jsonPath: .spec.version name: Version type: string - jsonPath: .spec.sourceRef.kind name: Source Kind type: string - jsonPath: .spec.sourceRef.name name: Source Name type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v1 schema: openAPIV3Schema: description: HelmChart is the Schema for the helmcharts API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: HelmChartSpec specifies the desired state of a Helm chart. properties: chart: description: |- Chart is the name or path the Helm chart is available at in the SourceRef. type: string ignoreMissingValuesFiles: description: |- IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. type: boolean interval: description: |- Interval at which the HelmChart SourceRef is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string reconcileStrategy: default: ChartVersion description: |- ReconcileStrategy determines what enables the creation of a new artifact. Valid values are ('ChartVersion', 'Revision'). See the documentation of the values for an explanation on their behavior. Defaults to ChartVersion when omitted. enum: - ChartVersion - Revision type: string sourceRef: description: SourceRef is the reference to the Source the chart is available at. properties: apiVersion: description: APIVersion of the referent. type: string kind: description: |- Kind of the referent, valid values are ('HelmRepository', 'GitRepository', 'Bucket'). enum: - HelmRepository - GitRepository - Bucket type: string name: description: Name of the referent. type: string required: - kind - name type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this source. type: boolean valuesFiles: description: |- ValuesFiles is an alternative list of values files to use as the chart values (values.yaml is not included by default), expected to be a relative path in the SourceRef. Values files are merged in the order of this list with the last file overriding the first. Ignored when omitted. items: type: string type: array verify: description: |- Verify contains the secret name containing the trusted public keys used to verify the signature and specifies which provider to use to check whether OCI image is authentic. This field is only supported when using HelmRepository source with spec.type 'oci'. Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. properties: matchOIDCIdentity: description: |- MatchOIDCIdentity specifies the identity matching criteria to use while verifying an OCI artifact which was signed using Cosign keyless signing. The artifact's identity is deemed to be verified if any of the specified matchers match against the identity. items: description: |- OIDCIdentityMatch specifies options for verifying the certificate identity, i.e. the issuer and the subject of the certificate. properties: issuer: description: |- Issuer specifies the regex pattern to match against to verify the OIDC issuer in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string subject: description: |- Subject specifies the regex pattern to match against to verify the identity subject in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string required: - issuer - subject type: object type: array provider: default: cosign description: Provider specifies the technology used to sign the OCI Artifact. enum: - cosign - notation type: string secretRef: description: |- SecretRef specifies the Kubernetes Secret containing the trusted public keys. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object version: default: '*' description: |- Version is the chart version semver expression, ignored for charts from GitRepository and Bucket sources. Defaults to latest when omitted. type: string required: - chart - interval - sourceRef type: object status: default: observedGeneration: -1 description: HelmChartStatus records the observed state of the HelmChart. properties: artifact: description: Artifact represents the output of the last successful reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the HelmChart. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedChartName: description: |- ObservedChartName is the last observed chart name as specified by the resolved chart reference. type: string observedGeneration: description: |- ObservedGeneration is the last observed generation of the HelmChart object. format: int64 type: integer observedSourceArtifactRevision: description: |- ObservedSourceArtifactRevision is the last observed Artifact.Revision of the HelmChartSpec.SourceRef. type: string observedValuesFiles: description: |- ObservedValuesFiles are the observed value files of the last successful reconciliation. It matches the chart in the last successfully reconciled artifact. items: type: string type: array url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact data is recommended. type: string type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.chart name: Chart type: string - jsonPath: .spec.version name: Version type: string - jsonPath: .spec.sourceRef.kind name: Source Kind type: string - jsonPath: .spec.sourceRef.name name: Source Name type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 HelmChart is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: HelmChart is the Schema for the helmcharts API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: HelmChartSpec specifies the desired state of a Helm chart. properties: accessFrom: description: |- AccessFrom specifies an Access Control List for allowing cross-namespace references to this object. NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 properties: namespaceSelectors: description: |- NamespaceSelectors is the list of namespace selectors to which this ACL applies. Items in this list are evaluated using a logical OR operation. items: description: |- NamespaceSelector selects the namespaces to which this ACL applies. An empty map of MatchLabels matches all namespaces in a cluster. properties: matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object type: array required: - namespaceSelectors type: object chart: description: |- Chart is the name or path the Helm chart is available at in the SourceRef. type: string ignoreMissingValuesFiles: description: |- IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. type: boolean interval: description: |- Interval at which the HelmChart SourceRef is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string reconcileStrategy: default: ChartVersion description: |- ReconcileStrategy determines what enables the creation of a new artifact. Valid values are ('ChartVersion', 'Revision'). See the documentation of the values for an explanation on their behavior. Defaults to ChartVersion when omitted. enum: - ChartVersion - Revision type: string sourceRef: description: SourceRef is the reference to the Source the chart is available at. properties: apiVersion: description: APIVersion of the referent. type: string kind: description: |- Kind of the referent, valid values are ('HelmRepository', 'GitRepository', 'Bucket'). enum: - HelmRepository - GitRepository - Bucket type: string name: description: Name of the referent. type: string required: - kind - name type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this source. type: boolean valuesFile: description: |- ValuesFile is an alternative values file to use as the default chart values, expected to be a relative path in the SourceRef. Deprecated in favor of ValuesFiles, for backwards compatibility the file specified here is merged before the ValuesFiles items. Ignored when omitted. type: string valuesFiles: description: |- ValuesFiles is an alternative list of values files to use as the chart values (values.yaml is not included by default), expected to be a relative path in the SourceRef. Values files are merged in the order of this list with the last file overriding the first. Ignored when omitted. items: type: string type: array verify: description: |- Verify contains the secret name containing the trusted public keys used to verify the signature and specifies which provider to use to check whether OCI image is authentic. This field is only supported when using HelmRepository source with spec.type 'oci'. Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. properties: matchOIDCIdentity: description: |- MatchOIDCIdentity specifies the identity matching criteria to use while verifying an OCI artifact which was signed using Cosign keyless signing. The artifact's identity is deemed to be verified if any of the specified matchers match against the identity. items: description: |- OIDCIdentityMatch specifies options for verifying the certificate identity, i.e. the issuer and the subject of the certificate. properties: issuer: description: |- Issuer specifies the regex pattern to match against to verify the OIDC issuer in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string subject: description: |- Subject specifies the regex pattern to match against to verify the identity subject in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string required: - issuer - subject type: object type: array provider: default: cosign description: Provider specifies the technology used to sign the OCI Artifact. enum: - cosign - notation type: string secretRef: description: |- SecretRef specifies the Kubernetes Secret containing the trusted public keys. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object version: default: '*' description: |- Version is the chart version semver expression, ignored for charts from GitRepository and Bucket sources. Defaults to latest when omitted. type: string required: - chart - interval - sourceRef type: object status: default: observedGeneration: -1 description: HelmChartStatus records the observed state of the HelmChart. properties: artifact: description: Artifact represents the output of the last successful reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the HelmChart. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedChartName: description: |- ObservedChartName is the last observed chart name as specified by the resolved chart reference. type: string observedGeneration: description: |- ObservedGeneration is the last observed generation of the HelmChart object. format: int64 type: integer observedSourceArtifactRevision: description: |- ObservedSourceArtifactRevision is the last observed Artifact.Revision of the HelmChartSpec.SourceRef. type: string observedValuesFiles: description: |- ObservedValuesFiles are the observed value files of the last successful reconciliation. It matches the chart in the last successfully reconciled artifact. items: type: string type: array url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact data is recommended. type: string type: object type: object served: true storage: false subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: helmrepositories.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io names: kind: HelmRepository listKind: HelmRepositoryList plural: helmrepositories shortNames: - helmrepo singular: helmrepository scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.url name: URL type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v1 schema: openAPIV3Schema: description: HelmRepository is the Schema for the helmrepositories API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- HelmRepositorySpec specifies the required configuration to produce an Artifact for a Helm repository index YAML. properties: accessFrom: description: |- AccessFrom specifies an Access Control List for allowing cross-namespace references to this object. NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 properties: namespaceSelectors: description: |- NamespaceSelectors is the list of namespace selectors to which this ACL applies. Items in this list are evaluated using a logical OR operation. items: description: |- NamespaceSelector selects the namespaces to which this ACL applies. An empty map of MatchLabels matches all namespaces in a cluster. properties: matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object type: array required: - namespaceSelectors type: object certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. It takes precedence over the values specified in the Secret referred to by `.spec.secretRef`. properties: name: description: Name of the referent. type: string required: - name type: object insecure: description: |- Insecure allows connecting to a non-TLS HTTP container registry. This field is only taken into account if the .spec.type field is set to 'oci'. type: boolean interval: description: |- Interval at which the HelmRepository URL is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string passCredentials: description: |- PassCredentials allows the credentials from the SecretRef to be passed on to a host that does not match the host as defined in URL. This may be required if the host of the advertised chart URLs in the index differ from the defined URL. Enabling this should be done with caution, as it can potentially result in credentials getting stolen in a MITM-attack. type: boolean provider: default: generic description: |- Provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. This field is optional, and only taken into account if the .spec.type field is set to 'oci'. When not specified, defaults to 'generic'. enum: - generic - aws - azure - gcp type: string secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the HelmRepository. For HTTP/S basic auth the secret must contain 'username' and 'password' fields. Support for TLS auth using the 'certFile' and 'keyFile', and/or 'caFile' keys is deprecated. Please use `.spec.certSecretRef` instead. properties: name: description: Name of the referent. type: string required: - name type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this HelmRepository. type: boolean timeout: description: |- Timeout is used for the index fetch operation for an HTTPS helm repository, and for remote OCI Repository operations like pulling for an OCI helm chart by the associated HelmChart. Its default value is 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string type: description: |- Type of the HelmRepository. When this field is set to "oci", the URL field value must be prefixed with "oci://". enum: - default - oci type: string url: description: |- URL of the Helm repository, a valid URL contains at least a protocol and host. pattern: ^(http|https|oci)://.*$ type: string required: - url type: object status: default: observedGeneration: -1 description: HelmRepositoryStatus records the observed state of the HelmRepository. properties: artifact: description: Artifact represents the last successful HelmRepository reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the HelmRepository. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: |- ObservedGeneration is the last observed generation of the HelmRepository object. format: int64 type: integer url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise HelmRepositoryStatus.Artifact data is recommended. type: string type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.url name: URL type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 HelmRepository is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: HelmRepository is the Schema for the helmrepositories API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- HelmRepositorySpec specifies the required configuration to produce an Artifact for a Helm repository index YAML. properties: accessFrom: description: |- AccessFrom specifies an Access Control List for allowing cross-namespace references to this object. NOTE: Not implemented, provisional as of https://github.com/fluxcd/flux2/pull/2092 properties: namespaceSelectors: description: |- NamespaceSelectors is the list of namespace selectors to which this ACL applies. Items in this list are evaluated using a logical OR operation. items: description: |- NamespaceSelector selects the namespaces to which this ACL applies. An empty map of MatchLabels matches all namespaces in a cluster. properties: matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object type: array required: - namespaceSelectors type: object certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. It takes precedence over the values specified in the Secret referred to by `.spec.secretRef`. properties: name: description: Name of the referent. type: string required: - name type: object insecure: description: |- Insecure allows connecting to a non-TLS HTTP container registry. This field is only taken into account if the .spec.type field is set to 'oci'. type: boolean interval: description: |- Interval at which the HelmRepository URL is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string passCredentials: description: |- PassCredentials allows the credentials from the SecretRef to be passed on to a host that does not match the host as defined in URL. This may be required if the host of the advertised chart URLs in the index differ from the defined URL. Enabling this should be done with caution, as it can potentially result in credentials getting stolen in a MITM-attack. type: boolean provider: default: generic description: |- Provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. This field is optional, and only taken into account if the .spec.type field is set to 'oci'. When not specified, defaults to 'generic'. enum: - generic - aws - azure - gcp type: string secretRef: description: |- SecretRef specifies the Secret containing authentication credentials for the HelmRepository. For HTTP/S basic auth the secret must contain 'username' and 'password' fields. Support for TLS auth using the 'certFile' and 'keyFile', and/or 'caFile' keys is deprecated. Please use `.spec.certSecretRef` instead. properties: name: description: Name of the referent. type: string required: - name type: object suspend: description: |- Suspend tells the controller to suspend the reconciliation of this HelmRepository. type: boolean timeout: description: |- Timeout is used for the index fetch operation for an HTTPS helm repository, and for remote OCI Repository operations like pulling for an OCI helm chart by the associated HelmChart. Its default value is 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string type: description: |- Type of the HelmRepository. When this field is set to "oci", the URL field value must be prefixed with "oci://". enum: - default - oci type: string url: description: |- URL of the Helm repository, a valid URL contains at least a protocol and host. pattern: ^(http|https|oci)://.*$ type: string required: - url type: object status: default: observedGeneration: -1 description: HelmRepositoryStatus records the observed state of the HelmRepository. properties: artifact: description: Artifact represents the last successful HelmRepository reconciliation. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the HelmRepository. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: |- ObservedGeneration is the last observed generation of the HelmRepository object. format: int64 type: integer url: description: |- URL is the dynamic fetch link for the latest Artifact. It is provided on a "best effort" basis, and using the precise HelmRepositoryStatus.Artifact data is recommended. type: string type: object type: object served: true storage: false subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: ocirepositories.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io names: kind: OCIRepository listKind: OCIRepositoryList plural: ocirepositories shortNames: - ocirepo singular: ocirepository scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.url name: URL type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: OCIRepository is the Schema for the ocirepositories API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: OCIRepositorySpec defines the desired state of OCIRepository properties: certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. properties: name: description: Name of the referent. type: string required: - name type: object ignore: description: |- Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are. type: string insecure: description: Insecure allows connecting to a non-TLS HTTP container registry. type: boolean interval: description: |- Interval at which the OCIRepository URL is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string layerSelector: description: |- LayerSelector specifies which layer should be extracted from the OCI artifact. When not specified, the first layer found in the artifact is selected. properties: mediaType: description: |- MediaType specifies the OCI media type of the layer which should be extracted from the OCI Artifact. The first layer matching this type is selected. type: string operation: description: |- Operation specifies how the selected layer should be processed. By default, the layer compressed content is extracted to storage. When the operation is set to 'copy', the layer compressed content is persisted to storage as it is. enum: - extract - copy type: string type: object provider: default: generic description: |- The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. When not specified, defaults to 'generic'. enum: - generic - aws - azure - gcp type: string proxySecretRef: description: |- ProxySecretRef specifies the Secret containing the proxy configuration to use while communicating with the container registry. properties: name: description: Name of the referent. type: string required: - name type: object ref: description: |- The OCI reference to pull and monitor for changes, defaults to the latest tag. properties: digest: description: |- Digest is the image digest to pull, takes precedence over SemVer. The value should be in the format 'sha256:'. type: string semver: description: |- SemVer is the range of tags to pull selecting the latest within the range, takes precedence over Tag. type: string semverFilter: description: SemverFilter is a regex pattern to filter the tags within the SemVer range. type: string tag: description: Tag is the image tag to pull, defaults to latest. type: string type: object secretRef: description: |- SecretRef contains the secret name containing the registry login credentials to resolve image metadata. The secret must be of type kubernetes.io/dockerconfigjson. properties: name: description: Name of the referent. type: string required: - name type: object serviceAccountName: description: |- ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate the image pull if the service account has attached pull secrets. For more information: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account type: string suspend: description: This flag tells the controller to suspend the reconciliation of this source. type: boolean timeout: default: 60s description: The timeout for remote OCI Repository operations like pulling, defaults to 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string url: description: |- URL is a reference to an OCI artifact repository hosted on a remote container registry. pattern: ^oci://.*$ type: string verify: description: |- Verify contains the secret name containing the trusted public keys used to verify the signature and specifies which provider to use to check whether OCI image is authentic. properties: matchOIDCIdentity: description: |- MatchOIDCIdentity specifies the identity matching criteria to use while verifying an OCI artifact which was signed using Cosign keyless signing. The artifact's identity is deemed to be verified if any of the specified matchers match against the identity. items: description: |- OIDCIdentityMatch specifies options for verifying the certificate identity, i.e. the issuer and the subject of the certificate. properties: issuer: description: |- Issuer specifies the regex pattern to match against to verify the OIDC issuer in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string subject: description: |- Subject specifies the regex pattern to match against to verify the identity subject in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string required: - issuer - subject type: object type: array provider: default: cosign description: Provider specifies the technology used to sign the OCI Artifact. enum: - cosign - notation type: string secretRef: description: |- SecretRef specifies the Kubernetes Secret containing the trusted public keys. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object required: - interval - url type: object status: default: observedGeneration: -1 description: OCIRepositoryStatus defines the observed state of OCIRepository properties: artifact: description: Artifact represents the output of the last successful OCI Repository sync. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the OCIRepository. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation. format: int64 type: integer observedIgnore: description: |- ObservedIgnore is the observed exclusion patterns used for constructing the source artifact. type: string observedLayerSelector: description: |- ObservedLayerSelector is the observed layer selector used for constructing the source artifact. properties: mediaType: description: |- MediaType specifies the OCI media type of the layer which should be extracted from the OCI Artifact. The first layer matching this type is selected. type: string operation: description: |- Operation specifies how the selected layer should be processed. By default, the layer compressed content is extracted to storage. When the operation is set to 'copy', the layer compressed content is persisted to storage as it is. enum: - extract - copy type: string type: object url: description: URL is the download link for the artifact output of the last OCI Repository sync. type: string type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.url name: URL type: string - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true deprecationWarning: v1beta2 OCIRepository is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: OCIRepository is the Schema for the ocirepositories API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: OCIRepositorySpec defines the desired state of OCIRepository properties: certSecretRef: description: |- CertSecretRef can be given the name of a Secret containing either or both of - a PEM-encoded client certificate (`tls.crt`) and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. Note: Support for the `caFile`, `certFile` and `keyFile` keys have been deprecated. properties: name: description: Name of the referent. type: string required: - name type: object ignore: description: |- Ignore overrides the set of excluded patterns in the .sourceignore format (which is the same as .gitignore). If not provided, a default will be used, consult the documentation for your version to find out what those are. type: string insecure: description: Insecure allows connecting to a non-TLS HTTP container registry. type: boolean interval: description: |- Interval at which the OCIRepository URL is checked for updates. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string layerSelector: description: |- LayerSelector specifies which layer should be extracted from the OCI artifact. When not specified, the first layer found in the artifact is selected. properties: mediaType: description: |- MediaType specifies the OCI media type of the layer which should be extracted from the OCI Artifact. The first layer matching this type is selected. type: string operation: description: |- Operation specifies how the selected layer should be processed. By default, the layer compressed content is extracted to storage. When the operation is set to 'copy', the layer compressed content is persisted to storage as it is. enum: - extract - copy type: string type: object provider: default: generic description: |- The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. When not specified, defaults to 'generic'. enum: - generic - aws - azure - gcp type: string proxySecretRef: description: |- ProxySecretRef specifies the Secret containing the proxy configuration to use while communicating with the container registry. properties: name: description: Name of the referent. type: string required: - name type: object ref: description: |- The OCI reference to pull and monitor for changes, defaults to the latest tag. properties: digest: description: |- Digest is the image digest to pull, takes precedence over SemVer. The value should be in the format 'sha256:'. type: string semver: description: |- SemVer is the range of tags to pull selecting the latest within the range, takes precedence over Tag. type: string semverFilter: description: SemverFilter is a regex pattern to filter the tags within the SemVer range. type: string tag: description: Tag is the image tag to pull, defaults to latest. type: string type: object secretRef: description: |- SecretRef contains the secret name containing the registry login credentials to resolve image metadata. The secret must be of type kubernetes.io/dockerconfigjson. properties: name: description: Name of the referent. type: string required: - name type: object serviceAccountName: description: |- ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate the image pull if the service account has attached pull secrets. For more information: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account type: string suspend: description: This flag tells the controller to suspend the reconciliation of this source. type: boolean timeout: default: 60s description: The timeout for remote OCI Repository operations like pulling, defaults to 60s. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string url: description: |- URL is a reference to an OCI artifact repository hosted on a remote container registry. pattern: ^oci://.*$ type: string verify: description: |- Verify contains the secret name containing the trusted public keys used to verify the signature and specifies which provider to use to check whether OCI image is authentic. properties: matchOIDCIdentity: description: |- MatchOIDCIdentity specifies the identity matching criteria to use while verifying an OCI artifact which was signed using Cosign keyless signing. The artifact's identity is deemed to be verified if any of the specified matchers match against the identity. items: description: |- OIDCIdentityMatch specifies options for verifying the certificate identity, i.e. the issuer and the subject of the certificate. properties: issuer: description: |- Issuer specifies the regex pattern to match against to verify the OIDC issuer in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string subject: description: |- Subject specifies the regex pattern to match against to verify the identity subject in the Fulcio certificate. The pattern must be a valid Go regular expression. type: string required: - issuer - subject type: object type: array provider: default: cosign description: Provider specifies the technology used to sign the OCI Artifact. enum: - cosign - notation type: string secretRef: description: |- SecretRef specifies the Kubernetes Secret containing the trusted public keys. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object required: - interval - url type: object status: default: observedGeneration: -1 description: OCIRepositoryStatus defines the observed state of OCIRepository properties: artifact: description: Artifact represents the output of the last successful OCI Repository sync. properties: digest: description: Digest is the digest of the file in the form of ':'. pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ type: string lastUpdateTime: description: |- LastUpdateTime is the timestamp corresponding to the last update of the Artifact. format: date-time type: string metadata: additionalProperties: type: string description: Metadata holds upstream information such as OCI annotations. type: object path: description: |- Path is the relative file path of the Artifact. It can be used to locate the file in the root of the Artifact storage on the local file system of the controller managing the Source. type: string revision: description: |- Revision is a human-readable identifier traceable in the origin source system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. type: string size: description: Size is the number of bytes in the file. format: int64 type: integer url: description: |- URL is the HTTP address of the Artifact as exposed by the controller managing the Source. It can be used to retrieve the Artifact for consumption, e.g. by another controller applying the Artifact contents. type: string required: - digest - lastUpdateTime - path - revision - url type: object conditions: description: Conditions holds the conditions for the OCIRepository. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array contentConfigChecksum: description: |- ContentConfigChecksum is a checksum of all the configurations related to the content of the source artifact: - .spec.ignore - .spec.layerSelector observed in .status.observedGeneration version of the object. This can be used to determine if the content configuration has changed and the artifact needs to be rebuilt. It has the format of `:`, for example: `sha256:`. Deprecated: Replaced with explicit fields for observed artifact content config in the status. type: string lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation. format: int64 type: integer observedIgnore: description: |- ObservedIgnore is the observed exclusion patterns used for constructing the source artifact. type: string observedLayerSelector: description: |- ObservedLayerSelector is the observed layer selector used for constructing the source artifact. properties: mediaType: description: |- MediaType specifies the OCI media type of the layer which should be extracted from the OCI Artifact. The first layer matching this type is selected. type: string operation: description: |- Operation specifies how the selected layer should be processed. By default, the layer compressed content is extracted to storage. When the operation is set to 'copy', the layer compressed content is persisted to storage as it is. enum: - extract - copy type: string type: object url: description: URL is the download link for the artifact output of the last OCI Repository sync. type: string type: object type: object served: true storage: false subresources: status: {} --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: source-controller namespace: flux-system --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: source-controller namespace: flux-system spec: ports: - name: http port: 80 protocol: TCP targetPort: http selector: app: source-controller type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: source-controller namespace: flux-system spec: replicas: 1 selector: matchLabels: app: source-controller strategy: type: Recreate template: metadata: annotations: prometheus.io/port: "8080" prometheus.io/scrape: "true" labels: app: source-controller app.kubernetes.io/component: source-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 spec: containers: - args: - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.cluster.local./ - --watch-all-namespaces=true - --log-level=info - --log-encoding=json - --enable-leader-election - --storage-path=/data - --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local. env: - name: RUNTIME_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: TUF_ROOT value: /tmp/.sigstore - name: GOMEMLIMIT valueFrom: resourceFieldRef: containerName: manager resource: limits.memory image: ghcr.io/fluxcd/source-controller:v1.7.4 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz port: healthz name: manager ports: - containerPort: 9090 name: http protocol: TCP - containerPort: 8080 name: http-prom protocol: TCP - containerPort: 9440 name: healthz protocol: TCP readinessProbe: httpGet: path: / port: http resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 50m memory: 64Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /data name: data - mountPath: /tmp name: tmp nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical securityContext: fsGroup: 1337 serviceAccountName: source-controller terminationGracePeriodSeconds: 10 volumes: - emptyDir: {} name: data - emptyDir: {} name: tmp --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: kustomize-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: kustomizations.kustomize.toolkit.fluxcd.io spec: group: kustomize.toolkit.fluxcd.io names: kind: Kustomization listKind: KustomizationList plural: kustomizations shortNames: - ks singular: kustomization scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v1 schema: openAPIV3Schema: description: Kustomization is the Schema for the kustomizations API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- KustomizationSpec defines the configuration to calculate the desired state from a Source using Kustomize. properties: commonMetadata: description: |- CommonMetadata specifies the common labels and annotations that are applied to all resources. Any existing label or annotation will be overridden if its key matches a common one. properties: annotations: additionalProperties: type: string description: Annotations to be added to the object's metadata. type: object labels: additionalProperties: type: string description: Labels to be added to the object's metadata. type: object type: object components: description: Components specifies relative paths to kustomize Components. items: type: string type: array decryption: description: Decrypt Kubernetes secrets before applying them on the cluster. properties: provider: description: Provider is the name of the decryption engine. enum: - sops type: string secretRef: description: |- The secret name containing the private OpenPGP keys used for decryption. A static credential for a cloud provider defined inside the Secret takes priority to secret-less authentication with the ServiceAccountName field. properties: name: description: Name of the referent. type: string required: - name type: object serviceAccountName: description: |- ServiceAccountName is the name of the service account used to authenticate with KMS services from cloud providers. If a static credential for a given cloud provider is defined inside the Secret referenced by SecretRef, that static credential takes priority. type: string required: - provider type: object deletionPolicy: description: |- DeletionPolicy can be used to control garbage collection when this Kustomization is deleted. Valid values are ('MirrorPrune', 'Delete', 'WaitForTermination', 'Orphan'). 'MirrorPrune' mirrors the Prune field (orphan if false, delete if true). Defaults to 'MirrorPrune'. enum: - MirrorPrune - Delete - WaitForTermination - Orphan type: string dependsOn: description: |- DependsOn may contain a DependencyReference slice with references to Kustomization resources that must be ready before this Kustomization can be reconciled. items: description: DependencyReference defines a Kustomization dependency on another Kustomization resource. properties: name: description: Name of the referent. type: string namespace: description: |- Namespace of the referent, defaults to the namespace of the Kustomization resource object that contains the reference. type: string readyExpr: description: |- ReadyExpr is a CEL expression that can be used to assess the readiness of a dependency. When specified, the built-in readiness check is replaced by the logic defined in the CEL expression. To make the CEL expression additive to the built-in readiness check, the feature gate `AdditiveCELDependencyCheck` must be set to `true`. type: string required: - name type: object type: array force: default: false description: |- Force instructs the controller to recreate resources when patching fails due to an immutable field change. type: boolean healthCheckExprs: description: |- HealthCheckExprs is a list of healthcheck expressions for evaluating the health of custom resources using Common Expression Language (CEL). The expressions are evaluated only when Wait or HealthChecks are specified. items: description: CustomHealthCheck defines the health check for custom resources. properties: apiVersion: description: APIVersion of the custom resource under evaluation. type: string current: description: |- Current is the CEL expression that determines if the status of the custom resource has reached the desired state. type: string failed: description: |- Failed is the CEL expression that determines if the status of the custom resource has failed to reach the desired state. type: string inProgress: description: |- InProgress is the CEL expression that determines if the status of the custom resource has not yet reached the desired state. type: string kind: description: Kind of the custom resource under evaluation. type: string required: - apiVersion - current - kind type: object type: array healthChecks: description: A list of resources to be included in the health assessment. items: description: |- NamespacedObjectKindReference contains enough information to locate the typed referenced Kubernetes resource object in any namespace. properties: apiVersion: description: API version of the referent, if not specified the Kubernetes preferred version will be used. type: string kind: description: Kind of the referent. type: string name: description: Name of the referent. type: string namespace: description: Namespace of the referent, when not specified it acts as LocalObjectReference. type: string required: - kind - name type: object type: array ignoreMissingComponents: description: |- IgnoreMissingComponents instructs the controller to ignore Components paths not found in source by removing them from the generated kustomization.yaml before running kustomize build. type: boolean images: description: |- Images is a list of (image name, new name, new tag or digest) for changing image names, tags or digests. This can also be achieved with a patch, but this operator is simpler to specify. items: description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. properties: digest: description: |- Digest is the value used to replace the original image tag. If digest is present NewTag value is ignored. type: string name: description: Name is a tag-less image name. type: string newName: description: NewName is the value used to replace the original name. type: string newTag: description: NewTag is the value used to replace the original tag. type: string required: - name type: object type: array interval: description: |- The interval at which to reconcile the Kustomization. This interval is approximate and may be subject to jitter to ensure efficient use of resources. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string kubeConfig: description: |- The KubeConfig for reconciling the Kustomization on a remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, forces the controller to act on behalf of that Service Account at the target cluster. If the --default-service-account flag is set, its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName is empty. properties: configMapRef: description: |- ConfigMapRef holds an optional name of a ConfigMap that contains the following keys: - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or `generic`. Required. - `cluster`: the fully qualified resource name of the Kubernetes cluster in the cloud provider API. Not used by the `generic` provider. Required when one of `address` or `ca.crt` is not set. - `address`: the address of the Kubernetes API server. Required for `generic`. For the other providers, if not specified, the first address in the cluster resource will be used, and if specified, it must match one of the addresses in the cluster resource. If audiences is not set, will be used as the audience for the `generic` provider. - `ca.crt`: the optional PEM-encoded CA certificate for the Kubernetes API server. If not set, the controller will use the CA certificate from the cluster resource. - `audiences`: the optional audiences as a list of line-break-separated strings for the Kubernetes ServiceAccount token. Defaults to the `address` for the `generic` provider, or to specific values for the other providers depending on the provider. - `serviceAccountName`: the optional name of the Kubernetes ServiceAccount in the same namespace that should be used for authentication. If not specified, the controller ServiceAccount will be used. Mutually exclusive with SecretRef. properties: name: description: Name of the referent. type: string required: - name type: object secretRef: description: |- SecretRef holds an optional name of a secret that contains a key with the kubeconfig file as the value. If no key is set, the key will default to 'value'. Mutually exclusive with ConfigMapRef. It is recommended that the kubeconfig is self-contained, and the secret is regularly updated if credentials such as a cloud-access-token expire. Cloud specific `cmd-path` auth helpers will not function without adding binaries and credentials to the Pod that is responsible for reconciling Kubernetes resources. Supported only for the generic provider. properties: key: description: Key in the Secret, when not specified an implementation-specific default key is used. type: string name: description: Name of the Secret. type: string required: - name type: object type: object x-kubernetes-validations: - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: has(self.configMapRef) || has(self.secretRef) - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: '!has(self.configMapRef) || !has(self.secretRef)' namePrefix: description: NamePrefix will prefix the names of all managed resources. maxLength: 200 minLength: 1 type: string nameSuffix: description: NameSuffix will suffix the names of all managed resources. maxLength: 200 minLength: 1 type: string patches: description: |- Strategic merge and JSON patches, defined as inline YAML objects, capable of targeting objects based on kind, label and annotation selectors. items: description: |- Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should be applied to. properties: patch: description: |- Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with an array of operation objects. type: string target: description: Target points to the resources that the patch document should be applied to. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - patch type: object type: array path: description: |- Path to the directory containing the kustomization.yaml file, or the set of plain YAMLs a kustomization.yaml should be generated for. Defaults to 'None', which translates to the root path of the SourceRef. type: string postBuild: description: |- PostBuild describes which actions to perform on the YAML manifest generated by building the kustomize overlay. properties: substitute: additionalProperties: type: string description: |- Substitute holds a map of key/value pairs. The variables defined in your YAML manifests that match any of the keys defined in the map will be substituted with the set value. Includes support for bash string replacement functions e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. type: object substituteFrom: description: |- SubstituteFrom holds references to ConfigMaps and Secrets containing the variables and their values to be substituted in the YAML manifests. The ConfigMap and the Secret data keys represent the var names, and they must match the vars declared in the manifests for the substitution to happen. items: description: |- SubstituteReference contains a reference to a resource containing the variables name and value. properties: kind: description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). enum: - Secret - ConfigMap type: string name: description: |- Name of the values referent. Should reside in the same namespace as the referring resource. maxLength: 253 minLength: 1 type: string optional: default: false description: |- Optional indicates whether the referenced resource must exist, or whether to tolerate its absence. If true and the referenced resource is absent, proceed as if the resource was present but empty, without any variables defined. type: boolean required: - kind - name type: object type: array type: object prune: description: Prune enables garbage collection. type: boolean retryInterval: description: |- The interval at which to retry a previously failed reconciliation. When not specified, the controller uses the KustomizationSpec.Interval value to retry failures. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string serviceAccountName: description: |- The name of the Kubernetes service account to impersonate when reconciling this Kustomization. type: string sourceRef: description: Reference of the source where the kustomization file is. properties: apiVersion: description: API version of the referent. type: string kind: description: Kind of the referent. enum: - OCIRepository - GitRepository - Bucket - ExternalArtifact type: string name: description: Name of the referent. type: string namespace: description: |- Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. type: string required: - kind - name type: object suspend: description: |- This flag tells the controller to suspend subsequent kustomize executions, it does not apply to already started executions. Defaults to false. type: boolean targetNamespace: description: |- TargetNamespace sets or overrides the namespace in the kustomization.yaml file. maxLength: 63 minLength: 1 type: string timeout: description: |- Timeout for validation, apply and health checking operations. Defaults to 'Interval' duration. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string wait: description: |- Wait instructs the controller to check the health of all the reconciled resources. When enabled, the HealthChecks are ignored. Defaults to false. type: boolean required: - interval - prune - sourceRef type: object status: default: observedGeneration: -1 description: KustomizationStatus defines the observed state of a kustomization. properties: conditions: items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array history: description: |- History contains a set of snapshots of the last reconciliation attempts tracking the revision, the state and the duration of each attempt. items: description: |- Snapshot represents a point-in-time record of a group of resources reconciliation, including timing information, status, and a unique digest identifier. properties: digest: description: Digest is the checksum in the format `:` of the resources in this snapshot. type: string firstReconciled: description: FirstReconciled is the time when this revision was first reconciled to the cluster. format: date-time type: string lastReconciled: description: LastReconciled is the time when this revision was last reconciled to the cluster. format: date-time type: string lastReconciledDuration: description: LastReconciledDuration is time it took to reconcile the resources in this revision. type: string lastReconciledStatus: description: LastReconciledStatus is the status of the last reconciliation. type: string metadata: additionalProperties: type: string description: Metadata contains additional information about the snapshot. type: object totalReconciliations: description: TotalReconciliations is the total number of reconciliations that have occurred for this snapshot. format: int64 type: integer required: - digest - firstReconciled - lastReconciled - lastReconciledDuration - lastReconciledStatus - totalReconciliations type: object type: array inventory: description: |- Inventory contains the list of Kubernetes resource object references that have been successfully applied. properties: entries: description: Entries of Kubernetes resource object references. items: description: ResourceRef contains the information necessary to locate a resource within a cluster. properties: id: description: |- ID is the string representation of the Kubernetes resource object's metadata, in the format '___'. type: string v: description: Version is the API version of the Kubernetes resource object's kind. type: string required: - id - v type: object type: array required: - entries type: object lastAppliedOriginRevision: description: |- The last successfully applied origin revision. Equals the origin revision of the applied Artifact from the referenced Source. Usually present on the Metadata of the applied Artifact and depends on the Source type, e.g. for OCI it's the value associated with the key "org.opencontainers.image.revision". type: string lastAppliedRevision: description: |- The last successfully applied revision. Equals the Revision of the applied Artifact from the referenced Source. type: string lastAttemptedRevision: description: LastAttemptedRevision is the revision of the last reconciliation attempt. type: string lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last reconciled generation. format: int64 type: integer type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 Kustomization is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: Kustomization is the Schema for the kustomizations API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: KustomizationSpec defines the configuration to calculate the desired state from a Source using Kustomize. properties: commonMetadata: description: |- CommonMetadata specifies the common labels and annotations that are applied to all resources. Any existing label or annotation will be overridden if its key matches a common one. properties: annotations: additionalProperties: type: string description: Annotations to be added to the object's metadata. type: object labels: additionalProperties: type: string description: Labels to be added to the object's metadata. type: object type: object components: description: Components specifies relative paths to specifications of other Components. items: type: string type: array decryption: description: Decrypt Kubernetes secrets before applying them on the cluster. properties: provider: description: Provider is the name of the decryption engine. enum: - sops type: string secretRef: description: The secret name containing the private OpenPGP keys used for decryption. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object dependsOn: description: |- DependsOn may contain a meta.NamespacedObjectReference slice with references to Kustomization resources that must be ready before this Kustomization can be reconciled. items: description: |- NamespacedObjectReference contains enough information to locate the referenced Kubernetes resource object in any namespace. properties: name: description: Name of the referent. type: string namespace: description: Namespace of the referent, when not specified it acts as LocalObjectReference. type: string required: - name type: object type: array force: default: false description: |- Force instructs the controller to recreate resources when patching fails due to an immutable field change. type: boolean healthChecks: description: A list of resources to be included in the health assessment. items: description: |- NamespacedObjectKindReference contains enough information to locate the typed referenced Kubernetes resource object in any namespace. properties: apiVersion: description: API version of the referent, if not specified the Kubernetes preferred version will be used. type: string kind: description: Kind of the referent. type: string name: description: Name of the referent. type: string namespace: description: Namespace of the referent, when not specified it acts as LocalObjectReference. type: string required: - kind - name type: object type: array images: description: |- Images is a list of (image name, new name, new tag or digest) for changing image names, tags or digests. This can also be achieved with a patch, but this operator is simpler to specify. items: description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. properties: digest: description: |- Digest is the value used to replace the original image tag. If digest is present NewTag value is ignored. type: string name: description: Name is a tag-less image name. type: string newName: description: NewName is the value used to replace the original name. type: string newTag: description: NewTag is the value used to replace the original tag. type: string required: - name type: object type: array interval: description: The interval at which to reconcile the Kustomization. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string kubeConfig: description: |- The KubeConfig for reconciling the Kustomization on a remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, forces the controller to act on behalf of that Service Account at the target cluster. If the --default-service-account flag is set, its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName is empty. properties: configMapRef: description: |- ConfigMapRef holds an optional name of a ConfigMap that contains the following keys: - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or `generic`. Required. - `cluster`: the fully qualified resource name of the Kubernetes cluster in the cloud provider API. Not used by the `generic` provider. Required when one of `address` or `ca.crt` is not set. - `address`: the address of the Kubernetes API server. Required for `generic`. For the other providers, if not specified, the first address in the cluster resource will be used, and if specified, it must match one of the addresses in the cluster resource. If audiences is not set, will be used as the audience for the `generic` provider. - `ca.crt`: the optional PEM-encoded CA certificate for the Kubernetes API server. If not set, the controller will use the CA certificate from the cluster resource. - `audiences`: the optional audiences as a list of line-break-separated strings for the Kubernetes ServiceAccount token. Defaults to the `address` for the `generic` provider, or to specific values for the other providers depending on the provider. - `serviceAccountName`: the optional name of the Kubernetes ServiceAccount in the same namespace that should be used for authentication. If not specified, the controller ServiceAccount will be used. Mutually exclusive with SecretRef. properties: name: description: Name of the referent. type: string required: - name type: object secretRef: description: |- SecretRef holds an optional name of a secret that contains a key with the kubeconfig file as the value. If no key is set, the key will default to 'value'. Mutually exclusive with ConfigMapRef. It is recommended that the kubeconfig is self-contained, and the secret is regularly updated if credentials such as a cloud-access-token expire. Cloud specific `cmd-path` auth helpers will not function without adding binaries and credentials to the Pod that is responsible for reconciling Kubernetes resources. Supported only for the generic provider. properties: key: description: Key in the Secret, when not specified an implementation-specific default key is used. type: string name: description: Name of the Secret. type: string required: - name type: object type: object x-kubernetes-validations: - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: has(self.configMapRef) || has(self.secretRef) - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: '!has(self.configMapRef) || !has(self.secretRef)' patches: description: |- Strategic merge and JSON patches, defined as inline YAML objects, capable of targeting objects based on kind, label and annotation selectors. items: description: |- Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should be applied to. properties: patch: description: |- Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with an array of operation objects. type: string target: description: Target points to the resources that the patch document should be applied to. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - patch type: object type: array patchesJson6902: description: |- JSON 6902 patches, defined as inline YAML objects. Deprecated: Use Patches instead. items: description: JSON6902Patch contains a JSON6902 patch and the target the patch should be applied to. properties: patch: description: Patch contains the JSON6902 patch document with an array of operation objects. items: description: |- JSON6902 is a JSON6902 operation object. https://datatracker.ietf.org/doc/html/rfc6902#section-4 properties: from: description: |- From contains a JSON-pointer value that references a location within the target document where the operation is performed. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations. type: string op: description: |- Op indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 enum: - test - remove - add - replace - move - copy type: string path: description: |- Path contains the JSON-pointer value that references a location within the target document where the operation is performed. The meaning of the value depends on the value of Op. type: string value: description: |- Value contains a valid JSON structure. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations. x-kubernetes-preserve-unknown-fields: true required: - op - path type: object type: array target: description: Target points to the resources that the patch document should be applied to. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - patch - target type: object type: array patchesStrategicMerge: description: |- Strategic merge patches, defined as inline YAML objects. Deprecated: Use Patches instead. items: x-kubernetes-preserve-unknown-fields: true type: array path: description: |- Path to the directory containing the kustomization.yaml file, or the set of plain YAMLs a kustomization.yaml should be generated for. Defaults to 'None', which translates to the root path of the SourceRef. type: string postBuild: description: |- PostBuild describes which actions to perform on the YAML manifest generated by building the kustomize overlay. properties: substitute: additionalProperties: type: string description: |- Substitute holds a map of key/value pairs. The variables defined in your YAML manifests that match any of the keys defined in the map will be substituted with the set value. Includes support for bash string replacement functions e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. type: object substituteFrom: description: |- SubstituteFrom holds references to ConfigMaps and Secrets containing the variables and their values to be substituted in the YAML manifests. The ConfigMap and the Secret data keys represent the var names and they must match the vars declared in the manifests for the substitution to happen. items: description: |- SubstituteReference contains a reference to a resource containing the variables name and value. properties: kind: description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). enum: - Secret - ConfigMap type: string name: description: |- Name of the values referent. Should reside in the same namespace as the referring resource. maxLength: 253 minLength: 1 type: string optional: default: false description: |- Optional indicates whether the referenced resource must exist, or whether to tolerate its absence. If true and the referenced resource is absent, proceed as if the resource was present but empty, without any variables defined. type: boolean required: - kind - name type: object type: array type: object prune: description: Prune enables garbage collection. type: boolean retryInterval: description: |- The interval at which to retry a previously failed reconciliation. When not specified, the controller uses the KustomizationSpec.Interval value to retry failures. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string serviceAccountName: description: |- The name of the Kubernetes service account to impersonate when reconciling this Kustomization. type: string sourceRef: description: Reference of the source where the kustomization file is. properties: apiVersion: description: API version of the referent. type: string kind: description: Kind of the referent. enum: - OCIRepository - GitRepository - Bucket type: string name: description: Name of the referent. type: string namespace: description: Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. type: string required: - kind - name type: object suspend: description: |- This flag tells the controller to suspend subsequent kustomize executions, it does not apply to already started executions. Defaults to false. type: boolean targetNamespace: description: |- TargetNamespace sets or overrides the namespace in the kustomization.yaml file. maxLength: 63 minLength: 1 type: string timeout: description: |- Timeout for validation, apply and health checking operations. Defaults to 'Interval' duration. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string validation: description: 'Deprecated: Not used in v1beta2.' enum: - none - client - server type: string wait: description: |- Wait instructs the controller to check the health of all the reconciled resources. When enabled, the HealthChecks are ignored. Defaults to false. type: boolean required: - interval - prune - sourceRef type: object status: default: observedGeneration: -1 description: KustomizationStatus defines the observed state of a kustomization. properties: conditions: items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array inventory: description: Inventory contains the list of Kubernetes resource object references that have been successfully applied. properties: entries: description: Entries of Kubernetes resource object references. items: description: ResourceRef contains the information necessary to locate a resource within a cluster. properties: id: description: |- ID is the string representation of the Kubernetes resource object's metadata, in the format '___'. type: string v: description: Version is the API version of the Kubernetes resource object's kind. type: string required: - id - v type: object type: array required: - entries type: object lastAppliedRevision: description: |- The last successfully applied revision. Equals the Revision of the applied Artifact from the referenced Source. type: string lastAttemptedRevision: description: LastAttemptedRevision is the revision of the last reconciliation attempt. type: string lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last reconciled generation. format: int64 type: integer type: object type: object served: true storage: false subresources: status: {} --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: kustomize-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: kustomize-controller namespace: flux-system --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: kustomize-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: kustomize-controller namespace: flux-system spec: replicas: 1 selector: matchLabels: app: kustomize-controller template: metadata: annotations: prometheus.io/port: "8080" prometheus.io/scrape: "true" labels: app: kustomize-controller app.kubernetes.io/component: kustomize-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 spec: containers: - args: - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.cluster.local./ - --watch-all-namespaces=true - --log-level=info - --log-encoding=json - --enable-leader-election env: - name: RUNTIME_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: GOMEMLIMIT valueFrom: resourceFieldRef: containerName: manager resource: limits.memory image: ghcr.io/fluxcd/kustomize-controller:v1.7.3 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz port: healthz name: manager ports: - containerPort: 8080 name: http-prom protocol: TCP - containerPort: 9440 name: healthz protocol: TCP readinessProbe: httpGet: path: /readyz port: healthz resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 100m memory: 64Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp name: temp nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical securityContext: fsGroup: 1337 serviceAccountName: kustomize-controller terminationGracePeriodSeconds: 60 volumes: - emptyDir: {} name: temp --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: helm-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: helmreleases.helm.toolkit.fluxcd.io spec: group: helm.toolkit.fluxcd.io names: kind: HelmRelease listKind: HelmReleaseList plural: helmreleases shortNames: - hr singular: helmrelease scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v2 schema: openAPIV3Schema: description: HelmRelease is the Schema for the helmreleases API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: HelmReleaseSpec defines the desired state of a Helm release. properties: chart: description: |- Chart defines the template of the v1.HelmChart that should be created for this HelmRelease. properties: metadata: description: ObjectMeta holds the template for metadata like labels and annotations. properties: annotations: additionalProperties: type: string description: |- Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ type: object labels: additionalProperties: type: string description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ type: object type: object spec: description: Spec holds the template for the v1.HelmChartSpec for this HelmRelease. properties: chart: description: The name or path the Helm chart is available at in the SourceRef. maxLength: 2048 minLength: 1 type: string ignoreMissingValuesFiles: description: IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. type: boolean interval: description: |- Interval at which to check the v1.Source for updates. Defaults to 'HelmReleaseSpec.Interval'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string reconcileStrategy: default: ChartVersion description: |- Determines what enables the creation of a new artifact. Valid values are ('ChartVersion', 'Revision'). See the documentation of the values for an explanation on their behavior. Defaults to ChartVersion when omitted. enum: - ChartVersion - Revision type: string sourceRef: description: The name and namespace of the v1.Source the chart is available at. properties: apiVersion: description: APIVersion of the referent. type: string kind: description: Kind of the referent. enum: - HelmRepository - GitRepository - Bucket type: string name: description: Name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: Namespace of the referent. maxLength: 63 minLength: 1 type: string required: - kind - name type: object valuesFiles: description: |- Alternative list of values files to use as the chart values (values.yaml is not included by default), expected to be a relative path in the SourceRef. Values files are merged in the order of this list with the last file overriding the first. Ignored when omitted. items: type: string type: array verify: description: |- Verify contains the secret name containing the trusted public keys used to verify the signature and specifies which provider to use to check whether OCI image is authentic. This field is only supported for OCI sources. Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. properties: provider: default: cosign description: Provider specifies the technology used to sign the OCI Helm chart. enum: - cosign - notation type: string secretRef: description: |- SecretRef specifies the Kubernetes Secret containing the trusted public keys. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object version: default: '*' description: |- Version semver expression, ignored for charts from v1.GitRepository and v1beta2.Bucket sources. Defaults to latest when omitted. type: string required: - chart - sourceRef type: object required: - spec type: object chartRef: description: |- ChartRef holds a reference to a source controller resource containing the Helm chart artifact. properties: apiVersion: description: APIVersion of the referent. type: string kind: description: Kind of the referent. enum: - OCIRepository - HelmChart - ExternalArtifact type: string name: description: Name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. maxLength: 63 minLength: 1 type: string required: - kind - name type: object commonMetadata: description: |- CommonMetadata specifies the common labels and annotations that are applied to all resources. Any existing label or annotation will be overridden if its key matches a common one. properties: annotations: additionalProperties: type: string description: Annotations to be added to the object's metadata. type: object labels: additionalProperties: type: string description: Labels to be added to the object's metadata. type: object type: object dependsOn: description: |- DependsOn may contain a DependencyReference slice with references to HelmRelease resources that must be ready before this HelmRelease can be reconciled. items: description: DependencyReference defines a HelmRelease dependency on another HelmRelease resource. properties: name: description: Name of the referent. type: string namespace: description: |- Namespace of the referent, defaults to the namespace of the HelmRelease resource object that contains the reference. type: string readyExpr: description: |- ReadyExpr is a CEL expression that can be used to assess the readiness of a dependency. When specified, the built-in readiness check is replaced by the logic defined in the CEL expression. To make the CEL expression additive to the built-in readiness check, the feature gate `AdditiveCELDependencyCheck` must be set to `true`. type: string required: - name type: object type: array driftDetection: description: |- DriftDetection holds the configuration for detecting and handling differences between the manifest in the Helm storage and the resources currently existing in the cluster. properties: ignore: description: |- Ignore contains a list of rules for specifying which changes to ignore during diffing. items: description: |- IgnoreRule defines a rule to selectively disregard specific changes during the drift detection process. properties: paths: description: |- Paths is a list of JSON Pointer (RFC 6901) paths to be excluded from consideration in a Kubernetes object. items: type: string type: array target: description: |- Target is a selector for specifying Kubernetes objects to which this rule applies. If Target is not set, the Paths will be ignored for all Kubernetes objects within the manifest of the Helm release. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - paths type: object type: array mode: description: |- Mode defines how differences should be handled between the Helm manifest and the manifest currently applied to the cluster. If not explicitly set, it defaults to DiffModeDisabled. enum: - enabled - warn - disabled type: string type: object install: description: Install holds the configuration for Helm install actions for this HelmRelease. properties: crds: description: |- CRDs upgrade CRDs from the Helm Chart's crds directory according to the CRD upgrade policy provided here. Valid values are `Skip`, `Create` or `CreateReplace`. Default is `Create` and if omitted CRDs are installed but not updated. Skip: do neither install nor replace (update) any CRDs. Create: new CRDs are created, existing CRDs are neither updated nor deleted. CreateReplace: new CRDs are created, existing CRDs are updated (replaced) but not deleted. By default, CRDs are applied (installed) during Helm install action. With this option users can opt in to CRD replace existing CRDs on Helm install actions, which is not (yet) natively supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions. enum: - Skip - Create - CreateReplace type: string createNamespace: description: |- CreateNamespace tells the Helm install action to create the HelmReleaseSpec.TargetNamespace if it does not exist yet. On uninstall, the namespace will not be garbage collected. type: boolean disableHooks: description: DisableHooks prevents hooks from running during the Helm install action. type: boolean disableOpenAPIValidation: description: |- DisableOpenAPIValidation prevents the Helm install action from validating rendered templates against the Kubernetes OpenAPI Schema. type: boolean disableSchemaValidation: description: |- DisableSchemaValidation prevents the Helm install action from validating the values against the JSON Schema. type: boolean disableTakeOwnership: description: |- DisableTakeOwnership disables taking ownership of existing resources during the Helm install action. Defaults to false. type: boolean disableWait: description: |- DisableWait disables the waiting for resources to be ready after a Helm install has been performed. type: boolean disableWaitForJobs: description: |- DisableWaitForJobs disables waiting for jobs to complete after a Helm install has been performed. type: boolean remediation: description: |- Remediation holds the remediation configuration for when the Helm install action for the HelmRelease fails. The default is to not perform any action. properties: ignoreTestFailures: description: |- IgnoreTestFailures tells the controller to skip remediation when the Helm tests are run after an install action but fail. Defaults to 'Test.IgnoreFailures'. type: boolean remediateLastFailure: description: |- RemediateLastFailure tells the controller to remediate the last failure, when no retries remain. Defaults to 'false'. type: boolean retries: description: |- Retries is the number of retries that should be attempted on failures before bailing. Remediation, using an uninstall, is performed between each attempt. Defaults to '0', a negative integer equals to unlimited retries. type: integer type: object replace: description: |- Replace tells the Helm install action to re-use the 'ReleaseName', but only if that name is a deleted release which remains in the history. type: boolean skipCRDs: description: |- SkipCRDs tells the Helm install action to not install any CRDs. By default, CRDs are installed if not already present. Deprecated use CRD policy (`crds`) attribute with value `Skip` instead. type: boolean strategy: description: |- Strategy defines the install strategy to use for this HelmRelease. Defaults to 'RemediateOnFailure'. properties: name: description: Name of the install strategy. enum: - RemediateOnFailure - RetryOnFailure type: string retryInterval: description: |- RetryInterval is the interval at which to retry a failed install. Can be used only when Name is set to RetryOnFailure. Defaults to '5m'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string required: - name type: object x-kubernetes-validations: - message: .retryInterval cannot be set when .name is 'RemediateOnFailure' rule: '!has(self.retryInterval) || self.name != ''RemediateOnFailure''' timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm install action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object interval: description: Interval at which to reconcile the Helm release. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string kubeConfig: description: |- KubeConfig for reconciling the HelmRelease on a remote cluster. When used in combination with HelmReleaseSpec.ServiceAccountName, forces the controller to act on behalf of that Service Account at the target cluster. If the --default-service-account flag is set, its value will be used as a controller level fallback for when HelmReleaseSpec.ServiceAccountName is empty. properties: configMapRef: description: |- ConfigMapRef holds an optional name of a ConfigMap that contains the following keys: - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or `generic`. Required. - `cluster`: the fully qualified resource name of the Kubernetes cluster in the cloud provider API. Not used by the `generic` provider. Required when one of `address` or `ca.crt` is not set. - `address`: the address of the Kubernetes API server. Required for `generic`. For the other providers, if not specified, the first address in the cluster resource will be used, and if specified, it must match one of the addresses in the cluster resource. If audiences is not set, will be used as the audience for the `generic` provider. - `ca.crt`: the optional PEM-encoded CA certificate for the Kubernetes API server. If not set, the controller will use the CA certificate from the cluster resource. - `audiences`: the optional audiences as a list of line-break-separated strings for the Kubernetes ServiceAccount token. Defaults to the `address` for the `generic` provider, or to specific values for the other providers depending on the provider. - `serviceAccountName`: the optional name of the Kubernetes ServiceAccount in the same namespace that should be used for authentication. If not specified, the controller ServiceAccount will be used. Mutually exclusive with SecretRef. properties: name: description: Name of the referent. type: string required: - name type: object secretRef: description: |- SecretRef holds an optional name of a secret that contains a key with the kubeconfig file as the value. If no key is set, the key will default to 'value'. Mutually exclusive with ConfigMapRef. It is recommended that the kubeconfig is self-contained, and the secret is regularly updated if credentials such as a cloud-access-token expire. Cloud specific `cmd-path` auth helpers will not function without adding binaries and credentials to the Pod that is responsible for reconciling Kubernetes resources. Supported only for the generic provider. properties: key: description: Key in the Secret, when not specified an implementation-specific default key is used. type: string name: description: Name of the Secret. type: string required: - name type: object type: object x-kubernetes-validations: - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: has(self.configMapRef) || has(self.secretRef) - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: '!has(self.configMapRef) || !has(self.secretRef)' maxHistory: description: |- MaxHistory is the number of revisions saved by Helm for this HelmRelease. Use '0' for an unlimited number of revisions; defaults to '5'. type: integer persistentClient: description: |- PersistentClient tells the controller to use a persistent Kubernetes client for this release. When enabled, the client will be reused for the duration of the reconciliation, instead of being created and destroyed for each (step of a) Helm action. This can improve performance, but may cause issues with some Helm charts that for example do create Custom Resource Definitions during installation outside Helm's CRD lifecycle hooks, which are then not observed to be available by e.g. post-install hooks. If not set, it defaults to true. type: boolean postRenderers: description: |- PostRenderers holds an array of Helm PostRenderers, which will be applied in order of their definition. items: description: PostRenderer contains a Helm PostRenderer specification. properties: kustomize: description: Kustomization to apply as PostRenderer. properties: images: description: |- Images is a list of (image name, new name, new tag or digest) for changing image names, tags or digests. This can also be achieved with a patch, but this operator is simpler to specify. items: description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. properties: digest: description: |- Digest is the value used to replace the original image tag. If digest is present NewTag value is ignored. type: string name: description: Name is a tag-less image name. type: string newName: description: NewName is the value used to replace the original name. type: string newTag: description: NewTag is the value used to replace the original tag. type: string required: - name type: object type: array patches: description: |- Strategic merge and JSON patches, defined as inline YAML objects, capable of targeting objects based on kind, label and annotation selectors. items: description: |- Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should be applied to. properties: patch: description: |- Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with an array of operation objects. type: string target: description: Target points to the resources that the patch document should be applied to. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - patch type: object type: array type: object type: object type: array releaseName: description: |- ReleaseName used for the Helm release. Defaults to a composition of '[TargetNamespace-]Name'. maxLength: 53 minLength: 1 type: string rollback: description: Rollback holds the configuration for Helm rollback actions for this HelmRelease. properties: cleanupOnFail: description: |- CleanupOnFail allows deletion of new resources created during the Helm rollback action when it fails. type: boolean disableHooks: description: DisableHooks prevents hooks from running during the Helm rollback action. type: boolean disableWait: description: |- DisableWait disables the waiting for resources to be ready after a Helm rollback has been performed. type: boolean disableWaitForJobs: description: |- DisableWaitForJobs disables waiting for jobs to complete after a Helm rollback has been performed. type: boolean force: description: Force forces resource updates through a replacement strategy. type: boolean recreate: description: Recreate performs pod restarts for the resource if applicable. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm rollback action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object serviceAccountName: description: |- The name of the Kubernetes service account to impersonate when reconciling this HelmRelease. maxLength: 253 minLength: 1 type: string storageNamespace: description: |- StorageNamespace used for the Helm storage. Defaults to the namespace of the HelmRelease. maxLength: 63 minLength: 1 type: string suspend: description: |- Suspend tells the controller to suspend reconciliation for this HelmRelease, it does not apply to already started reconciliations. Defaults to false. type: boolean targetNamespace: description: |- TargetNamespace to target when performing operations for the HelmRelease. Defaults to the namespace of the HelmRelease. maxLength: 63 minLength: 1 type: string test: description: Test holds the configuration for Helm test actions for this HelmRelease. properties: enable: description: |- Enable enables Helm test actions for this HelmRelease after an Helm install or upgrade action has been performed. type: boolean filters: description: Filters is a list of tests to run or exclude from running. items: description: Filter holds the configuration for individual Helm test filters. properties: exclude: description: Exclude specifies whether the named test should be excluded. type: boolean name: description: Name is the name of the test. maxLength: 253 minLength: 1 type: string required: - name type: object type: array ignoreFailures: description: |- IgnoreFailures tells the controller to skip remediation when the Helm tests are run but fail. Can be overwritten for tests run after install or upgrade actions in 'Install.IgnoreTestFailures' and 'Upgrade.IgnoreTestFailures'. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation during the performance of a Helm test action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm action. Defaults to '5m0s'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string uninstall: description: Uninstall holds the configuration for Helm uninstall actions for this HelmRelease. properties: deletionPropagation: default: background description: |- DeletionPropagation specifies the deletion propagation policy when a Helm uninstall is performed. enum: - background - foreground - orphan type: string disableHooks: description: DisableHooks prevents hooks from running during the Helm rollback action. type: boolean disableWait: description: |- DisableWait disables waiting for all the resources to be deleted after a Helm uninstall is performed. type: boolean keepHistory: description: |- KeepHistory tells Helm to remove all associated resources and mark the release as deleted, but retain the release history. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm uninstall action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object upgrade: description: Upgrade holds the configuration for Helm upgrade actions for this HelmRelease. properties: cleanupOnFail: description: |- CleanupOnFail allows deletion of new resources created during the Helm upgrade action when it fails. type: boolean crds: description: |- CRDs upgrade CRDs from the Helm Chart's crds directory according to the CRD upgrade policy provided here. Valid values are `Skip`, `Create` or `CreateReplace`. Default is `Skip` and if omitted CRDs are neither installed nor upgraded. Skip: do neither install nor replace (update) any CRDs. Create: new CRDs are created, existing CRDs are neither updated nor deleted. CreateReplace: new CRDs are created, existing CRDs are updated (replaced) but not deleted. By default, CRDs are not applied during Helm upgrade action. With this option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions. enum: - Skip - Create - CreateReplace type: string disableHooks: description: DisableHooks prevents hooks from running during the Helm upgrade action. type: boolean disableOpenAPIValidation: description: |- DisableOpenAPIValidation prevents the Helm upgrade action from validating rendered templates against the Kubernetes OpenAPI Schema. type: boolean disableSchemaValidation: description: |- DisableSchemaValidation prevents the Helm upgrade action from validating the values against the JSON Schema. type: boolean disableTakeOwnership: description: |- DisableTakeOwnership disables taking ownership of existing resources during the Helm upgrade action. Defaults to false. type: boolean disableWait: description: |- DisableWait disables the waiting for resources to be ready after a Helm upgrade has been performed. type: boolean disableWaitForJobs: description: |- DisableWaitForJobs disables waiting for jobs to complete after a Helm upgrade has been performed. type: boolean force: description: Force forces resource updates through a replacement strategy. type: boolean preserveValues: description: |- PreserveValues will make Helm reuse the last release's values and merge in overrides from 'Values'. Setting this flag makes the HelmRelease non-declarative. type: boolean remediation: description: |- Remediation holds the remediation configuration for when the Helm upgrade action for the HelmRelease fails. The default is to not perform any action. properties: ignoreTestFailures: description: |- IgnoreTestFailures tells the controller to skip remediation when the Helm tests are run after an upgrade action but fail. Defaults to 'Test.IgnoreFailures'. type: boolean remediateLastFailure: description: |- RemediateLastFailure tells the controller to remediate the last failure, when no retries remain. Defaults to 'false' unless 'Retries' is greater than 0. type: boolean retries: description: |- Retries is the number of retries that should be attempted on failures before bailing. Remediation, using 'Strategy', is performed between each attempt. Defaults to '0', a negative integer equals to unlimited retries. type: integer strategy: description: Strategy to use for failure remediation. Defaults to 'rollback'. enum: - rollback - uninstall type: string type: object strategy: description: |- Strategy defines the upgrade strategy to use for this HelmRelease. Defaults to 'RemediateOnFailure'. properties: name: description: Name of the upgrade strategy. enum: - RemediateOnFailure - RetryOnFailure type: string retryInterval: description: |- RetryInterval is the interval at which to retry a failed upgrade. Can be used only when Name is set to RetryOnFailure. Defaults to '5m'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string required: - name type: object x-kubernetes-validations: - message: .retryInterval can only be set when .name is 'RetryOnFailure' rule: '!has(self.retryInterval) || self.name == ''RetryOnFailure''' timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm upgrade action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object values: description: Values holds the values for this Helm release. x-kubernetes-preserve-unknown-fields: true valuesFrom: description: |- ValuesFrom holds references to resources containing Helm values for this HelmRelease, and information about how they should be merged. items: description: |- ValuesReference contains a reference to a resource containing Helm values, and optionally the key they can be found at. properties: kind: description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). enum: - Secret - ConfigMap type: string name: description: |- Name of the values referent. Should reside in the same namespace as the referring resource. maxLength: 253 minLength: 1 type: string optional: description: |- Optional marks this ValuesReference as optional. When set, a not found error for the values reference is ignored, but any ValuesKey, TargetPath or transient error will still result in a reconciliation failure. type: boolean targetPath: description: |- TargetPath is the YAML dot notation path the value should be merged at. When set, the ValuesKey is expected to be a single flat value. Defaults to 'None', which results in the values getting merged at the root. maxLength: 250 pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$ type: string valuesKey: description: |- ValuesKey is the data key where the values.yaml or a specific value can be found at. Defaults to 'values.yaml'. maxLength: 253 pattern: ^[\-._a-zA-Z0-9]+$ type: string required: - kind - name type: object type: array required: - interval type: object x-kubernetes-validations: - message: either chart or chartRef must be set rule: (has(self.chart) && !has(self.chartRef)) || (!has(self.chart) && has(self.chartRef)) status: default: observedGeneration: -1 description: HelmReleaseStatus defines the observed state of a HelmRelease. properties: conditions: description: Conditions holds the conditions for the HelmRelease. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array failures: description: |- Failures is the reconciliation failure count against the latest desired state. It is reset after a successful reconciliation. format: int64 type: integer helmChart: description: |- HelmChart is the namespaced name of the HelmChart resource created by the controller for the HelmRelease. type: string history: description: |- History holds the history of Helm releases performed for this HelmRelease up to the last successfully completed release. items: description: |- Snapshot captures a point-in-time copy of the status information for a Helm release, as managed by the controller. properties: apiVersion: description: |- APIVersion is the API version of the Snapshot. Provisional: when the calculation method of the Digest field is changed, this field will be used to distinguish between the old and new methods. type: string appVersion: description: AppVersion is the chart app version of the release object in storage. type: string chartName: description: ChartName is the chart name of the release object in storage. type: string chartVersion: description: |- ChartVersion is the chart version of the release object in storage. type: string configDigest: description: |- ConfigDigest is the checksum of the config (better known as "values") of the release object in storage. It has the format of `:`. type: string deleted: description: Deleted is when the release was deleted. format: date-time type: string digest: description: |- Digest is the checksum of the release object in storage. It has the format of `:`. type: string firstDeployed: description: FirstDeployed is when the release was first deployed. format: date-time type: string lastDeployed: description: LastDeployed is when the release was last deployed. format: date-time type: string name: description: Name is the name of the release. type: string namespace: description: Namespace is the namespace the release is deployed to. type: string ociDigest: description: OCIDigest is the digest of the OCI artifact associated with the release. type: string status: description: Status is the current state of the release. type: string testHooks: additionalProperties: description: |- TestHookStatus holds the status information for a test hook as observed to be run by the controller. properties: lastCompleted: description: LastCompleted is the time the test hook last completed. format: date-time type: string lastStarted: description: LastStarted is the time the test hook was last started. format: date-time type: string phase: description: Phase the test hook was observed to be in. type: string type: object description: |- TestHooks is the list of test hooks for the release as observed to be run by the controller. type: object version: description: Version is the version of the release object in storage. type: integer required: - chartName - chartVersion - configDigest - digest - firstDeployed - lastDeployed - name - namespace - status - version type: object type: array installFailures: description: |- InstallFailures is the install failure count against the latest desired state. It is reset after a successful reconciliation. format: int64 type: integer lastAttemptedConfigDigest: description: |- LastAttemptedConfigDigest is the digest for the config (better known as "values") of the last reconciliation attempt. type: string lastAttemptedGeneration: description: |- LastAttemptedGeneration is the last generation the controller attempted to reconcile. format: int64 type: integer lastAttemptedReleaseAction: description: |- LastAttemptedReleaseAction is the last release action performed for this HelmRelease. It is used to determine the active retry or remediation strategy. enum: - install - upgrade type: string lastAttemptedReleaseActionDuration: description: |- LastAttemptedReleaseActionDuration is the duration of the last release action performed for this HelmRelease. type: string lastAttemptedRevision: description: |- LastAttemptedRevision is the Source revision of the last reconciliation attempt. For OCIRepository sources, the 12 first characters of the digest are appended to the chart version e.g. "1.2.3+1234567890ab". type: string lastAttemptedRevisionDigest: description: |- LastAttemptedRevisionDigest is the digest of the last reconciliation attempt. This is only set for OCIRepository sources. type: string lastAttemptedValuesChecksum: description: |- LastAttemptedValuesChecksum is the SHA1 checksum for the values of the last reconciliation attempt. Deprecated: Use LastAttemptedConfigDigest instead. type: string lastHandledForceAt: description: |- LastHandledForceAt holds the value of the most recent force request value, so a change of the annotation value can be detected. type: string lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string lastHandledResetAt: description: |- LastHandledResetAt holds the value of the most recent reset request value, so a change of the annotation value can be detected. type: string lastReleaseRevision: description: |- LastReleaseRevision is the revision of the last successful Helm release. Deprecated: Use History instead. type: integer observedCommonMetadataDigest: description: |- ObservedCommonMetadataDigest is the digest for the common metadata of the last successful reconciliation attempt. type: string observedGeneration: description: ObservedGeneration is the last observed generation. format: int64 type: integer observedPostRenderersDigest: description: |- ObservedPostRenderersDigest is the digest for the post-renderers of the last successful reconciliation attempt. type: string storageNamespace: description: |- StorageNamespace is the namespace of the Helm release storage for the current release. maxLength: 63 minLength: 1 type: string upgradeFailures: description: |- UpgradeFailures is the upgrade failure count against the latest desired state. It is reset after a successful reconciliation. format: int64 type: integer type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v2beta2 HelmRelease is deprecated, upgrade to v2 name: v2beta2 schema: openAPIV3Schema: description: HelmRelease is the Schema for the helmreleases API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: HelmReleaseSpec defines the desired state of a Helm release. properties: chart: description: |- Chart defines the template of the v1beta2.HelmChart that should be created for this HelmRelease. properties: metadata: description: ObjectMeta holds the template for metadata like labels and annotations. properties: annotations: additionalProperties: type: string description: |- Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ type: object labels: additionalProperties: type: string description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ type: object type: object spec: description: Spec holds the template for the v1beta2.HelmChartSpec for this HelmRelease. properties: chart: description: The name or path the Helm chart is available at in the SourceRef. maxLength: 2048 minLength: 1 type: string ignoreMissingValuesFiles: description: IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. type: boolean interval: description: |- Interval at which to check the v1.Source for updates. Defaults to 'HelmReleaseSpec.Interval'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string reconcileStrategy: default: ChartVersion description: |- Determines what enables the creation of a new artifact. Valid values are ('ChartVersion', 'Revision'). See the documentation of the values for an explanation on their behavior. Defaults to ChartVersion when omitted. enum: - ChartVersion - Revision type: string sourceRef: description: The name and namespace of the v1.Source the chart is available at. properties: apiVersion: description: APIVersion of the referent. type: string kind: description: Kind of the referent. enum: - HelmRepository - GitRepository - Bucket type: string name: description: Name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: Namespace of the referent. maxLength: 63 minLength: 1 type: string required: - kind - name type: object valuesFile: description: |- Alternative values file to use as the default chart values, expected to be a relative path in the SourceRef. Deprecated in favor of ValuesFiles, for backwards compatibility the file defined here is merged before the ValuesFiles items. Ignored when omitted. type: string valuesFiles: description: |- Alternative list of values files to use as the chart values (values.yaml is not included by default), expected to be a relative path in the SourceRef. Values files are merged in the order of this list with the last file overriding the first. Ignored when omitted. items: type: string type: array verify: description: |- Verify contains the secret name containing the trusted public keys used to verify the signature and specifies which provider to use to check whether OCI image is authentic. This field is only supported for OCI sources. Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. properties: provider: default: cosign description: Provider specifies the technology used to sign the OCI Helm chart. enum: - cosign - notation type: string secretRef: description: |- SecretRef specifies the Kubernetes Secret containing the trusted public keys. properties: name: description: Name of the referent. type: string required: - name type: object required: - provider type: object version: default: '*' description: |- Version semver expression, ignored for charts from v1beta2.GitRepository and v1beta2.Bucket sources. Defaults to latest when omitted. type: string required: - chart - sourceRef type: object required: - spec type: object chartRef: description: |- ChartRef holds a reference to a source controller resource containing the Helm chart artifact. Note: this field is provisional to the v2 API, and not actively used by v2beta2 HelmReleases. properties: apiVersion: description: APIVersion of the referent. type: string kind: description: Kind of the referent. enum: - OCIRepository - HelmChart type: string name: description: Name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference. maxLength: 63 minLength: 1 type: string required: - kind - name type: object dependsOn: description: |- DependsOn may contain a meta.NamespacedObjectReference slice with references to HelmRelease resources that must be ready before this HelmRelease can be reconciled. items: description: |- NamespacedObjectReference contains enough information to locate the referenced Kubernetes resource object in any namespace. properties: name: description: Name of the referent. type: string namespace: description: Namespace of the referent, when not specified it acts as LocalObjectReference. type: string required: - name type: object type: array driftDetection: description: |- DriftDetection holds the configuration for detecting and handling differences between the manifest in the Helm storage and the resources currently existing in the cluster. properties: ignore: description: |- Ignore contains a list of rules for specifying which changes to ignore during diffing. items: description: |- IgnoreRule defines a rule to selectively disregard specific changes during the drift detection process. properties: paths: description: |- Paths is a list of JSON Pointer (RFC 6901) paths to be excluded from consideration in a Kubernetes object. items: type: string type: array target: description: |- Target is a selector for specifying Kubernetes objects to which this rule applies. If Target is not set, the Paths will be ignored for all Kubernetes objects within the manifest of the Helm release. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - paths type: object type: array mode: description: |- Mode defines how differences should be handled between the Helm manifest and the manifest currently applied to the cluster. If not explicitly set, it defaults to DiffModeDisabled. enum: - enabled - warn - disabled type: string type: object install: description: Install holds the configuration for Helm install actions for this HelmRelease. properties: crds: description: |- CRDs upgrade CRDs from the Helm Chart's crds directory according to the CRD upgrade policy provided here. Valid values are `Skip`, `Create` or `CreateReplace`. Default is `Create` and if omitted CRDs are installed but not updated. Skip: do neither install nor replace (update) any CRDs. Create: new CRDs are created, existing CRDs are neither updated nor deleted. CreateReplace: new CRDs are created, existing CRDs are updated (replaced) but not deleted. By default, CRDs are applied (installed) during Helm install action. With this option users can opt in to CRD replace existing CRDs on Helm install actions, which is not (yet) natively supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions. enum: - Skip - Create - CreateReplace type: string createNamespace: description: |- CreateNamespace tells the Helm install action to create the HelmReleaseSpec.TargetNamespace if it does not exist yet. On uninstall, the namespace will not be garbage collected. type: boolean disableHooks: description: DisableHooks prevents hooks from running during the Helm install action. type: boolean disableOpenAPIValidation: description: |- DisableOpenAPIValidation prevents the Helm install action from validating rendered templates against the Kubernetes OpenAPI Schema. type: boolean disableWait: description: |- DisableWait disables the waiting for resources to be ready after a Helm install has been performed. type: boolean disableWaitForJobs: description: |- DisableWaitForJobs disables waiting for jobs to complete after a Helm install has been performed. type: boolean remediation: description: |- Remediation holds the remediation configuration for when the Helm install action for the HelmRelease fails. The default is to not perform any action. properties: ignoreTestFailures: description: |- IgnoreTestFailures tells the controller to skip remediation when the Helm tests are run after an install action but fail. Defaults to 'Test.IgnoreFailures'. type: boolean remediateLastFailure: description: |- RemediateLastFailure tells the controller to remediate the last failure, when no retries remain. Defaults to 'false'. type: boolean retries: description: |- Retries is the number of retries that should be attempted on failures before bailing. Remediation, using an uninstall, is performed between each attempt. Defaults to '0', a negative integer equals to unlimited retries. type: integer type: object replace: description: |- Replace tells the Helm install action to re-use the 'ReleaseName', but only if that name is a deleted release which remains in the history. type: boolean skipCRDs: description: |- SkipCRDs tells the Helm install action to not install any CRDs. By default, CRDs are installed if not already present. Deprecated use CRD policy (`crds`) attribute with value `Skip` instead. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm install action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object interval: description: Interval at which to reconcile the Helm release. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string kubeConfig: description: |- KubeConfig for reconciling the HelmRelease on a remote cluster. When used in combination with HelmReleaseSpec.ServiceAccountName, forces the controller to act on behalf of that Service Account at the target cluster. If the --default-service-account flag is set, its value will be used as a controller level fallback for when HelmReleaseSpec.ServiceAccountName is empty. properties: configMapRef: description: |- ConfigMapRef holds an optional name of a ConfigMap that contains the following keys: - `provider`: the provider to use. One of `aws`, `azure`, `gcp`, or `generic`. Required. - `cluster`: the fully qualified resource name of the Kubernetes cluster in the cloud provider API. Not used by the `generic` provider. Required when one of `address` or `ca.crt` is not set. - `address`: the address of the Kubernetes API server. Required for `generic`. For the other providers, if not specified, the first address in the cluster resource will be used, and if specified, it must match one of the addresses in the cluster resource. If audiences is not set, will be used as the audience for the `generic` provider. - `ca.crt`: the optional PEM-encoded CA certificate for the Kubernetes API server. If not set, the controller will use the CA certificate from the cluster resource. - `audiences`: the optional audiences as a list of line-break-separated strings for the Kubernetes ServiceAccount token. Defaults to the `address` for the `generic` provider, or to specific values for the other providers depending on the provider. - `serviceAccountName`: the optional name of the Kubernetes ServiceAccount in the same namespace that should be used for authentication. If not specified, the controller ServiceAccount will be used. Mutually exclusive with SecretRef. properties: name: description: Name of the referent. type: string required: - name type: object secretRef: description: |- SecretRef holds an optional name of a secret that contains a key with the kubeconfig file as the value. If no key is set, the key will default to 'value'. Mutually exclusive with ConfigMapRef. It is recommended that the kubeconfig is self-contained, and the secret is regularly updated if credentials such as a cloud-access-token expire. Cloud specific `cmd-path` auth helpers will not function without adding binaries and credentials to the Pod that is responsible for reconciling Kubernetes resources. Supported only for the generic provider. properties: key: description: Key in the Secret, when not specified an implementation-specific default key is used. type: string name: description: Name of the Secret. type: string required: - name type: object type: object x-kubernetes-validations: - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: has(self.configMapRef) || has(self.secretRef) - message: exactly one of spec.kubeConfig.configMapRef or spec.kubeConfig.secretRef must be specified rule: '!has(self.configMapRef) || !has(self.secretRef)' maxHistory: description: |- MaxHistory is the number of revisions saved by Helm for this HelmRelease. Use '0' for an unlimited number of revisions; defaults to '5'. type: integer persistentClient: description: |- PersistentClient tells the controller to use a persistent Kubernetes client for this release. When enabled, the client will be reused for the duration of the reconciliation, instead of being created and destroyed for each (step of a) Helm action. This can improve performance, but may cause issues with some Helm charts that for example do create Custom Resource Definitions during installation outside Helm's CRD lifecycle hooks, which are then not observed to be available by e.g. post-install hooks. If not set, it defaults to true. type: boolean postRenderers: description: |- PostRenderers holds an array of Helm PostRenderers, which will be applied in order of their definition. items: description: PostRenderer contains a Helm PostRenderer specification. properties: kustomize: description: Kustomization to apply as PostRenderer. properties: images: description: |- Images is a list of (image name, new name, new tag or digest) for changing image names, tags or digests. This can also be achieved with a patch, but this operator is simpler to specify. items: description: Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag. properties: digest: description: |- Digest is the value used to replace the original image tag. If digest is present NewTag value is ignored. type: string name: description: Name is a tag-less image name. type: string newName: description: NewName is the value used to replace the original name. type: string newTag: description: NewTag is the value used to replace the original tag. type: string required: - name type: object type: array patches: description: |- Strategic merge and JSON patches, defined as inline YAML objects, capable of targeting objects based on kind, label and annotation selectors. items: description: |- Patch contains an inline StrategicMerge or JSON6902 patch, and the target the patch should be applied to. properties: patch: description: |- Patch contains an inline StrategicMerge patch or an inline JSON6902 patch with an array of operation objects. type: string target: description: Target points to the resources that the patch document should be applied to. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - patch type: object type: array patchesJson6902: description: |- JSON 6902 patches, defined as inline YAML objects. Deprecated: use Patches instead. items: description: JSON6902Patch contains a JSON6902 patch and the target the patch should be applied to. properties: patch: description: Patch contains the JSON6902 patch document with an array of operation objects. items: description: |- JSON6902 is a JSON6902 operation object. https://datatracker.ietf.org/doc/html/rfc6902#section-4 properties: from: description: |- From contains a JSON-pointer value that references a location within the target document where the operation is performed. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations. type: string op: description: |- Op indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 enum: - test - remove - add - replace - move - copy type: string path: description: |- Path contains the JSON-pointer value that references a location within the target document where the operation is performed. The meaning of the value depends on the value of Op. type: string value: description: |- Value contains a valid JSON structure. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations. x-kubernetes-preserve-unknown-fields: true required: - op - path type: object type: array target: description: Target points to the resources that the patch document should be applied to. properties: annotationSelector: description: |- AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. type: string group: description: |- Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string kind: description: |- Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string labelSelector: description: |- LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. type: string name: description: Name to match resources with. type: string namespace: description: Namespace to select resources from. type: string version: description: |- Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md type: string type: object required: - patch - target type: object type: array patchesStrategicMerge: description: |- Strategic merge patches, defined as inline YAML objects. Deprecated: use Patches instead. items: x-kubernetes-preserve-unknown-fields: true type: array type: object type: object type: array releaseName: description: |- ReleaseName used for the Helm release. Defaults to a composition of '[TargetNamespace-]Name'. maxLength: 53 minLength: 1 type: string rollback: description: Rollback holds the configuration for Helm rollback actions for this HelmRelease. properties: cleanupOnFail: description: |- CleanupOnFail allows deletion of new resources created during the Helm rollback action when it fails. type: boolean disableHooks: description: DisableHooks prevents hooks from running during the Helm rollback action. type: boolean disableWait: description: |- DisableWait disables the waiting for resources to be ready after a Helm rollback has been performed. type: boolean disableWaitForJobs: description: |- DisableWaitForJobs disables waiting for jobs to complete after a Helm rollback has been performed. type: boolean force: description: Force forces resource updates through a replacement strategy. type: boolean recreate: description: Recreate performs pod restarts for the resource if applicable. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm rollback action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object serviceAccountName: description: |- The name of the Kubernetes service account to impersonate when reconciling this HelmRelease. maxLength: 253 minLength: 1 type: string storageNamespace: description: |- StorageNamespace used for the Helm storage. Defaults to the namespace of the HelmRelease. maxLength: 63 minLength: 1 type: string suspend: description: |- Suspend tells the controller to suspend reconciliation for this HelmRelease, it does not apply to already started reconciliations. Defaults to false. type: boolean targetNamespace: description: |- TargetNamespace to target when performing operations for the HelmRelease. Defaults to the namespace of the HelmRelease. maxLength: 63 minLength: 1 type: string test: description: Test holds the configuration for Helm test actions for this HelmRelease. properties: enable: description: |- Enable enables Helm test actions for this HelmRelease after an Helm install or upgrade action has been performed. type: boolean filters: description: Filters is a list of tests to run or exclude from running. items: description: Filter holds the configuration for individual Helm test filters. properties: exclude: description: Exclude specifies whether the named test should be excluded. type: boolean name: description: Name is the name of the test. maxLength: 253 minLength: 1 type: string required: - name type: object type: array ignoreFailures: description: |- IgnoreFailures tells the controller to skip remediation when the Helm tests are run but fail. Can be overwritten for tests run after install or upgrade actions in 'Install.IgnoreTestFailures' and 'Upgrade.IgnoreTestFailures'. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation during the performance of a Helm test action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm action. Defaults to '5m0s'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string uninstall: description: Uninstall holds the configuration for Helm uninstall actions for this HelmRelease. properties: deletionPropagation: default: background description: |- DeletionPropagation specifies the deletion propagation policy when a Helm uninstall is performed. enum: - background - foreground - orphan type: string disableHooks: description: DisableHooks prevents hooks from running during the Helm rollback action. type: boolean disableWait: description: |- DisableWait disables waiting for all the resources to be deleted after a Helm uninstall is performed. type: boolean keepHistory: description: |- KeepHistory tells Helm to remove all associated resources and mark the release as deleted, but retain the release history. type: boolean timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm uninstall action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object upgrade: description: Upgrade holds the configuration for Helm upgrade actions for this HelmRelease. properties: cleanupOnFail: description: |- CleanupOnFail allows deletion of new resources created during the Helm upgrade action when it fails. type: boolean crds: description: |- CRDs upgrade CRDs from the Helm Chart's crds directory according to the CRD upgrade policy provided here. Valid values are `Skip`, `Create` or `CreateReplace`. Default is `Skip` and if omitted CRDs are neither installed nor upgraded. Skip: do neither install nor replace (update) any CRDs. Create: new CRDs are created, existing CRDs are neither updated nor deleted. CreateReplace: new CRDs are created, existing CRDs are updated (replaced) but not deleted. By default, CRDs are not applied during Helm upgrade action. With this option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions. enum: - Skip - Create - CreateReplace type: string disableHooks: description: DisableHooks prevents hooks from running during the Helm upgrade action. type: boolean disableOpenAPIValidation: description: |- DisableOpenAPIValidation prevents the Helm upgrade action from validating rendered templates against the Kubernetes OpenAPI Schema. type: boolean disableWait: description: |- DisableWait disables the waiting for resources to be ready after a Helm upgrade has been performed. type: boolean disableWaitForJobs: description: |- DisableWaitForJobs disables waiting for jobs to complete after a Helm upgrade has been performed. type: boolean force: description: Force forces resource updates through a replacement strategy. type: boolean preserveValues: description: |- PreserveValues will make Helm reuse the last release's values and merge in overrides from 'Values'. Setting this flag makes the HelmRelease non-declarative. type: boolean remediation: description: |- Remediation holds the remediation configuration for when the Helm upgrade action for the HelmRelease fails. The default is to not perform any action. properties: ignoreTestFailures: description: |- IgnoreTestFailures tells the controller to skip remediation when the Helm tests are run after an upgrade action but fail. Defaults to 'Test.IgnoreFailures'. type: boolean remediateLastFailure: description: |- RemediateLastFailure tells the controller to remediate the last failure, when no retries remain. Defaults to 'false' unless 'Retries' is greater than 0. type: boolean retries: description: |- Retries is the number of retries that should be attempted on failures before bailing. Remediation, using 'Strategy', is performed between each attempt. Defaults to '0', a negative integer equals to unlimited retries. type: integer strategy: description: Strategy to use for failure remediation. Defaults to 'rollback'. enum: - rollback - uninstall type: string type: object timeout: description: |- Timeout is the time to wait for any individual Kubernetes operation (like Jobs for hooks) during the performance of a Helm upgrade action. Defaults to 'HelmReleaseSpec.Timeout'. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string type: object values: description: Values holds the values for this Helm release. x-kubernetes-preserve-unknown-fields: true valuesFrom: description: |- ValuesFrom holds references to resources containing Helm values for this HelmRelease, and information about how they should be merged. items: description: |- ValuesReference contains a reference to a resource containing Helm values, and optionally the key they can be found at. properties: kind: description: Kind of the values referent, valid values are ('Secret', 'ConfigMap'). enum: - Secret - ConfigMap type: string name: description: |- Name of the values referent. Should reside in the same namespace as the referring resource. maxLength: 253 minLength: 1 type: string optional: description: |- Optional marks this ValuesReference as optional. When set, a not found error for the values reference is ignored, but any ValuesKey, TargetPath or transient error will still result in a reconciliation failure. type: boolean targetPath: description: |- TargetPath is the YAML dot notation path the value should be merged at. When set, the ValuesKey is expected to be a single flat value. Defaults to 'None', which results in the values getting merged at the root. maxLength: 250 pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$ type: string valuesKey: description: |- ValuesKey is the data key where the values.yaml or a specific value can be found at. Defaults to 'values.yaml'. maxLength: 253 pattern: ^[\-._a-zA-Z0-9]+$ type: string required: - kind - name type: object type: array required: - interval type: object x-kubernetes-validations: - message: either chart or chartRef must be set rule: (has(self.chart) && !has(self.chartRef)) || (!has(self.chart) && has(self.chartRef)) status: default: observedGeneration: -1 description: HelmReleaseStatus defines the observed state of a HelmRelease. properties: conditions: description: Conditions holds the conditions for the HelmRelease. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array failures: description: |- Failures is the reconciliation failure count against the latest desired state. It is reset after a successful reconciliation. format: int64 type: integer helmChart: description: |- HelmChart is the namespaced name of the HelmChart resource created by the controller for the HelmRelease. type: string history: description: |- History holds the history of Helm releases performed for this HelmRelease up to the last successfully completed release. items: description: |- Snapshot captures a point-in-time copy of the status information for a Helm release, as managed by the controller. properties: apiVersion: description: |- APIVersion is the API version of the Snapshot. Provisional: when the calculation method of the Digest field is changed, this field will be used to distinguish between the old and new methods. type: string appVersion: description: AppVersion is the chart app version of the release object in storage. type: string chartName: description: ChartName is the chart name of the release object in storage. type: string chartVersion: description: |- ChartVersion is the chart version of the release object in storage. type: string configDigest: description: |- ConfigDigest is the checksum of the config (better known as "values") of the release object in storage. It has the format of `:`. type: string deleted: description: Deleted is when the release was deleted. format: date-time type: string digest: description: |- Digest is the checksum of the release object in storage. It has the format of `:`. type: string firstDeployed: description: FirstDeployed is when the release was first deployed. format: date-time type: string lastDeployed: description: LastDeployed is when the release was last deployed. format: date-time type: string name: description: Name is the name of the release. type: string namespace: description: Namespace is the namespace the release is deployed to. type: string ociDigest: description: OCIDigest is the digest of the OCI artifact associated with the release. type: string status: description: Status is the current state of the release. type: string testHooks: additionalProperties: description: |- TestHookStatus holds the status information for a test hook as observed to be run by the controller. properties: lastCompleted: description: LastCompleted is the time the test hook last completed. format: date-time type: string lastStarted: description: LastStarted is the time the test hook was last started. format: date-time type: string phase: description: Phase the test hook was observed to be in. type: string type: object description: |- TestHooks is the list of test hooks for the release as observed to be run by the controller. type: object version: description: Version is the version of the release object in storage. type: integer required: - chartName - chartVersion - configDigest - digest - firstDeployed - lastDeployed - name - namespace - status - version type: object type: array installFailures: description: |- InstallFailures is the install failure count against the latest desired state. It is reset after a successful reconciliation. format: int64 type: integer lastAppliedRevision: description: |- LastAppliedRevision is the revision of the last successfully applied source. Deprecated: the revision can now be found in the History. type: string lastAttemptedConfigDigest: description: |- LastAttemptedConfigDigest is the digest for the config (better known as "values") of the last reconciliation attempt. type: string lastAttemptedGeneration: description: |- LastAttemptedGeneration is the last generation the controller attempted to reconcile. format: int64 type: integer lastAttemptedReleaseAction: description: |- LastAttemptedReleaseAction is the last release action performed for this HelmRelease. It is used to determine the active remediation strategy. enum: - install - upgrade type: string lastAttemptedRevision: description: |- LastAttemptedRevision is the Source revision of the last reconciliation attempt. For OCIRepository sources, the 12 first characters of the digest are appended to the chart version e.g. "1.2.3+1234567890ab". type: string lastAttemptedRevisionDigest: description: |- LastAttemptedRevisionDigest is the digest of the last reconciliation attempt. This is only set for OCIRepository sources. type: string lastAttemptedValuesChecksum: description: |- LastAttemptedValuesChecksum is the SHA1 checksum for the values of the last reconciliation attempt. Deprecated: Use LastAttemptedConfigDigest instead. type: string lastHandledForceAt: description: |- LastHandledForceAt holds the value of the most recent force request value, so a change of the annotation value can be detected. type: string lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string lastHandledResetAt: description: |- LastHandledResetAt holds the value of the most recent reset request value, so a change of the annotation value can be detected. type: string lastReleaseRevision: description: |- LastReleaseRevision is the revision of the last successful Helm release. Deprecated: Use History instead. type: integer observedGeneration: description: ObservedGeneration is the last observed generation. format: int64 type: integer observedPostRenderersDigest: description: |- ObservedPostRenderersDigest is the digest for the post-renderers of the last successful reconciliation attempt. type: string storageNamespace: description: |- StorageNamespace is the namespace of the Helm release storage for the current release. maxLength: 63 minLength: 1 type: string upgradeFailures: description: |- UpgradeFailures is the upgrade failure count against the latest desired state. It is reset after a successful reconciliation. format: int64 type: integer type: object type: object served: true storage: false subresources: status: {} --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: helm-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: helm-controller namespace: flux-system --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: helm-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: helm-controller namespace: flux-system spec: replicas: 1 selector: matchLabels: app: helm-controller template: metadata: annotations: prometheus.io/port: "8080" prometheus.io/scrape: "true" labels: app: helm-controller app.kubernetes.io/component: helm-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 spec: containers: - args: - --events-addr=http://notification-controller.$(RUNTIME_NAMESPACE).svc.cluster.local./ - --watch-all-namespaces=true - --log-level=info - --log-encoding=json - --enable-leader-election env: - name: RUNTIME_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: GOMEMLIMIT valueFrom: resourceFieldRef: containerName: manager resource: limits.memory image: ghcr.io/fluxcd/helm-controller:v1.4.5 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz port: healthz name: manager ports: - containerPort: 8080 name: http-prom protocol: TCP - containerPort: 9440 name: healthz protocol: TCP readinessProbe: httpGet: path: /readyz port: healthz resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 100m memory: 64Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp name: temp nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical securityContext: fsGroup: 1337 serviceAccountName: helm-controller terminationGracePeriodSeconds: 600 volumes: - emptyDir: {} name: temp --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: alerts.notification.toolkit.fluxcd.io spec: group: notification.toolkit.fluxcd.io names: kind: Alert listKind: AlertList plural: alerts singular: alert scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 Alert is deprecated, upgrade to v1beta3 name: v1beta2 schema: openAPIV3Schema: description: Alert is the Schema for the alerts API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: AlertSpec defines an alerting rule for events involving a list of objects. properties: eventMetadata: additionalProperties: type: string description: |- EventMetadata is an optional field for adding metadata to events dispatched by the controller. This can be used for enhancing the context of the event. If a field would override one already present on the original event as generated by the emitter, then the override doesn't happen, i.e. the original value is preserved, and an info log is printed. type: object eventSeverity: default: info description: |- EventSeverity specifies how to filter events based on severity. If set to 'info' no events will be filtered. enum: - info - error type: string eventSources: description: |- EventSources specifies how to filter events based on the involved object kind, name and namespace. items: description: |- CrossNamespaceObjectReference contains enough information to let you locate the typed referenced object at cluster level properties: apiVersion: description: API version of the referent type: string kind: description: Kind of the referent enum: - Bucket - GitRepository - Kustomization - HelmRelease - HelmChart - HelmRepository - ImageRepository - ImagePolicy - ImageUpdateAutomation - OCIRepository type: string matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. MatchLabels requires the name to be set to `*`. type: object name: description: |- Name of the referent If multiple resources are targeted `*` may be set. maxLength: 253 minLength: 1 type: string namespace: description: Namespace of the referent maxLength: 253 minLength: 1 type: string required: - kind - name type: object type: array exclusionList: description: |- ExclusionList specifies a list of Golang regular expressions to be used for excluding messages. items: type: string type: array inclusionList: description: |- InclusionList specifies a list of Golang regular expressions to be used for including messages. items: type: string type: array providerRef: description: ProviderRef specifies which Provider this Alert should use. properties: name: description: Name of the referent. type: string required: - name type: object summary: description: Summary holds a short description of the impact and affected cluster. maxLength: 255 type: string suspend: description: |- Suspend tells the controller to suspend subsequent events handling for this Alert. type: boolean required: - eventSources - providerRef type: object status: default: observedGeneration: -1 description: AlertStatus defines the observed state of the Alert. properties: conditions: description: Conditions holds the conditions for the Alert. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation. format: int64 type: integer type: object type: object served: true storage: false subresources: status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta3 schema: openAPIV3Schema: description: Alert is the Schema for the alerts API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: AlertSpec defines an alerting rule for events involving a list of objects. properties: eventMetadata: additionalProperties: type: string description: |- EventMetadata is an optional field for adding metadata to events dispatched by the controller. This can be used for enhancing the context of the event. If a field would override one already present on the original event as generated by the emitter, then the override doesn't happen, i.e. the original value is preserved, and an info log is printed. type: object eventSeverity: default: info description: |- EventSeverity specifies how to filter events based on severity. If set to 'info' no events will be filtered. enum: - info - error type: string eventSources: description: |- EventSources specifies how to filter events based on the involved object kind, name and namespace. items: description: |- CrossNamespaceObjectReference contains enough information to let you locate the typed referenced object at cluster level properties: apiVersion: description: API version of the referent type: string kind: description: Kind of the referent enum: - Bucket - GitRepository - Kustomization - HelmRelease - HelmChart - HelmRepository - ImageRepository - ImagePolicy - ImageUpdateAutomation - OCIRepository type: string matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. MatchLabels requires the name to be set to `*`. type: object name: description: |- Name of the referent If multiple resources are targeted `*` may be set. maxLength: 253 minLength: 1 type: string namespace: description: Namespace of the referent maxLength: 253 minLength: 1 type: string required: - kind - name type: object type: array exclusionList: description: |- ExclusionList specifies a list of Golang regular expressions to be used for excluding messages. items: type: string type: array inclusionList: description: |- InclusionList specifies a list of Golang regular expressions to be used for including messages. items: type: string type: array providerRef: description: ProviderRef specifies which Provider this Alert should use. properties: name: description: Name of the referent. type: string required: - name type: object summary: description: |- Summary holds a short description of the impact and affected cluster. Deprecated: Use EventMetadata instead. maxLength: 255 type: string suspend: description: |- Suspend tells the controller to suspend subsequent events handling for this Alert. type: boolean required: - eventSources - providerRef type: object type: object served: true storage: true subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: providers.notification.toolkit.fluxcd.io spec: group: notification.toolkit.fluxcd.io names: kind: Provider listKind: ProviderList plural: providers singular: provider scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 Provider is deprecated, upgrade to v1beta3 name: v1beta2 schema: openAPIV3Schema: description: Provider is the Schema for the providers API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: ProviderSpec defines the desired state of the Provider. properties: address: description: |- Address specifies the endpoint, in a generic sense, to where alerts are sent. What kind of endpoint depends on the specific Provider type being used. For the generic Provider, for example, this is an HTTP/S address. For other Provider types this could be a project ID or a namespace. maxLength: 2048 type: string certSecretRef: description: |- CertSecretRef specifies the Secret containing a PEM-encoded CA certificate (in the `ca.crt` key). Note: Support for the `caFile` key has been deprecated. properties: name: description: Name of the referent. type: string required: - name type: object channel: description: Channel specifies the destination channel where events should be posted. maxLength: 2048 type: string interval: description: Interval at which to reconcile the Provider with its Secret references. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string proxy: description: Proxy the HTTP/S address of the proxy server. maxLength: 2048 pattern: ^(http|https)://.*$ type: string secretRef: description: |- SecretRef specifies the Secret containing the authentication credentials for this Provider. properties: name: description: Name of the referent. type: string required: - name type: object suspend: description: |- Suspend tells the controller to suspend subsequent events handling for this Provider. type: boolean timeout: description: Timeout for sending alerts to the Provider. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string type: description: Type specifies which Provider implementation to use. enum: - slack - discord - msteams - rocket - generic - generic-hmac - github - gitlab - gitea - bitbucketserver - bitbucket - azuredevops - googlechat - googlepubsub - webex - sentry - azureeventhub - telegram - lark - matrix - opsgenie - alertmanager - grafana - githubdispatch - pagerduty - datadog type: string username: description: Username specifies the name under which events are posted. maxLength: 2048 type: string required: - type type: object status: default: observedGeneration: -1 description: ProviderStatus defines the observed state of the Provider. properties: conditions: description: Conditions holds the conditions for the Provider. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last reconciled generation. format: int64 type: integer type: object type: object served: true storage: false subresources: status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta3 schema: openAPIV3Schema: description: Provider is the Schema for the providers API properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: ProviderSpec defines the desired state of the Provider. properties: address: description: |- Address specifies the endpoint, in a generic sense, to where alerts are sent. What kind of endpoint depends on the specific Provider type being used. For the generic Provider, for example, this is an HTTP/S address. For other Provider types this could be a project ID or a namespace. maxLength: 2048 type: string certSecretRef: description: |- CertSecretRef specifies the Secret containing TLS certificates for secure communication. Supported configurations: - CA-only: Server authentication (provide ca.crt only) - mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key) - Client-only: Client authentication with system CA (provide tls.crt + tls.key only) Legacy keys "caFile", "certFile", "keyFile" are supported but deprecated. Use "ca.crt", "tls.crt", "tls.key" instead. properties: name: description: Name of the referent. type: string required: - name type: object channel: description: Channel specifies the destination channel where events should be posted. maxLength: 2048 type: string commitStatusExpr: description: |- CommitStatusExpr is a CEL expression that evaluates to a string value that can be used to generate a custom commit status message for use with eligible Provider types (github, gitlab, gitea, bitbucketserver, bitbucket, azuredevops). Supported variables are: event, provider, and alert. type: string interval: description: |- Interval at which to reconcile the Provider with its Secret references. Deprecated and not used in v1beta3. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string proxy: description: |- Proxy the HTTP/S address of the proxy server. Deprecated: Use ProxySecretRef instead. Will be removed in v1. maxLength: 2048 pattern: ^(http|https)://.*$ type: string proxySecretRef: description: |- ProxySecretRef specifies the Secret containing the proxy configuration for this Provider. The Secret should contain an 'address' key with the HTTP/S address of the proxy server. Optional 'username' and 'password' keys can be provided for proxy authentication. properties: name: description: Name of the referent. type: string required: - name type: object secretRef: description: |- SecretRef specifies the Secret containing the authentication credentials for this Provider. properties: name: description: Name of the referent. type: string required: - name type: object serviceAccountName: description: |- ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate with cloud provider services through workload identity. This enables multi-tenant authentication without storing static credentials. Supported provider types: azureeventhub, azuredevops, googlepubsub When specified, the controller will: 1. Create an OIDC token for the specified ServiceAccount 2. Exchange it for cloud provider credentials via STS 3. Use the obtained credentials for API authentication When unspecified, controller-level authentication is used (single-tenant). An error is thrown if static credentials are also defined in SecretRef. This field requires the ObjectLevelWorkloadIdentity feature gate to be enabled. type: string suspend: description: |- Suspend tells the controller to suspend subsequent events handling for this Provider. type: boolean timeout: description: Timeout for sending alerts to the Provider. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ type: string type: description: Type specifies which Provider implementation to use. enum: - slack - discord - msteams - rocket - generic - generic-hmac - github - gitlab - gitea - bitbucketserver - bitbucket - azuredevops - googlechat - googlepubsub - webex - sentry - azureeventhub - telegram - lark - matrix - opsgenie - alertmanager - grafana - githubdispatch - pagerduty - datadog - nats - zulip - otel type: string username: description: Username specifies the name under which events are posted. maxLength: 2048 type: string required: - type type: object x-kubernetes-validations: - message: spec.commitStatusExpr is only supported for the 'github', 'gitlab', 'gitea', 'bitbucketserver', 'bitbucket', 'azuredevops' provider types rule: self.type == 'github' || self.type == 'gitlab' || self.type == 'gitea' || self.type == 'bitbucketserver' || self.type == 'bitbucket' || self.type == 'azuredevops' || !has(self.commitStatusExpr) type: object served: true storage: true subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.19.0 labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: receivers.notification.toolkit.fluxcd.io spec: group: notification.toolkit.fluxcd.io names: kind: Receiver listKind: ReceiverList plural: receivers singular: receiver scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string name: v1 schema: openAPIV3Schema: description: Receiver is the Schema for the receivers API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: ReceiverSpec defines the desired state of the Receiver. properties: events: description: |- Events specifies the list of event types to handle, e.g. 'push' for GitHub or 'Push Hook' for GitLab. items: type: string type: array interval: default: 10m description: Interval at which to reconcile the Receiver with its Secret references. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string resourceFilter: description: |- ResourceFilter is a CEL expression expected to return a boolean that is evaluated for each resource referenced in the Resources field when a webhook is received. If the expression returns false then the controller will not request a reconciliation for the resource. When the expression is specified the controller will parse it and mark the object as terminally failed if the expression is invalid or does not return a boolean. type: string resources: description: A list of resources to be notified about changes. items: description: |- CrossNamespaceObjectReference contains enough information to let you locate the typed referenced object at cluster level properties: apiVersion: description: API version of the referent type: string kind: description: Kind of the referent enum: - Bucket - GitRepository - Kustomization - HelmRelease - HelmChart - HelmRepository - ImageRepository - ImagePolicy - ImageUpdateAutomation - OCIRepository type: string matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. MatchLabels requires the name to be set to `*`. type: object name: description: |- Name of the referent If multiple resources are targeted `*` may be set. maxLength: 253 minLength: 1 type: string namespace: description: Namespace of the referent maxLength: 253 minLength: 1 type: string required: - kind - name type: object type: array secretRef: description: |- SecretRef specifies the Secret containing the token used to validate the payload authenticity. properties: name: description: Name of the referent. type: string required: - name type: object suspend: description: |- Suspend tells the controller to suspend subsequent events handling for this receiver. type: boolean type: description: |- Type of webhook sender, used to determine the validation procedure and payload deserialization. enum: - generic - generic-hmac - github - gitlab - bitbucket - harbor - dockerhub - quay - gcr - nexus - acr - cdevents type: string required: - resources - secretRef - type type: object status: default: observedGeneration: -1 description: ReceiverStatus defines the observed state of the Receiver. properties: conditions: description: Conditions holds the conditions for the Receiver. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation of the Receiver object. format: int64 type: integer webhookPath: description: |- WebhookPath is the generated incoming webhook address in the format of '/hook/sha256sum(token+name+namespace)'. type: string type: object type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready type: string - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string deprecated: true deprecationWarning: v1beta2 Receiver is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: description: Receiver is the Schema for the receivers API. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: ReceiverSpec defines the desired state of the Receiver. properties: events: description: |- Events specifies the list of event types to handle, e.g. 'push' for GitHub or 'Push Hook' for GitLab. items: type: string type: array interval: description: Interval at which to reconcile the Receiver with its Secret references. pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ type: string resources: description: A list of resources to be notified about changes. items: description: |- CrossNamespaceObjectReference contains enough information to let you locate the typed referenced object at cluster level properties: apiVersion: description: API version of the referent type: string kind: description: Kind of the referent enum: - Bucket - GitRepository - Kustomization - HelmRelease - HelmChart - HelmRepository - ImageRepository - ImagePolicy - ImageUpdateAutomation - OCIRepository type: string matchLabels: additionalProperties: type: string description: |- MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. MatchLabels requires the name to be set to `*`. type: object name: description: |- Name of the referent If multiple resources are targeted `*` may be set. maxLength: 253 minLength: 1 type: string namespace: description: Namespace of the referent maxLength: 253 minLength: 1 type: string required: - kind - name type: object type: array secretRef: description: |- SecretRef specifies the Secret containing the token used to validate the payload authenticity. properties: name: description: Name of the referent. type: string required: - name type: object suspend: description: |- Suspend tells the controller to suspend subsequent events handling for this receiver. type: boolean type: description: |- Type of webhook sender, used to determine the validation procedure and payload deserialization. enum: - generic - generic-hmac - github - gitlab - bitbucket - harbor - dockerhub - quay - gcr - nexus - acr type: string required: - resources - secretRef - type type: object status: default: observedGeneration: -1 description: ReceiverStatus defines the observed state of the Receiver. properties: conditions: description: Conditions holds the conditions for the Receiver. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object type: array lastHandledReconcileAt: description: |- LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string observedGeneration: description: ObservedGeneration is the last observed generation of the Receiver object. format: int64 type: integer url: description: |- URL is the generated incoming webhook address in the format of '/hook/sha256sum(token+name+namespace)'. Deprecated: Replaced by WebhookPath. type: string webhookPath: description: |- WebhookPath is the generated incoming webhook address in the format of '/hook/sha256sum(token+name+namespace)'. type: string type: object type: object served: true storage: false subresources: status: {} --- apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 name: notification-controller namespace: flux-system --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: notification-controller namespace: flux-system spec: ports: - name: http port: 80 protocol: TCP targetPort: http selector: app: notification-controller type: ClusterIP --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: webhook-receiver namespace: flux-system spec: ports: - name: http port: 80 protocol: TCP targetPort: http-webhook selector: app: notification-controller type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 control-plane: controller name: notification-controller namespace: flux-system spec: replicas: 1 selector: matchLabels: app: notification-controller template: metadata: annotations: prometheus.io/port: "8080" prometheus.io/scrape: "true" labels: app: notification-controller app.kubernetes.io/component: notification-controller app.kubernetes.io/instance: flux-system app.kubernetes.io/part-of: flux app.kubernetes.io/version: v2.7.5 spec: containers: - args: - --watch-all-namespaces=true - --log-level=info - --log-encoding=json - --enable-leader-election env: - name: RUNTIME_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: GOMEMLIMIT valueFrom: resourceFieldRef: containerName: manager resource: limits.memory image: ghcr.io/fluxcd/notification-controller:v1.7.5 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz port: healthz name: manager ports: - containerPort: 9090 name: http protocol: TCP - containerPort: 9292 name: http-webhook protocol: TCP - containerPort: 8080 name: http-prom protocol: TCP - containerPort: 9440 name: healthz protocol: TCP readinessProbe: httpGet: path: /readyz port: healthz resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 100m memory: 64Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp name: temp nodeSelector: kubernetes.io/os: linux securityContext: fsGroup: 1337 serviceAccountName: notification-controller terminationGracePeriodSeconds: 10 volumes: - emptyDir: {} name: temp ================================================ FILE: cluster/homelab/base/flux-system/gotk-patch.yaml ================================================ --- apiVersion: apps/v1 kind: Deployment metadata: name: source-controller namespace: flux-system spec: template: spec: containers: - name: manager resources: limits: memory: 2Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: helm-controller namespace: flux-system spec: template: spec: containers: - name: manager resources: limits: memory: 2Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: kustomize-controller namespace: flux-system spec: template: spec: containers: - name: manager resources: limits: memory: 2Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: notification-controller namespace: flux-system spec: template: spec: containers: - name: manager resources: limits: memory: 2Gi --- apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: flux-system namespace: flux-system spec: interval: 2m0s ================================================ FILE: cluster/homelab/base/flux-system/gotk-sync.yaml ================================================ # This manifest was generated by flux. DO NOT EDIT. --- apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: flux-system namespace: flux-system spec: interval: 1m0s ref: branch: master secretRef: name: flux-system url: ssh://git@github.com/Michaelpalacce/HomeLab --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: flux-system namespace: flux-system spec: interval: 10m0s path: ./cluster/homelab/base prune: true sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/base/flux-system/kustomization.yaml ================================================ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - gotk-components.yaml - gotk-sync.yaml patchesStrategicMerge: - gotk-patch.yaml #Ref: https://flux-iac.github.io/tofu-controller/use-tf-controller/flux-receiver-and-alert/ patches: - patch: | - op: add path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/eventSources/items/properties/kind/enum/- value: Terraform - op: add path: /spec/versions/1/schema/openAPIV3Schema/properties/spec/properties/eventSources/items/properties/kind/enum/- value: Terraform target: kind: CustomResourceDefinition name: alerts.notification.toolkit.fluxcd.io - patch: | - op: add path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/resources/items/properties/kind/enum/- value: Terraform - op: add path: /spec/versions/1/schema/openAPIV3Schema/properties/spec/properties/resources/items/properties/kind/enum/- value: Terraform target: kind: CustomResourceDefinition name: receivers.notification.toolkit.fluxcd.io - patch: | - op: add path: /rules/- value: apiGroups: [ 'infra.contrib.fluxcd.io' ] resources: [ '*' ] verbs: [ '*' ] target: kind: ClusterRole name: crd-controller-flux-system ================================================ FILE: cluster/homelab/base/helm.yaml ================================================ --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: helm namespace: flux-system spec: interval: 10m path: ./cluster/homelab/helm prune: true decryption: provider: sops secretRef: name: sops-age sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/base/terraform.yaml ================================================ --- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: terraform namespace: flux-system spec: interval: 10m path: ./cluster/homelab/terraform prune: true decryption: provider: sops secretRef: name: sops-age sourceRef: kind: GitRepository name: flux-system ================================================ FILE: cluster/homelab/configs/flux/alert.yaml ================================================ --- apiVersion: notification.toolkit.fluxcd.io/v1beta3 kind: Alert metadata: name: discord-alert namespace: flux-system spec: providerRef: name: discord eventMetadata: summary: Cluster impacted env: homelab cluster: homelab eventSeverity: error eventSources: - kind: GitRepository name: '*' - kind: Kustomization name: '*' - kind: HelmRelease name: '*' ================================================ FILE: cluster/homelab/configs/flux/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - notification.sops.yaml - alert.yaml ================================================ FILE: cluster/homelab/configs/flux/notification.sops.yaml ================================================ apiVersion: notification.toolkit.fluxcd.io/v1beta3 kind: Provider metadata: name: discord namespace: flux-system spec: type: discord secretRef: name: discord-webhook sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxdG03UXdIWHR2QjJKRGVy bldvOEM3bTdsVDdWZlJ3MXNyb3gyd3JWSmwwCkhKTWZUdjZZMWdCaTlJOXdLR2hC MkVkQ2IybUlpS3U1bDhhQ0JBT0M2QzgKLS0tIEV1c3dnNzI5QmZ3anE5MDZQbi9q WC9CcHYrL3lOVC9KOTNVcE1nK2QyWjAKAK3yc3BRn77Ix/KU8FC36vmGxn6tT3OR gJcxaHbHd7XTO8NTkbDyYem1yO84dx9UYpx+s6z8ELcfhXjCOtrFxg== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-04-06T14:43:36Z" mac: ENC[AES256_GCM,data:S0KrIyiVUu4GU9y28In8JZrVTHdY4bK6sH0shBeM1sgOZh/1I7MTkoCS8pU5GM+YnU41WAIlQJCznZeWALrdSI+Q0t5P1+1lh30+XuWF8Nx/DPROFEAU8HRBe5KhHqB8guoxLiHLvGxX0yqp5WnjHZSL8WHkD89HqAblev0RZds=,iv:ANGoj9VH9aZ6n606wwJulMLrWusovRTjMyyDbLH9IQc=,tag:Fuzalw61kkPHNJ6K4TY0iQ==,type:str] pgp: [] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.8.1 --- apiVersion: v1 kind: Secret metadata: name: discord-webhook namespace: flux-system stringData: address: ENC[AES256_GCM,data:/NxCwohlFJPCng1/7bOmd6dKoJP3sjeP/9+Iw4pLl4OaMiS9bZy13RXHcpQ7mzA9RL/5pAGzDaeUfntrAMMZ4/waqYFQm3Ug42lG/JhT+yXpXNki0H0c0++4mjZeQcnxHGHvgsn2BMp/HGS0XRRK/+qP0FRTVda+RA==,iv:o5F7aZZhKACpZ5gvyV3hPDCikf7XbGNG9FEnc9YrYIY=,tag:NA5dJ5P6nBgUBFZP0I5KFQ==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxdG03UXdIWHR2QjJKRGVy bldvOEM3bTdsVDdWZlJ3MXNyb3gyd3JWSmwwCkhKTWZUdjZZMWdCaTlJOXdLR2hC MkVkQ2IybUlpS3U1bDhhQ0JBT0M2QzgKLS0tIEV1c3dnNzI5QmZ3anE5MDZQbi9q WC9CcHYrL3lOVC9KOTNVcE1nK2QyWjAKAK3yc3BRn77Ix/KU8FC36vmGxn6tT3OR gJcxaHbHd7XTO8NTkbDyYem1yO84dx9UYpx+s6z8ELcfhXjCOtrFxg== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-04-06T14:43:36Z" mac: ENC[AES256_GCM,data:S0KrIyiVUu4GU9y28In8JZrVTHdY4bK6sH0shBeM1sgOZh/1I7MTkoCS8pU5GM+YnU41WAIlQJCznZeWALrdSI+Q0t5P1+1lh30+XuWF8Nx/DPROFEAU8HRBe5KhHqB8guoxLiHLvGxX0yqp5WnjHZSL8WHkD89HqAblev0RZds=,iv:ANGoj9VH9aZ6n606wwJulMLrWusovRTjMyyDbLH9IQc=,tag:Fuzalw61kkPHNJ6K4TY0iQ==,type:str] pgp: [] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.8.1 ================================================ FILE: cluster/homelab/configs/istio/external-gateway-adygenova.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: external-adygenova namespace: istio-gateway spec: addresses: - type: IPAddress value: 192.168.1.18 gatewayClassName: istio listeners: - name: http port: 80 protocol: HTTP allowedRoutes: namespaces: from: All - name: https hostname: "adygenova.com" port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: adygenova-cert allowedRoutes: namespaces: from: All ================================================ FILE: cluster/homelab/configs/istio/external-gateway-replacedby.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: external-replacedby namespace: istio-gateway spec: addresses: - type: IPAddress value: 192.168.1.17 gatewayClassName: istio listeners: - name: http port: 80 protocol: HTTP allowedRoutes: namespaces: from: All - name: https hostname: "replacedby.net" port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: replacedby-cert allowedRoutes: namespaces: from: All ================================================ FILE: cluster/homelab/configs/istio/external-gateway.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: external namespace: istio-gateway spec: addresses: - type: IPAddress value: 192.168.1.16 gatewayClassName: istio listeners: - name: http port: 80 protocol: HTTP allowedRoutes: namespaces: from: All - name: https hostname: "sgenov.dev" port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: ingress allowedRoutes: namespaces: from: All # allowedRoutes: # namespaces: # from: Selector # selector: # matchLabels: # kubernetes.io/metadata.name: default ================================================ FILE: cluster/homelab/configs/istio/internal-gateway.yaml ================================================ apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: internal namespace: istio-gateway spec: addresses: - type: IPAddress value: 192.168.1.15 gatewayClassName: istio listeners: - name: http port: 80 protocol: HTTP allowedRoutes: namespaces: from: All - name: https hostname: "*.sgenov.dev" port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: ingress allowedRoutes: namespaces: from: All ================================================ FILE: cluster/homelab/configs/istio/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - internal-gateway.yaml - external-gateway.yaml - external-gateway-adygenova.yaml - external-gateway-replacedby.yaml - namespace.yaml ================================================ FILE: cluster/homelab/configs/istio/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: istio-gateway ================================================ FILE: cluster/homelab/configs/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - flux - velero - metallb - kyverno # Commented out to prevent accidental upgrades... turns out automated upgrades are a bad idea due to incompatibilities.One issue I ran into was with longhorn, which was not compatible with the latest version of k3s and resulted in a broken cluster that I had to recreate. # - system-upgrade - istio ================================================ FILE: cluster/homelab/configs/kyverno/cleanup-empty-replicasets.yaml ================================================ #The described logic currently deletes the ReplicaSets created 30 seconds ago. You can adjust this timeframe according to your specific requirements. apiVersion: kyverno.io/v2beta1 kind: ClusterCleanupPolicy metadata: name: cleanup-empty-replicasets annotations: policies.kyverno.io/title: Cleanup Empty ReplicaSets policies.kyverno.io/category: Other policies.kyverno.io/severity: medium policies.kyverno.io/subject: ReplicaSet kyverno.io/kyverno-version: 1.11.1 policies.kyverno.io/minversion: 1.9.0 kyverno.io/kubernetes-version: "1.27" policies.kyverno.io/description: >- ReplicaSets serve as an intermediate controller for various Pod controllers like Deployments. When a new version of a Deployment is initiated, it generates a new ReplicaSet with the specified number of replicas and scales down the current one to zero. Consequently, numerous empty ReplicaSets may accumulate in the cluster, leading to clutter and potential false positives in policy reports if enabled. This cleanup policy is designed to remove empty ReplicaSets across the cluster within a specified timeframe, for instance, ReplicaSets created one day ago, ensuring the ability to rollback to previous ReplicaSets in case of deployment issues spec: match: any: - resources: kinds: - ReplicaSet exclude: any: - resources: namespaces: - kube-system conditions: all: - key: "{{ target.spec.replicas }}" operator: Equals value: 0 - key: "{{ time_diff('{{target.metadata.creationTimestamp}}','{{ time_now_utc() }}') }}" operator: GreaterThan value: "0h0m30s" schedule: "*/1 * * * *" --- apiVersion: kyverno.io/v2 kind: ClusterCleanupPolicy metadata: name: clean-bare-pods annotations: policies.kyverno.io/title: Cleanup Bare Pods policies.kyverno.io/category: Other policies.kyverno.io/severity: medium policies.kyverno.io/subject: Pod kyverno.io/kyverno-version: 1.11.1 policies.kyverno.io/minversion: 1.10.0 pod-policies.kyverno.io/autogen-controllers: none kyverno.io/kubernetes-version: "1.27" policies.kyverno.io/description: >- A bare Pod is any Pod created directly and not owned by a controller such as a Deployment or Job. Bare Pods are often create manually by users in an attempt to troubleshoot an issue. If left in the cluster, they create clutter, increase cost, and can be a security risk. Bare Pods can be cleaned up periodically through use of a policy. This policy finds and removes all bare Pods across the cluster. spec: match: any: - resources: kinds: - Pod conditions: all: - key: "{{ target.metadata.ownerReferences[] || `[]` }}" operator: Equals value: [] schedule: "*/1 * * * *" ================================================ FILE: cluster/homelab/configs/kyverno/default-network-policy.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: generate-networkpolicy-existing annotations: policies.kyverno.io/title: Generate NetworkPolicy to Existing Namespaces policies.kyverno.io/category: Other policies.kyverno.io/severity: medium policies.kyverno.io/subject: Namespace, NetworkPolicy kyverno.io/kyverno-version: 1.7.0 policies.kyverno.io/minversion: 1.7.0 kyverno.io/kubernetes-version: "1.23" policies.kyverno.io/description: >- A NetworkPolicy is often a critical piece when provisioning new Namespaces, but there may be existing Namespaces which also need the same resource. Creating each one individually or manipulating each Namespace in order to trigger creation is additional overhead. This policy creates a new NetworkPolicy for existing Namespaces which results in a default deny behavior and labels it with created-by=kyverno. This also generates some additional ns specific networkpolicies. spec: generateExisting: true rules: - name: generate-paperless-networkpolicy match: any: - resources: kinds: - Namespace names: - tika - gotenberg - paperless-ngx generate: kind: NetworkPolicy apiVersion: networking.k8s.io/v1 name: "{{request.object.metadata.name}}-default-deny" namespace: "{{request.object.metadata.name}}" synchronize: true data: metadata: labels: created-by: kyverno spec: podSelector: {} policyTypes: - Egress egress: # It's ok internally to these namespaces - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "tika" - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "gotenberg" - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "paperless-ngx" # DNS is allowed (CoreDNS) - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 # Allow everywhere but not internally, don't want it communicating to local network - to: - ipBlock: cidr: 0.0.0.0/0 except: - 10.0.0.0/8 # RFC 1918 - Class A private - 172.16.0.0/12 # RFC 1918 - Class B private - 192.168.0.0/16 # RFC 1918 - Class C private - name: generate-existing-networkpolicy exclude: any: - resources: namespaces: - longhorn-system - kyverno - kube-system - flux-system - velero # We want to communicate to all namespaces for backup reasons - observeability # Has it's own - uptimekuma # A little bit down :) - homepage # A little bit down :) - cnpg-system # These work together, they have their own policy - tika - gotenberg - paperless-ngx # Fix this later - reflector - system-upgrade - metallb-system - istio-system - istio-gateway - cert-manager match: any: - resources: kinds: - Namespace generate: kind: NetworkPolicy apiVersion: networking.k8s.io/v1 name: "{{request.object.metadata.name}}-default-deny" namespace: "{{request.object.metadata.name}}" synchronize: true data: metadata: labels: created-by: kyverno spec: podSelector: {} policyTypes: - Egress egress: # Allow everywhere but not internally, don't want it communicating to local network - to: - ipBlock: cidr: 0.0.0.0/0 except: - 10.0.0.0/8 # RFC 1918 - Class A private - 172.16.0.0/12 # RFC 1918 - Class B private - 192.168.0.0/16 # RFC 1918 - Class C private # It's ok internally to the namespace - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "{{request.object.metadata.name}}" # DNS is allowed (CoreDNS) - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 - name: generate-homepage-networkpolicy match: any: - resources: kinds: - Namespace names: - homepage generate: kind: NetworkPolicy apiVersion: networking.k8s.io/v1 name: "{{request.object.metadata.name}}-default-deny" namespace: "{{request.object.metadata.name}}" synchronize: true data: metadata: labels: created-by: kyverno spec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 10.0.0.0/8 - ipBlock: cidr: 192.168.0.0/16 # It's ok internally to the namespace - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "{{request.object.metadata.name}}" # DNS is allowed (CoreDNS) - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 - name: generate-uptimekuma-networkpolicy match: any: - resources: kinds: - Namespace names: - uptimekuma generate: kind: NetworkPolicy apiVersion: networking.k8s.io/v1 name: "{{request.object.metadata.name}}-default-deny" namespace: "{{request.object.metadata.name}}" synchronize: true data: metadata: labels: created-by: kyverno spec: podSelector: {} policyTypes: - Egress egress: # Allow everywhere but not internal RFC1918 (except 192.168/16) - to: - ipBlock: cidr: 0.0.0.0/0 ports: - protocol: TCP port: 53 - protocol: UDP port: 53 - protocol: TCP port: 80 - protocol: TCP port: 443 - to: - ipBlock: cidr: 192.168.1.22/32 # Some cases where we are doing internal TCP checks - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "firefly" ports: - protocol: TCP port: 5432 # postgres - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "reactiveresume" ports: - protocol: TCP port: 5432 # postgres - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "wallabag" ports: - protocol: TCP port: 5432 # postgres - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "observeability" ports: - protocol: TCP port: 3100 # Loki - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "n8n" ports: - protocol: TCP port: 5432 # postgres - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "vikunja" ports: - protocol: TCP port: 5432 # postgres - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "velero" ports: - protocol: TCP port: 8085 # velero port # It's ok internally to the namespace - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: "{{request.object.metadata.name}}" # DNS is allowed (CoreDNS) - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 ================================================ FILE: cluster/homelab/configs/kyverno/disallow-default.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-default-namespace annotations: pod-policies.kyverno.io/autogen-controllers: none policies.kyverno.io/title: Disallow Default Namespace policies.kyverno.io/minversion: 1.6.0 policies.kyverno.io/category: Multi-Tenancy policies.kyverno.io/severity: medium policies.kyverno.io/subject: Pod policies.kyverno.io/description: >- Kubernetes Namespaces are an optional feature that provide a way to segment and isolate cluster resources across multiple applications and users. As a best practice, workloads should be isolated with Namespaces. Namespaces should be required and the default (empty) Namespace should not be used. This policy validates that Pods specify a Namespace name other than `default`. Rule auto-generation is disabled here due to Pod controllers need to specify the `namespace` field under the top-level `metadata` object and not at the Pod template level. spec: background: true rules: - name: validate-namespace match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "Using 'default' namespace is not allowed." pattern: metadata: namespace: "!default" - name: validate-podcontroller-namespace match: any: - resources: kinds: - DaemonSet - Deployment - Job - StatefulSet validate: failureAction: Enforce message: "Using 'default' namespace is not allowed for pod controllers." pattern: metadata: namespace: "!default" ================================================ FILE: cluster/homelab/configs/kyverno/disallow-helm-tiller.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-helm-tiller annotations: policies.kyverno.io/title: Disallow Helm Tiller policies.kyverno.io/category: Sample policies.kyverno.io/minversion: 1.6.0 policies.kyverno.io/severity: medium policies.kyverno.io/subject: Pod policies.kyverno.io/description: >- Tiller, found in Helm v2, has known security challenges. It requires administrative privileges and acts as a shared resource accessible to any authenticated user. Tiller can lead to privilege escalation as restricted users can impact other users. It is recommended to use Helm v3+ which does not contain Tiller for these reasons. This policy validates that there is not an image containing the name `tiller`. spec: background: true rules: - name: validate-helm-tiller match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "Helm Tiller is not allowed" foreach: - list: "request.object.spec.containers" pattern: image: "!*tiller*" - list: "request.object.spec.initContainers" pattern: image: "!*tiller*" - list: "request.object.spec.ephemeralContainers" pattern: image: "!*tiller*" ================================================ FILE: cluster/homelab/configs/kyverno/disallow-latest-tag.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-latest-tag annotations: policies.kyverno.io/title: Disallow Latest Tag policies.kyverno.io/category: Best Practices policies.kyverno.io/minversion: 1.6.0 policies.kyverno.io/severity: medium policies.kyverno.io/subject: Pod policies.kyverno.io/description: >- The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application Pod. This policy validates that the image specifies a tag and that it is not called `latest`. spec: background: true rules: - name: require-image-tag match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "An image tag is required." foreach: - list: "request.object.spec.containers" pattern: image: "*:*" - list: "request.object.spec.initContainers" pattern: image: "*:*" - list: "request.object.spec.ephemeralContainers" pattern: image: "*:*" - name: validate-image-tag match: any: - resources: kinds: - Pod validate: failureAction: Enforce message: "Using a mutable image tag e.g. 'latest' is not allowed." foreach: - list: "request.object.spec.containers" pattern: image: "!*:latest" - list: "request.object.spec.initContainers" pattern: image: "!*:latest" - list: "request.object.spec.ephemeralContainers" pattern: image: "!*:latest" ================================================ FILE: cluster/homelab/configs/kyverno/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kyverno-policies namespace: kyverno spec: interval: 10m install: createNamespace: true chart: spec: chart: kyverno-policies version: 3.8.0 interval: 10m sourceRef: kind: HelmRepository name: kyverno namespace: flux-system ================================================ FILE: cluster/homelab/configs/kyverno/inject-image-pull-secrets.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: inject-default-image-pull-secret annotations: policies.kyverno.io/title: Inject default image pull secret policies.kyverno.io/category: Best Practices policies.kyverno.io/subject: ServiceAccount, ImagePullSecrets policies.kyverno.io/description: >- Adds 'default-image-pull-secret' to the 'imagePullSecrets' list of any ServiceAccount created or updated. This ensures that pods using the SA can pull images from private registries. policies.kyverno.io/severity: low kyverno.io/kyverno-version: 1.7.0 policies.kyverno.io/minversion: 1.7.0 kyverno.io/kubernetes-version: "1.23" spec: rules: - name: inject-image-pull-secret match: any: - resources: kinds: - ServiceAccount mutate: mutateExistingOnPolicyUpdate: true targets: - kind: ServiceAccount name: default apiVersion: v1 patchStrategicMerge: imagePullSecrets: - name: default-image-pull-secret ================================================ FILE: cluster/homelab/configs/kyverno/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: # - helm-release.yaml - no-privileged.yaml - cleanup-empty-replicasets.yaml - disallow-default.yaml - disallow-helm-tiller.yaml - require-drop-all.yaml - restrict-service-external-ips.yaml - restrict-node-port.yaml # - default-network-policy.yaml - inject-image-pull-secrets.yaml ================================================ FILE: cluster/homelab/configs/kyverno/no-privileged.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-privileged-containers annotations: policies.kyverno.io/title: Disallow Privileged Containers policies.kyverno.io/category: Pod Security Standards (Baseline) policies.kyverno.io/severity: medium policies.kyverno.io/subject: Pod kyverno.io/kyverno-version: 1.6.0 kyverno.io/kubernetes-version: "1.22-1.23" policies.kyverno.io/description: >- Privileged mode disables most security mechanisms and must not be allowed. This policy ensures Pods do not call for privileged mode. spec: background: true rules: - name: privileged-containers match: any: - resources: kinds: - Pod exclude: any: - resources: namespaces: - kured - longhorn-system - system-upgrade validate: failureAction: Enforce message: >- Privileged mode is disallowed. The fields spec.containers[*].securityContext.privileged, spec.initContainers[*].securityContext.privileged, and spec.ephemeralContainers[*].securityContext.privileged must be unset or set to `false`. pattern: spec: =(ephemeralContainers): - =(securityContext): =(privileged): "false" =(initContainers): - =(securityContext): =(privileged): "false" containers: - =(securityContext): =(privileged): "false" ================================================ FILE: cluster/homelab/configs/kyverno/require-drop-all.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: drop-all-capabilities annotations: policies.kyverno.io/title: Drop All Capabilities policies.kyverno.io/category: Best Practices policies.kyverno.io/severity: medium policies.kyverno.io/minversion: 1.6.0 policies.kyverno.io/subject: Pod policies.kyverno.io/description: >- Capabilities permit privileged actions without giving full root access. All capabilities should be dropped from a Pod, with only those required added back. This policy ensures that all containers explicitly specify the `drop: ["ALL"]` ability. Note that this policy also illustrates how to cover drop entries in any case although this may not strictly conform to the Pod Security Standards. spec: background: true rules: - name: require-drop-all exclude: any: - resources: namespaces: - longhorn-system - kube-system - metallb-system # @TODO: This may be fixable... - kured - velero - system-upgrade match: any: - resources: kinds: - Pod preconditions: all: - key: "{{ request.operation || 'BACKGROUND' }}" operator: NotEquals value: DELETE validate: failureAction: Audit message: >- Containers must drop `ALL` capabilities. foreach: - list: request.object.spec.[ephemeralContainers, initContainers, containers][] deny: conditions: all: - key: ALL operator: AnyNotIn value: "{{ element.securityContext.capabilities.drop[].to_upper(@) || `[]` }}" ================================================ FILE: cluster/homelab/configs/kyverno/restrict-node-port.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: restrict-nodeport annotations: policies.kyverno.io/title: Disallow NodePort policies.kyverno.io/category: Best Practices policies.kyverno.io/minversion: 1.6.0 policies.kyverno.io/severity: medium policies.kyverno.io/subject: Service policies.kyverno.io/description: >- A Kubernetes Service of type NodePort uses a host port to receive traffic from any source. A NetworkPolicy cannot be used to control traffic to host ports. Although NodePort Services can be useful, their use must be limited to Services with additional upstream security checks. This policy validates that any new Services do not use the `NodePort` type. spec: background: true rules: - name: validate-nodeport match: any: - resources: kinds: - Service validate: failureAction: Enforce message: "Services of type NodePort are not allowed." pattern: spec: =(type): "!NodePort" ================================================ FILE: cluster/homelab/configs/kyverno/restrict-service-external-ips.yaml ================================================ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: restrict-external-ips annotations: policies.kyverno.io/title: Restrict External IPs policies.kyverno.io/category: Best Practices policies.kyverno.io/minversion: 1.6.0 policies.kyverno.io/severity: medium policies.kyverno.io/subject: Service policies.kyverno.io/description: >- Service externalIPs can be used for a MITM attack (CVE-2020-8554). Restrict externalIPs or limit to a known set of addresses. See: https://github.com/kyverno/kyverno/issues/1367. This policy validates that the `externalIPs` field is not set on a Service. spec: background: true rules: - name: check-ips match: any: - resources: kinds: - Service validate: failureAction: Enforce message: "externalIPs are not allowed." pattern: spec: # restrict external IP addresses # you can alternatively restrict to a known set of addresses using: # =(externalIPs): ["37.10.11.53", "153.10.20.1"] X(externalIPs): "null" ================================================ FILE: cluster/homelab/configs/metallb/ip-pool.yaml ================================================ apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 192.168.1.5-192.168.1.19 ================================================ FILE: cluster/homelab/configs/metallb/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ip-pool.yaml - l2-advertisement.yaml ================================================ FILE: cluster/homelab/configs/metallb/l2-advertisement.yaml ================================================ apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: default namespace: metallb-system ================================================ FILE: cluster/homelab/configs/system-upgrade/README.md ================================================ # Warning This is disabled since automatic updates may end up breaking something due to deprecations. ================================================ FILE: cluster/homelab/configs/system-upgrade/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - plans/stable ================================================ FILE: cluster/homelab/configs/system-upgrade/plans/latest/agent.yaml ================================================ --- # Agent plan apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: agent-plan namespace: system-upgrade spec: concurrency: 1 cordon: true nodeSelector: matchExpressions: - key: node-role.kubernetes.io/master operator: DoesNotExist prepare: args: - prepare - server-plan image: rancher/k3s-upgrade serviceAccountName: system-upgrade upgrade: image: rancher/k3s-upgrade channel: https://update.k3s.io/v1-release/channels/latest ================================================ FILE: cluster/homelab/configs/system-upgrade/plans/latest/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization spec: dependsOn: - name: core - name: helm resources: - agent.yaml - server.yaml ================================================ FILE: cluster/homelab/configs/system-upgrade/plans/latest/server.yaml ================================================ --- # Server plan apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: server-plan namespace: system-upgrade spec: concurrency: 1 cordon: true nodeSelector: matchExpressions: - key: node-role.kubernetes.io/master operator: In values: - "true" serviceAccountName: system-upgrade upgrade: image: rancher/k3s-upgrade channel: https://update.k3s.io/v1-release/channels/latest ================================================ FILE: cluster/homelab/configs/system-upgrade/plans/stable/agent.yaml ================================================ --- # Agent plan apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: agent-plan namespace: system-upgrade spec: concurrency: 1 cordon: true nodeSelector: matchExpressions: - key: node-role.kubernetes.io/master operator: DoesNotExist prepare: args: - prepare - server-plan image: rancher/k3s-upgrade serviceAccountName: system-upgrade upgrade: image: rancher/k3s-upgrade channel: https://update.k3s.io/v1-release/channels/stable ================================================ FILE: cluster/homelab/configs/system-upgrade/plans/stable/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - agent.yaml - server.yaml ================================================ FILE: cluster/homelab/configs/system-upgrade/plans/stable/server.yaml ================================================ --- # Server plan apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: server-plan namespace: system-upgrade spec: concurrency: 1 cordon: true nodeSelector: matchExpressions: - key: node-role.kubernetes.io/master operator: In values: - "true" serviceAccountName: system-upgrade upgrade: image: rancher/k3s-upgrade channel: https://update.k3s.io/v1-release/channels/stable ================================================ FILE: cluster/homelab/configs/velero/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - schedule.yaml ================================================ FILE: cluster/homelab/configs/velero/schedule.yaml ================================================ apiVersion: velero.io/v1 kind: Schedule metadata: name: general namespace: velero spec: schedule: "00 01 * * 6" template: hooks: {} includedNamespaces: # Either not important, not containing any information or they are easily recoverable - freshrss # RSS are not fatal - openbooks - cyberchef - diagrams - storage - koffan - foldingathome snapshotVolumes: true ttl: 730h0m0s # 1 Month useOwnerReferencesInBackup: false --- apiVersion: velero.io/v1 kind: Schedule metadata: name: sensitive namespace: velero spec: schedule: "00 01 * * 1,5" template: hooks: {} includedNamespaces: # Related to my homelab or automation - media - n8n - uptimekuma - go-ddns-controller-system - nodered - changedetection snapshotVolumes: true ttl: 1460h0m0s # 2 Month useOwnerReferencesInBackup: false --- apiVersion: velero.io/v1 kind: Schedule metadata: name: critical namespace: velero spec: schedule: "00 01 * * *" template: hooks: {} includedNamespaces: # Data I don't want to lose - replacedby - vikunja - website - reactiveresume - homebox - paperless-ngx - firefly - wallabag - linkwarden - mealie snapshotVolumes: true ttl: 2190h0m0s useOwnerReferencesInBackup: false ================================================ FILE: cluster/homelab/core/archive/cgroup-gc/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cgroup-gc namespace: cgroup-gc spec: interval: 10m install: createNamespace: true chart: spec: chart: ./Helm/apps/cgroup-gc reconcileStrategy: Revision sourceRef: kind: GitRepository name: flux-system namespace: flux-system ================================================ FILE: cluster/homelab/core/archive/cgroup-gc/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/archive/cgroup-gc/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: cgroup-gc ================================================ FILE: cluster/homelab/core/archive/kube-vip/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kube-vip namespace: kube-vip spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: kube-vip version: 0.9.8 interval: 10m sourceRef: kind: HelmRepository name: kube-vip namespace: flux-system values: image: repository: ghcr.io/kube-vip/kube-vip tag: "v1.1.2" env: lb_enable: "true" lb_port: "6443" ================================================ FILE: cluster/homelab/core/archive/kube-vip/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/archive/kube-vip/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: kube-vip ================================================ FILE: cluster/homelab/core/cert-manager/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cert-manager namespace: cert-manager spec: interval: 10m install: createNamespace: true chart: spec: chart: cert-manager version: v1.20.2 interval: 10m sourceRef: kind: HelmRepository name: cert-manager namespace: flux-system values: installCRDs: true deploymentAnnotations: certmanager.k8s.io/disable-validation: "true" config: enableGatewayAPI: true crds: enabled: true enableCertificateOwnerRef: true # automatically remove secrets if cert is removed ================================================ FILE: cluster/homelab/core/cert-manager/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml ================================================ FILE: cluster/homelab/core/cert-manager/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: cert-manager ================================================ FILE: cluster/homelab/core/cert-manager/secret.sops.yaml ================================================ apiVersion: v1 kind: Secret type: Opaque metadata: name: cloudflare namespace: cert-manager data: apikey: ENC[AES256_GCM,data:GEwv4zsXma9KNxjpTHEUPktOWt8iPY3iWn5Qg2IbhwF5LzHHljOj+wtNWPuR6w9AhJHf65DIYMM=,iv:0sIMJyLLSPt7rPMddOdTupr3sxFfLfBsqllGatxJSmQ=,tag:NwTiQuHJD7zxItdNUu+aew==,type:str] sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5YzAwNjR4SlVjanZILzc4 Y2pyN3Fydkt1dHgyR0RqRkcyZERld0hIcFNJClB6M3RLUEpQZnFhMXBZYW1QcnVp c3ZSS2RsblNocSswWGpMRFNQclZzakEKLS0tIDg3WCtNVWF3OE1uU3pJdjdwTCtB V2hkT08zTk1yRjQ4ZjFCMHl1cVhZSEUKeqKiXOZ5VnrTZEg0F/v2zTaLY+0mEOcP GOGM3OF3KlYDxKL2Yiy7DuhfauDgjKByg+x7z6KWM8MfV1PbT/pNOw== -----END AGE ENCRYPTED FILE----- lastmodified: "2024-03-26T13:57:41Z" mac: ENC[AES256_GCM,data:EVFpktWkrG9ZhhFrnOX55Ll1Pft+jlaQXRvf0ut9AJ1ES+rNO68PENM/4w3zLBDv23dEd5uIXeWZlXPsvbJPm8IK5kDC+GXkel3YU46ITLTfNROpYSsm6yh7EWFaMtj0/Eeo2b3lfpCJ0OwghKzhQ/4BbnM6FqkKlTUXj/NKsAc=,iv:cdzzGNnQA/G3MXr4WXr73Wsdqvre6ivagAHPCxS4c5k=,tag:0/nL0HD9sklDP1mRFrdWNQ==,type:str] pgp: [] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.8.1 ================================================ FILE: cluster/homelab/core/cluster-critical/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - priority-classes.yaml ================================================ FILE: cluster/homelab/core/cluster-critical/priority-classes.yaml ================================================ --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: default-priority value: 0 globalDefault: true description: "Default priority of pods. Generally 0 is used without specifying it, but adding it for explicitness." --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: general-priority value: 1000 globalDefault: false description: "For general workload of apps that are not important." --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: sensitive-priority value: 2000 globalDefault: false description: "Related to my homelab or automation." --- apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: critical-priority value: 3000 globalDefault: false description: "Apps I don't want to go down." ================================================ FILE: cluster/homelab/core/cnpg/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cnpg namespace: cnpg-system spec: interval: 1h install: createNamespace: true chart: spec: chart: cloudnative-pg version: 0.28.0 interval: 1h sourceRef: kind: HelmRepository name: cnpg namespace: flux-system values: image: repository: ghcr.io/cloudnative-pg/cloudnative-pg pullPolicy: IfNotPresent tag: "1.29.0" monitoring: podMonitorEnabled: true podMonitorAdditionalLabels: release: observeability grafanaDashboard: create: true config: create: true name: cnpg-controller-manager-config secret: false clusterWide: true # -- The content of the configmap/secret, see # https://cloudnative-pg.io/documentation/current/operator_conf/#available-options # for all the available options. data: INHERITED_ANNOTATIONS: backup.velero.io/* # INHERITED_LABELS: environment, workload, app # WATCH_NAMESPACE: namespace-a,namespace-b # -- The maximum number of concurrent reconciles. Defaults to 10. maxConcurrentReconciles: 10 ================================================ FILE: cluster/homelab/core/cnpg/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/cnpg/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: cnpg-system labels: monitoring.coreos.com/serviceMonitor: "true" ================================================ FILE: cluster/homelab/core/descheduler/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: descheduler namespace: kube-system spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: descheduler version: 0.35.1 interval: 10m sourceRef: kind: HelmRepository name: descheduler namespace: flux-system ================================================ FILE: cluster/homelab/core/descheduler/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml ================================================ FILE: cluster/homelab/core/istio/cni-helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istio-cni namespace: istio-system spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: cni version: 1.29.2 interval: 10m sourceRef: kind: HelmRepository name: istio namespace: flux-system values: profile: ambient global: platform: k3s ================================================ FILE: cluster/homelab/core/istio/control-plane-helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istiod namespace: istio-system spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: istiod version: 1.29.2 interval: 10m sourceRef: kind: HelmRepository name: istio namespace: flux-system values: profile: ambient ================================================ FILE: cluster/homelab/core/istio/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - control-plane-helm-release.yaml - cni-helm-release.yaml - ztunnel-helm-release.yaml ================================================ FILE: cluster/homelab/core/istio/ztunnel-helm-release.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: ztunnel namespace: istio-system spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: ztunnel version: 1.29.2 interval: 10m sourceRef: kind: HelmRepository name: istio namespace: flux-system ================================================ FILE: cluster/homelab/core/kured/helm-release.sops.yaml ================================================ apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kured namespace: kured spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: kured version: 5.11.0 interval: 10m sourceRef: kind: HelmRepository name: kubereboot namespace: flux-system values: configuration: drainGracePeriod: ENC[AES256_GCM,data:2Td0Vw==,iv:UJHIic7+cOmT6q8v0Pakfy7FvDNUwvqGX698sFBpipM=,tag:R0HgYh0oLsldq76CgngGwg==,type:int] drainTimeout: ENC[AES256_GCM,data:FlOOtjg=,iv:see4FeKoJUsHk7LOu+/ZzY3GR4SBO7egdA1t+XqQMTg=,tag:7tYYPrI48stvMMAU8d9Omw==,type:str] forceReboot: ENC[AES256_GCM,data:3OgvH/M=,iv:FBoepgdrSrEe8R7xWk19fxT97LklI9tGCi2Fl90fKkk=,tag:YULlbrO2jg90jingMj9/OQ==,type:bool] #ENC[AES256_GCM,data:p58DFDFzk1DNaY2JnEqwy1g=,iv:QMm6RsHnz8a3sjHup17XlLegUWg46ZFGFKOWVAmJ/cI=,tag:Byj6iWeJJMZLA/QRVzrvbA==,type:comment] startTime: ENC[AES256_GCM,data:9vJzN2Y=,iv:iZ3SOxdM0IhZ/Pl1flnoozQMnNytu+rpHTALKbXGzDg=,tag:G0S4JBatU4DhFGkPIBiVDw==,type:str] #ENC[AES256_GCM,data:PwhGuZQETUNB9G/wWmSwlaI=,iv:Sq7bjgxldqKPSRo7rKbmTHApYQf7RVW9zW08hAfVBhw=,tag:dRLxpUZwYqRQENg4BMaMcQ==,type:comment] endTime: ENC[AES256_GCM,data:oRM8M5g=,iv:E24JzYa+Nyul8Blp0VMIG7VApcYhq57T9N07jJw2xK8=,tag:+G5M4Wx3jcIvOdvNBs1Urg==,type:str] #ENC[AES256_GCM,data:5fx84FA6Lq86A/iM1UEUM7SulY4eUHqaSk3lziN029TzvYqtsb/RzO3PYLNqTU2qaBwCeRRaowZ+iKe1tHbKdex6nMt+TUz1wlIJA4XS9mI5pq6SUMV7xOjiplh4YsXo,iv:/IQ1Dnd+5ZaSRGXMA5jY4pqth3sb3mRHAaAU9uw3L3k=,tag:TE0CaA+2g0VYi0NH6Yl/Aw==,type:comment] #ENC[AES256_GCM,data:bJ7fEcDqcE5EDMQc3/7klXRfRUOGeKvLS5KE5OxYkKd31Q==,iv:nVboVs/+SwFkwkdd9N6anhiwTryg7aAC0fbWCMxR9/8=,tag:yorWOET9WHAXOGl1IP5vtQ==,type:comment] notifyUrl: ENC[AES256_GCM,data:jVHLn79qAR9bmCQM455cG7EmTvmkAzzK/r6qNb1WkXfUVkDxF6y0oJjmmpEex/alqRISbocEvVabzJEg1d7m/6FNwz8wRF+4NTDMNGcWiPHbF6OAVMbMma6ts2NwsXVUojE=,iv:4GfvaOMlgZyPz0k4aY8PMBm16blGzYLMzlru6WObwIE=,tag:VRQbXd3FSIef3R8DfG6wsw==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0RWlKYkQ0L1cvd1FzV01j TEhXWitrSmVYc0xQNXZKNjRYcFJtcUdpNkRJCkwvdVpucUlZR3RnTXlyVnd1dlRz bkVNZWo4MFhCUDZMbk9TQXVJTDhHY28KLS0tIGlEbllMa2FsMHp1RFRBczF0dlND cFhiSXpnNW5TK3FUbjNPdGlaaWNWMU0KwCUiirHe9HKRT+8FbjtCt1RKgYRWbY2b H8EYEq180QqJn1d2RXlqZh6ughtZYe3C8cHT2riG13vebNj81r9oeA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-05-16T06:40:14Z" mac: ENC[AES256_GCM,data:QqA98BTEQnfOzlEXXHtLR/OzOlHKiDkZHhlRxb5GnY7bTh1cf9diLbrdnomdl7Aa6tywnE+r8oMz+zWBZyb1egjlbrYq2JG/e161O3jtrBnGJbfIoMncOdSCdhLQJ5OGdddu5o+9ZIoUsVidCCICU8rP+HS2lXm+oEjTExKinrI=,iv:2mnpopavMeYr36ZIIgWJao4hka2hN3Vcqvory5WG0ak=,tag:vAJ6Ym9oO3cqkx8OYhnBMg==,type:str] encrypted_regex: ^(values)$ version: 3.10.2 ================================================ FILE: cluster/homelab/core/kured/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.sops.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/kured/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: kured ================================================ FILE: cluster/homelab/core/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - cluster-critical - cnpg - reflector - system-upgrade - longhorn-system - velero - cert-manager - kyverno # - kured # - trivy - descheduler - metallb - istio - mariadb-operator - tofu-controller ================================================ FILE: cluster/homelab/core/kyverno/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kyverno namespace: kyverno spec: interval: 10m install: createNamespace: true chart: spec: chart: kyverno version: 3.8.0 interval: 10m sourceRef: kind: HelmRepository name: kyverno namespace: flux-system values: admissionController: serviceMonitor: additionalLabels: release: observeability enabled: true backgroundController: serviceMonitor: additionalLabels: release: observeability enabled: true rbac: clusterRole: extraResources: - apiGroups: - "admissionregistration.k8s.io" resources: - validatingwebhookconfigurations verbs: - get - list - watch - update - patch - apiGroups: - "" resources: - serviceaccounts verbs: - create - update - delete - patch cleanupController: rbac: clusterRole: extraResources: - apiGroups: - "" resources: - pods verbs: - delete - get - list - watch - apiGroups: - apps resources: - replicasets verbs: - delete - get - list - watch serviceMonitor: additionalLabels: release: observeability enabled: true reportsController: serviceMonitor: additionalLabels: release: observeability enabled: true grafana: enabled: true labels: grafana_dashboard: "1" config: resourceFilters: - "[Event,*,*]" - "[*/*,kube-system,*]" - "[*/*,kube-public,*]" - "[*/*,kube-node-lease,*]" - "[Node,*,*]" - "[Node/?*,*,*]" - "[APIService,*,*]" - "[APIService/?*,*,*]" - "[TokenReview,*,*]" - "[SubjectAccessReview,*,*]" - "[SelfSubjectAccessReview,*,*]" - "[Binding,*,*]" - "[Pod/binding,*,*]" # We comment these out, so we can delete empty replicas # - '[ReplicaSet,*,*]' # - '[ReplicaSet/?*,*,*]' - "[EphemeralReport,*,*]" - "[ClusterEphemeralReport,*,*]" # exclude resources from the chart - '[ClusterRole,*,{{ template "kyverno.admission-controller.roleName" . }}]' - '[ClusterRole,*,{{ template "kyverno.admission-controller.roleName" . }}:core]' - '[ClusterRole,*,{{ template "kyverno.admission-controller.roleName" . }}:additional]' - '[ClusterRole,*,{{ template "kyverno.background-controller.roleName" . }}]' - '[ClusterRole,*,{{ template "kyverno.background-controller.roleName" . }}:core]' - '[ClusterRole,*,{{ template "kyverno.background-controller.roleName" . }}:additional]' - '[ClusterRole,*,{{ template "kyverno.cleanup-controller.roleName" . }}]' - '[ClusterRole,*,{{ template "kyverno.cleanup-controller.roleName" . }}:core]' - '[ClusterRole,*,{{ template "kyverno.cleanup-controller.roleName" . }}:additional]' - '[ClusterRole,*,{{ template "kyverno.reports-controller.roleName" . }}]' - '[ClusterRole,*,{{ template "kyverno.reports-controller.roleName" . }}:core]' - '[ClusterRole,*,{{ template "kyverno.reports-controller.roleName" . }}:additional]' - '[ClusterRoleBinding,*,{{ template "kyverno.admission-controller.roleName" . }}]' - '[ClusterRoleBinding,*,{{ template "kyverno.background-controller.roleName" . }}]' - '[ClusterRoleBinding,*,{{ template "kyverno.cleanup-controller.roleName" . }}]' - '[ClusterRoleBinding,*,{{ template "kyverno.reports-controller.roleName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceAccountName" . }}]' - '[ServiceAccount/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceAccountName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.serviceAccountName" . }}]' - '[ServiceAccount/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.serviceAccountName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.serviceAccountName" . }}]' - '[ServiceAccount/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.serviceAccountName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.serviceAccountName" . }}]' - '[ServiceAccount/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.serviceAccountName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.roleName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.roleName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.roleName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.roleName" . }}]' - '[RoleBinding,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.roleName" . }}]' - '[RoleBinding,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.roleName" . }}]' - '[RoleBinding,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.roleName" . }}]' - '[RoleBinding,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.roleName" . }}]' - '[ConfigMap,{{ include "kyverno.namespace" . }},{{ template "kyverno.config.configMapName" . }}]' - '[ConfigMap,{{ include "kyverno.namespace" . }},{{ template "kyverno.config.metricsConfigMapName" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[Deployment/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[Deployment/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[Deployment/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[Deployment/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}-*]' - '[Pod/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}-*]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-*]' - '[Pod/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-*]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-*]' - '[Pod/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-*]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-*]' - '[Pod/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-*]' - '[Job,{{ include "kyverno.namespace" . }},{{ template "kyverno.fullname" . }}-hook-pre-delete]' - '[Job/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.fullname" . }}-hook-pre-delete]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[NetworkPolicy/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[NetworkPolicy/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[NetworkPolicy/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[NetworkPolicy/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[PodDisruptionBudget/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[PodDisruptionBudget/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[PodDisruptionBudget/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[PodDisruptionBudget/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}]' - '[Service/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}-metrics]' - '[Service/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}-metrics]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-metrics]' - '[Service/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-metrics]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[Service/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-metrics]' - '[Service/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-metrics]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-metrics]' - '[Service/?*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-metrics]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.admission-controller.name" . }}]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.background-controller.name" . }}]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.reports-controller.name" . }}]' - '[Secret,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}.{{ template "kyverno.namespace" . }}.svc.*]' - '[Secret,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}.{{ template "kyverno.namespace" . }}.svc.*]' - "[ValidatingWebhookConfiguration,*,longhorn-webhook-validator]" - "[MutatingWebhookConfiguration,*,longhorn-webhook-mutator]" ================================================ FILE: cluster/homelab/core/kyverno/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/kyverno/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: kyverno labels: monitoring.coreos.com/serviceMonitor: "true" ================================================ FILE: cluster/homelab/core/longhorn-system/db-storageclass.yaml ================================================ --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: longhorn-db parameters: dataEngine: v1 dataLocality: best-effort disableRevisionCounter: "true" fromBackup: "" fsType: ext4 numberOfReplicas: "3" staleReplicaTimeout: "30" unmapMarkSnapChainRemoved: ignored provisioner: driver.longhorn.io reclaimPolicy: Retain volumeBindingMode: Immediate allowVolumeExpansion: true ================================================ FILE: cluster/homelab/core/longhorn-system/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: longhorn-system namespace: longhorn-system spec: interval: 10m install: createNamespace: true chart: spec: chart: longhorn version: 1.11.1 interval: 10m sourceRef: kind: HelmRepository name: longhorn-system namespace: flux-system values: image: longhorn: manager: tag: v1.11.0-hotfix-1 instanceManager: tag: v1.11.0-hotfix-1 # REF: https://longhorn.io/docs/1.11.0/important-notes/#longhorn-manager-image preUpgradeChecker: jobEnabled: true upgradeVersionCheck: false enablePSP: false networkPolicies: enabled: true type: "k3s" httproute: enabled: true parentRefs: - name: internal namespace: istio-gateway hostnames: - "longhorn.sgenov.dev" annotations: gethomepage.dev/enabled: "true" gethomepage.dev/description: Block Storage For Kubernetes gethomepage.dev/group: Storage gethomepage.dev/icon: longhorn gethomepage.dev/name: Longhorn longhornManager: tolerations: - key: "CriticalAddonsOnly" operator: "Equal" effect: "NoSchedule" value: longhornDriver: tolerations: - key: "CriticalAddonsOnly" operator: "Equal" effect: "NoSchedule" value: defaultSettings: taintToleration: "CriticalAddonsOnly:NoSchedule" ================================================ FILE: cluster/homelab/core/longhorn-system/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - db-storageclass.yaml ================================================ FILE: cluster/homelab/core/longhorn-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: longhorn-system ================================================ FILE: cluster/homelab/core/mariadb-operator/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: mariadb-operator namespace: mariadb-operator spec: interval: 10m install: createNamespace: true upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: mariadb-operator version: "26.3.0" interval: 10m sourceRef: kind: HelmRepository name: mariadb-operator namespace: flux-system values: logLevel: INFO metrics: enabled: true serviceMonitor: enabled: true ================================================ FILE: cluster/homelab/core/mariadb-operator/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/mariadb-operator/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: mariadb-operator ================================================ FILE: cluster/homelab/core/metallb/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: metallb namespace: metallb-system spec: interval: 10m install: createNamespace: true upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: metallb version: 0.15.3 interval: 10m sourceRef: kind: HelmRepository name: metallb namespace: flux-system values: controller: image: repository: quay.io/metallb/controller tag: v0.15.3 speaker: tolerations: - key: "CriticalAddonsOnly" operator: "Equal" effect: "NoSchedule" value: ================================================ FILE: cluster/homelab/core/metallb/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/metallb/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: metallb-system labels: pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: cluster/homelab/core/reflector/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: reflector namespace: reflector spec: interval: 10m install: createNamespace: true chart: spec: chart: reflector version: 10.0.40 interval: 10m sourceRef: kind: HelmRepository name: reflector namespace: flux-system values: livenessProbe: periodSeconds: 30 readinessProbe: periodSeconds: 10 ================================================ FILE: cluster/homelab/core/reflector/image_pull_secret.sops.yaml ================================================ apiVersion: v1 kind: Secret type: kubernetes.io/dockerconfigjson metadata: name: default-image-pull-secret namespace: reflector annotations: reflector.v1.k8s.emberstack.com/reflection-auto-enabled: ENC[AES256_GCM,data:JMnZKQ==,iv:Z632W6d/L1dX88iZkyYhSRYe0kwAyTqR7NRHmiCve1I=,tag:LRiZQ41cVOfBb+dSwEINXw==,type:str] reflector.v1.k8s.emberstack.com/reflection-allowed: ENC[AES256_GCM,data:lUrzvA==,iv:QmzvM0s8eNgP65goqPM4raZQDQkkpCvkT/76NMqU1wM=,tag:uasqBARRkKYElLm/TkvJpw==,type:str] data: .dockerconfigjson: ENC[AES256_GCM,data:zOcDxtHJv3iy0MnALoaGkmeXy1V1fcAte1/3X1BjQVUis7Xu/3+ivrl37EW+NAPY1EZxxP3hH66y/WrLDftpwBFYJwdL9wI9z68Umd/P/BY3BSk4C3UGTTpnz6/jJ4PATckpJu/5fgl9ZeP5HMNB5oFi9oxnw9BMCgwXq3CmHJBdkRmc00gOO0+L9+tX5wbY7riHU4A+GNNIecx0RHVSPMXq7S/FRkSv5s2x13t/hYHsb2xjQ7shgqqzNa3DNPzwCcmxQaGstjJuly/tYbSCERaVMqITVLFqlwXjnYr2OtOXDwGPADPqvcFSR4NFk6kHFB9V/Lz6/adRuLplAb3nfA==,iv:0FOjWyCoyTte7dzfujgbeBQK0Q3bx7x8gyZMHXE9sG4=,tag:Nrnhh+JpkMoSWrfU3FGIHg==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTMDFMM0xBczY0Uy9Xc0xW T2dzb1o2eGFMSnBCNWVrcUhJNDhWOXl2aVQwCkxuVDMrYmpYTFZFSUZ1TGFEQXF5 anBneWxnT2ZQWmVaanpQT3hEMVl5TnMKLS0tIHlDSHd2Wk4yeVZqRlpYRUl1eHFX QVY5UmxsMjl1WlpNeXlkb1BsWi9jTVkKGMZpwmhisdXI676q6Iggz195AgaAXy/C SdbIZlHKWq1UQtmGPu6rEpN9rK0he+R/ZHkGvrP6o+EeRatB3gccIA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-10-24T19:54:45Z" mac: ENC[AES256_GCM,data:uKmSxsJhXAM+TFdgvNhZ3fD3GDbDVmX+oFr/pHPmk1YAZ26GKcjfuVnpV3MJg7+sLQhLVknVYscTLoNafB78fjzj5djqxjtMzig6QQhKpVnXksTaWQxU5qP80lWblmm64qKJXJGrme3TIrOD8MI+iN9JMx19YTvf9BbCN9qFCzg=,iv:QStr2wlMqA5ES9n0/GGq+KKFXPXsz/v43po12Ymj4aU=,tag:uqYgGaPuzHO6IASQL19T2A==,type:str] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.11.0 ================================================ FILE: cluster/homelab/core/reflector/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - image_pull_secret.sops.yaml ================================================ FILE: cluster/homelab/core/reflector/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: reflector ================================================ FILE: cluster/homelab/core/rook-ceph/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: rook-ceph namespace: rook-ceph spec: interval: 10m timeout: 15m install: createNamespace: true crds: CreateReplace remediation: retries: -1 upgrade: cleanupOnFail: true remediation: retries: 3 chart: spec: chart: rook-ceph version: v1.19.5 interval: 10m sourceRef: kind: HelmRepository name: rook-release namespace: flux-system values: image: repository: ghcr.io/rook/ceph tag: v1.19.5 pullPolicy: IfNotPresent crds: # -- Whether the helm chart should create and update the CRDs. If false, the CRDs must be # managed independently with deploy/examples/crds.yaml. # **WARNING** Only set during first deployment. If later disabled the cluster may be DESTROYED. # If the CRDs are deleted in this case, see # [the disaster recovery guide](https://rook.io/docs/rook/latest/Troubleshooting/disaster-recovery/#restoring-crds-after-deletion) # to restore them. enabled: true # # -- Pod resource requests & limits resources: limits: memory: 512Mi requests: cpu: 200m memory: 128Mi # -- Global log level for the operator. # Options: `ERROR`, `WARNING`, `INFO`, `DEBUG` logLevel: INFO # -- If true, scale down the rook operator. # This is useful for administrative actions where the rook operator must be scaled down, while using gitops style tooling # to deploy your helm charts. scaleDownOperator: false enableDiscoveryDaemon: true monitoring: # -- Enable monitoring. Requires Prometheus to be pre-installed. # Enabling will also create RBAC rules to allow Operator to create ServiceMonitors enabled: false ================================================ FILE: cluster/homelab/core/rook-ceph/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml ================================================ FILE: cluster/homelab/core/system-upgrade/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - https://github.com/rancher/system-upgrade-controller.git?ref=v0.19.0 # There is a kustomization spec inside of the git repo, may be good to monitor for new releases in the future images: - name: rancher/system-upgrade-controller newTag: v0.19.0 # overwrite since there is a newer version ================================================ FILE: cluster/homelab/core/tofu-controller/helm-release.yaml ================================================ # Ref: https://raw.githubusercontent.com/flux-iac/tofu-controller/main/docs/release.yaml --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: tofu-controller namespace: flux-system spec: chart: spec: chart: tofu-controller sourceRef: kind: HelmRepository name: tofu-controller version: "0.16.2" interval: 10m releaseName: tofu-controller targetNamespace: flux-system install: crds: Create remediation: retries: -1 upgrade: crds: CreateReplace remediation: retries: -1 values: replicaCount: 1 concurrency: 24 resources: limits: cpu: 1000m memory: 2Gi requests: cpu: 400m memory: 64Mi caCertValidityDuration: 24h certRotationCheckFrequency: 30m ================================================ FILE: cluster/homelab/core/tofu-controller/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml ================================================ FILE: cluster/homelab/core/trivy/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: trivy-operator namespace: trivy-system spec: interval: 10m install: createNamespace: true upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: trivy-operator version: 0.32.1 interval: 10m sourceRef: kind: HelmRepository name: aqua namespace: flux-system values: service: headless: true metricsPort: 80 serviceMonitor: labels: release: observeability enabled: true trivy: ignoreUnfixed: true # targetWorkloads: "pod,statefulset,daemonset,replicaset,cronjob" # Targeting only my specific apps targetNamespaces: "" trivyOperator: reportResourceLabels: "owner,app" operator: # -- configAuditScannerEnabled the flag to enable configuration audit scanner configAuditScannerEnabled: true # -- rbacAssessmentScannerEnabled the flag to enable rbac assessment scanner rbacAssessmentScannerEnabled: true # -- infraAssessmentScannerEnabled the flag to enable infra assessment scanner infraAssessmentScannerEnabled: true # -- clusterComplianceEnabled the flag to enable cluster compliance scanner clusterComplianceEnabled: true metricsFindingsEnabled: true # -- metricsVulnIdEnabled the flag to enable metrics about cve vulns id # be aware of metrics cardinality is significantly increased with this feature enabled. metricsVulnIdEnabled: true # -- exposedSecretScannerEnabled the flag to enable exposed secret scanner exposedSecretScannerEnabled: true # -- MetricsExposedSecretInfo the flag to enable metrics about exposed secrets # be aware of metrics cardinality is significantly increased with this feature enabled. metricsExposedSecretInfo: true # -- MetricsConfigAuditInfo the flag to enable metrics about configuration audits # be aware of metrics cardinality is significantly increased with this feature enabled. metricsConfigAuditInfo: true # -- MetricsRbacAssessmentInfo the flag to enable metrics about Rbac Assessment # be aware of metrics cardinality is significantly increased with this feature enabled. metricsRbacAssessmentInfo: true # -- MetricsInfraAssessmentInfo the flag to enable metrics about Infra Assessment # be aware of metrics cardinality is significantly increased with this feature enabled. metricsInfraAssessmentInfo: true # -- MetricsImageInfo the flag to enable metrics about Image Information of scanned images # This information has image os information including os family, name/version, and if end of service life has been reached # be aware of metrics cardinality is significantly increased with this feature enabled. metricsImageInfo: true # -- MetricsClusterComplianceInfo the flag to enable metrics about Cluster Compliance # be aware of metrics cardinality is significantly increased with this feature enabled. metricsClusterComplianceInfo: true ================================================ FILE: cluster/homelab/core/trivy/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/core/trivy/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: trivy-system labels: monitoring.coreos.com/serviceMonitor: "true" ================================================ FILE: cluster/homelab/core/velero/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: velero namespace: velero spec: interval: 10m install: createNamespace: true crds: CreateReplace remediation: retries: 3 upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: velero version: 11.4.0 interval: 10m sourceRef: kind: HelmRepository name: velero namespace: flux-system values: snapshotsEnabled: false image: repository: velero/velero tag: v1.18.0 upgradeCRDs: true initContainers: - name: velero-plugin-for-aws image: velero/velero-plugin-for-aws:v1.14.0 volumeMounts: - mountPath: /target name: plugins metrics: enabled: false scrapeInterval: 120s scrapeTimeout: 30s deployNodeAgent: true # Override kubectl image - use Bitnami's AWS ECR repo.. still has versions. # Probably will fail at some point # Ref: https://github.com/vmware-tanzu/helm-charts/issues/698 kubectl: image: repository: public.ecr.aws/bitnami/kubectl credentials: existingSecret: cloud-credentials-wasabi configuration: repositoryMaintenanceJob: repositoryConfigData: global: keepLatestMaintenanceJobs: 1 # features: EnableCSI backupStorageLocation: - name: default provider: aws default: true bucket: sgenov-velero config: region: eu-central-2 s3ForcePathStyle: true s3Url: https://s3.eu-central-2.wasabisys.com checksumAlgorithm: "" - name: wasabi provider: aws default: false bucket: sgenov-velero config: region: eu-central-2 s3ForcePathStyle: true s3Url: https://s3.eu-central-2.wasabisys.com checksumAlgorithm: "" ================================================ FILE: cluster/homelab/core/velero/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml - secret.sops.yaml ================================================ FILE: cluster/homelab/core/velero/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: velero ================================================ FILE: cluster/homelab/core/velero/secret.sops.yaml ================================================ apiVersion: v1 data: cloud: ENC[AES256_GCM,data:ifpf4GSj3jk+40kBFs3/Uy0dzuz3KhUJFx2eY8WJZa641NDcLhbq53e3VPmwYANkYwKoN28CrlGlqUm8KGX69eH6HCgNEDjdcTfS/2hC729jZP2bM15owahvCtDaubiiMcPb3MeQV51x7yu1HsXO+JJ8+SMx1JGa/skKbENmGCsHH6Ah7YWuGnfaH636GHXJUaQXuQ==,iv:5AA7slnaJD+2rGLYaB3OMpLd3oJjL3wmJIM3XbfIDaA=,tag:DbeoVoOOJvTsNoq0Rt/PXw==,type:str] kind: Secret metadata: name: cloud-credentials-wasabi namespace: velero type: Opaque sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaMnRpejIzT1ZzcXlsa2ta a2lUeFVyZjBabEo5Mk9OaHd0WGJNS3krMmdnCjZHMGZYODFHdTU5VWU1M3lwaDRS OEhPMXQvSldCd3hOejhzaWJRd0lLZ0EKLS0tIGZLdTdsMk1SM3M2THRKaWw4dVlG SWRleUpjK2JTMzdSanp3dXdsUVpqL2sKLHkhM+tSaiMC6CBRz2n3cHLQIHqzQSFW Nz+m3Ott2Ov2h3oR1JhCRJGaSqrht/jBQykhCchxY4ds602bZfzG3Q== -----END AGE ENCRYPTED FILE----- lastmodified: "2024-03-26T13:55:32Z" mac: ENC[AES256_GCM,data:sdbXrEqCGCX001meZziH7cG2k9/gdRGkvUV+zGW/4jwsIc8oCuKPd1aAfn6a5c7MQH5JT3Z2+S2cpAOthaYUuPeKGL26do4D/Na470BHKn/QGkHJsB36MNgLOCzeHIPfWuto5rvIKQbrOcTvXnZx7R7pzZMTkeyFizbfQbkc4sk=,iv:Tv1m8fo+XP2/mkg84ZpKHx2b+PBXgmkqfBuHkdSNDCo=,tag:qwmctWBpPuSq3985p6GnEQ==,type:str] pgp: [] encrypted_regex: ^(data|stringData|annotations|)$ version: 3.8.1 ================================================ FILE: cluster/homelab/crds/external-snapshotter/crds.yaml ================================================ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-csi/external-snapshotter/pull/1337 controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshotclasses.groupsnapshot.storage.k8s.io spec: group: groupsnapshot.storage.k8s.io names: kind: VolumeGroupSnapshotClass listKind: VolumeGroupSnapshotClassList plural: volumegroupsnapshotclasses shortNames: - vgsclass - vgsclasses singular: volumegroupsnapshotclass scope: Cluster versions: - additionalPrinterColumns: - jsonPath: .driver name: Driver type: string - description: Determines whether a VolumeGroupSnapshotContent created through the VolumeGroupSnapshotClass should be deleted when its bound VolumeGroupSnapshot is deleted. jsonPath: .deletionPolicy name: DeletionPolicy type: string - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true name: v1beta1 schema: openAPIV3Schema: description: |- VolumeGroupSnapshotClass specifies parameters that a underlying storage system uses when creating a volume group snapshot. A specific VolumeGroupSnapshotClass is used by specifying its name in a VolumeGroupSnapshot object. VolumeGroupSnapshotClasses are non-namespaced. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string deletionPolicy: description: |- DeletionPolicy determines whether a VolumeGroupSnapshotContent created through the VolumeGroupSnapshotClass should be deleted when its bound VolumeGroupSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are kept. "Delete" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are deleted. Required. enum: - Delete - Retain type: string driver: description: |- Driver is the name of the storage driver expected to handle this VolumeGroupSnapshotClass. Required. type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object parameters: additionalProperties: type: string description: |- Parameters is a key-value map with storage driver specific parameters for creating group snapshots. These values are opaque to Kubernetes and are passed directly to the driver. type: object required: - deletionPolicy - driver type: object served: true storage: false subresources: {} - additionalPrinterColumns: - jsonPath: .driver name: Driver type: string - description: Determines whether a VolumeGroupSnapshotContent created through the VolumeGroupSnapshotClass should be deleted when its bound VolumeGroupSnapshot is deleted. jsonPath: .deletionPolicy name: DeletionPolicy type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta2 schema: openAPIV3Schema: description: |- VolumeGroupSnapshotClass specifies parameters that a underlying storage system uses when creating a volume group snapshot. A specific VolumeGroupSnapshotClass is used by specifying its name in a VolumeGroupSnapshot object. VolumeGroupSnapshotClasses are non-namespaced. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string deletionPolicy: description: |- DeletionPolicy determines whether a VolumeGroupSnapshotContent created through the VolumeGroupSnapshotClass should be deleted when its bound VolumeGroupSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are kept. "Delete" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are deleted. Required. enum: - Delete - Retain type: string x-kubernetes-validations: - message: deletionPolicy is immutable once set rule: self == oldSelf driver: description: |- Driver is the name of the storage driver expected to handle this VolumeGroupSnapshotClass. Required. type: string x-kubernetes-validations: - message: driver is immutable once set rule: self == oldSelf kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object parameters: additionalProperties: type: string description: |- Parameters is a key-value map with storage driver specific parameters for creating group snapshots. These values are opaque to Kubernetes and are passed directly to the driver. type: object x-kubernetes-validations: - message: parameters are immutable once set rule: self == oldSelf required: - deletionPolicy - driver type: object served: true storage: true subresources: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-csi/external-snapshotter/pull/1337 controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshotcontents.groupsnapshot.storage.k8s.io spec: conversion: strategy: Webhook webhook: clientConfig: service: name: snapshot-conversion-webhook-service namespace: default path: /convert conversionReviewVersions: - v1 group: groupsnapshot.storage.k8s.io names: kind: VolumeGroupSnapshotContent listKind: VolumeGroupSnapshotContentList plural: volumegroupsnapshotcontents shortNames: - vgsc - vgscs singular: volumegroupsnapshotcontent scope: Cluster versions: - additionalPrinterColumns: - description: Indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: Determines whether this VolumeGroupSnapshotContent and its physical group snapshot on the underlying storage system should be deleted when its bound VolumeGroupSnapshot is deleted. jsonPath: .spec.deletionPolicy name: DeletionPolicy type: string - description: Name of the CSI driver used to create the physical group snapshot on the underlying storage system. jsonPath: .spec.driver name: Driver type: string - description: Name of the VolumeGroupSnapshotClass from which this group snapshot was (or will be) created. jsonPath: .spec.volumeGroupSnapshotClassName name: VolumeGroupSnapshotClass type: string - description: Namespace of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent object is bound. jsonPath: .spec.volumeGroupSnapshotRef.namespace name: VolumeGroupSnapshotNamespace type: string - description: Name of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent object is bound. jsonPath: .spec.volumeGroupSnapshotRef.name name: VolumeGroupSnapshot type: string - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true name: v1beta1 schema: openAPIV3Schema: description: |- VolumeGroupSnapshotContent represents the actual "on-disk" group snapshot object in the underlying storage system properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- Spec defines properties of a VolumeGroupSnapshotContent created by the underlying storage system. Required. properties: deletionPolicy: description: |- DeletionPolicy determines whether this VolumeGroupSnapshotContent and the physical group snapshot on the underlying storage system should be deleted when the bound VolumeGroupSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are kept. "Delete" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are deleted. For dynamically provisioned group snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeGroupSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeGroupSnapshotContent object. Required. enum: - Delete - Retain type: string driver: description: |- Driver is the name of the CSI driver used to create the physical group snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. type: string source: description: |- Source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. properties: groupSnapshotHandles: description: |- GroupSnapshotHandles specifies the CSI "group_snapshot_id" of a pre-existing group snapshot and a list of CSI "snapshot_id" of pre-existing snapshots on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. properties: volumeGroupSnapshotHandle: description: |- VolumeGroupSnapshotHandle specifies the CSI "group_snapshot_id" of a pre-existing group snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. Required. type: string volumeSnapshotHandles: description: |- VolumeSnapshotHandles is a list of CSI "snapshot_id" of pre-existing snapshots on the underlying storage system for which Kubernetes objects representation were (or should be) created. This field is immutable. Required. items: type: string type: array required: - volumeGroupSnapshotHandle - volumeSnapshotHandles type: object x-kubernetes-validations: - message: groupSnapshotHandles is immutable rule: self == oldSelf volumeHandles: description: |- VolumeHandles is a list of volume handles on the backend to be snapshotted together. It is specified for dynamic provisioning of the VolumeGroupSnapshot. This field is immutable. items: type: string type: array x-kubernetes-validations: - message: volumeHandles is immutable rule: self == oldSelf type: object x-kubernetes-validations: - message: volumeHandles is required once set rule: '!has(oldSelf.volumeHandles) || has(self.volumeHandles)' - message: groupSnapshotHandles is required once set rule: '!has(oldSelf.groupSnapshotHandles) || has(self.groupSnapshotHandles)' - message: exactly one of volumeHandles and groupSnapshotHandles must be set rule: (has(self.volumeHandles) && !has(self.groupSnapshotHandles)) || (!has(self.volumeHandles) && has(self.groupSnapshotHandles)) volumeGroupSnapshotClassName: description: |- VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass from which this group snapshot was (or will be) created. Note that after provisioning, the VolumeGroupSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. For dynamic provisioning, this field must be set. This field may be unset for pre-provisioned snapshots. type: string volumeGroupSnapshotRef: description: |- VolumeGroupSnapshotRef specifies the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent object is bound. VolumeGroupSnapshot.Spec.VolumeGroupSnapshotContentName field must reference to this VolumeGroupSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeGroupSnapshotContent object, name and namespace of the VolumeGroupSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. properties: apiVersion: description: API version of the referent. type: string fieldPath: description: |- If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future. type: string kind: description: |- Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string name: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string namespace: description: |- Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ type: string resourceVersion: description: |- Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency type: string uid: description: |- UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids type: string type: object x-kubernetes-map-type: atomic x-kubernetes-validations: - message: both volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace must be set rule: has(self.name) && has(self.__namespace__) required: - deletionPolicy - driver - source - volumeGroupSnapshotRef type: object status: description: status represents the current information of a group snapshot. properties: creationTime: description: |- CreationTime is the timestamp when the point-in-time group snapshot is taken by the underlying storage system. If not specified, it indicates the creation time is unknown. If not specified, it means the readiness of a group snapshot is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command date +%s%N returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. This field is the source for the CreationTime field in VolumeGroupSnapshotStatus format: date-time type: string error: description: |- Error is the last observed error during group snapshot creation, if any. Upon success after retry, this error field will be cleared. properties: message: description: |- message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: |- ReadyToUse indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. type: boolean volumeGroupSnapshotHandle: description: |- VolumeGroupSnapshotHandle is a unique id returned by the CSI driver to identify the VolumeGroupSnapshot on the storage system. If a storage system does not provide such an id, the CSI driver can choose to return the VolumeGroupSnapshot name. type: string volumeSnapshotHandlePairList: description: |- VolumeSnapshotHandlePairList is a list of CSI "volume_id" and "snapshot_id" pair returned by the CSI driver to identify snapshots and their source volumes on the storage system. items: description: VolumeSnapshotHandlePair defines a pair of a source volume handle and a snapshot handle properties: snapshotHandle: description: |- SnapshotHandle is a unique id returned by the CSI driver to identify a volume snapshot on the storage system Required. type: string volumeHandle: description: |- VolumeHandle is a unique id returned by the CSI driver to identify a volume on the storage system Required. type: string required: - snapshotHandle - volumeHandle type: object type: array type: object required: - spec type: object served: true storage: false subresources: status: {} - additionalPrinterColumns: - description: Indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: Determines whether this VolumeGroupSnapshotContent and its physical group snapshot on the underlying storage system should be deleted when its bound VolumeGroupSnapshot is deleted. jsonPath: .spec.deletionPolicy name: DeletionPolicy type: string - description: Name of the CSI driver used to create the physical group snapshot on the underlying storage system. jsonPath: .spec.driver name: Driver type: string - description: Name of the VolumeGroupSnapshotClass from which this group snapshot was (or will be) created. jsonPath: .spec.volumeGroupSnapshotClassName name: VolumeGroupSnapshotClass type: string - description: Namespace of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent object is bound. jsonPath: .spec.volumeGroupSnapshotRef.namespace name: VolumeGroupSnapshotNamespace type: string - description: Name of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent object is bound. jsonPath: .spec.volumeGroupSnapshotRef.name name: VolumeGroupSnapshot type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta2 schema: openAPIV3Schema: description: |- VolumeGroupSnapshotContent represents the actual "on-disk" group snapshot object in the underlying storage system properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- Spec defines properties of a VolumeGroupSnapshotContent created by the underlying storage system. Required. properties: deletionPolicy: description: |- DeletionPolicy determines whether this VolumeGroupSnapshotContent and the physical group snapshot on the underlying storage system should be deleted when the bound VolumeGroupSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are kept. "Delete" means that the VolumeGroupSnapshotContent and its physical group snapshot on underlying storage system are deleted. For dynamically provisioned group snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeGroupSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeGroupSnapshotContent object. Required. enum: - Delete - Retain type: string driver: description: |- Driver is the name of the CSI driver used to create the physical group snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. type: string x-kubernetes-validations: - message: driver is immutable once set rule: self == oldSelf source: description: |- Source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. properties: groupSnapshotHandles: description: |- GroupSnapshotHandles specifies the CSI "group_snapshot_id" of a pre-existing group snapshot and a list of CSI "snapshot_id" of pre-existing snapshots on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. properties: volumeGroupSnapshotHandle: description: |- VolumeGroupSnapshotHandle specifies the CSI "group_snapshot_id" of a pre-existing group snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. Required. type: string volumeSnapshotHandles: description: |- VolumeSnapshotHandles is a list of CSI "snapshot_id" of pre-existing snapshots on the underlying storage system for which Kubernetes objects representation were (or should be) created. This field is immutable. Required. items: type: string type: array required: - volumeGroupSnapshotHandle - volumeSnapshotHandles type: object x-kubernetes-validations: - message: groupSnapshotHandles is immutable rule: self == oldSelf volumeHandles: description: |- VolumeHandles is a list of volume handles on the backend to be snapshotted together. It is specified for dynamic provisioning of the VolumeGroupSnapshot. This field is immutable. items: type: string type: array x-kubernetes-validations: - message: volumeHandles is immutable rule: self == oldSelf type: object x-kubernetes-validations: - message: volumeHandles is required once set rule: '!has(oldSelf.volumeHandles) || has(self.volumeHandles)' - message: groupSnapshotHandles is required once set rule: '!has(oldSelf.groupSnapshotHandles) || has(self.groupSnapshotHandles)' - message: exactly one of volumeHandles and groupSnapshotHandles must be set rule: (has(self.volumeHandles) && !has(self.groupSnapshotHandles)) || (!has(self.volumeHandles) && has(self.groupSnapshotHandles)) volumeGroupSnapshotClassName: description: |- VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass from which this group snapshot was (or will be) created. Note that after provisioning, the VolumeGroupSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. For dynamic provisioning, this field must be set. This field may be unset for pre-provisioned snapshots. type: string x-kubernetes-validations: - message: volumeGroupSnapshotClassName is immutable once set rule: self == oldSelf volumeGroupSnapshotRef: description: |- VolumeGroupSnapshotRef specifies the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent object is bound. VolumeGroupSnapshot.Spec.VolumeGroupSnapshotContentName field must reference to this VolumeGroupSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeGroupSnapshotContent object, name and namespace of the VolumeGroupSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. properties: apiVersion: description: API version of the referent. type: string fieldPath: description: |- If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future. type: string kind: description: |- Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string name: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string namespace: description: |- Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ type: string resourceVersion: description: |- Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency type: string uid: description: |- UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids type: string type: object x-kubernetes-map-type: atomic x-kubernetes-validations: - message: both volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace must be set rule: has(self.name) && has(self.__namespace__) - message: volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace are immutable rule: self.name == oldSelf.name && self.__namespace__ == oldSelf.__namespace__ - message: volumeGroupSnapshotRef.uid is immutable once set rule: '!has(oldSelf.uid) || (has(self.uid) && self.uid == oldSelf.uid)' required: - deletionPolicy - driver - source - volumeGroupSnapshotRef type: object status: description: status represents the current information of a group snapshot. properties: creationTime: description: |- CreationTime is the timestamp when the point-in-time group snapshot is taken by the underlying storage system. If not specified, it indicates the creation time is unknown. If not specified, it means the readiness of a group snapshot is unknown. This field is the source for the CreationTime field in VolumeGroupSnapshotStatus format: date-time type: string error: description: |- Error is the last observed error during group snapshot creation, if any. Upon success after retry, this error field will be cleared. properties: message: description: |- message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: |- ReadyToUse indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. type: boolean volumeGroupSnapshotHandle: description: |- VolumeGroupSnapshotHandle is a unique id returned by the CSI driver to identify the VolumeGroupSnapshot on the storage system. If a storage system does not provide such an id, the CSI driver can choose to return the VolumeGroupSnapshot name. type: string x-kubernetes-validations: - message: volumeGroupSnapshotHandle is immutable once set rule: self == oldSelf volumeSnapshotInfoList: description: |- This field is introduced in v1beta2 It is replacing VolumeSnapshotHandlePairList VolumeSnapshotInfoList is a list of snapshot information returned by by the CSI driver to identify snapshots on the storage system. items: description: |- The VolumeSnapshotInfo struct is added in v1beta2 VolumeSnapshotInfo contains information for a snapshot properties: creationTime: description: |- creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. format: int64 type: integer readyToUse: description: ReadyToUse indicates if the snapshot is ready to be used to restore a volume. type: boolean restoreSize: description: |- RestoreSize represents the minimum size of volume required to create a volume from this snapshot. format: int64 type: integer snapshotHandle: description: SnapshotHandle is the CSI "snapshot_id" of this snapshot on the underlying storage system. type: string volumeHandle: description: |- VolumeHandle specifies the CSI "volume_id" of the volume from which this snapshot was taken from. type: string type: object type: array type: object required: - spec type: object served: true storage: true subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-csi/external-snapshotter/pull/1337 controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshots.groupsnapshot.storage.k8s.io spec: group: groupsnapshot.storage.k8s.io names: kind: VolumeGroupSnapshot listKind: VolumeGroupSnapshotList plural: volumegroupsnapshots shortNames: - vgs singular: volumegroupsnapshot scope: Namespaced versions: - additionalPrinterColumns: - description: Indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: The name of the VolumeGroupSnapshotClass requested by the VolumeGroupSnapshot. jsonPath: .spec.volumeGroupSnapshotClassName name: VolumeGroupSnapshotClass type: string - description: Name of the VolumeGroupSnapshotContent object to which the VolumeGroupSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeGroupSnapshot and VolumeGroupSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. jsonPath: .status.boundVolumeGroupSnapshotContentName name: VolumeGroupSnapshotContent type: string - description: Timestamp when the point-in-time group snapshot was taken by the underlying storage system. jsonPath: .status.creationTime name: CreationTime type: date - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true name: v1beta1 schema: openAPIV3Schema: description: |- VolumeGroupSnapshot is a user's request for creating either a point-in-time group snapshot or binding to a pre-existing group snapshot. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- Spec defines the desired characteristics of a group snapshot requested by a user. Required. properties: source: description: |- Source specifies where a group snapshot will be created from. This field is immutable after creation. Required. properties: selector: description: |- Selector is a label query over persistent volume claims that are to be grouped together for snapshotting. This labelSelector will be used to match the label added to a PVC. If the label is added or removed to a volume after a group snapshot is created, the existing group snapshots won't be modified. Once a VolumeGroupSnapshotContent is created and the sidecar starts to process it, the volume list will not change with retries. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic x-kubernetes-validations: - message: selector is immutable rule: self == oldSelf volumeGroupSnapshotContentName: description: |- VolumeGroupSnapshotContentName specifies the name of a pre-existing VolumeGroupSnapshotContent object representing an existing volume group snapshot. This field should be set if the volume group snapshot already exists and only needs a representation in Kubernetes. This field is immutable. type: string x-kubernetes-validations: - message: volumeGroupSnapshotContentName is immutable rule: self == oldSelf type: object x-kubernetes-validations: - message: selector is required once set rule: '!has(oldSelf.selector) || has(self.selector)' - message: volumeGroupSnapshotContentName is required once set rule: '!has(oldSelf.volumeGroupSnapshotContentName) || has(self.volumeGroupSnapshotContentName)' - message: exactly one of selector and volumeGroupSnapshotContentName must be set rule: (has(self.selector) && !has(self.volumeGroupSnapshotContentName)) || (!has(self.selector) && has(self.volumeGroupSnapshotContentName)) volumeGroupSnapshotClassName: description: |- VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass requested by the VolumeGroupSnapshot. VolumeGroupSnapshotClassName may be left nil to indicate that the default class will be used. Empty string is not allowed for this field. type: string x-kubernetes-validations: - message: volumeGroupSnapshotClassName must not be the empty string when set rule: size(self) > 0 required: - source type: object status: description: |- Status represents the current information of a group snapshot. Consumers must verify binding between VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent point to each other) before using this object. properties: boundVolumeGroupSnapshotContentName: description: |- BoundVolumeGroupSnapshotContentName is the name of the VolumeGroupSnapshotContent object to which this VolumeGroupSnapshot object intends to bind to. If not specified, it indicates that the VolumeGroupSnapshot object has not been successfully bound to a VolumeGroupSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent point at each other) before using this object. type: string creationTime: description: |- CreationTime is the timestamp when the point-in-time group snapshot is taken by the underlying storage system. If not specified, it may indicate that the creation time of the group snapshot is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command date +%s%N returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. This field is updated based on the CreationTime field in VolumeGroupSnapshotContentStatus format: date-time type: string error: description: |- Error is the last observed error during group snapshot creation, if any. This field could be helpful to upper level controllers (i.e., application controller) to decide whether they should continue on waiting for the group snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurs during the group snapshot creation. Upon success, this error field will be cleared. properties: message: description: |- message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: |- ReadyToUse indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. If not specified, it means the readiness of a group snapshot is unknown. type: boolean type: object required: - spec type: object served: true storage: false subresources: status: {} - additionalPrinterColumns: - description: Indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: The name of the VolumeGroupSnapshotClass requested by the VolumeGroupSnapshot. jsonPath: .spec.volumeGroupSnapshotClassName name: VolumeGroupSnapshotClass type: string - description: Name of the VolumeGroupSnapshotContent object to which the VolumeGroupSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeGroupSnapshot and VolumeGroupSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. jsonPath: .status.boundVolumeGroupSnapshotContentName name: VolumeGroupSnapshotContent type: string - description: Timestamp when the point-in-time group snapshot was taken by the underlying storage system. jsonPath: .status.creationTime name: CreationTime type: date - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta2 schema: openAPIV3Schema: description: |- VolumeGroupSnapshot is a user's request for creating either a point-in-time group snapshot or binding to a pre-existing group snapshot. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- Spec defines the desired characteristics of a group snapshot requested by a user. Required. properties: source: description: |- Source specifies where a group snapshot will be created from. This field is immutable after creation. Required. properties: selector: description: |- Selector is a label query over persistent volume claims that are to be grouped together for snapshotting. This labelSelector will be used to match the label added to a PVC. If the label is added or removed to a volume after a group snapshot is created, the existing group snapshots won't be modified. Once a VolumeGroupSnapshotContent is created and the sidecar starts to process it, the volume list will not change with retries. properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic x-kubernetes-validations: - message: selector is immutable rule: self == oldSelf volumeGroupSnapshotContentName: description: |- VolumeGroupSnapshotContentName specifies the name of a pre-existing VolumeGroupSnapshotContent object representing an existing volume group snapshot. This field should be set if the volume group snapshot already exists and only needs a representation in Kubernetes. This field is immutable. type: string x-kubernetes-validations: - message: volumeGroupSnapshotContentName is immutable rule: self == oldSelf type: object x-kubernetes-validations: - message: selector is required once set rule: '!has(oldSelf.selector) || has(self.selector)' - message: volumeGroupSnapshotContentName is required once set rule: '!has(oldSelf.volumeGroupSnapshotContentName) || has(self.volumeGroupSnapshotContentName)' - message: exactly one of selector and volumeGroupSnapshotContentName must be set rule: (has(self.selector) && !has(self.volumeGroupSnapshotContentName)) || (!has(self.selector) && has(self.volumeGroupSnapshotContentName)) volumeGroupSnapshotClassName: description: |- VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass requested by the VolumeGroupSnapshot. VolumeGroupSnapshotClassName may be left nil to indicate that the default class will be used. Empty string is not allowed for this field. type: string x-kubernetes-validations: - message: volumeGroupSnapshotClassName must not be the empty string when set rule: size(self) > 0 required: - source type: object status: description: |- Status represents the current information of a group snapshot. Consumers must verify binding between VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent point to each other) before using this object. properties: boundVolumeGroupSnapshotContentName: description: |- BoundVolumeGroupSnapshotContentName is the name of the VolumeGroupSnapshotContent object to which this VolumeGroupSnapshot object intends to bind to. If not specified, it indicates that the VolumeGroupSnapshot object has not been successfully bound to a VolumeGroupSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent point at each other) before using this object. type: string x-kubernetes-validations: - message: boundVolumeGroupSnapshotContentName is immutable once set rule: self == oldSelf creationTime: description: |- CreationTime is the timestamp when the point-in-time group snapshot is taken by the underlying storage system. If not specified, it may indicate that the creation time of the group snapshot is unknown. This field is updated based on the CreationTime field in VolumeGroupSnapshotContentStatus format: date-time type: string error: description: |- Error is the last observed error during group snapshot creation, if any. This field could be helpful to upper level controllers (i.e., application controller) to decide whether they should continue on waiting for the group snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurs during the group snapshot creation. Upon success, this error field will be cleared. properties: message: description: |- message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: |- ReadyToUse indicates if all the individual snapshots in the group are ready to be used to restore a group of volumes. ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. If not specified, it means the readiness of a group snapshot is unknown. type: boolean type: object required: - spec type: object served: true storage: true subresources: status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-csi/external-snapshotter/pull/814 controller-gen.kubebuilder.io/version: v0.15.0 name: volumesnapshotclasses.snapshot.storage.k8s.io spec: group: snapshot.storage.k8s.io names: kind: VolumeSnapshotClass listKind: VolumeSnapshotClassList plural: volumesnapshotclasses shortNames: - vsclass - vsclasses singular: volumesnapshotclass scope: Cluster versions: - additionalPrinterColumns: - jsonPath: .driver name: Driver type: string - description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. jsonPath: .deletionPolicy name: DeletionPolicy type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- VolumeSnapshotClass specifies parameters that a underlying storage system uses when creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses are non-namespaced properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string deletionPolicy: description: |- deletionPolicy determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. Required. enum: - Delete - Retain type: string driver: description: |- driver is the name of the storage driver that handles this VolumeSnapshotClass. Required. type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object parameters: additionalProperties: type: string description: |- parameters is a key-value map with storage driver specific parameters for creating snapshots. These values are opaque to Kubernetes. type: object required: - deletionPolicy - driver type: object served: true storage: true subresources: {} - additionalPrinterColumns: - jsonPath: .driver name: Driver type: string - description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. jsonPath: .deletionPolicy name: DeletionPolicy type: string - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true deprecationWarning: snapshot.storage.k8s.io/v1beta1 VolumeSnapshotClass is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshotClass name: v1beta1 schema: openAPIV3Schema: description: VolumeSnapshotClass specifies parameters that a underlying storage system uses when creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses are non-namespaced properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string deletionPolicy: description: deletionPolicy determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. Required. enum: - Delete - Retain type: string driver: description: driver is the name of the storage driver that handles this VolumeSnapshotClass. Required. type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string parameters: additionalProperties: type: string description: parameters is a key-value map with storage driver specific parameters for creating snapshots. These values are opaque to Kubernetes. type: object required: - deletionPolicy - driver type: object served: false storage: false subresources: {} status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-csi/external-snapshotter/pull/955 controller-gen.kubebuilder.io/version: v0.15.0 name: volumesnapshotcontents.snapshot.storage.k8s.io spec: group: snapshot.storage.k8s.io names: kind: VolumeSnapshotContent listKind: VolumeSnapshotContentList plural: volumesnapshotcontents shortNames: - vsc - vscs singular: volumesnapshotcontent scope: Cluster versions: - additionalPrinterColumns: - description: Indicates if the snapshot is ready to be used to restore a volume. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: Represents the complete size of the snapshot in bytes jsonPath: .status.restoreSize name: RestoreSize type: integer - description: Determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. jsonPath: .spec.deletionPolicy name: DeletionPolicy type: string - description: Name of the CSI driver used to create the physical snapshot on the underlying storage system. jsonPath: .spec.driver name: Driver type: string - description: Name of the VolumeSnapshotClass to which this snapshot belongs. jsonPath: .spec.volumeSnapshotClassName name: VolumeSnapshotClass type: string - description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. jsonPath: .spec.volumeSnapshotRef.name name: VolumeSnapshot type: string - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. jsonPath: .spec.volumeSnapshotRef.namespace name: VolumeSnapshotNamespace type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- VolumeSnapshotContent represents the actual "on-disk" snapshot object in the underlying storage system properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- spec defines properties of a VolumeSnapshotContent created by the underlying storage system. Required. properties: deletionPolicy: description: |- deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. For dynamically provisioned snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeSnapshotContent object. Required. enum: - Delete - Retain type: string driver: description: |- driver is the name of the CSI driver used to create the physical snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. type: string source: description: |- source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. properties: snapshotHandle: description: |- snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. type: string x-kubernetes-validations: - message: snapshotHandle is immutable rule: self == oldSelf volumeHandle: description: |- volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot should be dynamically taken from. This field is immutable. type: string x-kubernetes-validations: - message: volumeHandle is immutable rule: self == oldSelf type: object x-kubernetes-validations: - message: volumeHandle is required once set rule: '!has(oldSelf.volumeHandle) || has(self.volumeHandle)' - message: snapshotHandle is required once set rule: '!has(oldSelf.snapshotHandle) || has(self.snapshotHandle)' - message: exactly one of volumeHandle and snapshotHandle must be set rule: (has(self.volumeHandle) && !has(self.snapshotHandle)) || (!has(self.volumeHandle) && has(self.snapshotHandle)) sourceVolumeMode: description: |- SourceVolumeMode is the mode of the volume whose snapshot is taken. Can be either “Filesystem” or “Block”. If not specified, it indicates the source volume's mode is unknown. This field is immutable. This field is an alpha field. type: string x-kubernetes-validations: - message: sourceVolumeMode is immutable rule: self == oldSelf volumeSnapshotClassName: description: |- name of the VolumeSnapshotClass from which this snapshot was (or will be) created. Note that after provisioning, the VolumeSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. type: string volumeSnapshotRef: description: |- volumeSnapshotRef specifies the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to this VolumeSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent object, name and namespace of the VolumeSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. properties: apiVersion: description: API version of the referent. type: string fieldPath: description: |- If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future. type: string kind: description: |- Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string name: description: |- Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string namespace: description: |- Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ type: string resourceVersion: description: |- Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency type: string uid: description: |- UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids type: string type: object x-kubernetes-map-type: atomic x-kubernetes-validations: - message: both spec.volumeSnapshotRef.name and spec.volumeSnapshotRef.namespace must be set rule: has(self.name) && has(self.__namespace__) required: - deletionPolicy - driver - source - volumeSnapshotRef type: object x-kubernetes-validations: - message: sourceVolumeMode is required once set rule: '!has(oldSelf.sourceVolumeMode) || has(self.sourceVolumeMode)' status: description: status represents the current information of a snapshot. properties: creationTime: description: |- creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it indicates the creation time is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command `date +%s%N` returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. format: int64 type: integer error: description: |- error is the last observed error during snapshot creation, if any. Upon success after retry, this error field will be cleared. properties: message: description: |- message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: |- readyToUse indicates if a snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. type: boolean restoreSize: description: |- restoreSize represents the complete size of the snapshot in bytes. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. format: int64 minimum: 0 type: integer snapshotHandle: description: |- snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. If not specified, it indicates that dynamic snapshot creation has either failed or it is still in progress. type: string volumeGroupSnapshotHandle: description: |- VolumeGroupSnapshotHandle is the CSI "group_snapshot_id" of a group snapshot on the underlying storage system. type: string type: object required: - spec type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - description: Indicates if the snapshot is ready to be used to restore a volume. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: Represents the complete size of the snapshot in bytes jsonPath: .status.restoreSize name: RestoreSize type: integer - description: Determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. jsonPath: .spec.deletionPolicy name: DeletionPolicy type: string - description: Name of the CSI driver used to create the physical snapshot on the underlying storage system. jsonPath: .spec.driver name: Driver type: string - description: Name of the VolumeSnapshotClass to which this snapshot belongs. jsonPath: .spec.volumeSnapshotClassName name: VolumeSnapshotClass type: string - description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. jsonPath: .spec.volumeSnapshotRef.name name: VolumeSnapshot type: string - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. jsonPath: .spec.volumeSnapshotRef.namespace name: VolumeSnapshotNamespace type: string - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true deprecationWarning: snapshot.storage.k8s.io/v1beta1 VolumeSnapshotContent is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshotContent name: v1beta1 schema: openAPIV3Schema: description: VolumeSnapshotContent represents the actual "on-disk" snapshot object in the underlying storage system properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string spec: description: spec defines properties of a VolumeSnapshotContent created by the underlying storage system. Required. properties: deletionPolicy: description: deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. For dynamically provisioned snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeSnapshotContent object. Required. enum: - Delete - Retain type: string driver: description: driver is the name of the CSI driver used to create the physical snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. type: string source: description: source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. properties: snapshotHandle: description: snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. type: string volumeHandle: description: volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot should be dynamically taken from. This field is immutable. type: string type: object volumeSnapshotClassName: description: name of the VolumeSnapshotClass from which this snapshot was (or will be) created. Note that after provisioning, the VolumeSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. type: string volumeSnapshotRef: description: volumeSnapshotRef specifies the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to this VolumeSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent object, name and namespace of the VolumeSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. properties: apiVersion: description: API version of the referent. type: string fieldPath: description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.' type: string kind: description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string name: description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string namespace: description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' type: string resourceVersion: description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' type: string uid: description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' type: string type: object required: - deletionPolicy - driver - source - volumeSnapshotRef type: object status: description: status represents the current information of a snapshot. properties: creationTime: description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it indicates the creation time is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command `date +%s%N` returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. format: int64 type: integer error: description: error is the last observed error during snapshot creation, if any. Upon success after retry, this error field will be cleared. properties: message: description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: readyToUse indicates if a snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. type: boolean restoreSize: description: restoreSize represents the complete size of the snapshot in bytes. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. format: int64 minimum: 0 type: integer snapshotHandle: description: snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. If not specified, it indicates that dynamic snapshot creation has either failed or it is still in progress. type: string type: object required: - spec type: object served: false storage: false subresources: status: {} status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-csi/external-snapshotter/pull/814 controller-gen.kubebuilder.io/version: v0.15.0 name: volumesnapshots.snapshot.storage.k8s.io spec: group: snapshot.storage.k8s.io names: kind: VolumeSnapshot listKind: VolumeSnapshotList plural: volumesnapshots shortNames: - vs singular: volumesnapshot scope: Namespaced versions: - additionalPrinterColumns: - description: Indicates if the snapshot is ready to be used to restore a volume. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: If a new snapshot needs to be created, this contains the name of the source PVC from which this snapshot was (or will be) created. jsonPath: .spec.source.persistentVolumeClaimName name: SourcePVC type: string - description: If a snapshot already exists, this contains the name of the existing VolumeSnapshotContent object representing the existing snapshot. jsonPath: .spec.source.volumeSnapshotContentName name: SourceSnapshotContent type: string - description: Represents the minimum size of volume required to rehydrate from this snapshot. jsonPath: .status.restoreSize name: RestoreSize type: string - description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. jsonPath: .spec.volumeSnapshotClassName name: SnapshotClass type: string - description: Name of the VolumeSnapshotContent object to which the VolumeSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. jsonPath: .status.boundVolumeSnapshotContentName name: SnapshotContent type: string - description: Timestamp when the point-in-time snapshot was taken by the underlying storage system. jsonPath: .status.creationTime name: CreationTime type: date - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- VolumeSnapshot is a user's request for either creating a point-in-time snapshot of a persistent volume, or binding to a pre-existing snapshot. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: |- spec defines the desired characteristics of a snapshot requested by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots Required. properties: source: description: |- source specifies where a snapshot will be created from. This field is immutable after creation. Required. properties: persistentVolumeClaimName: description: |- persistentVolumeClaimName specifies the name of the PersistentVolumeClaim object representing the volume from which a snapshot should be created. This PVC is assumed to be in the same namespace as the VolumeSnapshot object. This field should be set if the snapshot does not exists, and needs to be created. This field is immutable. type: string x-kubernetes-validations: - message: persistentVolumeClaimName is immutable rule: self == oldSelf volumeSnapshotContentName: description: |- volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent object representing an existing volume snapshot. This field should be set if the snapshot already exists and only needs a representation in Kubernetes. This field is immutable. type: string x-kubernetes-validations: - message: volumeSnapshotContentName is immutable rule: self == oldSelf type: object x-kubernetes-validations: - message: persistentVolumeClaimName is required once set rule: '!has(oldSelf.persistentVolumeClaimName) || has(self.persistentVolumeClaimName)' - message: volumeSnapshotContentName is required once set rule: '!has(oldSelf.volumeSnapshotContentName) || has(self.volumeSnapshotContentName)' - message: exactly one of volumeSnapshotContentName and persistentVolumeClaimName must be set rule: (has(self.volumeSnapshotContentName) && !has(self.persistentVolumeClaimName)) || (!has(self.volumeSnapshotContentName) && has(self.persistentVolumeClaimName)) volumeSnapshotClassName: description: |- VolumeSnapshotClassName is the name of the VolumeSnapshotClass requested by the VolumeSnapshot. VolumeSnapshotClassName may be left nil to indicate that the default SnapshotClass should be used. A given cluster may have multiple default Volume SnapshotClasses: one default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, VolumeSnapshotSource will be checked to figure out what the associated CSI Driver is, and the default VolumeSnapshotClass associated with that CSI Driver will be used. If more than one VolumeSnapshotClass exist for a given CSI Driver and more than one have been marked as default, CreateSnapshot will fail and generate an event. Empty string is not allowed for this field. type: string x-kubernetes-validations: - message: volumeSnapshotClassName must not be the empty string when set rule: size(self) > 0 required: - source type: object status: description: |- status represents the current information of a snapshot. Consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object. properties: boundVolumeSnapshotContentName: description: |- boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent object to which this VolumeSnapshot object intends to bind to. If not specified, it indicates that the VolumeSnapshot object has not been successfully bound to a VolumeSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object. type: string creationTime: description: |- creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it may indicate that the creation time of the snapshot is unknown. format: date-time type: string error: description: |- error is the last observed error during snapshot creation, if any. This field could be helpful to upper level controllers(i.e., application controller) to decide whether they should continue on waiting for the snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurs during the snapshot creation. Upon success, this error field will be cleared. properties: message: description: |- message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information. type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: |- readyToUse indicates if the snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. type: boolean restoreSize: description: |- restoreSize represents the minimum size of volume required to create a volume from this snapshot. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ type: string x-kubernetes-int-or-string: true volumeGroupSnapshotName: description: |- VolumeGroupSnapshotName is the name of the VolumeGroupSnapshot of which this VolumeSnapshot is a part of. type: string type: object required: - spec type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - description: Indicates if the snapshot is ready to be used to restore a volume. jsonPath: .status.readyToUse name: ReadyToUse type: boolean - description: If a new snapshot needs to be created, this contains the name of the source PVC from which this snapshot was (or will be) created. jsonPath: .spec.source.persistentVolumeClaimName name: SourcePVC type: string - description: If a snapshot already exists, this contains the name of the existing VolumeSnapshotContent object representing the existing snapshot. jsonPath: .spec.source.volumeSnapshotContentName name: SourceSnapshotContent type: string - description: Represents the minimum size of volume required to rehydrate from this snapshot. jsonPath: .status.restoreSize name: RestoreSize type: string - description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. jsonPath: .spec.volumeSnapshotClassName name: SnapshotClass type: string - description: Name of the VolumeSnapshotContent object to which the VolumeSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. jsonPath: .status.boundVolumeSnapshotContentName name: SnapshotContent type: string - description: Timestamp when the point-in-time snapshot was taken by the underlying storage system. jsonPath: .status.creationTime name: CreationTime type: date - jsonPath: .metadata.creationTimestamp name: Age type: date deprecated: true deprecationWarning: snapshot.storage.k8s.io/v1beta1 VolumeSnapshot is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshot name: v1beta1 schema: openAPIV3Schema: description: VolumeSnapshot is a user's request for either creating a point-in-time snapshot of a persistent volume, or binding to a pre-existing snapshot. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string spec: description: 'spec defines the desired characteristics of a snapshot requested by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots Required.' properties: source: description: source specifies where a snapshot will be created from. This field is immutable after creation. Required. properties: persistentVolumeClaimName: description: persistentVolumeClaimName specifies the name of the PersistentVolumeClaim object representing the volume from which a snapshot should be created. This PVC is assumed to be in the same namespace as the VolumeSnapshot object. This field should be set if the snapshot does not exists, and needs to be created. This field is immutable. type: string volumeSnapshotContentName: description: volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent object representing an existing volume snapshot. This field should be set if the snapshot already exists and only needs a representation in Kubernetes. This field is immutable. type: string type: object volumeSnapshotClassName: description: 'VolumeSnapshotClassName is the name of the VolumeSnapshotClass requested by the VolumeSnapshot. VolumeSnapshotClassName may be left nil to indicate that the default SnapshotClass should be used. A given cluster may have multiple default Volume SnapshotClasses: one default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, VolumeSnapshotSource will be checked to figure out what the associated CSI Driver is, and the default VolumeSnapshotClass associated with that CSI Driver will be used. If more than one VolumeSnapshotClass exist for a given CSI Driver and more than one have been marked as default, CreateSnapshot will fail and generate an event. Empty string is not allowed for this field.' type: string required: - source type: object status: description: status represents the current information of a snapshot. Consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object. properties: boundVolumeSnapshotContentName: description: 'boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent object to which this VolumeSnapshot object intends to bind to. If not specified, it indicates that the VolumeSnapshot object has not been successfully bound to a VolumeSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object.' type: string creationTime: description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it may indicate that the creation time of the snapshot is unknown. format: date-time type: string error: description: error is the last observed error during snapshot creation, if any. This field could be helpful to upper level controllers(i.e., application controller) to decide whether they should continue on waiting for the snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurs during the snapshot creation. Upon success, this error field will be cleared. properties: message: description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' type: string time: description: time is the timestamp when the error was encountered. format: date-time type: string type: object readyToUse: description: readyToUse indicates if the snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. type: boolean restoreSize: description: restoreSize represents the minimum size of volume required to create a volume from this snapshot. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ type: string x-kubernetes-int-or-string: true type: object required: - spec type: object served: false storage: false subresources: status: {} status: acceptedNames: kind: "" plural: "" conditions: [] storedVersions: [] ================================================ FILE: cluster/homelab/crds/external-snapshotter/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - crds.yaml ================================================ FILE: cluster/homelab/crds/gateway-api/crds.yaml ================================================ # Generated with: kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.4.0" apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard labels: gateway.networking.k8s.io/policy: Direct name: backendtlspolicies.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api kind: BackendTLSPolicy listKind: BackendTLSPolicyList plural: backendtlspolicies shortNames: - btlspolicy singular: backendtlspolicy scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- BackendTLSPolicy provides a way to configure how a Gateway connects to a Backend via TLS. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of BackendTLSPolicy. properties: options: additionalProperties: description: |- AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. maxLength: 4096 minLength: 0 type: string description: |- Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites. A set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API. Support: Implementation-specific maxProperties: 16 type: object targetRefs: description: |- TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy. TargetRefs must be _distinct_. This means either that: * They select different targets. If this is the case, then targetRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, and `name` must be unique across all targetRef entries in the BackendTLSPolicy. * They select different sectionNames in the same target. When more than one BackendTLSPolicy selects the same target and sectionName, implementations MUST determine precedence using the following criteria, continuing on ties: * The older policy by creation timestamp takes precedence. For example, a policy with a creation timestamp of "2021-07-15 01:02:03" MUST be given precedence over a policy with a creation timestamp of "2021-07-15 01:02:04". * The policy appearing first in alphabetical order by {name}. For example, a policy named `bar` is given precedence over a policy named `baz`. For any BackendTLSPolicy that does not take precedence, the implementation MUST ensure the `Accepted` Condition is set to `status: False`, with Reason `Conflicted`. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource items: description: |- LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a direct policy to. This should be used as part of Policy resources that can target single resources. For more information on how this policy attachment mode works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API. Note: This should only be used for direct policy attachment when references to SectionName are actually needed. In all other cases, LocalPolicyTargetReference should be used. properties: group: description: Group is the group of the target resource. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the target resource. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the target resource. maxLength: 253 minLength: 1 type: string sectionName: description: |- SectionName is the name of a section within the target resource. When unspecified, this targetRef targets the entire resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name * HTTPRoute: HTTPRouteRule name * Service: Port name If a SectionName is specified, but does not exist on the targeted object, the Policy must fail to attach, and the policy implementation should record a `ResolvedRefs` or similar Condition in the Policy's status. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - group - kind - name type: object maxItems: 16 minItems: 1 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when targetRefs includes 2 or more references to the same target rule: "self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" - message: sectionName must be unique when targetRefs includes 2 or more references to the same target rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)))) validation: description: Validation contains backend TLS validation configuration. properties: caCertificateRefs: description: |- CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod. If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation. A CACertificateRef is invalid if: * It refers to a resource that cannot be resolved (e.g., the referenced resource does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` and the Message of the Condition must indicate which reference is invalid and why. * It refers to an unknown or unsupported kind of resource. In this case, the Reason must be set to `InvalidKind` and the Message of the Condition must explain which kind of resource is unknown or unsupported. * It refers to a resource in another namespace. This may change in future spec updates. Implementations MAY choose to perform further validation of the certificate content (e.g., checking expiry or enforcing specific formats). In such cases, an implementation-specific Reason and Message must be set for the invalid reference. In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason and Message that indicate the cause of the error. Connections using an invalid CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. If ALL CACertificateRefs are invalid, the implementation MUST also ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `NoValidCACertificate`. A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific. Support: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`. Support: Implementation-specific - More than one reference, other kinds of resources, or a single reference that includes multiple certificates. items: description: |- LocalObjectReference identifies an API object within the namespace of the referrer. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object. properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object maxItems: 8 type: array x-kubernetes-list-type: atomic hostname: description: |- Hostname is used for two purposes in the connection between Gateways and backends: 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. 3. If SubjectAltNames are specified, Hostname can be used for certificate selection but MUST NOT be used for authentication. If you want to use the value of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string subjectAltNames: description: |- SubjectAltNames contains one or more Subject Alternative Names. When specified the certificate served from the backend MUST have at least one Subject Alternate Name matching one of the specified SubjectAltNames. Support: Extended items: description: SubjectAltName represents Subject Alternative Name. properties: hostname: description: |- Hostname contains Subject Alternative Name specified in DNS name format. Required when Type is set to Hostname, ignored otherwise. Support: Core maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string type: description: |- Type determines the format of the Subject Alternative Name. Always required. Support: Core enum: - Hostname - URI type: string uri: description: |- URI contains Subject Alternative Name specified in a full URI format. It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". Required when Type is set to URI, ignored otherwise. Support: Core maxLength: 253 minLength: 1 pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? type: string required: - type type: object x-kubernetes-validations: - message: SubjectAltName element must contain Hostname, if Type is set to Hostname rule: '!(self.type == "Hostname" && (!has(self.hostname) || self.hostname == ""))' - message: SubjectAltName element must not contain Hostname, if Type is not set to Hostname rule: '!(self.type != "Hostname" && has(self.hostname) && self.hostname != "")' - message: SubjectAltName element must contain URI, if Type is set to URI rule: '!(self.type == "URI" && (!has(self.uri) || self.uri == ""))' - message: SubjectAltName element must not contain URI, if Type is not set to URI rule: '!(self.type != "URI" && has(self.uri) && self.uri != "")' maxItems: 5 type: array x-kubernetes-list-type: atomic wellKnownCACertificates: description: |- WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod. If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field, or the supplied value is not recognized, the implementation MUST ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `Invalid`. Support: Implementation-specific enum: - System type: string required: - hostname type: object x-kubernetes-validations: - message: must not contain both CACertificateRefs and WellKnownCACertificates rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates != "")' - message: must specify either CACertificateRefs or WellKnownCACertificates rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates != "") required: - targetRefs - validation type: object status: description: Status defines the current state of BackendTLSPolicy. properties: ancestors: description: |- Ancestors is a list of ancestor resources (usually Gateways) that are associated with the policy, and the status of the policy with respect to each ancestor. When this policy attaches to a parent, the controller that manages the parent and the ancestors MUST add an entry to this list when the controller first sees the policy and SHOULD update the entry as appropriate when the relevant ancestor is modified. Note that choosing the relevant ancestor is left to the Policy designers; an important part of Policy design is designing the right object level at which to namespace this status. Note also that implementations MUST ONLY populate ancestor status for the Ancestor resources they are responsible for. Implementations MUST use the ControllerName field to uniquely identify the entries in this list that they are responsible for. Note that to achieve this, the list of PolicyAncestorStatus structs MUST be treated as a map with a composite key, made up of the AncestorRef and ControllerName fields combined. A maximum of 16 ancestors will be represented in this list. An empty list means the Policy is not relevant for any ancestors. If this slice is full, implementations MUST NOT add further entries. Instead they MUST consider the policy unimplementable and signal that on any related resources such as the ancestor that would be referenced here. For example, if this list was full on BackendTLSPolicy, no additional Gateways would be able to reference the Service targeted by the BackendTLSPolicy. items: description: |- PolicyAncestorStatus describes the status of a route with respect to an associated Ancestor. Ancestors refer to objects that are either the Target of a policy or above it in terms of object hierarchy. For example, if a policy targets a Service, the Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most useful object to place Policy status on, so we recommend that implementations SHOULD use Gateway as the PolicyAncestorStatus object unless the designers have a _very_ good reason otherwise. In the context of policy attachment, the Ancestor is used to distinguish which resource results in a distinct application of this policy. For example, if a policy targets a Service, it may have a distinct result per attached Gateway. Policies targeting the same resource may have different effects depending on the ancestors of those resources. For example, different Gateways targeting the same Service may have different capabilities, especially if they have different underlying implementations. For example, in BackendTLSPolicy, the Policy attaches to a Service that is used as a backend in a HTTPRoute that is itself attached to a Gateway. In this case, the relevant object for status is the Gateway, and that is the ancestor object referred to in this status. Note that a parent is also an ancestor, so for objects where the parent is the relevant object for status, this struct SHOULD still be used. This struct is intended to be used in a slice that's effectively a map, with a composite key made up of the AncestorRef and the ControllerName. properties: ancestorRef: description: |- AncestorRef corresponds with a ParentRef in the spec that this PolicyAncestorStatus struct describes the status of. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object conditions: description: Conditions describes the status of the Policy with respect to the given Ancestor. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 minItems: 1 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map controllerName: description: |- ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. Example: "example.net/gateway-controller". The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string required: - ancestorRef - conditions - controllerName type: object maxItems: 16 type: array x-kubernetes-list-type: atomic required: - ancestors type: object required: - spec type: object served: true storage: true subresources: status: {} - deprecated: true deprecationWarning: The v1alpha3 version of BackendTLSPolicy has been deprecated and will be removed in a future release of the API. Please upgrade to v1. name: v1alpha3 schema: openAPIV3Schema: description: |- BackendTLSPolicy provides a way to configure how a Gateway connects to a Backend via TLS. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of BackendTLSPolicy. properties: options: additionalProperties: description: |- AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. maxLength: 4096 minLength: 0 type: string description: |- Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites. A set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API. Support: Implementation-specific maxProperties: 16 type: object targetRefs: description: |- TargetRefs identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy. TargetRefs must be _distinct_. This means either that: * They select different targets. If this is the case, then targetRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, and `name` must be unique across all targetRef entries in the BackendTLSPolicy. * They select different sectionNames in the same target. When more than one BackendTLSPolicy selects the same target and sectionName, implementations MUST determine precedence using the following criteria, continuing on ties: * The older policy by creation timestamp takes precedence. For example, a policy with a creation timestamp of "2021-07-15 01:02:03" MUST be given precedence over a policy with a creation timestamp of "2021-07-15 01:02:04". * The policy appearing first in alphabetical order by {name}. For example, a policy named `bar` is given precedence over a policy named `baz`. For any BackendTLSPolicy that does not take precedence, the implementation MUST ensure the `Accepted` Condition is set to `status: False`, with Reason `Conflicted`. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource items: description: |- LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a direct policy to. This should be used as part of Policy resources that can target single resources. For more information on how this policy attachment mode works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API. Note: This should only be used for direct policy attachment when references to SectionName are actually needed. In all other cases, LocalPolicyTargetReference should be used. properties: group: description: Group is the group of the target resource. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the target resource. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the target resource. maxLength: 253 minLength: 1 type: string sectionName: description: |- SectionName is the name of a section within the target resource. When unspecified, this targetRef targets the entire resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name * HTTPRoute: HTTPRouteRule name * Service: Port name If a SectionName is specified, but does not exist on the targeted object, the Policy must fail to attach, and the policy implementation should record a `ResolvedRefs` or similar Condition in the Policy's status. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - group - kind - name type: object maxItems: 16 minItems: 1 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when targetRefs includes 2 or more references to the same target rule: "self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" - message: sectionName must be unique when targetRefs includes 2 or more references to the same target rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)))) validation: description: Validation contains backend TLS validation configuration. properties: caCertificateRefs: description: |- CACertificateRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod. If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If CACertificateRefs is empty or unspecified, the configuration for WellKnownCACertificates MUST be honored instead if supported by the implementation. A CACertificateRef is invalid if: * It refers to a resource that cannot be resolved (e.g., the referenced resource does not exist) or is misconfigured (e.g., a ConfigMap does not contain a key named `ca.crt`). In this case, the Reason must be set to `InvalidCACertificateRef` and the Message of the Condition must indicate which reference is invalid and why. * It refers to an unknown or unsupported kind of resource. In this case, the Reason must be set to `InvalidKind` and the Message of the Condition must explain which kind of resource is unknown or unsupported. * It refers to a resource in another namespace. This may change in future spec updates. Implementations MAY choose to perform further validation of the certificate content (e.g., checking expiry or enforcing specific formats). In such cases, an implementation-specific Reason and Message must be set for the invalid reference. In all cases, the implementation MUST ensure the `ResolvedRefs` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason and Message that indicate the cause of the error. Connections using an invalid CACertificateRef MUST fail, and the client MUST receive an HTTP 5xx error response. If ALL CACertificateRefs are invalid, the implementation MUST also ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `NoValidCACertificate`. A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific. Support: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`. Support: Implementation-specific - More than one reference, other kinds of resources, or a single reference that includes multiple certificates. items: description: |- LocalObjectReference identifies an API object within the namespace of the referrer. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object. properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object maxItems: 8 type: array x-kubernetes-list-type: atomic hostname: description: |- Hostname is used for two purposes in the connection between Gateways and backends: 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified. 3. If SubjectAltNames are specified, Hostname can be used for certificate selection but MUST NOT be used for authentication. If you want to use the value of the Hostname field for authentication, you MUST add it to the SubjectAltNames list. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string subjectAltNames: description: |- SubjectAltNames contains one or more Subject Alternative Names. When specified the certificate served from the backend MUST have at least one Subject Alternate Name matching one of the specified SubjectAltNames. Support: Extended items: description: SubjectAltName represents Subject Alternative Name. properties: hostname: description: |- Hostname contains Subject Alternative Name specified in DNS name format. Required when Type is set to Hostname, ignored otherwise. Support: Core maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string type: description: |- Type determines the format of the Subject Alternative Name. Always required. Support: Core enum: - Hostname - URI type: string uri: description: |- URI contains Subject Alternative Name specified in a full URI format. It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". Required when Type is set to URI, ignored otherwise. Support: Core maxLength: 253 minLength: 1 pattern: ^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))? type: string required: - type type: object x-kubernetes-validations: - message: SubjectAltName element must contain Hostname, if Type is set to Hostname rule: '!(self.type == "Hostname" && (!has(self.hostname) || self.hostname == ""))' - message: SubjectAltName element must not contain Hostname, if Type is not set to Hostname rule: '!(self.type != "Hostname" && has(self.hostname) && self.hostname != "")' - message: SubjectAltName element must contain URI, if Type is set to URI rule: '!(self.type == "URI" && (!has(self.uri) || self.uri == ""))' - message: SubjectAltName element must not contain URI, if Type is not set to URI rule: '!(self.type != "URI" && has(self.uri) && self.uri != "")' maxItems: 5 type: array x-kubernetes-list-type: atomic wellKnownCACertificates: description: |- WellKnownCACertificates specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod. If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs must be specified with at least one entry for a valid configuration. Only one of CACertificateRefs or WellKnownCACertificates may be specified, not both. If an implementation does not support the WellKnownCACertificates field, or the supplied value is not recognized, the implementation MUST ensure the `Accepted` Condition on the BackendTLSPolicy is set to `status: False`, with a Reason `Invalid`. Support: Implementation-specific enum: - System type: string required: - hostname type: object x-kubernetes-validations: - message: must not contain both CACertificateRefs and WellKnownCACertificates rule: '!(has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 && has(self.wellKnownCACertificates) && self.wellKnownCACertificates != "")' - message: must specify either CACertificateRefs or WellKnownCACertificates rule: (has(self.caCertificateRefs) && size(self.caCertificateRefs) > 0 || has(self.wellKnownCACertificates) && self.wellKnownCACertificates != "") required: - targetRefs - validation type: object status: description: Status defines the current state of BackendTLSPolicy. properties: ancestors: description: |- Ancestors is a list of ancestor resources (usually Gateways) that are associated with the policy, and the status of the policy with respect to each ancestor. When this policy attaches to a parent, the controller that manages the parent and the ancestors MUST add an entry to this list when the controller first sees the policy and SHOULD update the entry as appropriate when the relevant ancestor is modified. Note that choosing the relevant ancestor is left to the Policy designers; an important part of Policy design is designing the right object level at which to namespace this status. Note also that implementations MUST ONLY populate ancestor status for the Ancestor resources they are responsible for. Implementations MUST use the ControllerName field to uniquely identify the entries in this list that they are responsible for. Note that to achieve this, the list of PolicyAncestorStatus structs MUST be treated as a map with a composite key, made up of the AncestorRef and ControllerName fields combined. A maximum of 16 ancestors will be represented in this list. An empty list means the Policy is not relevant for any ancestors. If this slice is full, implementations MUST NOT add further entries. Instead they MUST consider the policy unimplementable and signal that on any related resources such as the ancestor that would be referenced here. For example, if this list was full on BackendTLSPolicy, no additional Gateways would be able to reference the Service targeted by the BackendTLSPolicy. items: description: |- PolicyAncestorStatus describes the status of a route with respect to an associated Ancestor. Ancestors refer to objects that are either the Target of a policy or above it in terms of object hierarchy. For example, if a policy targets a Service, the Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most useful object to place Policy status on, so we recommend that implementations SHOULD use Gateway as the PolicyAncestorStatus object unless the designers have a _very_ good reason otherwise. In the context of policy attachment, the Ancestor is used to distinguish which resource results in a distinct application of this policy. For example, if a policy targets a Service, it may have a distinct result per attached Gateway. Policies targeting the same resource may have different effects depending on the ancestors of those resources. For example, different Gateways targeting the same Service may have different capabilities, especially if they have different underlying implementations. For example, in BackendTLSPolicy, the Policy attaches to a Service that is used as a backend in a HTTPRoute that is itself attached to a Gateway. In this case, the relevant object for status is the Gateway, and that is the ancestor object referred to in this status. Note that a parent is also an ancestor, so for objects where the parent is the relevant object for status, this struct SHOULD still be used. This struct is intended to be used in a slice that's effectively a map, with a composite key made up of the AncestorRef and the ControllerName. properties: ancestorRef: description: |- AncestorRef corresponds with a ParentRef in the spec that this PolicyAncestorStatus struct describes the status of. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object conditions: description: Conditions describes the status of the Policy with respect to the given Ancestor. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 minItems: 1 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map controllerName: description: |- ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. Example: "example.net/gateway-controller". The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string required: - ancestorRef - conditions - controllerName type: object maxItems: 16 type: array x-kubernetes-list-type: atomic required: - ancestors type: object required: - spec type: object served: false storage: false status: acceptedNames: kind: "" plural: "" conditions: null storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: gatewayclasses.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api kind: GatewayClass listKind: GatewayClassList plural: gatewayclasses shortNames: - gc singular: gatewayclass scope: Cluster versions: - additionalPrinterColumns: - jsonPath: .spec.controllerName name: Controller type: string - jsonPath: .status.conditions[?(@.type=="Accepted")].status name: Accepted type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .spec.description name: Description priority: 1 type: string name: v1 schema: openAPIV3Schema: description: |- GatewayClass describes a class of Gateways available to the user for creating Gateway resources. It is recommended that this resource be used as a template for Gateways. This means that a Gateway is based on the state of the GatewayClass at the time it was created and changes to the GatewayClass or associated parameters are not propagated down to existing Gateways. This recommendation is intended to limit the blast radius of changes to GatewayClass or associated parameters. If implementations choose to propagate GatewayClass changes to existing Gateways, that MUST be clearly documented by the implementation. Whenever one or more Gateways are using a GatewayClass, implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the associated GatewayClass. This ensures that a GatewayClass associated with a Gateway is not deleted while in use. GatewayClass is a Cluster level resource. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of GatewayClass. properties: controllerName: description: |- ControllerName is the name of the controller that is managing Gateways of this class. The value of this field MUST be a domain prefixed path. Example: "example.net/gateway-controller". This field is not mutable and cannot be empty. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string x-kubernetes-validations: - message: Value is immutable rule: self == oldSelf description: description: Description helps describe a GatewayClass with more details. maxLength: 64 type: string parametersRef: description: |- ParametersRef is a reference to a resource that contains the configuration parameters corresponding to the GatewayClass. This is optional if the controller does not require any additional configuration. ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, or an implementation-specific custom resource. The resource can be cluster-scoped or namespace-scoped. If the referent cannot be found, refers to an unsupported kind, or when the data within that resource is malformed, the GatewayClass SHOULD be rejected with the "Accepted" status condition set to "False" and an "InvalidParameters" reason. A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified, the merging behavior is implementation specific. It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. Support: Implementation-specific properties: group: description: Group is the group of the referent. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. This field is required when referring to a Namespace-scoped resource and MUST be unset when referring to a Cluster-scoped resource. maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - group - kind - name type: object required: - controllerName type: object status: default: conditions: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted description: |- Status defines the current state of GatewayClass. Implementations MUST populate status on all GatewayClass resources which specify their controller name. properties: conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted description: |- Conditions is the current status from the controller for this GatewayClass. Controllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map supportedFeatures: description: |- SupportedFeatures is the set of features the GatewayClass support. It MUST be sorted in ascending alphabetical order by the Name key. items: properties: name: description: |- FeatureName is used to describe distinct features that are covered by conformance tests. type: string required: - name type: object maxItems: 64 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object required: - spec type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.controllerName name: Controller type: string - jsonPath: .status.conditions[?(@.type=="Accepted")].status name: Accepted type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - jsonPath: .spec.description name: Description priority: 1 type: string name: v1beta1 schema: openAPIV3Schema: description: |- GatewayClass describes a class of Gateways available to the user for creating Gateway resources. It is recommended that this resource be used as a template for Gateways. This means that a Gateway is based on the state of the GatewayClass at the time it was created and changes to the GatewayClass or associated parameters are not propagated down to existing Gateways. This recommendation is intended to limit the blast radius of changes to GatewayClass or associated parameters. If implementations choose to propagate GatewayClass changes to existing Gateways, that MUST be clearly documented by the implementation. Whenever one or more Gateways are using a GatewayClass, implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the associated GatewayClass. This ensures that a GatewayClass associated with a Gateway is not deleted while in use. GatewayClass is a Cluster level resource. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of GatewayClass. properties: controllerName: description: |- ControllerName is the name of the controller that is managing Gateways of this class. The value of this field MUST be a domain prefixed path. Example: "example.net/gateway-controller". This field is not mutable and cannot be empty. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string x-kubernetes-validations: - message: Value is immutable rule: self == oldSelf description: description: Description helps describe a GatewayClass with more details. maxLength: 64 type: string parametersRef: description: |- ParametersRef is a reference to a resource that contains the configuration parameters corresponding to the GatewayClass. This is optional if the controller does not require any additional configuration. ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, or an implementation-specific custom resource. The resource can be cluster-scoped or namespace-scoped. If the referent cannot be found, refers to an unsupported kind, or when the data within that resource is malformed, the GatewayClass SHOULD be rejected with the "Accepted" status condition set to "False" and an "InvalidParameters" reason. A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified, the merging behavior is implementation specific. It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. Support: Implementation-specific properties: group: description: Group is the group of the referent. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. This field is required when referring to a Namespace-scoped resource and MUST be unset when referring to a Cluster-scoped resource. maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - group - kind - name type: object required: - controllerName type: object status: default: conditions: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted description: |- Status defines the current state of GatewayClass. Implementations MUST populate status on all GatewayClass resources which specify their controller name. properties: conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted description: |- Conditions is the current status from the controller for this GatewayClass. Controllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map supportedFeatures: description: |- SupportedFeatures is the set of features the GatewayClass support. It MUST be sorted in ascending alphabetical order by the Name key. items: properties: name: description: |- FeatureName is used to describe distinct features that are covered by conformance tests. type: string required: - name type: object maxItems: 64 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object required: - spec type: object served: true storage: false subresources: status: {} status: acceptedNames: kind: "" plural: "" conditions: null storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: gateways.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api kind: Gateway listKind: GatewayList plural: gateways shortNames: - gtw singular: gateway scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.gatewayClassName name: Class type: string - jsonPath: .status.addresses[*].value name: Address type: string - jsonPath: .status.conditions[?(@.type=="Programmed")].status name: Programmed type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- Gateway represents an instance of a service-traffic handling infrastructure by binding Listeners to a set of IP addresses. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of Gateway. properties: addresses: description: |- Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in an associated entry in GatewayStatus.Conditions. The Addresses field represents a request for the address(es) on the "outside of the Gateway", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to. If no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses. The implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses. Support: Extended items: description: GatewaySpecAddress describes an address that can be bound to a Gateway. oneOf: - properties: type: enum: - IPAddress value: anyOf: - format: ipv4 - format: ipv6 - properties: type: not: enum: - IPAddress properties: type: default: IPAddress description: Type of the address. maxLength: 253 minLength: 1 pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string value: description: |- When a value is unspecified, an implementation SHOULD automatically assign an address matching the requested type if possible. If an implementation does not support an empty value, they MUST set the "Programmed" condition in status to False with a reason of "AddressNotAssigned". Examples: `1.2.3.4`, `128::1`, `my-ip-address`. maxLength: 253 type: string type: object x-kubernetes-validations: - message: Hostname value must be empty or contain only valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) rule: 'self.type == ''Hostname'' ? (!has(self.value) || self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$""")): true' maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique rule: "self.all(a1, a1.type == 'IPAddress' && has(a1.value) ? self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value == a1.value) : true )" - message: Hostname values must be unique rule: "self.all(a1, a1.type == 'Hostname' && has(a1.value) ? self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value == a1.value) : true )" gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a GatewayClass resource. maxLength: 253 minLength: 1 type: string infrastructure: description: |- Infrastructure defines infrastructure level attributes about this Gateway instance. Support: Extended properties: annotations: additionalProperties: description: |- AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. maxLength: 4096 minLength: 0 type: string description: |- Annotations that SHOULD be applied to any resources created in response to this Gateway. For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. An implementation may chose to add additional implementation-specific annotations as they see fit. Support: Extended maxProperties: 8 type: object x-kubernetes-validations: - message: Annotation keys must be in the form of an optional DNS subdomain prefix followed by a required name segment of up to 63 characters. rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) - message: If specified, the annotation key's prefix must be a DNS subdomain not longer than 253 characters in total. rule: self.all(key, key.split("/")[0].size() < 253) labels: additionalProperties: description: |- LabelValue is the value of a label in the Gateway API. This is used for validation of maps such as Gateway infrastructure labels. This matches the Kubernetes label validation rules: * must be 63 characters or less (can be empty), * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. Valid values include: * MyValue * my.name * 123-my-value maxLength: 63 minLength: 0 pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ type: string description: |- Labels that SHOULD be applied to any resources created in response to this Gateway. For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. For other implementations, this refers to any relevant (implementation specific) "labels" concepts. An implementation may chose to add additional implementation-specific labels as they see fit. If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels change, it SHOULD clearly warn about this behavior in documentation. Support: Extended maxProperties: 8 type: object x-kubernetes-validations: - message: Label keys must be in the form of an optional DNS subdomain prefix followed by a required name segment of up to 63 characters. rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) - message: If specified, the label key's prefix must be a DNS subdomain not longer than 253 characters in total. rule: self.all(key, key.split("/")[0].size() < 253) parametersRef: description: |- ParametersRef is a reference to a resource that contains the configuration parameters corresponding to the Gateway. This is optional if the controller does not require any additional configuration. This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, the merging behavior is implementation specific. It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. If the referent cannot be found, refers to an unsupported kind, or when the data within that resource is malformed, the Gateway SHOULD be rejected with the "Accepted" status condition set to "False" and an "InvalidParameters" reason. Support: Implementation-specific properties: group: description: Group is the group of the referent. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object type: object listeners: description: |- Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At least one Listener MUST be specified. ## Distinct Listeners Each Listener in a set of Listeners (for example, in a single Gateway) MUST be _distinct_, in that a traffic flow MUST be able to be assigned to exactly one listener. (This section uses "set of Listeners" rather than "Listeners in a single Gateway" because implementations MAY merge configuration from multiple Gateways onto a single data plane, and these rules _also_ apply in that case). Practically, this means that each listener in a set MUST have a unique combination of Port, Protocol, and, if supported by the protocol, Hostname. Some combinations of port, protocol, and TLS settings are considered Core support and MUST be supported by implementations based on the objects they support: HTTPRoute 1. HTTPRoute, Port: 80, Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided TLSRoute 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough "Distinct" Listeners have the following property: **The implementation can match inbound requests to a single distinct Listener**. When multiple Listeners share values for fields (for example, two Listeners with the same Port value), the implementation can match requests to only one of the Listeners using other Listener fields. When multiple listeners have the same value for the Protocol field, then each of the Listeners with matching Protocol values MUST have different values for other fields. The set of fields that MUST be different for a Listener differs per protocol. The following rules define the rules for what fields MUST be considered for Listeners to be distinct with each protocol currently defined in the Gateway API spec. The set of listeners that all share a protocol value MUST have _different_ values for _at least one_ of these fields to be distinct: * **HTTP, HTTPS, TLS**: Port, Hostname * **TCP, UDP**: Port One **very** important rule to call out involves what happens when an implementation: * Supports TCP protocol Listeners, as well as HTTP, HTTPS, or TLS protocol Listeners, and * sees HTTP, HTTPS, or TLS protocols with the same `port` as one with TCP Protocol. In this case all the Listeners that share a port with the TCP Listener are not distinct and so MUST NOT be accepted. If an implementation does not support TCP Protocol Listeners, then the previous rule does not apply, and the TCP Listeners SHOULD NOT be accepted. Note that the `tls` field is not used for determining if a listener is distinct, because Listeners that _only_ differ on TLS config will still conflict in all cases. ### Listeners that are distinct only by Hostname When the Listeners are distinct based only on Hostname, inbound request hostnames MUST match from the most specific to least specific Hostname values to choose the correct Listener and its associated set of Routes. Exact matches MUST be processed before wildcard matches, and wildcard matches MUST be processed before fallback (empty Hostname value) matches. For example, `"foo.example.com"` takes precedence over `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. Additionally, if there are multiple wildcard entries, more specific wildcard entries must be processed before less specific wildcard entries. For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. The precise definition here is that the higher the number of dots in the hostname to the right of the wildcard character, the higher the precedence. The wildcard character will match any number of characters _and dots_ to the left, however, so `"*.example.com"` will match both `"foo.bar.example.com"` _and_ `"bar.example.com"`. ## Handling indistinct Listeners If a set of Listeners contains Listeners that are not distinct, then those Listeners are _Conflicted_, and the implementation MUST set the "Conflicted" condition in the Listener Status to "True". The words "indistinct" and "conflicted" are considered equivalent for the purpose of this documentation. Implementations MAY choose to accept a Gateway with some Conflicted Listeners only if they only accept the partial Listener set that contains no Conflicted Listeners. Specifically, an implementation MAY accept a partial Listener set subject to the following rules: * The implementation MUST NOT pick one conflicting Listener as the winner. ALL indistinct Listeners must not be accepted for processing. * At least one distinct Listener MUST be present, or else the Gateway effectively contains _no_ Listeners, and must be rejected from processing as a whole. The implementation MUST set a "ListenersNotValid" condition on the Gateway Status when the Gateway contains Conflicted Listeners whether or not they accept the Gateway. That Condition SHOULD clearly indicate in the Message which Listeners are conflicted, and which are Accepted. Additionally, the Listener status for those listeners SHOULD indicate which Listeners are conflicted and not Accepted. ## General Listener behavior Note that, for all distinct Listeners, requests SHOULD match at most one Listener. For example, if Listeners are defined for "foo.example.com" and "*.example.com", a request to "foo.example.com" SHOULD only be routed using routes attached to the "foo.example.com" Listener (and not the "*.example.com" Listener). This concept is known as "Listener Isolation", and it is an Extended feature of Gateway API. Implementations that do not support Listener Isolation MUST clearly document this, and MUST NOT claim support for the `GatewayHTTPListenerIsolation` feature. Implementations that _do_ support Listener Isolation SHOULD claim support for the Extended `GatewayHTTPListenerIsolation` feature and pass the associated conformance tests. ## Compatible Listeners A Gateway's Listeners are considered _compatible_ if: 1. They are distinct. 2. The implementation can serve them in compliance with the Addresses requirement that all Listeners are available on all assigned addresses. Compatible combinations in Extended support are expected to vary across implementations. A combination that is compatible for one implementation may not be compatible for another. For example, an implementation that cannot serve both TCP and UDP listeners on the same address, or cannot mix HTTPS and generic TLS listens on the same port would not consider those cases compatible, even though they are distinct. Implementations MAY merge separate Gateways onto a single set of Addresses if all Listeners across all Gateways are compatible. In a future release the MinItems=1 requirement MAY be dropped. Support: Core items: description: |- Listener embodies the concept of a logical endpoint where a Gateway accepts network connections. properties: allowedRoutes: default: namespaces: from: Same description: |- AllowedRoutes defines the types of routes that MAY be attached to a Listener and the trusted namespaces where those Route resources MAY be present. Although a client request may match multiple route rules, only one rule may ultimately receive the request. Matching precedence MUST be determined in order of the following criteria: * The most specific match as defined by the Route type. * The oldest Route based on creation timestamp. For example, a Route with a creation timestamp of "2020-09-08 01:02:03" is given precedence over a Route with a creation timestamp of "2020-09-08 01:02:04". * If everything else is equivalent, the Route appearing first in alphabetical order (namespace/name) should be given precedence. For example, foo/bar is given precedence over foo/baz. All valid rules within a Route attached to this Listener should be implemented. Invalid Route rules can be ignored (sometimes that will mean the full Route). If a Route rule transitions from valid to invalid, support for that Route rule should be dropped to ensure consistency. For example, even if a filter specified by a Route rule is invalid, the rest of the rules within that Route should still be supported. Support: Core properties: kinds: description: |- Kinds specifies the groups and kinds of Routes that are allowed to bind to this Gateway Listener. When unspecified or empty, the kinds of Routes selected are determined using the Listener protocol. A RouteGroupKind MUST correspond to kinds of Routes that are compatible with the application protocol specified in the Listener's Protocol field. If an implementation does not support or recognize this resource type, it MUST set the "ResolvedRefs" condition to False for this Listener with the "InvalidRouteKinds" reason. Support: Core items: description: RouteGroupKind indicates the group and kind of a Route resource. properties: group: default: gateway.networking.k8s.io description: Group is the group of the Route. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is the kind of the Route. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string required: - kind type: object maxItems: 8 type: array x-kubernetes-list-type: atomic namespaces: default: from: Same description: |- Namespaces indicates namespaces from which Routes may be attached to this Listener. This is restricted to the namespace of this Gateway by default. Support: Core properties: from: default: Same description: |- From indicates where Routes will be selected for this Gateway. Possible values are: * All: Routes in all namespaces may be used by this Gateway. * Selector: Routes in namespaces selected by the selector may be used by this Gateway. * Same: Only Routes in the same namespace may be used by this Gateway. Support: Core enum: - All - Selector - Same type: string selector: description: |- Selector must be specified when From is set to "Selector". In that case, only Routes in Namespaces matching this Selector will be selected by this Gateway. This field is ignored for other values of "From". Support: Core properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic type: object type: object hostname: description: |- Hostname specifies the virtual hostname to match for protocol types that define this concept. When unspecified, all hostnames are matched. This field is ignored for protocols that don't require hostname based matching. Implementations MUST apply Hostname matching appropriately for each of the following protocols: * TLS: The Listener Hostname MUST match the SNI. * HTTP: The Listener Hostname MUST match the Host header of the request. * HTTPS: The Listener Hostname SHOULD match both the SNI and Host header. Note that this does not require the SNI and Host header to be the same. The semantics of this are described in more detail below. To ensure security, Section 11.1 of RFC-6066 emphasizes that server implementations that rely on SNI hostname matching MUST also verify hostnames within the application protocol. Section 9.1.2 of RFC-7540 provides a mechanism for servers to reject the reuse of a connection by responding with the HTTP 421 Misdirected Request status code. This indicates that the origin server has rejected the request because it appears to have been misdirected. To detect misdirected requests, Gateways SHOULD match the authority of the requests with all the SNI hostname(s) configured across all the Gateway Listeners on the same port and protocol: * If another Listener has an exact match or more specific wildcard entry, the Gateway SHOULD return a 421. * If the current Listener (selected by SNI matching during ClientHello) does not match the Host: * If another Listener does match the Host the Gateway SHOULD return a 421. * If no other Listener matches the Host, the Gateway MUST return a 404. For HTTPRoute and TLSRoute resources, there is an interaction with the `spec.hostnames` array. When both listener and route specify hostnames, there MUST be an intersection between the values for a Route to be accepted. For more information, refer to the Route specific Hostnames documentation. Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. Support: Core maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string name: description: |- Name is the name of the Listener. This name MUST be unique within a Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string port: description: |- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. Support: Core format: int32 maximum: 65535 minimum: 1 type: integer protocol: description: |- Protocol specifies the network protocol this listener expects to receive. Support: Core maxLength: 255 minLength: 1 pattern: ^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ type: string tls: description: |- TLS is the TLS configuration for the Listener. This field is required if the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake. Support: Core properties: certificateRefs: description: |- CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener. A single CertificateRef to a Kubernetes Secret has "Core" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the "ResolvedRefs" condition MUST be set to False for this listener with the "RefNotPermitted" reason. This field is required to have at least one element when the mode is set to "Terminate" (default) and is optional otherwise. CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls Support: Implementation-specific (More than one reference or other resource types) items: description: |- SecretObjectReference identifies an API object including its namespace, defaulting to Secret. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object. properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Secret description: Kind is kind of the referent. For example "Secret". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referenced object. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - name type: object maxItems: 64 type: array x-kubernetes-list-type: atomic mode: default: Terminate description: |- Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes: - Terminate: The TLS session between the downstream client and the Gateway is terminated at the Gateway. This mode requires certificates to be specified in some way, such as populating the certificateRefs field. - Passthrough: The TLS session is NOT terminated by the Gateway. This implies that the Gateway can't decipher the TLS stream except for the ClientHello message of the TLS protocol. The certificateRefs field is ignored in this mode. Support: Core enum: - Terminate - Passthrough type: string options: additionalProperties: description: |- AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. maxLength: 4096 minLength: 0 type: string description: |- Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites. A set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API. Support: Implementation-specific maxProperties: 16 type: object type: object x-kubernetes-validations: - message: certificateRefs or options must be specified when mode is Terminate rule: "self.mode == 'Terminate' ? size(self.certificateRefs) > 0 || size(self.options) > 0 : true" required: - name - port - protocol type: object maxItems: 64 minItems: 1 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map x-kubernetes-validations: - message: tls must not be specified for protocols ['HTTP', 'TCP', 'UDP'] rule: "self.all(l, l.protocol in ['HTTP', 'TCP', 'UDP'] ? !has(l.tls) : true)" - message: tls mode must be Terminate for protocol HTTPS rule: "self.all(l, (l.protocol == 'HTTPS' && has(l.tls)) ? (l.tls.mode == '' || l.tls.mode == 'Terminate') : true)" - message: hostname must not be specified for protocols ['TCP', 'UDP'] rule: "self.all(l, l.protocol in ['TCP', 'UDP'] ? (!has(l.hostname) || l.hostname == '') : true)" - message: Listener name must be unique within the Gateway rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) - message: Combination of port, protocol and hostname must be unique for each listener rule: "self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))" required: - gatewayClassName - listeners type: object status: default: conditions: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Programmed description: Status defines the current state of Gateway. properties: addresses: description: |- Addresses lists the network addresses that have been bound to the Gateway. This list may differ from the addresses provided in the spec under some conditions: * no addresses are specified, all addresses are dynamically assigned * a combination of specified and dynamic addresses are assigned * a specified address was unusable (e.g. already in use) items: description: GatewayStatusAddress describes a network address that is bound to a Gateway. oneOf: - properties: type: enum: - IPAddress value: anyOf: - format: ipv4 - format: ipv6 - properties: type: not: enum: - IPAddress properties: type: default: IPAddress description: Type of the address. maxLength: 253 minLength: 1 pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string value: description: |- Value of the address. The validity of the values will depend on the type and support by the controller. Examples: `1.2.3.4`, `128::1`, `my-ip-address`. maxLength: 253 minLength: 1 type: string required: - value type: object x-kubernetes-validations: - message: Hostname value must only contain valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): true' maxItems: 16 type: array x-kubernetes-list-type: atomic conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Programmed description: |- Conditions describe the current conditions of the Gateway. Implementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary to describe Gateway state. Known condition types are: * "Accepted" * "Programmed" * "Ready" items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map listeners: description: Listeners provide status for each unique listener port defined in the Spec. items: description: ListenerStatus is the status associated with a Listener. properties: attachedRoutes: description: |- AttachedRoutes represents the total number of Routes that have been successfully attached to this Listener. Successful attachment of a Route to a Listener is based solely on the combination of the AllowedRoutes field on the corresponding Listener and the Route's ParentRefs field. A Route is successfully attached to a Listener when it is selected by the Listener's AllowedRoutes field AND the Route has a valid ParentRef selecting the whole Gateway resource or a specific Listener as a parent resource (more detail on attachment semantics can be found in the documentation on the various Route kinds ParentRefs fields). Listener or Route status does not impact successful attachment, i.e. the AttachedRoutes field count MUST be set for Listeners with condition Accepted: false and MUST count successfully attached Routes that may themselves have Accepted: false conditions. Uses for this field include troubleshooting Route attachment and measuring blast radius/impact of changes to a Listener. format: int32 type: integer conditions: description: Conditions describe the current condition of this listener. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map name: description: Name is the name of the Listener that this status corresponds to. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string supportedKinds: description: |- SupportedKinds is the list indicating the Kinds supported by this listener. This MUST represent the kinds an implementation supports for that Listener configuration. If kinds are specified in Spec that are not supported, they MUST NOT appear in this list and an implementation MUST set the "ResolvedRefs" condition to "False" with the "InvalidRouteKinds" reason. If both valid and invalid Route kinds are specified, the implementation MUST reference the valid Route kinds that have been specified. items: description: RouteGroupKind indicates the group and kind of a Route resource. properties: group: default: gateway.networking.k8s.io description: Group is the group of the Route. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is the kind of the Route. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string required: - kind type: object maxItems: 8 type: array x-kubernetes-list-type: atomic required: - attachedRoutes - conditions - name - supportedKinds type: object maxItems: 64 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object required: - spec type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.gatewayClassName name: Class type: string - jsonPath: .status.addresses[*].value name: Address type: string - jsonPath: .status.conditions[?(@.type=="Programmed")].status name: Programmed type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta1 schema: openAPIV3Schema: description: |- Gateway represents an instance of a service-traffic handling infrastructure by binding Listeners to a set of IP addresses. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of Gateway. properties: addresses: description: |- Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in an associated entry in GatewayStatus.Conditions. The Addresses field represents a request for the address(es) on the "outside of the Gateway", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to. If no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses. The implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses. Support: Extended items: description: GatewaySpecAddress describes an address that can be bound to a Gateway. oneOf: - properties: type: enum: - IPAddress value: anyOf: - format: ipv4 - format: ipv6 - properties: type: not: enum: - IPAddress properties: type: default: IPAddress description: Type of the address. maxLength: 253 minLength: 1 pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string value: description: |- When a value is unspecified, an implementation SHOULD automatically assign an address matching the requested type if possible. If an implementation does not support an empty value, they MUST set the "Programmed" condition in status to False with a reason of "AddressNotAssigned". Examples: `1.2.3.4`, `128::1`, `my-ip-address`. maxLength: 253 type: string type: object x-kubernetes-validations: - message: Hostname value must be empty or contain only valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) rule: 'self.type == ''Hostname'' ? (!has(self.value) || self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$""")): true' maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: IPAddress values must be unique rule: "self.all(a1, a1.type == 'IPAddress' && has(a1.value) ? self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value == a1.value) : true )" - message: Hostname values must be unique rule: "self.all(a1, a1.type == 'Hostname' && has(a1.value) ? self.exists_one(a2, a2.type == a1.type && has(a2.value) && a2.value == a1.value) : true )" gatewayClassName: description: |- GatewayClassName used for this Gateway. This is the name of a GatewayClass resource. maxLength: 253 minLength: 1 type: string infrastructure: description: |- Infrastructure defines infrastructure level attributes about this Gateway instance. Support: Extended properties: annotations: additionalProperties: description: |- AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. maxLength: 4096 minLength: 0 type: string description: |- Annotations that SHOULD be applied to any resources created in response to this Gateway. For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. An implementation may chose to add additional implementation-specific annotations as they see fit. Support: Extended maxProperties: 8 type: object x-kubernetes-validations: - message: Annotation keys must be in the form of an optional DNS subdomain prefix followed by a required name segment of up to 63 characters. rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) - message: If specified, the annotation key's prefix must be a DNS subdomain not longer than 253 characters in total. rule: self.all(key, key.split("/")[0].size() < 253) labels: additionalProperties: description: |- LabelValue is the value of a label in the Gateway API. This is used for validation of maps such as Gateway infrastructure labels. This matches the Kubernetes label validation rules: * must be 63 characters or less (can be empty), * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. Valid values include: * MyValue * my.name * 123-my-value maxLength: 63 minLength: 0 pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ type: string description: |- Labels that SHOULD be applied to any resources created in response to this Gateway. For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. For other implementations, this refers to any relevant (implementation specific) "labels" concepts. An implementation may chose to add additional implementation-specific labels as they see fit. If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels change, it SHOULD clearly warn about this behavior in documentation. Support: Extended maxProperties: 8 type: object x-kubernetes-validations: - message: Label keys must be in the form of an optional DNS subdomain prefix followed by a required name segment of up to 63 characters. rule: self.all(key, key.matches(r"""^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$""")) - message: If specified, the label key's prefix must be a DNS subdomain not longer than 253 characters in total. rule: self.all(key, key.split("/")[0].size() < 253) parametersRef: description: |- ParametersRef is a reference to a resource that contains the configuration parameters corresponding to the Gateway. This is optional if the controller does not require any additional configuration. This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, the merging behavior is implementation specific. It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. If the referent cannot be found, refers to an unsupported kind, or when the data within that resource is malformed, the Gateway SHOULD be rejected with the "Accepted" status condition set to "False" and an "InvalidParameters" reason. Support: Implementation-specific properties: group: description: Group is the group of the referent. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object type: object listeners: description: |- Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At least one Listener MUST be specified. ## Distinct Listeners Each Listener in a set of Listeners (for example, in a single Gateway) MUST be _distinct_, in that a traffic flow MUST be able to be assigned to exactly one listener. (This section uses "set of Listeners" rather than "Listeners in a single Gateway" because implementations MAY merge configuration from multiple Gateways onto a single data plane, and these rules _also_ apply in that case). Practically, this means that each listener in a set MUST have a unique combination of Port, Protocol, and, if supported by the protocol, Hostname. Some combinations of port, protocol, and TLS settings are considered Core support and MUST be supported by implementations based on the objects they support: HTTPRoute 1. HTTPRoute, Port: 80, Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided TLSRoute 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough "Distinct" Listeners have the following property: **The implementation can match inbound requests to a single distinct Listener**. When multiple Listeners share values for fields (for example, two Listeners with the same Port value), the implementation can match requests to only one of the Listeners using other Listener fields. When multiple listeners have the same value for the Protocol field, then each of the Listeners with matching Protocol values MUST have different values for other fields. The set of fields that MUST be different for a Listener differs per protocol. The following rules define the rules for what fields MUST be considered for Listeners to be distinct with each protocol currently defined in the Gateway API spec. The set of listeners that all share a protocol value MUST have _different_ values for _at least one_ of these fields to be distinct: * **HTTP, HTTPS, TLS**: Port, Hostname * **TCP, UDP**: Port One **very** important rule to call out involves what happens when an implementation: * Supports TCP protocol Listeners, as well as HTTP, HTTPS, or TLS protocol Listeners, and * sees HTTP, HTTPS, or TLS protocols with the same `port` as one with TCP Protocol. In this case all the Listeners that share a port with the TCP Listener are not distinct and so MUST NOT be accepted. If an implementation does not support TCP Protocol Listeners, then the previous rule does not apply, and the TCP Listeners SHOULD NOT be accepted. Note that the `tls` field is not used for determining if a listener is distinct, because Listeners that _only_ differ on TLS config will still conflict in all cases. ### Listeners that are distinct only by Hostname When the Listeners are distinct based only on Hostname, inbound request hostnames MUST match from the most specific to least specific Hostname values to choose the correct Listener and its associated set of Routes. Exact matches MUST be processed before wildcard matches, and wildcard matches MUST be processed before fallback (empty Hostname value) matches. For example, `"foo.example.com"` takes precedence over `"*.example.com"`, and `"*.example.com"` takes precedence over `""`. Additionally, if there are multiple wildcard entries, more specific wildcard entries must be processed before less specific wildcard entries. For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`. The precise definition here is that the higher the number of dots in the hostname to the right of the wildcard character, the higher the precedence. The wildcard character will match any number of characters _and dots_ to the left, however, so `"*.example.com"` will match both `"foo.bar.example.com"` _and_ `"bar.example.com"`. ## Handling indistinct Listeners If a set of Listeners contains Listeners that are not distinct, then those Listeners are _Conflicted_, and the implementation MUST set the "Conflicted" condition in the Listener Status to "True". The words "indistinct" and "conflicted" are considered equivalent for the purpose of this documentation. Implementations MAY choose to accept a Gateway with some Conflicted Listeners only if they only accept the partial Listener set that contains no Conflicted Listeners. Specifically, an implementation MAY accept a partial Listener set subject to the following rules: * The implementation MUST NOT pick one conflicting Listener as the winner. ALL indistinct Listeners must not be accepted for processing. * At least one distinct Listener MUST be present, or else the Gateway effectively contains _no_ Listeners, and must be rejected from processing as a whole. The implementation MUST set a "ListenersNotValid" condition on the Gateway Status when the Gateway contains Conflicted Listeners whether or not they accept the Gateway. That Condition SHOULD clearly indicate in the Message which Listeners are conflicted, and which are Accepted. Additionally, the Listener status for those listeners SHOULD indicate which Listeners are conflicted and not Accepted. ## General Listener behavior Note that, for all distinct Listeners, requests SHOULD match at most one Listener. For example, if Listeners are defined for "foo.example.com" and "*.example.com", a request to "foo.example.com" SHOULD only be routed using routes attached to the "foo.example.com" Listener (and not the "*.example.com" Listener). This concept is known as "Listener Isolation", and it is an Extended feature of Gateway API. Implementations that do not support Listener Isolation MUST clearly document this, and MUST NOT claim support for the `GatewayHTTPListenerIsolation` feature. Implementations that _do_ support Listener Isolation SHOULD claim support for the Extended `GatewayHTTPListenerIsolation` feature and pass the associated conformance tests. ## Compatible Listeners A Gateway's Listeners are considered _compatible_ if: 1. They are distinct. 2. The implementation can serve them in compliance with the Addresses requirement that all Listeners are available on all assigned addresses. Compatible combinations in Extended support are expected to vary across implementations. A combination that is compatible for one implementation may not be compatible for another. For example, an implementation that cannot serve both TCP and UDP listeners on the same address, or cannot mix HTTPS and generic TLS listens on the same port would not consider those cases compatible, even though they are distinct. Implementations MAY merge separate Gateways onto a single set of Addresses if all Listeners across all Gateways are compatible. In a future release the MinItems=1 requirement MAY be dropped. Support: Core items: description: |- Listener embodies the concept of a logical endpoint where a Gateway accepts network connections. properties: allowedRoutes: default: namespaces: from: Same description: |- AllowedRoutes defines the types of routes that MAY be attached to a Listener and the trusted namespaces where those Route resources MAY be present. Although a client request may match multiple route rules, only one rule may ultimately receive the request. Matching precedence MUST be determined in order of the following criteria: * The most specific match as defined by the Route type. * The oldest Route based on creation timestamp. For example, a Route with a creation timestamp of "2020-09-08 01:02:03" is given precedence over a Route with a creation timestamp of "2020-09-08 01:02:04". * If everything else is equivalent, the Route appearing first in alphabetical order (namespace/name) should be given precedence. For example, foo/bar is given precedence over foo/baz. All valid rules within a Route attached to this Listener should be implemented. Invalid Route rules can be ignored (sometimes that will mean the full Route). If a Route rule transitions from valid to invalid, support for that Route rule should be dropped to ensure consistency. For example, even if a filter specified by a Route rule is invalid, the rest of the rules within that Route should still be supported. Support: Core properties: kinds: description: |- Kinds specifies the groups and kinds of Routes that are allowed to bind to this Gateway Listener. When unspecified or empty, the kinds of Routes selected are determined using the Listener protocol. A RouteGroupKind MUST correspond to kinds of Routes that are compatible with the application protocol specified in the Listener's Protocol field. If an implementation does not support or recognize this resource type, it MUST set the "ResolvedRefs" condition to False for this Listener with the "InvalidRouteKinds" reason. Support: Core items: description: RouteGroupKind indicates the group and kind of a Route resource. properties: group: default: gateway.networking.k8s.io description: Group is the group of the Route. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is the kind of the Route. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string required: - kind type: object maxItems: 8 type: array x-kubernetes-list-type: atomic namespaces: default: from: Same description: |- Namespaces indicates namespaces from which Routes may be attached to this Listener. This is restricted to the namespace of this Gateway by default. Support: Core properties: from: default: Same description: |- From indicates where Routes will be selected for this Gateway. Possible values are: * All: Routes in all namespaces may be used by this Gateway. * Selector: Routes in namespaces selected by the selector may be used by this Gateway. * Same: Only Routes in the same namespace may be used by this Gateway. Support: Core enum: - All - Selector - Same type: string selector: description: |- Selector must be specified when From is set to "Selector". In that case, only Routes in Namespaces matching this Selector will be selected by this Gateway. This field is ignored for other values of "From". Support: Core properties: matchExpressions: description: matchExpressions is a list of label selector requirements. The requirements are ANDed. items: description: |- A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. properties: key: description: key is the label key that the selector applies to. type: string operator: description: |- operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. items: type: string type: array x-kubernetes-list-type: atomic required: - key - operator type: object type: array x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. type: object type: object x-kubernetes-map-type: atomic type: object type: object hostname: description: |- Hostname specifies the virtual hostname to match for protocol types that define this concept. When unspecified, all hostnames are matched. This field is ignored for protocols that don't require hostname based matching. Implementations MUST apply Hostname matching appropriately for each of the following protocols: * TLS: The Listener Hostname MUST match the SNI. * HTTP: The Listener Hostname MUST match the Host header of the request. * HTTPS: The Listener Hostname SHOULD match both the SNI and Host header. Note that this does not require the SNI and Host header to be the same. The semantics of this are described in more detail below. To ensure security, Section 11.1 of RFC-6066 emphasizes that server implementations that rely on SNI hostname matching MUST also verify hostnames within the application protocol. Section 9.1.2 of RFC-7540 provides a mechanism for servers to reject the reuse of a connection by responding with the HTTP 421 Misdirected Request status code. This indicates that the origin server has rejected the request because it appears to have been misdirected. To detect misdirected requests, Gateways SHOULD match the authority of the requests with all the SNI hostname(s) configured across all the Gateway Listeners on the same port and protocol: * If another Listener has an exact match or more specific wildcard entry, the Gateway SHOULD return a 421. * If the current Listener (selected by SNI matching during ClientHello) does not match the Host: * If another Listener does match the Host the Gateway SHOULD return a 421. * If no other Listener matches the Host, the Gateway MUST return a 404. For HTTPRoute and TLSRoute resources, there is an interaction with the `spec.hostnames` array. When both listener and route specify hostnames, there MUST be an intersection between the values for a Route to be accepted. For more information, refer to the Route specific Hostnames documentation. Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. Support: Core maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string name: description: |- Name is the name of the Listener. This name MUST be unique within a Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string port: description: |- Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. Support: Core format: int32 maximum: 65535 minimum: 1 type: integer protocol: description: |- Protocol specifies the network protocol this listener expects to receive. Support: Core maxLength: 255 minLength: 1 pattern: ^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ type: string tls: description: |- TLS is the TLS configuration for the Listener. This field is required if the Protocol field is "HTTPS" or "TLS". It is invalid to set this field if the Protocol field is "HTTP", "TCP", or "UDP". The association of SNIs to Certificate defined in ListenerTLSConfig is defined based on the Hostname field for this listener. The GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake. Support: Core properties: certificateRefs: description: |- CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener. A single CertificateRef to a Kubernetes Secret has "Core" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the "ResolvedRefs" condition MUST be set to False for this listener with the "RefNotPermitted" reason. This field is required to have at least one element when the mode is set to "Terminate" (default) and is optional otherwise. CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls Support: Implementation-specific (More than one reference or other resource types) items: description: |- SecretObjectReference identifies an API object including its namespace, defaulting to Secret. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object. properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Secret description: Kind is kind of the referent. For example "Secret". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referenced object. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - name type: object maxItems: 64 type: array x-kubernetes-list-type: atomic mode: default: Terminate description: |- Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes: - Terminate: The TLS session between the downstream client and the Gateway is terminated at the Gateway. This mode requires certificates to be specified in some way, such as populating the certificateRefs field. - Passthrough: The TLS session is NOT terminated by the Gateway. This implies that the Gateway can't decipher the TLS stream except for the ClientHello message of the TLS protocol. The certificateRefs field is ignored in this mode. Support: Core enum: - Terminate - Passthrough type: string options: additionalProperties: description: |- AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. maxLength: 4096 minLength: 0 type: string description: |- Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites. A set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API. Support: Implementation-specific maxProperties: 16 type: object type: object x-kubernetes-validations: - message: certificateRefs or options must be specified when mode is Terminate rule: "self.mode == 'Terminate' ? size(self.certificateRefs) > 0 || size(self.options) > 0 : true" required: - name - port - protocol type: object maxItems: 64 minItems: 1 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map x-kubernetes-validations: - message: tls must not be specified for protocols ['HTTP', 'TCP', 'UDP'] rule: "self.all(l, l.protocol in ['HTTP', 'TCP', 'UDP'] ? !has(l.tls) : true)" - message: tls mode must be Terminate for protocol HTTPS rule: "self.all(l, (l.protocol == 'HTTPS' && has(l.tls)) ? (l.tls.mode == '' || l.tls.mode == 'Terminate') : true)" - message: hostname must not be specified for protocols ['TCP', 'UDP'] rule: "self.all(l, l.protocol in ['TCP', 'UDP'] ? (!has(l.hostname) || l.hostname == '') : true)" - message: Listener name must be unique within the Gateway rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) - message: Combination of port, protocol and hostname must be unique for each listener rule: "self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))" required: - gatewayClassName - listeners type: object status: default: conditions: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Programmed description: Status defines the current state of Gateway. properties: addresses: description: |- Addresses lists the network addresses that have been bound to the Gateway. This list may differ from the addresses provided in the spec under some conditions: * no addresses are specified, all addresses are dynamically assigned * a combination of specified and dynamic addresses are assigned * a specified address was unusable (e.g. already in use) items: description: GatewayStatusAddress describes a network address that is bound to a Gateway. oneOf: - properties: type: enum: - IPAddress value: anyOf: - format: ipv4 - format: ipv6 - properties: type: not: enum: - IPAddress properties: type: default: IPAddress description: Type of the address. maxLength: 253 minLength: 1 pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string value: description: |- Value of the address. The validity of the values will depend on the type and support by the controller. Examples: `1.2.3.4`, `128::1`, `my-ip-address`. maxLength: 253 minLength: 1 type: string required: - value type: object x-kubernetes-validations: - message: Hostname value must only contain valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): true' maxItems: 16 type: array x-kubernetes-list-type: atomic conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Accepted - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller reason: Pending status: Unknown type: Programmed description: |- Conditions describe the current conditions of the Gateway. Implementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary to describe Gateway state. Known condition types are: * "Accepted" * "Programmed" * "Ready" items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map listeners: description: Listeners provide status for each unique listener port defined in the Spec. items: description: ListenerStatus is the status associated with a Listener. properties: attachedRoutes: description: |- AttachedRoutes represents the total number of Routes that have been successfully attached to this Listener. Successful attachment of a Route to a Listener is based solely on the combination of the AllowedRoutes field on the corresponding Listener and the Route's ParentRefs field. A Route is successfully attached to a Listener when it is selected by the Listener's AllowedRoutes field AND the Route has a valid ParentRef selecting the whole Gateway resource or a specific Listener as a parent resource (more detail on attachment semantics can be found in the documentation on the various Route kinds ParentRefs fields). Listener or Route status does not impact successful attachment, i.e. the AttachedRoutes field count MUST be set for Listeners with condition Accepted: false and MUST count successfully attached Routes that may themselves have Accepted: false conditions. Uses for this field include troubleshooting Route attachment and measuring blast radius/impact of changes to a Listener. format: int32 type: integer conditions: description: Conditions describe the current condition of this listener. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map name: description: Name is the name of the Listener that this status corresponds to. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string supportedKinds: description: |- SupportedKinds is the list indicating the Kinds supported by this listener. This MUST represent the kinds an implementation supports for that Listener configuration. If kinds are specified in Spec that are not supported, they MUST NOT appear in this list and an implementation MUST set the "ResolvedRefs" condition to "False" with the "InvalidRouteKinds" reason. If both valid and invalid Route kinds are specified, the implementation MUST reference the valid Route kinds that have been specified. items: description: RouteGroupKind indicates the group and kind of a Route resource. properties: group: default: gateway.networking.k8s.io description: Group is the group of the Route. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is the kind of the Route. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string required: - kind type: object maxItems: 8 type: array x-kubernetes-list-type: atomic required: - attachedRoutes - conditions - name - supportedKinds type: object maxItems: 64 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object required: - spec type: object served: true storage: false subresources: status: {} status: acceptedNames: kind: "" plural: "" conditions: null storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: grpcroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api kind: GRPCRoute listKind: GRPCRouteList plural: grpcroutes singular: grpcroute scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.hostnames name: Hostnames type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- GRPCRoute provides a way to route gRPC requests. This includes the capability to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. Filters can be used to specify additional processing steps. Backends specify where matching requests will be routed. GRPCRoute falls under extended support within the Gateway API. Within the following specification, the word "MUST" indicates that an implementation supporting GRPCRoute must conform to the indicated requirement, but an implementation not supporting this route type need not follow the requirement unless explicitly indicated. Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` MUST accept HTTP/2 connections without an initial upgrade from HTTP/1.1, i.e. via ALPN. If the implementation does not support this, then it MUST set the "Accepted" condition to "False" for the affected listener with a reason of "UnsupportedProtocol". Implementations MAY also accept HTTP/2 connections with an upgrade from HTTP/1. Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` MUST support HTTP/2 over cleartext TCP (h2c, https://www.rfc-editor.org/rfc/rfc7540#section-3.1) without an initial upgrade from HTTP/1.1, i.e. with prior knowledge (https://www.rfc-editor.org/rfc/rfc7540#section-3.4). If the implementation does not support this, then it MUST set the "Accepted" condition to "False" for the affected listener with a reason of "UnsupportedProtocol". Implementations MAY also accept HTTP/2 connections with an upgrade from HTTP/1, i.e. without prior knowledge. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of GRPCRoute. properties: hostnames: description: |- Hostnames defines a set of hostnames to match against the GRPC Host header to select a GRPCRoute to process the request. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label MUST appear by itself as the first label. If a hostname is specified by both the Listener and GRPCRoute, there MUST be at least one intersecting hostname for the GRPCRoute to be attached to the Listener. For example: * A Listener with `test.example.com` as the hostname matches GRPCRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches GRPCRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `test.example.com` and `*.example.com` would both match. On the other hand, `example.com` and `test.example.net` would not match. Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. If both the Listener and GRPCRoute have specified hostnames, any GRPCRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the GRPCRoute specified `test.example.com` and `test.example.net`, `test.example.net` MUST NOT be considered for a match. If both the Listener and GRPCRoute have specified hostnames, and none match with the criteria above, then the GRPCRoute MUST NOT be accepted by the implementation. The implementation MUST raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. If a Route (A) of type HTTPRoute or GRPCRoute is attached to a Listener and that listener already has another Route (B) of the other type attached and the intersection of the hostnames of A and B is non-empty, then the implementation MUST accept exactly one of these two routes, determined by the following criteria, in order: * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by "{namespace}/{name}". The rejected Route MUST raise an 'Accepted' condition with a status of 'False' in the corresponding RouteParentStatus. Support: Core items: description: |- Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. Hostname can be "precise" which is a domain name without the terminating dot of a network host (e.g. "foo.example.com") or "wildcard", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed. maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string maxItems: 16 type: array x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a "producer" route, or the mesh implementation must support and allow "consumer" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a "producer" route for a Service in a different namespace from the Route. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. ParentRefs must be _distinct_. This means either that: * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. Some examples: * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. items: description: |- ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object maxItems: 32 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when parentRefs includes 2 or more references to the same parent rule: "self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" - message: sectionName must be unique when parentRefs includes 2 or more references to the same parent rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)))) rules: description: Rules are a list of GRPC matchers, filters and actions. items: description: |- GRPCRouteRule defines the semantics for matching a gRPC request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). properties: backendRefs: description: |- BackendRefs defines the backend(s) where matching requests should be sent. Failure behavior here depends on how many BackendRefs are specified and how many are invalid. If *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive an `UNAVAILABLE` status. See the GRPCBackendRef definition for the rules about what makes a single GRPCBackendRef invalid. When a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive an `UNAVAILABLE` status. For example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status. Implementations may choose how that 50 percent is determined. Support: Core for Kubernetes Service Support: Implementation-specific for any other resource Support for weight: Core items: description: |- GRPCBackendRef defines how a GRPCRoute forwards a gRPC request. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. properties: filters: description: |- Filters defined at this level MUST be executed if and only if the request is being forwarded to the backend defined here. Support: Implementation-specific (For broader support of filters, use the Filters field in GRPCRouteRule.) items: description: |- GRPCRouteFilter defines processing steps that must be completed during the request or response lifecycle. GRPCRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. properties: extensionRef: description: |- ExtensionRef is an optional, implementation-specific extension to the "filter" behavior. For example, resource "myroutefilter" in group "networking.example.net"). ExtensionRef MUST NOT be used for core and extended filters. Support: Implementation-specific This filter can be used multiple times within the same rule. properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request headers. Support: Core properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object requestMirror: description: |- RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. Support: Extended properties: backendRef: description: |- BackendRef references a resource where mirrored requests are sent. Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the "ResolvedRefs" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the "ResolvedRefs" condition on the Route is set to `status: False`, with the "RefNotPermitted" reason and not configure this backend in the underlying implementation. In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" fraction: description: |- Fraction represents the fraction of requests that should be mirrored to BackendRef. Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. properties: denominator: default: 100 format: int32 minimum: 1 type: integer numerator: format: int32 minimum: 0 type: integer required: - numerator type: object x-kubernetes-validations: - message: numerator must be less than or equal to denominator rule: self.numerator <= self.denominator percent: description: |- Percent represents the percentage of requests that should be mirrored to BackendRef. Its minimum value is 0 (indicating 0% of requests) and its maximum value is 100 (indicating 100% of requests). Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. format: int32 maximum: 100 minimum: 0 type: integer required: - backendRef type: object x-kubernetes-validations: - message: Only one of percent or fraction may be specified in HTTPRequestMirrorFilter rule: "!(has(self.percent) && has(self.fraction))" responseHeaderModifier: description: |- ResponseHeaderModifier defines a schema for a filter that modifies response headers. Support: Extended properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object type: description: |- Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: - Core: Filter types and their corresponding configuration defined by "Support: Core" in this package, e.g. "RequestHeaderModifier". All implementations supporting GRPCRoute MUST support core filters. - Extended: Filter types and their corresponding configuration defined by "Support: Extended" in this package, e.g. "RequestMirror". Implementers are encouraged to support extended filters. - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` MUST be set to "ExtensionRef" for custom filters. Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. enum: - ResponseHeaderModifier - RequestHeaderModifier - RequestMirror - ExtensionRef type: string required: - type type: object x-kubernetes-validations: - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier rule: "!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type rule: "!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier rule: "!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type rule: "!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" - message: filter.requestMirror must be nil if the filter.type is not RequestMirror rule: "!(has(self.requestMirror) && self.type != 'RequestMirror')" - message: filter.requestMirror must be specified for RequestMirror filter.type rule: "!(!has(self.requestMirror) && self.type == 'RequestMirror')" - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef rule: "!(has(self.extensionRef) && self.type != 'ExtensionRef')" - message: filter.extensionRef must be specified for ExtensionRef filter.type rule: "!(!has(self.extensionRef) && self.type == 'ExtensionRef')" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 - message: ResponseHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer weight: default: 1 description: |- Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. Support for this field varies based on the context where used. format: int32 maximum: 1000000 minimum: 0 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" maxItems: 16 type: array x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match this rule. The effects of ordering of multiple behaviors are currently unspecified. This can change in the future based on feedback during the alpha stage. Conformance-levels at this level are defined based on the type of filter: - ALL core filters MUST be supported by all implementations that support GRPCRoute. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across implementations. Specifying the same filter multiple times is not supported unless explicitly indicated in the filter. If an implementation cannot support a combination of filters, it must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error. Support: Core items: description: |- GRPCRouteFilter defines processing steps that must be completed during the request or response lifecycle. GRPCRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. properties: extensionRef: description: |- ExtensionRef is an optional, implementation-specific extension to the "filter" behavior. For example, resource "myroutefilter" in group "networking.example.net"). ExtensionRef MUST NOT be used for core and extended filters. Support: Implementation-specific This filter can be used multiple times within the same rule. properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request headers. Support: Core properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object requestMirror: description: |- RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. Support: Extended properties: backendRef: description: |- BackendRef references a resource where mirrored requests are sent. Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the "ResolvedRefs" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the "ResolvedRefs" condition on the Route is set to `status: False`, with the "RefNotPermitted" reason and not configure this backend in the underlying implementation. In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" fraction: description: |- Fraction represents the fraction of requests that should be mirrored to BackendRef. Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. properties: denominator: default: 100 format: int32 minimum: 1 type: integer numerator: format: int32 minimum: 0 type: integer required: - numerator type: object x-kubernetes-validations: - message: numerator must be less than or equal to denominator rule: self.numerator <= self.denominator percent: description: |- Percent represents the percentage of requests that should be mirrored to BackendRef. Its minimum value is 0 (indicating 0% of requests) and its maximum value is 100 (indicating 100% of requests). Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. format: int32 maximum: 100 minimum: 0 type: integer required: - backendRef type: object x-kubernetes-validations: - message: Only one of percent or fraction may be specified in HTTPRequestMirrorFilter rule: "!(has(self.percent) && has(self.fraction))" responseHeaderModifier: description: |- ResponseHeaderModifier defines a schema for a filter that modifies response headers. Support: Extended properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object type: description: |- Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: - Core: Filter types and their corresponding configuration defined by "Support: Core" in this package, e.g. "RequestHeaderModifier". All implementations supporting GRPCRoute MUST support core filters. - Extended: Filter types and their corresponding configuration defined by "Support: Extended" in this package, e.g. "RequestMirror". Implementers are encouraged to support extended filters. - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` MUST be set to "ExtensionRef" for custom filters. Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. enum: - ResponseHeaderModifier - RequestHeaderModifier - RequestMirror - ExtensionRef type: string required: - type type: object x-kubernetes-validations: - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier rule: "!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type rule: "!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier rule: "!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type rule: "!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" - message: filter.requestMirror must be nil if the filter.type is not RequestMirror rule: "!(has(self.requestMirror) && self.type != 'RequestMirror')" - message: filter.requestMirror must be specified for RequestMirror filter.type rule: "!(!has(self.requestMirror) && self.type == 'RequestMirror')" - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef rule: "!(has(self.extensionRef) && self.type != 'ExtensionRef')" - message: filter.extensionRef must be specified for ExtensionRef filter.type rule: "!(!has(self.extensionRef) && self.type == 'ExtensionRef')" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 - message: ResponseHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 matches: description: |- Matches define conditions used for matching the rule against incoming gRPC requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. For example, take the following matches configuration: ``` matches: - method: service: foo.bar headers: values: version: 2 - method: service: foo.bar.v2 ``` For a request to match against this rule, it MUST satisfy EITHER of the two conditions: - service of foo.bar AND contains the header `version: 2` - service of foo.bar.v2 See the documentation for GRPCRouteMatch on how to specify multiple match conditions to be ANDed together. If no matches are specified, the implementation MUST match every gRPC request. Proxy or Load Balancer routing configuration generated from GRPCRoutes MUST prioritize rules based on the following criteria, continuing on ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. Precedence MUST be given to the rule with the largest number of: * Characters in a matching non-wildcard hostname. * Characters in a matching hostname. * Characters in a matching service. * Characters in a matching method. * Header matches. If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by "{namespace}/{name}". If ties still exist within the Route that has been given precedence, matching precedence MUST be granted to the first matching rule meeting the above criteria. items: description: |- GRPCRouteMatch defines the predicate used to match requests to a given action. Multiple match types are ANDed together, i.e. the match will evaluate to true only if all conditions are satisfied. For example, the match below will match a gRPC request only if its service is `foo` AND it contains the `version: v1` header: ``` matches: - method: type: Exact service: "foo" headers: - name: "version" value "v1" ``` properties: headers: description: |- Headers specifies gRPC request header matchers. Multiple match values are ANDed together, meaning, a request MUST match all the specified headers to select the route. items: description: |- GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request headers. properties: name: description: |- Name is the name of the gRPC Header to be matched. If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: default: Exact description: Type specifies how to match against the value of the header. enum: - Exact - RegularExpression type: string value: description: Value is the value of the gRPC Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map method: description: |- Method specifies a gRPC request service/method matcher. If this field is not specified, all services and methods will match. properties: method: description: |- Value of the method to match against. If left empty or omitted, will match all services. At least one of Service and Method MUST be a non-empty string. maxLength: 1024 type: string service: description: |- Value of the service to match against. If left empty or omitted, will match any service. At least one of Service and Method MUST be a non-empty string. maxLength: 1024 type: string type: default: Exact description: |- Type specifies how to match against the service and/or method. Support: Core (Exact with service and method specified) Support: Implementation-specific (Exact with method specified but no service specified) Support: Implementation-specific (RegularExpression) enum: - Exact - RegularExpression type: string type: object x-kubernetes-validations: - message: One or both of 'service' or 'method' must be specified rule: "has(self.type) ? has(self.service) || has(self.method) : true" - message: service must only contain valid characters (matching ^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$) rule: '(!has(self.type) || self.type == ''Exact'') && has(self.service) ? self.service.matches(r"""^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$"""): true' - message: method must only contain valid characters (matching ^[A-Za-z_][A-Za-z_0-9]*$) rule: '(!has(self.type) || self.type == ''Exact'') && has(self.method) ? self.method.matches(r"""^[A-Za-z_][A-Za-z_0-9]*$"""): true' type: object maxItems: 64 type: array x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string type: object maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128 rule: "(self.size() > 0 ? (has(self[0].matches) ? self[0].matches.size() : 0) : 0) + (self.size() > 1 ? (has(self[1].matches) ? self[1].matches.size() : 0) : 0) + (self.size() > 2 ? (has(self[2].matches) ? self[2].matches.size() : 0) : 0) + (self.size() > 3 ? (has(self[3].matches) ? self[3].matches.size() : 0) : 0) + (self.size() > 4 ? (has(self[4].matches) ? self[4].matches.size() : 0) : 0) + (self.size() > 5 ? (has(self[5].matches) ? self[5].matches.size() : 0) : 0) + (self.size() > 6 ? (has(self[6].matches) ? self[6].matches.size() : 0) : 0) + (self.size() > 7 ? (has(self[7].matches) ? self[7].matches.size() : 0) : 0) + (self.size() > 8 ? (has(self[8].matches) ? self[8].matches.size() : 0) : 0) + (self.size() > 9 ? (has(self[9].matches) ? self[9].matches.size() : 0) : 0) + (self.size() > 10 ? (has(self[10].matches) ? self[10].matches.size() : 0) : 0) + (self.size() > 11 ? (has(self[11].matches) ? self[11].matches.size() : 0) : 0) + (self.size() > 12 ? (has(self[12].matches) ? self[12].matches.size() : 0) : 0) + (self.size() > 13 ? (has(self[13].matches) ? self[13].matches.size() : 0) : 0) + (self.size() > 14 ? (has(self[14].matches) ? self[14].matches.size() : 0) : 0) + (self.size() > 15 ? (has(self[15].matches) ? self[15].matches.size() : 0) : 0) <= 128" type: object status: description: Status defines the current state of GRPCRoute. properties: parents: description: |- Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway. items: description: |- RouteParentStatus describes the status of a route with respect to an associated Parent. properties: conditions: description: |- Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the "Accepted" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. A Route MUST be considered "Accepted" if at least one of the Route's rules is implemented by the Gateway. There are a number of cases where the "Accepted" condition may not be set due to lack of controller visibility, that includes when: * The Route refers to a nonexistent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 minItems: 1 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map controllerName: description: |- ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. Example: "example.net/gateway-controller". The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string parentRef: description: |- ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object required: - conditions - controllerName - parentRef type: object maxItems: 32 type: array x-kubernetes-list-type: atomic required: - parents type: object required: - spec type: object served: true storage: true subresources: status: {} status: acceptedNames: kind: "" plural: "" conditions: null storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: httproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api kind: HTTPRoute listKind: HTTPRouteList plural: httproutes singular: httproute scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.hostnames name: Hostnames type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1 schema: openAPIV3Schema: description: |- HTTPRoute provides a way to route HTTP requests. This includes the capability to match requests by hostname, path, header, or query param. Filters can be used to specify additional processing steps. Backends specify where matching requests should be routed. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of HTTPRoute. properties: hostnames: description: |- Hostnames defines a set of hostnames that should match against the HTTP Host header to select a HTTPRoute used to process the request. Implementations MUST ignore any port value specified in the HTTP Host header while performing a match and (absent of any applicable header modification configuration) MUST forward this header unmodified to the backend. Valid values for Hostnames are determined by RFC 1123 definition of a hostname with 2 notable exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. If a hostname is specified by both the Listener and HTTPRoute, there must be at least one intersecting hostname for the HTTPRoute to be attached to the Listener. For example: * A Listener with `test.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `*.example.com`, `test.example.com`, and `foo.test.example.com` would all match. On the other hand, `example.com` and `test.example.net` would not match. Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. If both the Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the HTTPRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match. If both the Listener and HTTPRoute have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. overlapping wildcard matching and exact matching hostnames), precedence must be given to rules from the HTTPRoute with the largest number of: * Characters in a matching non-wildcard hostname. * Characters in a matching hostname. If ties exist across multiple Routes, the matching precedence rules for HTTPRouteMatches takes over. Support: Core items: description: |- Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. Hostname can be "precise" which is a domain name without the terminating dot of a network host (e.g. "foo.example.com") or "wildcard", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed. maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string maxItems: 16 type: array x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a "producer" route, or the mesh implementation must support and allow "consumer" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a "producer" route for a Service in a different namespace from the Route. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. ParentRefs must be _distinct_. This means either that: * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. Some examples: * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. items: description: |- ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object maxItems: 32 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when parentRefs includes 2 or more references to the same parent rule: "self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" - message: sectionName must be unique when parentRefs includes 2 or more references to the same parent rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)))) rules: default: - matches: - path: type: PathPrefix value: / description: Rules are a list of HTTP matchers, filters and actions. items: description: |- HTTPRouteRule defines semantics for matching an HTTP request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). properties: backendRefs: description: |- BackendRefs defines the backend(s) where matching requests should be sent. Failure behavior here depends on how many BackendRefs are specified and how many are invalid. If *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive a 500 status code. See the HTTPBackendRef definition for the rules about what makes a single HTTPBackendRef invalid. When a HTTPBackendRef is invalid, 500 status codes MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive a 500 status code. For example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic must receive a 500. Implementations may choose how that 50 percent is determined. When a HTTPBackendRef refers to a Service that has no ready endpoints, implementations SHOULD return a 503 for requests to that backend instead. If an implementation chooses to do this, all of the above rules for 500 responses MUST also apply for responses that return a 503. Support: Core for Kubernetes Service Support: Extended for Kubernetes ServiceImport Support: Implementation-specific for any other resource Support for weight: Core items: description: |- HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. properties: filters: description: |- Filters defined at this level should be executed if and only if the request is being forwarded to the backend defined here. Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.) items: description: |- HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. properties: extensionRef: description: |- ExtensionRef is an optional, implementation-specific extension to the "filter" behavior. For example, resource "myroutefilter" in group "networking.example.net"). ExtensionRef MUST NOT be used for core and extended filters. This filter can be used multiple times within the same rule. Support: Implementation-specific properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request headers. Support: Core properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object requestMirror: description: |- RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. Support: Extended properties: backendRef: description: |- BackendRef references a resource where mirrored requests are sent. Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the "ResolvedRefs" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the "ResolvedRefs" condition on the Route is set to `status: False`, with the "RefNotPermitted" reason and not configure this backend in the underlying implementation. In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" fraction: description: |- Fraction represents the fraction of requests that should be mirrored to BackendRef. Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. properties: denominator: default: 100 format: int32 minimum: 1 type: integer numerator: format: int32 minimum: 0 type: integer required: - numerator type: object x-kubernetes-validations: - message: numerator must be less than or equal to denominator rule: self.numerator <= self.denominator percent: description: |- Percent represents the percentage of requests that should be mirrored to BackendRef. Its minimum value is 0 (indicating 0% of requests) and its maximum value is 100 (indicating 100% of requests). Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. format: int32 maximum: 100 minimum: 0 type: integer required: - backendRef type: object x-kubernetes-validations: - message: Only one of percent or fraction may be specified in HTTPRequestMirrorFilter rule: "!(has(self.percent) && has(self.fraction))" requestRedirect: description: |- RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. Support: Core properties: hostname: description: |- Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: description: |- Port is the port to be used in the value of the `Location` header in the response. If no port is specified, the redirect port MUST be derived using the following rules: * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically "http" to port 80 and "https" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: description: |- Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Extended enum: - http - https type: string statusCode: default: 302 description: |- StatusCode is the HTTP status code to be used in response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: description: |- ResponseHeaderModifier defines a schema for a filter that modifies response headers. Support: Extended properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object type: description: |- Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: - Core: Filter types and their corresponding configuration defined by "Support: Core" in this package, e.g. "RequestHeaderModifier". All implementations must support core filters. - Extended: Filter types and their corresponding configuration defined by "Support: Extended" in this package, e.g. "RequestMirror". Implementers are encouraged to support extended filters. - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to "ExtensionRef" for custom filters. Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier - RequestMirror - RequestRedirect - URLRewrite - ExtensionRef type: string urlRewrite: description: |- URLRewrite defines a schema for a filter that modifies a request during forwarding. Support: Extended properties: hostname: description: |- Hostname is the value to be used to replace the Host header value during forwarding. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines a path rewrite. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" type: object required: - type type: object x-kubernetes-validations: - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier rule: "!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type rule: "!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier rule: "!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type rule: "!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" - message: filter.requestMirror must be nil if the filter.type is not RequestMirror rule: "!(has(self.requestMirror) && self.type != 'RequestMirror')" - message: filter.requestMirror must be specified for RequestMirror filter.type rule: "!(!has(self.requestMirror) && self.type == 'RequestMirror')" - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect rule: "!(has(self.requestRedirect) && self.type != 'RequestRedirect')" - message: filter.requestRedirect must be specified for RequestRedirect filter.type rule: "!(!has(self.requestRedirect) && self.type == 'RequestRedirect')" - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite rule: "!(has(self.urlRewrite) && self.type != 'URLRewrite')" - message: filter.urlRewrite must be specified for URLRewrite filter.type rule: "!(!has(self.urlRewrite) && self.type == 'URLRewrite')" - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef rule: "!(has(self.extensionRef) && self.type != 'ExtensionRef')" - message: filter.extensionRef must be specified for ExtensionRef filter.type rule: "!(!has(self.extensionRef) && self.type == 'ExtensionRef')" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: "!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 - message: ResponseHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 - message: RequestRedirect filter cannot be repeated rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 - message: URLRewrite filter cannot be repeated rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer weight: default: 1 description: |- Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. Support for this field varies based on the context where used. format: int32 maximum: 1000000 minimum: 0 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" maxItems: 16 type: array x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match this rule. Wherever possible, implementations SHOULD implement filters in the order they are specified. Implementations MAY choose to implement this ordering strictly, rejecting any combination or order of filters that cannot be supported. If implementations choose a strict interpretation of filter ordering, they MUST clearly document that behavior. To reject an invalid combination or order of filters, implementations SHOULD consider the Route Rules with this configuration invalid. If all Route Rules in a Route are invalid, the entire Route would be considered invalid. If only a portion of Route Rules are invalid, implementations MUST set the "PartiallyInvalid" condition for the Route. Conformance-levels at this level are defined based on the type of filter: - ALL core filters MUST be supported by all implementations. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across implementations. Specifying the same filter multiple times is not supported unless explicitly indicated in the filter. All filters are expected to be compatible with each other except for the URLRewrite and RequestRedirect filters, which may not be combined. If an implementation cannot support other combinations of filters, they must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error. Support: Core items: description: |- HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. properties: extensionRef: description: |- ExtensionRef is an optional, implementation-specific extension to the "filter" behavior. For example, resource "myroutefilter" in group "networking.example.net"). ExtensionRef MUST NOT be used for core and extended filters. This filter can be used multiple times within the same rule. Support: Implementation-specific properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request headers. Support: Core properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object requestMirror: description: |- RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. Support: Extended properties: backendRef: description: |- BackendRef references a resource where mirrored requests are sent. Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the "ResolvedRefs" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the "ResolvedRefs" condition on the Route is set to `status: False`, with the "RefNotPermitted" reason and not configure this backend in the underlying implementation. In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" fraction: description: |- Fraction represents the fraction of requests that should be mirrored to BackendRef. Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. properties: denominator: default: 100 format: int32 minimum: 1 type: integer numerator: format: int32 minimum: 0 type: integer required: - numerator type: object x-kubernetes-validations: - message: numerator must be less than or equal to denominator rule: self.numerator <= self.denominator percent: description: |- Percent represents the percentage of requests that should be mirrored to BackendRef. Its minimum value is 0 (indicating 0% of requests) and its maximum value is 100 (indicating 100% of requests). Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. format: int32 maximum: 100 minimum: 0 type: integer required: - backendRef type: object x-kubernetes-validations: - message: Only one of percent or fraction may be specified in HTTPRequestMirrorFilter rule: "!(has(self.percent) && has(self.fraction))" requestRedirect: description: |- RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. Support: Core properties: hostname: description: |- Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: description: |- Port is the port to be used in the value of the `Location` header in the response. If no port is specified, the redirect port MUST be derived using the following rules: * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically "http" to port 80 and "https" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: description: |- Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Extended enum: - http - https type: string statusCode: default: 302 description: |- StatusCode is the HTTP status code to be used in response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: description: |- ResponseHeaderModifier defines a schema for a filter that modifies response headers. Support: Extended properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object type: description: |- Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: - Core: Filter types and their corresponding configuration defined by "Support: Core" in this package, e.g. "RequestHeaderModifier". All implementations must support core filters. - Extended: Filter types and their corresponding configuration defined by "Support: Extended" in this package, e.g. "RequestMirror". Implementers are encouraged to support extended filters. - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to "ExtensionRef" for custom filters. Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier - RequestMirror - RequestRedirect - URLRewrite - ExtensionRef type: string urlRewrite: description: |- URLRewrite defines a schema for a filter that modifies a request during forwarding. Support: Extended properties: hostname: description: |- Hostname is the value to be used to replace the Host header value during forwarding. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines a path rewrite. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" type: object required: - type type: object x-kubernetes-validations: - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier rule: "!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type rule: "!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier rule: "!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type rule: "!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" - message: filter.requestMirror must be nil if the filter.type is not RequestMirror rule: "!(has(self.requestMirror) && self.type != 'RequestMirror')" - message: filter.requestMirror must be specified for RequestMirror filter.type rule: "!(!has(self.requestMirror) && self.type == 'RequestMirror')" - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect rule: "!(has(self.requestRedirect) && self.type != 'RequestRedirect')" - message: filter.requestRedirect must be specified for RequestRedirect filter.type rule: "!(!has(self.requestRedirect) && self.type == 'RequestRedirect')" - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite rule: "!(has(self.urlRewrite) && self.type != 'URLRewrite')" - message: filter.urlRewrite must be specified for URLRewrite filter.type rule: "!(!has(self.urlRewrite) && self.type == 'URLRewrite')" - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef rule: "!(has(self.extensionRef) && self.type != 'ExtensionRef')" - message: filter.extensionRef must be specified for ExtensionRef filter.type rule: "!(!has(self.extensionRef) && self.type == 'ExtensionRef')" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: "!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 - message: ResponseHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 - message: RequestRedirect filter cannot be repeated rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 - message: URLRewrite filter cannot be repeated rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 matches: default: - path: type: PathPrefix value: / description: |- Matches define conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. For example, take the following matches configuration: ``` matches: - path: value: "/foo" headers: - name: "version" value: "v2" - path: value: "/v2/foo" ``` For a request to match against this rule, a request must satisfy EITHER of the two conditions: - path prefixed with `/foo` AND contains the header `version: v2` - path prefix of `/v2/foo` See the documentation for HTTPRouteMatch on how to specify multiple match conditions that should be ANDed together. If no matches are specified, the default is a prefix path match on "/", which has the effect of matching every HTTP request. Proxy or Load Balancer routing configuration generated from HTTPRoutes MUST prioritize matches based on the following criteria, continuing on ties. Across all rules specified on applicable Routes, precedence must be given to the match having: * "Exact" path match. * "Prefix" path match with largest number of characters. * Method match. * Largest number of header matches. * Largest number of query param matches. Note: The precedence of RegularExpression path matches are implementation-specific. If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by "{namespace}/{name}". If ties still exist within an HTTPRoute, matching precedence MUST be granted to the FIRST matching rule (in list order) with a match meeting the above criteria. When no rules matching a request have been successfully attached to the parent a request is coming from, a HTTP 404 status code MUST be returned. items: description: "HTTPRouteMatch defines the predicate used to match requests to a given\naction. Multiple match types are ANDed together, i.e. the match will\nevaluate to true only if all conditions are satisfied.\n\nFor example, the match below will match a HTTP request only if its path\nstarts with `/foo` AND it contains the `version: v1` header:\n\n```\nmatch:\n\n\tpath:\n\t \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t \ value \"v1\"\n\n```" properties: headers: description: |- Headers specifies HTTP request header matchers. Multiple match values are ANDed together, meaning, a request must match all the specified headers to select the route. items: description: |- HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request headers. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. When a header is repeated in an HTTP request, it is implementation-specific behavior as to how this is represented. Generally, proxies should follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding processing a repeated header, with special handling for "Set-Cookie". maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: default: Exact description: |- Type specifies how to match against the value of the header. Support: Core (Exact) Support: Implementation-specific (RegularExpression) Since RegularExpression HeaderMatchType has implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect. enum: - Exact - RegularExpression type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map method: description: |- Method specifies HTTP method matcher. When specified, this route will be matched only if the request has the specified method. Support: Extended enum: - GET - HEAD - POST - PUT - DELETE - CONNECT - OPTIONS - TRACE - PATCH type: string path: default: type: PathPrefix value: / description: |- Path specifies a HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. properties: type: default: PathPrefix description: |- Type specifies how to match against the path Value. Support: Core (Exact, PathPrefix) Support: Implementation-specific (RegularExpression) enum: - Exact - PathPrefix - RegularExpression type: string value: default: / description: Value of the HTTP path to match against. maxLength: 1024 type: string type: object x-kubernetes-validations: - message: value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? self.value.startsWith('/') : true" - message: must not contain '//' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('//') : true" - message: must not contain '/./' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/./') : true" - message: must not contain '/../' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/../') : true" - message: must not contain '%2f' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2f') : true" - message: must not contain '%2F' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2F') : true" - message: must not contain '#' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('#') : true" - message: must not end with '/..' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/..') : true" - message: must not end with '/.' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/.') : true" - message: type must be one of ['Exact', 'PathPrefix', 'RegularExpression'] rule: self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression' - message: must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix'] rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") : true' queryParams: description: |- QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, meaning, a request must match all the specified query parameters to select the route. Support: Extended items: description: |- HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP query parameters. properties: name: description: |- Name is the name of the HTTP query param to be matched. This must be an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). If multiple entries specify equivalent query param names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent query param name MUST be ignored. If a query param is repeated in an HTTP request, the behavior is purposely left undefined, since different data planes have different capabilities. However, it is *recommended* that implementations should match against the first value of the param if the data plane supports it, as this behavior is expected in other load balancing contexts outside of the Gateway API. Users SHOULD NOT route traffic based on repeated query params to guard themselves against potential differences in the implementations. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: default: Exact description: |- Type specifies how to match against the value of the query parameter. Support: Extended (Exact) Support: Implementation-specific (RegularExpression) Since RegularExpression QueryParamMatchType has Implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect. enum: - Exact - RegularExpression type: string value: description: Value is the value of HTTP query param to be matched. maxLength: 1024 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object maxItems: 64 type: array x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string timeouts: description: |- Timeouts defines the timeouts that can be configured for an HTTP request. Support: Extended properties: backendRequest: description: |- BackendRequest specifies a timeout for an individual request from the gateway to a backend. This covers the time from when the request first starts being sent from the gateway to when the full response has been received from the backend. Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout completely. Implementations that cannot completely disable the timeout MUST instead interpret the zero duration as the longest possible value to which the timeout can be set. An entire client HTTP transaction with a gateway, covered by the Request timeout, may result in more than one call from the gateway to the destination backend, for example, if automatic retries are supported. The value of BackendRequest must be a Gateway API Duration string as defined by GEP-2257. When this field is unspecified, its behavior is implementation-specific; when specified, the value of BackendRequest must be no more than the value of the Request timeout (since the Request timeout encompasses the BackendRequest timeout). Support: Extended pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string request: description: |- Request specifies the maximum duration for a gateway to respond to an HTTP request. If the gateway has not been able to respond before this deadline is met, the gateway MUST return a timeout error. For example, setting the `rules.timeouts.request` field to the value `10s` in an `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds to complete. Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout completely. Implementations that cannot completely disable the timeout MUST instead interpret the zero duration as the longest possible value to which the timeout can be set. This timeout is intended to cover as close to the whole request-response transaction as possible although an implementation MAY choose to start the timeout after the entire request stream has been received instead of immediately after the transaction is initiated by the client. The value of Request is a Gateway API Duration string as defined by GEP-2257. When this field is unspecified, request timeout behavior is implementation-specific. Support: Extended pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string type: object x-kubernetes-validations: - message: backendRequest timeout cannot be longer than request timeout rule: "!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration('0s') && duration(self.backendRequest) > duration(self.request))" type: object x-kubernetes-validations: - message: RequestRedirect filter must not be used together with backendRefs rule: "(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true" - message: When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" - message: When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" - message: Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" - message: Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128 rule: "(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128" type: object status: description: Status defines the current state of HTTPRoute. properties: parents: description: |- Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway. items: description: |- RouteParentStatus describes the status of a route with respect to an associated Parent. properties: conditions: description: |- Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the "Accepted" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. A Route MUST be considered "Accepted" if at least one of the Route's rules is implemented by the Gateway. There are a number of cases where the "Accepted" condition may not be set due to lack of controller visibility, that includes when: * The Route refers to a nonexistent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 minItems: 1 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map controllerName: description: |- ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. Example: "example.net/gateway-controller". The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string parentRef: description: |- ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object required: - conditions - controllerName - parentRef type: object maxItems: 32 type: array x-kubernetes-list-type: atomic required: - parents type: object required: - spec type: object served: true storage: true subresources: status: {} - additionalPrinterColumns: - jsonPath: .spec.hostnames name: Hostnames type: string - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta1 schema: openAPIV3Schema: description: |- HTTPRoute provides a way to route HTTP requests. This includes the capability to match requests by hostname, path, header, or query param. Filters can be used to specify additional processing steps. Backends specify where matching requests should be routed. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of HTTPRoute. properties: hostnames: description: |- Hostnames defines a set of hostnames that should match against the HTTP Host header to select a HTTPRoute used to process the request. Implementations MUST ignore any port value specified in the HTTP Host header while performing a match and (absent of any applicable header modification configuration) MUST forward this header unmodified to the backend. Valid values for Hostnames are determined by RFC 1123 definition of a hostname with 2 notable exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. If a hostname is specified by both the Listener and HTTPRoute, there must be at least one intersecting hostname for the HTTPRoute to be attached to the Listener. For example: * A Listener with `test.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `*.example.com`, `test.example.com`, and `foo.test.example.com` would all match. On the other hand, `example.com` and `test.example.net` would not match. Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. If both the Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the HTTPRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match. If both the Listener and HTTPRoute have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. overlapping wildcard matching and exact matching hostnames), precedence must be given to rules from the HTTPRoute with the largest number of: * Characters in a matching non-wildcard hostname. * Characters in a matching hostname. If ties exist across multiple Routes, the matching precedence rules for HTTPRouteMatches takes over. Support: Core items: description: |- Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. Hostname can be "precise" which is a domain name without the terminating dot of a network host (e.g. "foo.example.com") or "wildcard", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed. maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string maxItems: 16 type: array x-kubernetes-list-type: atomic parentRefs: description: |- ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a "producer" route, or the mesh implementation must support and allow "consumer" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a "producer" route for a Service in a different namespace from the Route. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. ParentRefs must be _distinct_. This means either that: * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. Some examples: * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. items: description: |- ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object maxItems: 32 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: sectionName must be specified when parentRefs includes 2 or more references to the same parent rule: "self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName) || p1.sectionName == '') == (!has(p2.sectionName) || p2.sectionName == '')) : true))" - message: sectionName must be unique when parentRefs includes 2 or more references to the same parent rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)))) rules: default: - matches: - path: type: PathPrefix value: / description: Rules are a list of HTTP matchers, filters and actions. items: description: |- HTTPRouteRule defines semantics for matching an HTTP request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). properties: backendRefs: description: |- BackendRefs defines the backend(s) where matching requests should be sent. Failure behavior here depends on how many BackendRefs are specified and how many are invalid. If *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive a 500 status code. See the HTTPBackendRef definition for the rules about what makes a single HTTPBackendRef invalid. When a HTTPBackendRef is invalid, 500 status codes MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive a 500 status code. For example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic must receive a 500. Implementations may choose how that 50 percent is determined. When a HTTPBackendRef refers to a Service that has no ready endpoints, implementations SHOULD return a 503 for requests to that backend instead. If an implementation chooses to do this, all of the above rules for 500 responses MUST also apply for responses that return a 503. Support: Core for Kubernetes Service Support: Extended for Kubernetes ServiceImport Support: Implementation-specific for any other resource Support for weight: Core items: description: |- HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. properties: filters: description: |- Filters defined at this level should be executed if and only if the request is being forwarded to the backend defined here. Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.) items: description: |- HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. properties: extensionRef: description: |- ExtensionRef is an optional, implementation-specific extension to the "filter" behavior. For example, resource "myroutefilter" in group "networking.example.net"). ExtensionRef MUST NOT be used for core and extended filters. This filter can be used multiple times within the same rule. Support: Implementation-specific properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request headers. Support: Core properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object requestMirror: description: |- RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. Support: Extended properties: backendRef: description: |- BackendRef references a resource where mirrored requests are sent. Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the "ResolvedRefs" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the "ResolvedRefs" condition on the Route is set to `status: False`, with the "RefNotPermitted" reason and not configure this backend in the underlying implementation. In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" fraction: description: |- Fraction represents the fraction of requests that should be mirrored to BackendRef. Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. properties: denominator: default: 100 format: int32 minimum: 1 type: integer numerator: format: int32 minimum: 0 type: integer required: - numerator type: object x-kubernetes-validations: - message: numerator must be less than or equal to denominator rule: self.numerator <= self.denominator percent: description: |- Percent represents the percentage of requests that should be mirrored to BackendRef. Its minimum value is 0 (indicating 0% of requests) and its maximum value is 100 (indicating 100% of requests). Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. format: int32 maximum: 100 minimum: 0 type: integer required: - backendRef type: object x-kubernetes-validations: - message: Only one of percent or fraction may be specified in HTTPRequestMirrorFilter rule: "!(has(self.percent) && has(self.fraction))" requestRedirect: description: |- RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. Support: Core properties: hostname: description: |- Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: description: |- Port is the port to be used in the value of the `Location` header in the response. If no port is specified, the redirect port MUST be derived using the following rules: * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically "http" to port 80 and "https" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: description: |- Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Extended enum: - http - https type: string statusCode: default: 302 description: |- StatusCode is the HTTP status code to be used in response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: description: |- ResponseHeaderModifier defines a schema for a filter that modifies response headers. Support: Extended properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object type: description: |- Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: - Core: Filter types and their corresponding configuration defined by "Support: Core" in this package, e.g. "RequestHeaderModifier". All implementations must support core filters. - Extended: Filter types and their corresponding configuration defined by "Support: Extended" in this package, e.g. "RequestMirror". Implementers are encouraged to support extended filters. - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to "ExtensionRef" for custom filters. Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier - RequestMirror - RequestRedirect - URLRewrite - ExtensionRef type: string urlRewrite: description: |- URLRewrite defines a schema for a filter that modifies a request during forwarding. Support: Extended properties: hostname: description: |- Hostname is the value to be used to replace the Host header value during forwarding. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines a path rewrite. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" type: object required: - type type: object x-kubernetes-validations: - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier rule: "!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type rule: "!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier rule: "!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type rule: "!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" - message: filter.requestMirror must be nil if the filter.type is not RequestMirror rule: "!(has(self.requestMirror) && self.type != 'RequestMirror')" - message: filter.requestMirror must be specified for RequestMirror filter.type rule: "!(!has(self.requestMirror) && self.type == 'RequestMirror')" - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect rule: "!(has(self.requestRedirect) && self.type != 'RequestRedirect')" - message: filter.requestRedirect must be specified for RequestRedirect filter.type rule: "!(!has(self.requestRedirect) && self.type == 'RequestRedirect')" - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite rule: "!(has(self.urlRewrite) && self.type != 'URLRewrite')" - message: filter.urlRewrite must be specified for URLRewrite filter.type rule: "!(!has(self.urlRewrite) && self.type == 'URLRewrite')" - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef rule: "!(has(self.extensionRef) && self.type != 'ExtensionRef')" - message: filter.extensionRef must be specified for ExtensionRef filter.type rule: "!(!has(self.extensionRef) && self.type == 'ExtensionRef')" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: "!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 - message: ResponseHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 - message: RequestRedirect filter cannot be repeated rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 - message: URLRewrite filter cannot be repeated rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer weight: default: 1 description: |- Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. Support for this field varies based on the context where used. format: int32 maximum: 1000000 minimum: 0 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" maxItems: 16 type: array x-kubernetes-list-type: atomic filters: description: |- Filters define the filters that are applied to requests that match this rule. Wherever possible, implementations SHOULD implement filters in the order they are specified. Implementations MAY choose to implement this ordering strictly, rejecting any combination or order of filters that cannot be supported. If implementations choose a strict interpretation of filter ordering, they MUST clearly document that behavior. To reject an invalid combination or order of filters, implementations SHOULD consider the Route Rules with this configuration invalid. If all Route Rules in a Route are invalid, the entire Route would be considered invalid. If only a portion of Route Rules are invalid, implementations MUST set the "PartiallyInvalid" condition for the Route. Conformance-levels at this level are defined based on the type of filter: - ALL core filters MUST be supported by all implementations. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across implementations. Specifying the same filter multiple times is not supported unless explicitly indicated in the filter. All filters are expected to be compatible with each other except for the URLRewrite and RequestRedirect filters, which may not be combined. If an implementation cannot support other combinations of filters, they must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error. Support: Core items: description: |- HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. properties: extensionRef: description: |- ExtensionRef is an optional, implementation-specific extension to the "filter" behavior. For example, resource "myroutefilter" in group "networking.example.net"). ExtensionRef MUST NOT be used for core and extended filters. This filter can be used multiple times within the same rule. Support: Implementation-specific properties: group: description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: Kind is kind of the referent. For example "HTTPRoute" or "Service". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string required: - group - kind - name type: object requestHeaderModifier: description: |- RequestHeaderModifier defines a schema for a filter that modifies request headers. Support: Core properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object requestMirror: description: |- RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. Support: Extended properties: backendRef: description: |- BackendRef references a resource where mirrored requests are sent. Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the "ResolvedRefs" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the "ResolvedRefs" condition on the Route is set to `status: False`, with the "RefNotPermitted" reason and not configure this backend in the underlying implementation. In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. Support: Extended for Kubernetes Service Support: Implementation-specific for any other resource properties: group: default: "" description: |- Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service description: |- Kind is the Kubernetes resource kind of the referent. For example "Service". Defaults to "Service" when not specified. ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. Support: Core (Services with a type other than ExternalName) Support: Implementation-specific (Services with type ExternalName) maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: Name is the name of the referent. maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer required: - name type: object x-kubernetes-validations: - message: Must have port for Service reference rule: "(size(self.group) == 0 && self.kind == 'Service') ? has(self.port) : true" fraction: description: |- Fraction represents the fraction of requests that should be mirrored to BackendRef. Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. properties: denominator: default: 100 format: int32 minimum: 1 type: integer numerator: format: int32 minimum: 0 type: integer required: - numerator type: object x-kubernetes-validations: - message: numerator must be less than or equal to denominator rule: self.numerator <= self.denominator percent: description: |- Percent represents the percentage of requests that should be mirrored to BackendRef. Its minimum value is 0 (indicating 0% of requests) and its maximum value is 100 (indicating 100% of requests). Only one of Fraction or Percent may be specified. If neither field is specified, 100% of requests will be mirrored. format: int32 maximum: 100 minimum: 0 type: integer required: - backendRef type: object x-kubernetes-validations: - message: Only one of percent or fraction may be specified in HTTPRequestMirrorFilter rule: "!(has(self.percent) && has(self.fraction))" requestRedirect: description: |- RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. Support: Core properties: hostname: description: |- Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" port: description: |- Port is the port to be used in the value of the `Location` header in the response. If no port is specified, the redirect port MUST be derived using the following rules: * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically "http" to port 80 and "https" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer scheme: description: |- Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Extended enum: - http - https type: string statusCode: default: 302 description: |- StatusCode is the HTTP status code to be used in response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. Support: Core enum: - 301 - 302 type: integer type: object responseHeaderModifier: description: |- ResponseHeaderModifier defines a schema for a filter that modifies response headers. Support: Extended properties: add: description: |- Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. Input: GET /foo HTTP/1.1 my-header: foo Config: add: - name: "my-header" value: "bar,baz" Output: GET /foo HTTP/1.1 my-header: foo,bar,baz items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map remove: description: |- Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz Config: remove: ["my-header1", "my-header3"] Output: GET /foo HTTP/1.1 my-header2: bar items: type: string maxItems: 16 type: array x-kubernetes-list-type: set set: description: |- Set overwrites the request with the given header (name, value) before the action. Input: GET /foo HTTP/1.1 my-header: foo Config: set: - name: "my-header" value: "bar" Output: GET /foo HTTP/1.1 my-header: bar items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object type: description: |- Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: - Core: Filter types and their corresponding configuration defined by "Support: Core" in this package, e.g. "RequestHeaderModifier". All implementations must support core filters. - Extended: Filter types and their corresponding configuration defined by "Support: Extended" in this package, e.g. "RequestMirror". Implementers are encouraged to support extended filters. - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to "ExtensionRef" for custom filters. Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - RequestHeaderModifier - ResponseHeaderModifier - RequestMirror - RequestRedirect - URLRewrite - ExtensionRef type: string urlRewrite: description: |- URLRewrite defines a schema for a filter that modifies a request during forwarding. Support: Extended properties: hostname: description: |- Hostname is the value to be used to replace the Host header value during forwarding. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string path: description: |- Path defines a path rewrite. Support: Extended properties: replaceFullPath: description: |- ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. maxLength: 1024 type: string replacePrefixMatch: description: |- ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch of "/xyz" would be modified to "/xyz/bar". Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. Request Path | Prefix Match | Replace Prefix | Modified Path maxLength: 1024 type: string type: description: |- Type defines the type of path modifier. Additional types may be added in a future release of the API. Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. enum: - ReplaceFullPath - ReplacePrefixMatch type: string required: - type type: object x-kubernetes-validations: - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' rule: "self.type == 'ReplaceFullPath' ? has(self.replaceFullPath) : true" - message: type must be 'ReplaceFullPath' when replaceFullPath is set rule: "has(self.replaceFullPath) ? self.type == 'ReplaceFullPath' : true" - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' rule: "self.type == 'ReplacePrefixMatch' ? has(self.replacePrefixMatch) : true" - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set rule: "has(self.replacePrefixMatch) ? self.type == 'ReplacePrefixMatch' : true" type: object required: - type type: object x-kubernetes-validations: - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier rule: "!(has(self.requestHeaderModifier) && self.type != 'RequestHeaderModifier')" - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type rule: "!(!has(self.requestHeaderModifier) && self.type == 'RequestHeaderModifier')" - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier rule: "!(has(self.responseHeaderModifier) && self.type != 'ResponseHeaderModifier')" - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type rule: "!(!has(self.responseHeaderModifier) && self.type == 'ResponseHeaderModifier')" - message: filter.requestMirror must be nil if the filter.type is not RequestMirror rule: "!(has(self.requestMirror) && self.type != 'RequestMirror')" - message: filter.requestMirror must be specified for RequestMirror filter.type rule: "!(!has(self.requestMirror) && self.type == 'RequestMirror')" - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect rule: "!(has(self.requestRedirect) && self.type != 'RequestRedirect')" - message: filter.requestRedirect must be specified for RequestRedirect filter.type rule: "!(!has(self.requestRedirect) && self.type == 'RequestRedirect')" - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite rule: "!(has(self.urlRewrite) && self.type != 'URLRewrite')" - message: filter.urlRewrite must be specified for URLRewrite filter.type rule: "!(!has(self.urlRewrite) && self.type == 'URLRewrite')" - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef rule: "!(has(self.extensionRef) && self.type != 'ExtensionRef')" - message: filter.extensionRef must be specified for ExtensionRef filter.type rule: "!(!has(self.extensionRef) && self.type == 'ExtensionRef')" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both rule: "!(self.exists(f, f.type == 'RequestRedirect') && self.exists(f, f.type == 'URLRewrite'))" - message: RequestHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 - message: ResponseHeaderModifier filter cannot be repeated rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 - message: RequestRedirect filter cannot be repeated rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 - message: URLRewrite filter cannot be repeated rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 matches: default: - path: type: PathPrefix value: / description: |- Matches define conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. For example, take the following matches configuration: ``` matches: - path: value: "/foo" headers: - name: "version" value: "v2" - path: value: "/v2/foo" ``` For a request to match against this rule, a request must satisfy EITHER of the two conditions: - path prefixed with `/foo` AND contains the header `version: v2` - path prefix of `/v2/foo` See the documentation for HTTPRouteMatch on how to specify multiple match conditions that should be ANDed together. If no matches are specified, the default is a prefix path match on "/", which has the effect of matching every HTTP request. Proxy or Load Balancer routing configuration generated from HTTPRoutes MUST prioritize matches based on the following criteria, continuing on ties. Across all rules specified on applicable Routes, precedence must be given to the match having: * "Exact" path match. * "Prefix" path match with largest number of characters. * Method match. * Largest number of header matches. * Largest number of query param matches. Note: The precedence of RegularExpression path matches are implementation-specific. If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by "{namespace}/{name}". If ties still exist within an HTTPRoute, matching precedence MUST be granted to the FIRST matching rule (in list order) with a match meeting the above criteria. When no rules matching a request have been successfully attached to the parent a request is coming from, a HTTP 404 status code MUST be returned. items: description: "HTTPRouteMatch defines the predicate used to match requests to a given\naction. Multiple match types are ANDed together, i.e. the match will\nevaluate to true only if all conditions are satisfied.\n\nFor example, the match below will match a HTTP request only if its path\nstarts with `/foo` AND it contains the `version: v1` header:\n\n```\nmatch:\n\n\tpath:\n\t \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t \ value \"v1\"\n\n```" properties: headers: description: |- Headers specifies HTTP request header matchers. Multiple match values are ANDed together, meaning, a request must match all the specified headers to select the route. items: description: |- HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request headers. properties: name: description: |- Name is the name of the HTTP Header to be matched. Name matching MUST be case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, "foo" and "Foo" are considered equivalent. When a header is repeated in an HTTP request, it is implementation-specific behavior as to how this is represented. Generally, proxies should follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding processing a repeated header, with special handling for "Set-Cookie". maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: default: Exact description: |- Type specifies how to match against the value of the header. Support: Core (Exact) Support: Implementation-specific (RegularExpression) Since RegularExpression HeaderMatchType has implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect. enum: - Exact - RegularExpression type: string value: description: Value is the value of HTTP Header to be matched. maxLength: 4096 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map method: description: |- Method specifies HTTP method matcher. When specified, this route will be matched only if the request has the specified method. Support: Extended enum: - GET - HEAD - POST - PUT - DELETE - CONNECT - OPTIONS - TRACE - PATCH type: string path: default: type: PathPrefix value: / description: |- Path specifies a HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. properties: type: default: PathPrefix description: |- Type specifies how to match against the path Value. Support: Core (Exact, PathPrefix) Support: Implementation-specific (RegularExpression) enum: - Exact - PathPrefix - RegularExpression type: string value: default: / description: Value of the HTTP path to match against. maxLength: 1024 type: string type: object x-kubernetes-validations: - message: value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? self.value.startsWith('/') : true" - message: must not contain '//' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('//') : true" - message: must not contain '/./' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/./') : true" - message: must not contain '/../' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('/../') : true" - message: must not contain '%2f' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2f') : true" - message: must not contain '%2F' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('%2F') : true" - message: must not contain '#' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.contains('#') : true" - message: must not end with '/..' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/..') : true" - message: must not end with '/.' when type one of ['Exact', 'PathPrefix'] rule: "(self.type in ['Exact','PathPrefix']) ? !self.value.endsWith('/.') : true" - message: type must be one of ['Exact', 'PathPrefix', 'RegularExpression'] rule: self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression' - message: must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix'] rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") : true' queryParams: description: |- QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, meaning, a request must match all the specified query parameters to select the route. Support: Extended items: description: |- HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP query parameters. properties: name: description: |- Name is the name of the HTTP query param to be matched. This must be an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). If multiple entries specify equivalent query param names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent query param name MUST be ignored. If a query param is repeated in an HTTP request, the behavior is purposely left undefined, since different data planes have different capabilities. However, it is *recommended* that implementations should match against the first value of the param if the data plane supports it, as this behavior is expected in other load balancing contexts outside of the Gateway API. Users SHOULD NOT route traffic based on repeated query params to guard themselves against potential differences in the implementations. maxLength: 256 minLength: 1 pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: default: Exact description: |- Type specifies how to match against the value of the query parameter. Support: Extended (Exact) Support: Implementation-specific (RegularExpression) Since RegularExpression QueryParamMatchType has Implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect. enum: - Exact - RegularExpression type: string value: description: Value is the value of HTTP query param to be matched. maxLength: 1024 minLength: 1 type: string required: - name - value type: object maxItems: 16 type: array x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map type: object maxItems: 64 type: array x-kubernetes-list-type: atomic name: description: |- Name is the name of the route rule. This name MUST be unique within a Route if it is set. Support: Extended maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string timeouts: description: |- Timeouts defines the timeouts that can be configured for an HTTP request. Support: Extended properties: backendRequest: description: |- BackendRequest specifies a timeout for an individual request from the gateway to a backend. This covers the time from when the request first starts being sent from the gateway to when the full response has been received from the backend. Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout completely. Implementations that cannot completely disable the timeout MUST instead interpret the zero duration as the longest possible value to which the timeout can be set. An entire client HTTP transaction with a gateway, covered by the Request timeout, may result in more than one call from the gateway to the destination backend, for example, if automatic retries are supported. The value of BackendRequest must be a Gateway API Duration string as defined by GEP-2257. When this field is unspecified, its behavior is implementation-specific; when specified, the value of BackendRequest must be no more than the value of the Request timeout (since the Request timeout encompasses the BackendRequest timeout). Support: Extended pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string request: description: |- Request specifies the maximum duration for a gateway to respond to an HTTP request. If the gateway has not been able to respond before this deadline is met, the gateway MUST return a timeout error. For example, setting the `rules.timeouts.request` field to the value `10s` in an `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds to complete. Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout completely. Implementations that cannot completely disable the timeout MUST instead interpret the zero duration as the longest possible value to which the timeout can be set. This timeout is intended to cover as close to the whole request-response transaction as possible although an implementation MAY choose to start the timeout after the entire request stream has been received instead of immediately after the transaction is initiated by the client. The value of Request is a Gateway API Duration string as defined by GEP-2257. When this field is unspecified, request timeout behavior is implementation-specific. Support: Extended pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string type: object x-kubernetes-validations: - message: backendRequest timeout cannot be longer than request timeout rule: "!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration('0s') && duration(self.backendRequest) > duration(self.request))" type: object x-kubernetes-validations: - message: RequestRedirect filter must not be used together with backendRefs rule: "(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true" - message: When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" - message: When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" - message: Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == 'ReplacePrefixMatch' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" - message: Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified rule: "(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == 'ReplacePrefixMatch' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != 'PathPrefix') ? false : true) : true" maxItems: 16 type: array x-kubernetes-list-type: atomic x-kubernetes-validations: - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128 rule: "(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128" type: object status: description: Status defines the current state of HTTPRoute. properties: parents: description: |- Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway. items: description: |- RouteParentStatus describes the status of a route with respect to an associated Parent. properties: conditions: description: |- Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the "Accepted" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. A Route MUST be considered "Accepted" if at least one of the Route's rules is implemented by the Gateway. There are a number of cases where the "Accepted" condition may not be set due to lack of controller visibility, that includes when: * The Route refers to a nonexistent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to. items: description: Condition contains details for one aspect of the current state of this API Resource. properties: lastTransitionTime: description: |- lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. format: date-time type: string message: description: |- message is a human readable message indicating details about the transition. This may be an empty string. maxLength: 32768 type: string observedGeneration: description: |- observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. format: int64 minimum: 0 type: integer reason: description: |- reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. maxLength: 1024 minLength: 1 pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ type: string status: description: status of the condition, one of True, False, Unknown. enum: - "True" - "False" - Unknown type: string type: description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string required: - lastTransitionTime - message - reason - status - type type: object maxItems: 8 minItems: 1 type: array x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map controllerName: description: |- ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. Example: "example.net/gateway-controller". The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string parentRef: description: |- ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. properties: group: default: gateway.networking.k8s.io description: |- Group is the group of the referent. When unspecified, "gateway.networking.k8s.io" is inferred. To set the core API group (such as for a "Service" kind referent), Group must be explicitly set to "" (empty string). Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway description: |- Kind is kind of the referent. There are two kinds of parent resources with "Core" support: * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, ClusterIP Services only) Support for other resources is Implementation-Specific. maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. Support: Core maxLength: 253 minLength: 1 type: string namespace: description: |- Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: description: |- Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Extended format: int32 maximum: 65535 minimum: 1 type: integer sectionName: description: |- SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: * Gateway: Listener name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. Support: Core maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - name type: object required: - conditions - controllerName - parentRef type: object maxItems: 32 type: array x-kubernetes-list-type: atomic required: - parents type: object required: - spec type: object served: true storage: false subresources: status: {} status: acceptedNames: kind: "" plural: "" conditions: null storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/3328 gateway.networking.k8s.io/bundle-version: v1.4.0 gateway.networking.k8s.io/channel: standard name: referencegrants.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api kind: ReferenceGrant listKind: ReferenceGrantList plural: referencegrants shortNames: - refgrant singular: referencegrant scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age type: date name: v1beta1 schema: openAPIV3Schema: description: |- ReferenceGrant identifies kinds of resources in other namespaces that are trusted to reference the specified kinds of resources in the same namespace as the policy. Each ReferenceGrant can be used to represent a unique trust relationship. Additional Reference Grants can be used to add to the set of trusted sources of inbound references for the namespace they are defined within. All cross-namespace references in Gateway API (with the exception of cross-namespace Gateway-route attachment) require a ReferenceGrant. ReferenceGrant is a form of runtime verification allowing users to assert which cross-namespace object references are permitted. Implementations that support ReferenceGrant MUST NOT permit cross-namespace references which have no grant, and MUST respond to the removal of a grant by revoking the access that the grant allowed. properties: apiVersion: description: |- APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: description: |- Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: description: Spec defines the desired state of ReferenceGrant. properties: from: description: |- From describes the trusted namespaces and kinds that can reference the resources described in "To". Each entry in this list MUST be considered to be an additional place that references can be valid from, or to put this another way, entries MUST be combined using OR. Support: Core items: description: ReferenceGrantFrom describes trusted namespaces and kinds. properties: group: description: |- Group is the group of the referent. When empty, the Kubernetes core API group is inferred. Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: |- Kind is the kind of the referent. Although implementations may support additional resources, the following types are part of the "Core" support level for this field. When used to permit a SecretObjectReference: * Gateway When used to permit a BackendObjectReference: * GRPCRoute * HTTPRoute * TCPRoute * TLSRoute * UDPRoute maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string namespace: description: |- Namespace is the namespace of the referent. Support: Core maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - group - kind - namespace type: object maxItems: 16 minItems: 1 type: array x-kubernetes-list-type: atomic to: description: |- To describes the resources that may be referenced by the resources described in "From". Each entry in this list MUST be considered to be an additional place that references can be valid to, or to put this another way, entries MUST be combined using OR. Support: Core items: description: |- ReferenceGrantTo describes what Kinds are allowed as targets of the references. properties: group: description: |- Group is the group of the referent. When empty, the Kubernetes core API group is inferred. Support: Core maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: description: |- Kind is the kind of the referent. Although implementations may support additional resources, the following types are part of the "Core" support level for this field: * Secret when used to permit a SecretObjectReference * Service when used to permit a BackendObjectReference maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: description: |- Name is the name of the referent. When unspecified, this policy refers to all resources of the specified Group and Kind in the local namespace. maxLength: 253 minLength: 1 type: string required: - group - kind type: object maxItems: 16 minItems: 1 type: array x-kubernetes-list-type: atomic required: - from - to type: object type: object served: true storage: true subresources: {} status: acceptedNames: kind: "" plural: "" conditions: null storedVersions: null ================================================ FILE: cluster/homelab/crds/gateway-api/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - crds.yaml ================================================ FILE: cluster/homelab/crds/istio/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istio-base namespace: istio-system spec: interval: 10m install: createNamespace: true upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: base version: 1.29.2 interval: 10m sourceRef: kind: HelmRepository name: istio namespace: flux-system ================================================ FILE: cluster/homelab/crds/istio/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/crds/istio/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: istio-system ================================================ FILE: cluster/homelab/crds/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - gateway-api - external-snapshotter # Velero gives an error if VolumeSnapshotClasses is missing - istio - mariadb-operator ================================================ FILE: cluster/homelab/crds/mariadb-operator/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: mariadb-operator-crds namespace: mariadb-operator spec: interval: 10m install: createNamespace: true upgrade: crds: CreateReplace remediation: retries: 3 chart: spec: chart: mariadb-operator-crds version: "26.3.0" interval: 10m sourceRef: kind: HelmRepository name: mariadb-operator namespace: flux-system ================================================ FILE: cluster/homelab/crds/mariadb-operator/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml - namespace.yaml ================================================ FILE: cluster/homelab/crds/mariadb-operator/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: mariadb-operator ================================================ FILE: cluster/homelab/helm/aqua/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/aqua/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: aqua namespace: flux-system spec: url: https://aquasecurity.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/bjw-s/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/bjw-s/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: bjw-s namespace: flux-system spec: url: https://bjw-s-labs.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/cert-manager/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/cert-manager/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: cert-manager namespace: flux-system spec: url: https://charts.jetstack.io interval: 5m ================================================ FILE: cluster/homelab/helm/cnpg/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/cnpg/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: cnpg namespace: flux-system spec: url: https://cloudnative-pg.github.io/charts interval: 10m ================================================ FILE: cluster/homelab/helm/descheduler/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/descheduler/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: descheduler namespace: flux-system spec: url: https://kubernetes-sigs.github.io/descheduler/ interval: 5m ================================================ FILE: cluster/homelab/helm/gabe565/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/gabe565/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: gabe565 namespace: flux-system spec: url: https://charts.gabe565.com interval: 5m ================================================ FILE: cluster/homelab/helm/go-ddns-controller/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/go-ddns-controller/repo.yaml ================================================ apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: go-ddns-controller namespace: flux-system spec: interval: 10m url: https://github.com/Michaelpalacce/go-ddns-controller ref: branch: master ================================================ FILE: cluster/homelab/helm/istio/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/istio/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: istio namespace: flux-system spec: url: https://istio-release.storage.googleapis.com/charts interval: 5m ================================================ FILE: cluster/homelab/helm/k8s-at-home/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/k8s-at-home/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: k8s-at-home namespace: flux-system spec: url: https://k8s-at-home.com/charts interval: 5m ================================================ FILE: cluster/homelab/helm/kube-vip/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/kube-vip/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kube-vip namespace: flux-system spec: url: https://kube-vip.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/kubereboot/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/kubereboot/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kubereboot namespace: flux-system spec: url: https://kubereboot.github.io/charts interval: 10m ================================================ FILE: cluster/homelab/helm/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - aqua - cnpg - observability - k8s-at-home - metrics-server - unofficial - longhorn-system - cert-manager - reflector - velero - kube-vip - kyverno - kubereboot - descheduler - gabe565 - go-ddns-controller - metallb - tika - maikumori - mariadb-operator - bjw-s - wger - istio - tofu-controller ================================================ FILE: cluster/homelab/helm/kyverno/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/kyverno/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kyverno namespace: flux-system spec: url: https://kyverno.github.io/kyverno interval: 10m ================================================ FILE: cluster/homelab/helm/longhorn-system/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - longhorn-repo.yaml ================================================ FILE: cluster/homelab/helm/longhorn-system/longhorn-repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: longhorn-system namespace: flux-system spec: url: https://charts.longhorn.io interval: 5m ================================================ FILE: cluster/homelab/helm/maikumori/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/maikumori/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: maikumori namespace: flux-system spec: url: https://maikumori.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/mariadb-operator/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/mariadb-operator/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: mariadb-operator namespace: flux-system spec: url: https://helm.mariadb.com/mariadb-operator interval: 5m ================================================ FILE: cluster/homelab/helm/metallb/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/metallb/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: metallb namespace: flux-system spec: url: https://metallb.github.io/metallb interval: 10m ================================================ FILE: cluster/homelab/helm/metrics-server/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/metrics-server/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: metrics-server namespace: flux-system spec: url: https://kubernetes-sigs.github.io/metrics-server/ interval: 5m ================================================ FILE: cluster/homelab/helm/observability/kube-prometheus-stack.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kube-prometheus-stack namespace: flux-system spec: url: https://prometheus-community.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/observability/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - kube-prometheus-stack.yaml - loki-stack.yaml ================================================ FILE: cluster/homelab/helm/observability/loki-stack.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: grafana namespace: flux-system spec: url: https://grafana.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/reflector/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/reflector/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: reflector namespace: flux-system spec: url: https://emberstack.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/rook/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/rook/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: rook-release namespace: flux-system spec: url: https://charts.rook.io/release interval: 5m ================================================ FILE: cluster/homelab/helm/tika/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/tika/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: tika namespace: flux-system spec: url: https://apache.jfrog.io/artifactory/tika interval: 5m ================================================ FILE: cluster/homelab/helm/tofu-controller/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/tofu-controller/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: tofu-controller namespace: flux-system spec: interval: 10m url: https://flux-iac.github.io/tofu-controller ================================================ FILE: cluster/homelab/helm/unofficial/jameswynn.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: homepage namespace: flux-system spec: url: https://jameswynn.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/unofficial/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - jameswynn.yaml ================================================ FILE: cluster/homelab/helm/velero/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/velero/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: velero namespace: flux-system spec: url: https://vmware-tanzu.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/helm/wger/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - repo.yaml ================================================ FILE: cluster/homelab/helm/wger/repo.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: wger namespace: flux-system spec: url: https://wger-project.github.io/helm-charts interval: 5m ================================================ FILE: cluster/homelab/storage/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - rook-ceph-cluster ================================================ FILE: cluster/homelab/storage/rook-ceph-cluster/helm-release.yaml ================================================ --- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: rook-ceph-cluster namespace: rook-ceph spec: interval: 10m timeout: 15m install: createNamespace: true crds: CreateReplace remediation: retries: -1 upgrade: cleanupOnFail: true remediation: retries: 3 chart: spec: chart: rook-ceph-cluster version: v1.19.5 interval: 10m sourceRef: kind: HelmRepository name: rook-release namespace: flux-system values: cephClusterSpec: cephVersion: image: quay.io/ceph/ceph:v20.2.1 dataDirHostPath: /var/lib/rook mon: count: 3 allowMultiplePerNode: false # enable the ceph dashboard for viewing cluster status dashboard: enabled: true # serve the dashboard under a subpath (useful when you are accessing the dashboard via a reverse proxy) urlPrefix: / # serve the dashboard at the given port. # port: 8443 # Serve the dashboard using SSL (if using ingress to expose the dashboard and `ssl: true` you need to set # the corresponding "backend protocol" annotation(s) for your ingress controller of choice) ssl: true # cluster level storage configuration and selection storage: useAllNodes: true useAllDevices: true # Only create OSDs on devices that match the regular expression filter, "sdb" in this example # @WARN: THIS WILL TAKE OVER `sdb` ENTIRELY, MAKE SURE IT'S RESERVED ONLY FOR CEPH deviceFilter: sdb # To control where various services will be scheduled by kubernetes, use the placement configuration sections below. # The example under 'all' would have all services scheduled on kubernetes nodes labeled with 'role=rook-node' and # the OSDs would specifically only be created on nodes labeled with 'role=rook-osd-node'. placement: all: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: role operator: In values: - rook-node osd: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: role operator: In values: - rook-osd-node resources: prepareosd: requests: cpu: "200m" memory: "200Mi" priorityClassNames: # If there are multiple nodes available in a failure domain (e.g. zones), the # mons and osds can be portable and set the system-cluster-critical priority class. mon: system-node-critical osd: system-node-critical mgr: system-cluster-critical disruptionManagement: managePodBudgets: true osdMaintenanceTimeout: 30 ================================================ FILE: cluster/homelab/storage/rook-ceph-cluster/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helm-release.yaml ================================================ FILE: cluster/homelab/template.secret.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: template namespace: default data: BOT_TOKEN: aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjU ================================================ FILE: cluster/homelab/terraform/homelab-iac-secrets.sops.yaml ================================================ kind: Secret apiVersion: v1 type: Opaque metadata: name: homelab-iac-secrets namespace: flux-system stringData: proxmox_api_token: ENC[AES256_GCM,data:k1OPPtkCNJnFovB18MgziczSUbx1RXtwzXjzHWN+NsQTiwScI61KLXY7Qm9DUq7rypftBrp0oc++YqY=,iv:s98g+wEYC9Ic+XHhXLUbDxBUDjxOBRJy5PuELJK+o2Q=,tag:QAJHuev0cgCy6FUrthaLKQ==,type:str] proxmox_ssh_password: ENC[AES256_GCM,data:LYfJhr9X0TSN9bdTl4k=,iv:NrVNh0jqy9h0CJgCrUI9mAr33tlMGhFYgff1RTlj81s=,tag:nzA+WqOvwBga7BHPOv/tcA==,type:str] cloudflare_api_key: ENC[AES256_GCM,data:wSnkNHBPrZoJlN3ews545xACAujn6taN7KlSxYDzvvYOJhjURg==,iv:oHuSVDE8pGfwfU5dljymOwKXrk5JzNuGBTSst+wAdTI=,tag:YZ3dMY8RiiLaD3o6mvi0gw==,type:str] sops: age: - recipient: age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5RThCRFRjcXdBYnlLQVRO VFB2R3NWU0kxZWFtVkw3ZUt3VEZMbjdVM1NvCldLMzhML2FrUVk0TkVxSEI5NXRt Z2h1RndnalJyeHF0cUNSNUt2WHBoSkUKLS0tIDRvZXk4ZWdOQ2UyM3liYmpMeFdE Yit1ZmttWlN4MEFLcWJZb2tTOXlFdWMK+Zl+dJC6znE9IkTYfhZx+lhv9hLyQZBm bm+5PXtQ+a6VYd1QwZptFrKHHeAI/XlE3hUHwzTDpNDqzl9VeRpbMw== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-01-14T23:17:40Z" mac: ENC[AES256_GCM,data:RjyRmbflStWU0zrwUWRcnzv6/Pse9I1GEEoNJaw/C0a7zpoLfuFQNMVwHiWvymxSufUYWWGpRwCasDL1BDNBvBvfPleTagACFoKJJ6Yv0Y3mf9fARMEHMj0iRidxCBj2I1YbD0YIVkb+XUAuN5GVrxwAL5KvEs1qSnkYAQ2xvcY=,iv:OBcEIf3sNBQqUhIoIqxIQwWkx3IOQeaJ043nWOd5Us0=,tag:Th8MicA4tye8JO5wSiIUOA==,type:str] encrypted_regex: (?i)password|webhook_url|token|key version: 3.11.0 ================================================ FILE: cluster/homelab/terraform/homelab-iac.yaml ================================================ --- apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: homelab-iac namespace: flux-system spec: interval: 30s url: https://github.com/Michaelpalacce/HomeLab-IaC ref: branch: master --- apiVersion: infra.contrib.fluxcd.io/v1alpha2 kind: Terraform metadata: name: homelab-iac namespace: flux-system spec: interval: 10m approvePlan: auto path: ./ sourceRef: kind: GitRepository name: homelab-iac namespace: flux-system varsFrom: - kind: Secret name: homelab-iac-secrets storeReadablePlan: human ================================================ FILE: cluster/homelab/terraform/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - homelab-iac.yaml - homelab-iac-secrets.sops.yaml ================================================ FILE: docs/Backups.md ================================================ # Backups Backups are done via [Velero](https://github.com/vmware-tanzu/velero). Currently, my backups are done using the Velero helm chart. A Velero Schedule Custom resource is created for every day at 5 in the morning that backups a bunch of my services. # Manual steps and General Knowledge : ## Installation: 1. Create a bucket in AWS S3 ( Mine is called `sgenov-backup` ) 2. Create a IAM user with the correct policy for S3 3. Get the IAM user's credentials 4. Create a new file: `velero-credentials` in the root of the folder ( see how it should look down below ) 5. In the project root, run: `velero install --use-restic --provider aws --plugins velero/velero-plugin-for-aws --bucket sgenov-velero-backup --secret-file ./velero-credentials --backup-location-config region=eu-west-1 --snapshot-location-config region=eu-west-1` 1. Make sure the bucket is empty! 2. --use-restic is used to back up PVCs `velero-credentials`: ~~~ [default] aws_access_key_id= aws_secret_access_key= ~~~ ## Creating backups: ### Manual: `velero backup create uptimekuma --include-namespaces uptimekuma --snapshot-volumes=true` Will backup the namespace uptimekuma ### From Schedule: `velero create backup --from-schedule general` ## Restoring backups: When restoring backups Velero will not restore objects that are already existing, so whatever you need to restore must be deleted first. If you are restoring pods from a deployment/statefulset/daemonsets/etc make sure to delete them too. **NOTE:** Velero will hang up if it can't restore all the restic volumes, so you may need to remove the restore or it will be stuck in `In progress` ### Manual: 1. Clear up namespace 2. Run `velero restore create uptimekuma1 --from-backup uptimekuma --restore-volumes=true`. Optionally add: `--include-namespaces postgresql` ### From Schedule: 1. Clear up any resources you wish to restore 2. Run: `velero restore create --from-schedule general --restore-volumes=true`. Optionally add: `--include-namespaces postgresql` ================================================ FILE: docs/Flux.md ================================================ # Flux ## Flux bootstrap 1. Add env variable GITHUB_TOKEN 2. Run: `flux bootstrap github --owner=Michaelpalacce --repository=HomeLab --branch=master --path=./cluster/homelab/base --personal` 3. Flux needs to run a reconciliation after which it will bootstrap the cluster with all apps in order. 1. Note: **This will take a while** ## How does it work? `cluster/homelab/base` is the entrypoint. It holds Kustomizations for all the other 3 modules as well as the flux-system ( which is the flux installation ) Each Kustomization is a separate file with dependencies of one another. ### Steps of import: 1. `helm.yaml` - Holds all the helm charts needed. 2. `core.yaml` - Depends on helm Kustomization and holds core functionality for the cluster to function like storage, certificates, ingress, etc. 3. `apps.yaml` - Depends on both `core.yaml` and `helm.yaml` and holds all the apps currently installed on my cluster. 4. `configs.yaml` - Depends on `core.yaml` and holds all the configurations for the cluster ================================================ FILE: docs/Getting Started.md ================================================ # Installing Kubernetes ## K3S and why are we using it - For raspberry pis who have limited resources we need something more minimalistic. k3s was made to run with limited resources in mind, so it seems like a good fit - We will not be using traefik, instead we are using istio ## Before installing anything It is highly advisory to go to each helm chart values.yaml file and check the different options and modify them as you wish. Things like ports, storage size etc. are good to be checked out. You may also want to check out the variables for the ansible scripts ## Setting up the cluster - First thing we are going to do is navigate to the `./ansible` folder - Set up your inventory file ( use mine as an example, the only thing different will probably be the IPs, but if you chose a different ansible user, make sure to modify accordingly ) **Note: This is not secure. Ideally you should either pass in your password every time or setup passwordless authentication** - **If you did not fix the iptables**, ( when it comes to raspberry pis ) do it now: `ansible -i hosts/inventory -b -m shell -a "iptables -F && update-alternatives --set iptables /usr/sbin/iptables-legacy && update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy && reboot" all -k` - Run `ansible-galaxy install -r playbooks/install/requirements.yml` to install all the needed ansible roles from Ansible Galaxy - Run `ansible-playbook -i hosts/inventory playbooks/install/main.yml ` - You should check the Troubleshooting options regarding svclb and enable container ip forwarding. Next Steps: - [Flux](./Flux.md) ================================================ FILE: docs/Longhorn.md ================================================ # Increasing PVC/volume Size Longhorn requires a few manual steps to achieve this. ## Steps: 1. Stop all pods the volume is attached to 2. Increase size of volume 3. Go to Longhorn UI 4. Attach the volume in maintenance mode 5. Wait for the resizing to finish 6. Start all pods ================================================ FILE: docs/SettingUpCertManager.md ================================================ # Resource to read: https://blog.darkedges.com/2020/05/04/cert-manager-kubernetes-cloudflare-dns-update/ It describes how to generate the API token from cloudflare. ================================================ FILE: docs/SettingUpRenovate.md ================================================ # Setting up Renovate Renovate is installed as a Github App and periodically checks my repository for new versions of docker images / helm charts / etc and creates Pull Requests with the update. ## Steps: 1. Initial Renovate setup by following the official documentation 2. Follow instructions [here](https://github.com/renovatebot/github-action#special-token-requirements-when-using-the-github-actions-manager) ================================================ FILE: docs/Sops.md ================================================ # SOPS Mozilla SOPS is a tool that allows you to commit encrypted secrets/data to git, without having to worry. Note to self: the agekey is stored in Vaultwarden! Guide: https://fluxcd.io/flux/guides/mozilla-sops/#encrypting-secrets-using-age 1. Generate an agekey 2. age-keygen -o age.agekey 3. cat age.agekey | kubectl create secret generic sops-age \ --namespace=flux-system \ --from-file=age.agekey=/dev/stdin ## Encrypting: ```bash sops --age age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn --encrypt --encrypted-regex '^(data|stringData|annotations|host)$' --in-place ``` ## Decrypting ```bash sops --age age1mq6usjzvvxvcp7tl03yjdqd0kgjhhvhz48kmg86p43nhx0jc75jssw0kfn --decrypt --encrypted-regex '^(data|stringData|annotations|host)$' --in-place ``` ## Troubleshooting ### Mac mismatch You can ignore the MAC mismatch: https://github.com/getsops/sops/discussions/942 ``` --ignore-mac ``` ================================================ FILE: docs/Troubleshooting.md ================================================ # Troubleshooting ## Cluster creation failed (or everything has gone to heck and I want to re-do it) - Run the k3s uninstall script https://rancher.com/docs/k3s/latest/en/installation/uninstall/ - Rerun `ansible-playbook -i inventory playbooks/install/main.yml --tags setup -k` ## Grafana is giving an error - Try deleting the prometheus data source and re-adding it ( there may be 2 data sources, grafana makes a mistake sometimes ) ## Ansible is not connection/is slow/hangs - God have mercy on your soul cause ain't nobody gonna help you ;( ## Longhorn storage has an issue - Check if it's dns, if it's not dns, I suggest you redo the entire cluster ## Clearing up containerd - Go to `./ansible` - Run: `ansible -i hosts/inventory -m shell -a "k3s crictl rmp -a" -b all` To remove all pods that are not up and running - Run: `ansible -i hosts/inventory -m shell -a "k3s crictl rmi --prune" -b all` To remove all images - Run: `ansible -i hosts/inventory -m shell -a "k3s crictl rm -a" -b all` ## Wallabag doesn't want to work correctly, it's giving me a wallabag_internal_settings table is not created Restarting the deployment helps. No idea why? ## Issues with Longhorn volumes mounting * Check out: https://longhorn.io/kb/troubleshooting-volume-with-multipath/ ## cgroup-gc This is a helm chart that installs a daemonset that will be deployed on all nodes with the purpose of clearing up cgroups. For more information: `https://serverfault.com/questions/976233/context-deadline-exceeded-preventing-pods-from-being-created-in-aks` ================================================ FILE: docs/tofu.md ================================================ # Tofu Controller The tofu controller allows me to apply my terraform config in a gitops way. ## Getting the tfstate Ref: https://flux-iac.github.io/tofu-controller/use-tf-controller/backup-and-restore-a-Terraform-state/ ```sh WORKSPACE=default NAME=homelab-iac kubectl get secret tfstate-${WORKSPACE}-${NAME} \ -ojsonpath='{.data.tfstate}' \ | base64 -d | gzip -d > terraform.tfstate ``` ## Restoring the tfstate ```sh gzip terraform.tfstate WORKSPACE=default NAME=my-stack kubectl create secret \ generic tfstate-${WORKSPACE}-${NAME} \ --from-file=tfstate=terraform.tfstate.gz \ --dry-run=client -o=yaml \ | yq e '.metadata.annotations["encoding"]="gzip"' - \ > tfstate-${WORKSPACE}-${NAME}.yaml kubectl apply -f tfstate-${WORKSPACE}-${NAME}.yaml ``` ## Viewing the plan You must set first ```diff apiVersion: infra.contrib.fluxcd.io/v1alpha2 kind: Terraform metadata: name: homelab-iac namespace: flux-system spec: interval: 1m # approvePlan: auto path: ./ sourceRef: kind: GitRepository name: homelab-iac namespace: flux-system varsFrom: - kind: Secret name: homelab-iac-secrets + storeReadablePlan: human ``` And then you can do: ```sh tfctl show plan homelab-iac ``` ================================================ FILE: local/docker-compose.yaml ================================================ services: tdarr: container_name: tdarr image: ghcr.io/haveagitgat/tdarr:latest restart: unless-stopped privileged: true network_mode: bridge deploy: resources: reservations: cpus: "0.00" devices: - driver: nvidia count: 1 capabilities: [gpu] limits: memory: 32G ports: - 8265:8265 # webUI port - 8266:8266 # server port - 8267:8267 # Internal node port environment: - TZ=Europe/Sofia - UMASK_SET=002 - serverIP=0.0.0.0 - serverPort=8266 - webUIPort=8265 - internalNode=true - nodeName=MyInternalNode volumes: - ./docker-data/tdarr/server:/app/server - ./docker-data/tdarr/configs:/app/configs - ./docker-data/tdarr/logs:/app/logs - media:/media - ./docker-data/tdarr/transcode_cache:/temp volumes: media: driver_opts: type: "nfs" o: "addr=192.168.1.39,nolock,rw,soft,nfsvers=4" device: ":/volume1/k3s/media" ================================================ FILE: upgrades/v1.35.0+k3s1.yaml ================================================ --- # Server plan apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: server-plan namespace: system-upgrade spec: concurrency: 1 cordon: true nodeSelector: matchExpressions: - key: node-role.kubernetes.io/master operator: In values: - "true" serviceAccountName: system-upgrade upgrade: image: rancher/k3s-upgrade version: v1.35.0+k3s1 --- # Agent plan apiVersion: upgrade.cattle.io/v1 kind: Plan metadata: name: agent-plan namespace: system-upgrade spec: concurrency: 1 cordon: true nodeSelector: matchExpressions: - key: node-role.kubernetes.io/master operator: DoesNotExist prepare: args: - prepare - server-plan image: rancher/k3s-upgrade serviceAccountName: system-upgrade upgrade: image: rancher/k3s-upgrade version: v1.35.0+k3s1