diff --git a/.gitignore b/.gitignore index 7b2d2eec..2f66320e 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,10 @@ config.tf.json # Terragrunt .terragrunt-cache + +# Kubernetes +*kubeconfig* + +# others +*.pem +*.key diff --git a/flake.lock b/flake.lock index 815a04f5..807b73af 100644 --- a/flake.lock +++ b/flake.lock @@ -167,15 +167,16 @@ "inputs": { "bitte": "bitte", "iogo": "iogo", - "nixpkgs": "nixpkgs_13", + "nix-deployer": "nix-deployer", + "nixpkgs": "nixpkgs_14", "ragenix": "ragenix_2" }, "locked": { - "lastModified": 1671562644, - "narHash": "sha256-zEfdg/z8pSqCn0puxgvKxa9ie87c7DY6QCSsTxPd8k4=", + "lastModified": 1690399428, + "narHash": "sha256-ziGk2TcHyA7hYZiJflvt3O9cguEaARj6045zt7kv9Cg=", "owner": "input-output-hk", "repo": "devshell-capsules", - "rev": "6660a8b43f563df66e2375adb4e2a54cd8792d5f", + "rev": "4b0311abd0f9f0f614d260b64cf9a87a8f6dc250", "type": "github" }, "original": { @@ -215,15 +216,15 @@ "inputs": { "flake-compat": "flake-compat_2", "nix": "nix_4", - "nixpkgs": "nixpkgs_15", + "nixpkgs": "nixpkgs_16", "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1678256717, - "narHash": "sha256-qUJJEs0yQI3e43zFSwZymrMZjNCyTrTdvZM29v+F91A=", + "lastModified": 1697058441, + "narHash": "sha256-gjtW+nkM9suMsjyid63HPmt6WZQEvuVqA5cOAf4lLM0=", "owner": "cachix", "repo": "devenv", - "rev": "ca23892d8b9f788be8d1d358c673c8d0f9b4f68f", + "rev": "55294461a62d90c8626feca22f52b0d3d0e18e39", "type": "github" }, "original": { @@ -356,11 +357,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1677714448, - "narHash": "sha256-Hq8qLs8xFu28aDjytfxjdC96bZ6pds21Yy09mSC156I=", + "lastModified": 1696343447, + "narHash": "sha256-B2xAZKLkkeRFG5XcHHSXXcP7To9Xzr59KXeZiRf4vdQ=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "dc531e3a9ce757041e1afaff8ee932725ca60002", + "rev": "c9afaba3dfa4085dbd2ccb38dfade5141e33d9d4", "type": "github" }, "original": { @@ -430,12 +431,15 @@ } }, "flake-utils_5": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1667395993, - "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", "owner": "numtide", "repo": "flake-utils", - "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", "type": "github" }, "original": { @@ -633,6 +637,22 @@ "type": "github" } }, + "lowdown-src_5": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, "nix": { "inputs": { "lowdown-src": "lowdown-src", @@ -654,6 +674,27 @@ "type": "github" } }, + "nix-deployer": { + "inputs": { + "lowdown-src": "lowdown-src_4", + "nixpkgs": "nixpkgs_13", + "nixpkgs-regression": "nixpkgs-regression_3" + }, + "locked": { + "lastModified": 1682676126, + "narHash": "sha256-CEj8KOj9wN285+c2VWnJhDsSF6OqSvOA9eY/naAuGpQ=", + "owner": "NixOS", + "repo": "nix", + "rev": "4504ee295738a2e7a1cb0a5d9cf94d03e861b5f5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "2.14-maintenance", + "repo": "nix", + "type": "github" + } + }, "nix_2": { "inputs": { "lowdown-src": "lowdown-src_2", @@ -695,12 +736,12 @@ }, "nix_4": { "inputs": { - "lowdown-src": "lowdown-src_4", + "lowdown-src": "lowdown-src_5", "nixpkgs": [ "devenv", "nixpkgs" ], - "nixpkgs-regression": "nixpkgs-regression_3" + "nixpkgs-regression": "nixpkgs-regression_4" }, "locked": { "lastModified": 1676545802, @@ -734,11 +775,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1677407201, - "narHash": "sha256-3blwdI9o1BAprkvlByHvtEm5HAIRn/XPjtcfiunpY7s=", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7f5639fa3b68054ca0b062866dc62b22c3f11505", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { @@ -795,18 +836,34 @@ "type": "github" } }, + "nixpkgs-regression_4": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, "nixpkgs-stable": { "locked": { - "lastModified": 1673800717, - "narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=", + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-22.11", + "ref": "nixos-23.05", "repo": "nixpkgs", "type": "github" } @@ -877,11 +934,27 @@ }, "nixpkgs_13": { "locked": { - "lastModified": 1658119717, - "narHash": "sha256-4upOZIQQ7Bc4CprqnHsKnqYfw+arJeAuU+QcpjYBXW0=", + "lastModified": 1670461440, + "narHash": "sha256-jy1LB8HOMKGJEGXgzFRLDU1CBGL0/LlkolgnqIsF0D8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04a75b2eecc0acf6239acf9dd04485ff8d14f425", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_14": { + "locked": { + "lastModified": 1684212024, + "narHash": "sha256-/3ZvkPuIXdyZqPR53qC7aaV5wiwMOY+ddbESOykZ9Vo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9eb60f25aff0d2218c848dd4574a0ab5e296cabe", + "rev": "d4825e5e4ac1de7d5bb99381534fd0af3875a26d", "type": "github" }, "original": { @@ -891,7 +964,7 @@ "type": "github" } }, - "nixpkgs_14": { + "nixpkgs_15": { "locked": { "lastModified": 1644525281, "narHash": "sha256-D3VuWLdnLmAXIkooWAtbTGSQI9Fc1lkvAr94wTxhnTU=", @@ -907,13 +980,13 @@ "type": "github" } }, - "nixpkgs_15": { + "nixpkgs_16": { "locked": { - "lastModified": 1677534593, - "narHash": "sha256-PuZSAHeq4/9pP/uYH1FcagQ3nLm/DrDrvKi/xC9glvw=", + "lastModified": 1678875422, + "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3ad64d9e2d5bf80c877286102355b1625891ae9a", + "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", "type": "github" }, "original": { @@ -923,7 +996,7 @@ "type": "github" } }, - "nixpkgs_16": { + "nixpkgs_17": { "locked": { "lastModified": 1685566663, "narHash": "sha256-btHN1czJ6rzteeCuE/PNrdssqYD2nIA4w48miQAFloM=", @@ -1159,11 +1232,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1677160285, - "narHash": "sha256-tBzpCjMP+P3Y3nKLYvdBkXBg3KvTMo3gvi8tLQaqXVY=", + "lastModified": 1688056373, + "narHash": "sha256-2+SDlNRTKsgo3LBRiMUcoEUb6sDViRNQhzJquZ4koOI=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "2bd861ab81469428d9c823ef72c4bb08372dd2c4", + "rev": "5843cf069272d92b60c3ed9e55b7a8989c01d4c7", "type": "github" }, "original": { @@ -1197,7 +1270,7 @@ "inputs": { "agenix": "agenix_3", "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_14", + "nixpkgs": "nixpkgs_15", "rust-overlay": "rust-overlay_2" }, "locked": { @@ -1219,7 +1292,7 @@ "capsules": "capsules", "devenv": "devenv", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_16" + "nixpkgs": "nixpkgs_17" } }, "rust-analyzer-src": { @@ -1357,6 +1430,21 @@ "type": "github" } }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "terranix": { "inputs": { "bats-assert": "bats-assert", diff --git a/flake.nix b/flake.nix index d0e07e71..7727890f 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,7 @@ systems = [ "x86_64-linux" "x86_64-darwin" + "aarch64-darwin" ]; # Raw flake outputs (generally not system-dependent) flake = { diff --git a/infra/account.hcl b/infra/account.hcl index 43358bd0..78ba7613 100644 --- a/infra/account.hcl +++ b/infra/account.hcl @@ -5,8 +5,9 @@ locals { aws_account_id = "677160962006" # aws_caller_arn = get_aws_caller_identity_arn() aws_profile = "dapps-world" - name = "dapps" - project = "dapps" + name = "scde" + project = "scde" + tribe = "smartcontracts" # Allow users to access k8s over aws_auth config users = [ # SRE diff --git a/infra/kubeconfig-dapps-prod-us-east-1 b/infra/kubeconfig-dapps-prod-us-east-1 index 1039bc6c..3d0c4a9c 100644 --- a/infra/kubeconfig-dapps-prod-us-east-1 +++ b/infra/kubeconfig-dapps-prod-us-east-1 @@ -1,5 +1,9 @@ apiVersion: v1 clusters: +- cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJZnVGRzZScTlwWkl3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TXpBNU1Ua3hORFF3TVRsYUZ3MHpNekE1TVRZeE5EUXdNVGxhTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUROVDdZVm5XbmF1VG5jWnRoOHBGdkhYY1ZoMmdSNW8yajJPYWFxOWJBd25ZY21ibmZxUGVsSDNET1AKbG1SbmVXY3FPWlZoWHVxUGY5V0l1d3d0MHI5SDRwTEFBb0NBQ21uVXRWbURMRUFCa3FkbXVOVW9hNjd2NE85SwpKVkpsREVUYXhSUS80b29xa0E3WEg3eW53VzIrcjdzUXZEUVRnZWpMd1lJaUFBb1k5L3hJSGpDT1hxdVpTMFJBCng1RUxTMUlOdTFIUTdkL29MQXJFWThpSEw3ZUFnZTVhM0hzaGZ5VUhFQnZySDJBb0c0QzdnZWFmMXVwY0JFLysKYTNwcHFSdUdCVEl1RDVMcythUE8xcnFOcnZqZldNcGhNTVRKa1NSZDRlRTk2TU91UlV1YzdSaDV6RHNmUjlncAovOVM1UGN6eEhaMlNUNGFncWNEZzZkbGhVOFVQQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJTOWFudHhsZGFxOTF3ekRBRVRSUjJQNHNwWFhUQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQmw1bTY4eFd5QwowSmVvY3RXVk1xZ21CT0dNWHYzcWdFU0hPMWkwM0poTE1jNWtUZFhzSWdRS3l5cGczUktuQmd3NktjbmhEY3BDClZpNGR4TGZoTE5KWWRsS3NCNkE5Z2ltNnZnVzJDOWFuSEl2STJKdVpNTHFhMGc5ZWlCbXJoVVMrWGx1c1BVd1IKWUQ1RUprMGRmZUcyTVRBVjFFb0V2QndySnNCTTFuRnNxMmdWMHR4UW12SlU5Yk1qTVd6UHIvR3NyWm8vTFRRSAo4ZkNPNUpILzU1dGJERzIycVF4MFVWK0ZnNzhXL0dIMUFKTW1tb1grakZMTEdGN29KbnBaM01ZSUpyRlZtUkNnCnQvUWpQZmIwTjE2Sml6Y0kwVWt1R0pCZDdJOEQ4bVJmN3pBUG1iTGthRDN5UW9iMGNrUWJwSElBbGxFcUJ6SkQKb3dGdjZEdG1GZDR5Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://966EEA9F960695631D9B66D87D004C31.gr7.us-east-1.eks.amazonaws.com + name: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-new-us-east-1 - cluster: certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ETXdNVEU1TVRFMU0xb1hEVE16TURJeU5qRTVNVEUxTTFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTG1ICkdna0hveVUwUzU1eC82L3VMTDUyblF6UHFVYktySWdyMDlqd1h3cDNhM2E0RHRxalVZUlp0Rm5GMkI3bkVmR2oKb3YrQTN5dGZRZ2lrMnphbmp2WHNZR1E5T1V0TVZmTW5GK2s0YXJpeE9BM0tTTFBEbGxsRE5Ed2NqcjN5OWtOagpQWmcwNEZTcFcvWGpoQ1Z2V2dVWDdreHRhR1JwRDl0RXNqUCsweVA3aFJhdkl2UHRJQXE4QVBkSGQzVXFlb1pRCkZ2VktrTGZ0cnMvQkNHTEhQWlV3T1RueFVUbGlmSUxXSi9yR3MyaDBMbk1qekw1TjJkTCtFQTRzbUZWWFFrQkwKdS96bzJNeE5pWmNhbWU4aTVmeWxDMTRpQUVOK09iOHp6QkQxOWUvbEI5RVM1TE5ZQzdZTHU1SjQwQkpKV0JOegp6Z2oybXZRckVtMGcrV29qVHlrQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZPYkFMZ2ZmTEpMZzY5bjJ0aE1tcVFhc3lGMG9NQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1VCc2R2Rm5pOWJVTTh6Y1lxcwpGeHp0eHJudjh5cnVvZnFVWkUvaHRSVXJ1WmZ3WnphRE8xQXdlRFBXeEZBa0w1NWdXUURRNEUyN0dXckIvQ29DCk5Jd3Q3czN4RzF5VHlIYlMwcCtLRU9rUDFUekpBZkhPc1ZrUDdTbGVwR1JjNlpDM2prTnkxRis0Vno4cHNXMjQKR2hDV1FQYWJHV2ErSVY0KzdlMzBKQ2c1Tm5HSGo3cXF3WW9iRWc3Ri9MczVoVStUU2c4STZzR1pCdisycHlJcQpNQnZsajdFWXNCcnBiclNTS2JJcFIrZE5aVXZNTDgzZWJKVGFJK1c0cCthZ0lGcEwzUk82bGUwNVdNZUR2ZHlyClZQanN5ZnpOeXBWRzFCSE9YOForV3hqTy9iay9CVUZiaVhwOUhGazJ4eWluMkFFN1RPMHJZKzd6VkdEMjRHM2EKRlJVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== server: https://7D34292509B3F5645A3E2EB833FEF03F.gr7.us-east-1.eks.amazonaws.com @@ -8,11 +12,34 @@ contexts: - context: cluster: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-us-east-1 user: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-us-east-1 - name: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-us-east-1 -current-context: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-us-east-1 + name: dapps-prod +- context: + cluster: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-new-us-east-1 + user: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-new-us-east-1 + name: dapps-prod-new +current-context: dapps-prod-new kind: Config preferences: {} users: +- name: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-new-us-east-1 + user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - --region + - us-east-1 + - eks + - get-token + - --cluster-name + - dapps-prod-new-us-east-1 + - --output + - json + command: aws + env: + - name: AWS_PROFILE + value: dapps-world + interactiveMode: IfAvailable + provideClusterInfo: false - name: arn:aws:eks:us-east-1:677160962006:cluster/dapps-prod-us-east-1 user: exec: @@ -24,7 +51,11 @@ users: - get-token - --cluster-name - dapps-prod-us-east-1 + - --output + - json command: aws env: - name: AWS_PROFILE value: dapps-world + interactiveMode: IfAvailable + provideClusterInfo: false diff --git a/infra/modules/eks/addons/locals.tf b/infra/modules/eks/addons/locals.tf new file mode 100644 index 00000000..39b55f6c --- /dev/null +++ b/infra/modules/eks/addons/locals.tf @@ -0,0 +1,73 @@ +locals { + + helm_wait = true + helm_create_namespace = true + + eks_addons = { + aws_load_balancer_controller = {} + metrics_server = {} + cluster_autoscaler = {} + cert_manager = {} + cert_manager_route53_hosted_zone_arns = [] + external_dns = {} + external_dns_route53_zone_arns = [] + node_local_dns = { + chart = "node-local-dns" + chart_version = "2.0.3" + repository = "https://charts.deliveryhero.io" + description = "A Helm chart for Node Local DNS" + namespace = "kube-system" + create_namespace = "false" + values = [] + set = [] + } + aws_ebs_csi_driver = { + chart = "aws-ebs-csi-driver" + chart_version = "2.24.0" + repository = "https://kubernetes-sigs.github.io/aws-ebs-csi-driver" + description = "A Helm chart for AWS EBS CSI Driver" + namespace = "kube-system" + create_namespace = "false" + values = [ + <<-EOF + controller: + serviceAccount: + create: true + annotations: + eks.amazonaws.com/role-arn: "${module.eks_addon_aws_ebs_csi_driver_iam_role.0.iam_role_arn}" + + storageClasses: + - name: ebs-sc + annotations: + storageclass.kubernetes.io/is-default-class: "false" + parameters: + fsType: ext4 + type: gp3 + encrypted: "true" + allowVolumeExpansion: true + reclaimPolicy: Delete + volumeBindingMode: WaitForFirstConsumer + EOF + ] + set = [] + } + traefik_load_balancer = { + chart = "traefik" + chart_version = "25.0.0" + repository = "https://traefik.github.io/charts" + description = "A Traefik based Kubernetes ingress controller" + namespace = "traefik" + values = [] + set = [] + } + kubevela_controller = { + chart = "vela-core" + chart_version = "1.9.6" + repository = "https://kubevela.github.io/charts" + description = "A Helm chart for KubeVela core" + namespace = "vela-system" + values = [] + set = [] + } + } +} diff --git a/infra/modules/eks/addons/main.tf b/infra/modules/eks/addons/main.tf new file mode 100644 index 00000000..d87a121e --- /dev/null +++ b/infra/modules/eks/addons/main.tf @@ -0,0 +1,192 @@ +terraform { + required_providers { + kubectl = { + source = "gavinbunney/kubectl" + version = "~> 1.14" + } + } +} + +provider "kubernetes" { + host = var.cluster_endpoint + cluster_ca_certificate = base64decode(var.cluster_certificate_authority_data) + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", var.cluster_name, "--profile", var.aws_profile] + } +} + +provider "helm" { + kubernetes { + host = var.cluster_endpoint + cluster_ca_certificate = base64decode(var.cluster_certificate_authority_data) + + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + # This requires the awscli to be installed locally where Terraform is executed + args = ["eks", "get-token", "--cluster-name", var.cluster_name, "--profile", var.aws_profile] + } + } +} + +provider "kubectl" { + host = var.cluster_endpoint + cluster_ca_certificate = base64decode(var.cluster_certificate_authority_data) + + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", var.cluster_name, "--profile", var.aws_profile] + } +} + +module "node_local_dns" { + count = try(var.eks_addons.node_local_dns, true) ? 1 : 0 + source = "aws-ia/eks-blueprints-addon/aws" + version = "1.1.1" + + chart = local.eks_addons.node_local_dns.chart + chart_version = local.eks_addons.node_local_dns.chart_version + repository = local.eks_addons.node_local_dns.repository + description = local.eks_addons.node_local_dns.description + namespace = local.eks_addons.node_local_dns.namespace + create_namespace = local.eks_addons.node_local_dns.create_namespace + values = local.eks_addons.node_local_dns.values + wait = local.helm_wait +} + +module "eks_addon_aws_ebs_csi_driver_iam_role" { + count = try(var.eks_addons.enable_aws_ebs_csi_driver, true) ? 1 : 0 + source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" + version = "5.30.0" + + role_name = "${var.cluster_name}-AmazonEBSCSIDriver" + + role_policy_arns = { + policy = "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy" + } + + oidc_providers = { + one = { + provider_arn = var.oidc_provider_arn + namespace_service_accounts = ["kube-system:ebs-csi-controller-sa"] + } + } +} + +module "eks_addon_aws_ebs_csi_driver" { + count = try(var.eks_addons.enable_aws_ebs_csi_driver, true) ? 1 : 0 + source = "aws-ia/eks-blueprints-addon/aws" + version = "1.1.1" + + chart = local.eks_addons.aws_ebs_csi_driver.chart + chart_version = local.eks_addons.aws_ebs_csi_driver.chart_version + repository = local.eks_addons.aws_ebs_csi_driver.repository + description = local.eks_addons.aws_ebs_csi_driver.description + namespace = local.eks_addons.aws_ebs_csi_driver.namespace + create_namespace = local.eks_addons.aws_ebs_csi_driver.create_namespace + values = local.eks_addons.aws_ebs_csi_driver.values + wait = local.helm_wait + + depends_on = [ + module.eks_addon_aws_ebs_csi_driver_iam_role + ] +} + +module "eks_addons" { + source = "aws-ia/eks-blueprints-addons/aws" + version = "1.9.2" + + cluster_name = var.cluster_name + cluster_endpoint = var.cluster_endpoint + cluster_version = var.cluster_version + oidc_provider_arn = var.oidc_provider_arn + + enable_aws_load_balancer_controller = try(var.eks_addons.enable_aws_load_balancer_controller, true) + aws_load_balancer_controller = try(var.eks_addons.aws_load_balancer_controller, local.eks_addons.aws_load_balancer_controller) + + enable_metrics_server = try(var.eks_addons.enable_metrics_server, true) + metrics_server = try(var.eks_addons.metrics_server, local.eks_addons.metrics_server) + + enable_cluster_autoscaler = try(var.eks_addons.enable_cluster_autoscaler, true) + cluster_autoscaler = try(var.eks_addons.cluster_autoscaler, local.eks_addons.cluster_autoscaler) + + enable_cert_manager = try(var.eks_addons.enable_cert_manager, false) + cert_manager = try(var.eks_addons.cert_manager, local.eks_addons.cert_manager) + cert_manager_route53_hosted_zone_arns = try(var.eks_addons.cert_manager.cert_manager_route53_hosted_zone_arns, local.eks_addons.cert_manager_route53_hosted_zone_arns) + + enable_external_dns = try(var.eks_addons.enable_external_dns, false) + external_dns = try(var.eks_addons.external_dns, local.eks_addons.external_dns) + external_dns_route53_zone_arns = try(var.eks_addons.external_dns_route53_zone_arns, local.eks_addons.external_dns_route53_zone_arns) +} + +resource "kubectl_manifest" "letsencrypt_issuer" { + count = try(var.eks_addons.enable_cert_manager, false) ? 1 : 0 + yaml_body = file("${path.module}/manifests/letsencrypt_issuer.yaml") + + depends_on = [ + module.eks_addons + ] +} + +data "kubectl_file_documents" "gateway_crds" { + content = file("${path.module}/manifests/gateway_crds.yaml") +} + +data "kubectl_file_documents" "gateway_system" { + content = file("${path.module}/manifests/gateway_system.yaml") +} + +resource "kubectl_manifest" "gateway_crds" { + for_each = try(var.eks_addons.enable_traefik_load_balancer, false) ? data.kubectl_file_documents.gateway_crds.manifests : {} + yaml_body = each.value +} + +resource "kubectl_manifest" "gateway_system" { + for_each = try(var.eks_addons.enable_traefik_load_balancer, false) ? data.kubectl_file_documents.gateway_system.manifests : {} + yaml_body = each.value +} + +module "eks_addon_traefik_load_balancer" { + count = try(var.eks_addons.enable_traefik_load_balancer, false) ? 1 : 0 + source = "aws-ia/eks-blueprints-addon/aws" + version = "1.1.1" + + chart = local.eks_addons.traefik_load_balancer.chart + chart_version = try(var.eks_addons.traefik_load_balancer.chart_version, local.eks_addons.traefik_load_balancer.chart_version) + repository = try(var.eks_addons.traefik_load_balancer.repository, local.eks_addons.traefik_load_balancer.repository) + description = try(var.eks_addons.traefik_load_balancer.description, local.eks_addons.traefik_load_balancer.description) + namespace = try(var.eks_addons.traefik_load_balancer.namespace, local.eks_addons.traefik_load_balancer.namespace) + create_namespace = try(var.eks_addons.traefik_load_balancer.create_namespace, local.helm_create_namespace) + values = try(var.eks_addons.traefik_load_balancer.values, local.eks_addons.traefik_load_balancer.values) + set = try(var.eks_addons.traefik_load_balancer.set, local.eks_addons.traefik_load_balancer.set) + wait = try(var.eks_addons.traefik_load_balancer.wait, local.helm_wait) + + depends_on = [ + module.eks_addons, + kubectl_manifest.gateway_crds, + kubectl_manifest.gateway_system + ] +} + +module "eks_addon_kubevela_controller" { + count = try(var.eks_addons.enable_kubevela_controller, false) ? 1 : 0 + source = "aws-ia/eks-blueprints-addon/aws" + version = "1.1.1" + + chart = local.eks_addons.kubevela_controller.chart + chart_version = try(var.eks_addons.kubevela_controller.chart_version, local.eks_addons.kubevela_controller.chart_version) + repository = try(var.eks_addons.kubevela_controller.repository, local.eks_addons.kubevela_controller.repository) + description = try(var.eks_addons.kubevela_controller.description, local.eks_addons.kubevela_controller.description) + namespace = try(var.eks_addons.kubevela_controller.namespace, local.eks_addons.kubevela_controller.namespace) + create_namespace = try(var.eks_addons.kubevela_controller.create_namespace, local.helm_create_namespace) + values = try(var.eks_addons.kubevela_controller.values, local.eks_addons.kubevela_controller.values) + set = try(var.eks_addons.kubevela_controller.set, local.eks_addons.kubevela_controller.set) + wait = try(var.eks_addons.kubevela_controller.wait, local.helm_wait) + + depends_on = [ + module.eks_addons + ] +} diff --git a/infra/modules/eks/addons/manifests/gateway_crds.yaml b/infra/modules/eks/addons/manifests/gateway_crds.yaml new file mode 100644 index 00000000..3b92b798 --- /dev/null +++ b/infra/modules/eks/addons/manifests/gateway_crds.yaml @@ -0,0 +1,3139 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + 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.controller + name: Controller + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the + user for creating Gateway resources. \n 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. \n Whenever one or more Gateways are using a GatewayClass, + implementations MUST 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. \n 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. \n Example: \"example.net/gateway-controller\". + \n This field is not mutable and cannot be empty. \n 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 + 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. \n 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. \n If the + referent cannot be found, the GatewayClass's \"InvalidParameters\" + status condition will be true. \n Support: Custom" + 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: Waiting + status: Unknown + type: Accepted + description: Status defines the current state of GatewayClass. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller + for this GatewayClass. \n 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. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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 + type: object + required: + - spec + type: object + served: true + storage: true + 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-sigs/gateway-api/pull/891 + creationTimestamp: null + 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=="Ready")].status + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + 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 the associated entry in + GatewayStatus.Addresses. \n 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. \n The .listener.hostname + field is used to route traffic that has already arrived at the Gateway + to the correct in-cluster destination. \n If no Addresses are specified, + the implementation MAY schedule the Gateway in an implementation-specific + manner, assigning an appropriate set of Addresses. \n The implementation + MUST bind all Listeners to every GatewayAddress that it assigns + to the Gateway and add a corresponding entry in GatewayStatus.Addresses. + \n Support: Core" + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + enum: + - IPAddress + - Hostname + - NamedAddress + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name + of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + 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. \n Each listener in a Gateway + must have a unique combination of Hostname, Port, and Protocol. + \n An implementation MAY group Listeners by Port and then collapse + each group of Listeners into a single Listener if the implementation + determines that the Listeners in the group are \"compatible\". An + implementation MAY also group together and collapse compatible Listeners + belonging to different Gateways. \n For example, an implementation + might consider Listeners to be compatible with each other if all + of the following conditions are met: \n 1. Either each Listener + within the group specifies the \"HTTP\" Protocol or each Listener + within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. + \n 2. Each Listener within the group specifies a Hostname that is + unique within the group. \n 3. As a special case, one Listener + within a group may omit Hostname, in which case this Listener + matches when no other Listener matches. \n If the implementation + does collapse compatible Listeners, the hostname provided in the + incoming client request MUST be matched to a Listener to find the + correct set of Routes. The incoming hostname MUST be matched using + the Hostname field for each Listener in order of most to least specific. + That is, exact matches must be processed before wildcard matches. + \n If this field specifies multiple Listeners that have the same + Port value but are not compatible, the implementation must raise + a \"Conflicted\" condition in the Listener status. \n 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. \n 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: \n * 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. \n 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. + \n 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. \n 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 \"InvalidRoutesRef\" + reason. \n 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 + 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. \n 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. \n + 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\". \n 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + 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. \n Implementations + MUST apply Hostname matching appropriately for each of the + following protocols: \n * 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 at both the TLS and HTTP protocol layers as + described above. If an implementation does not ensure that + both the SNI and Host header match the Listener hostname, + \ it MUST clearly document that. \n 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. \n 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. \n 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. + \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener + expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-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\". \n The association + of SNIs to Certificate defined in GatewayTLSConfig is defined + based on the Hostname field for this listener. \n The GatewayClass + MUST use the longest matching SNI out of all available certificates + for any TLS handshake. \n 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. \n 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. + \n References to a resource in different namespace are + invalid UNLESS there is a ReferencePolicy in the target + namespace that allows the certificate to be attached. + If a ReferencePolicy does not allow this reference, the + \"ResolvedRefs\" condition MUST be set to False for this + listener with the \"InvalidCertificateRef\" reason. \n + This field is required to have at least one element when + the mode is set to \"Terminate\" (default) and is optional + otherwise. \n CertificateRefs can reference to standard + Kubernetes resources, i.e. Secret, or implementation-specific + custom resources. \n Support: Core - A single reference + to a Kubernetes Secret \n Support: Implementation-specific + (More than one reference or other resource types)" + items: + description: "SecretObjectReference identifies an API + object including its namespace, defaulting to Secret. + \n 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. \n 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, "networking.k8s.io". When unspecified (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 + "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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. + \n Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to + allow that namespace's owner to accept the reference. + See the ReferencePolicy documentation for details. + \n 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 + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS + session initiated by the client. There are two possible + modes: \n - Terminate: The TLS session between the downstream + client and the Gateway is terminated at the Gateway. + This mode requires certificateRefs to be set and contain + at least one element. - 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. CertificateRefs + field is ignored in this mode. \n 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. \n 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. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: Status defines the current state of Gateway. + properties: + addresses: + description: Addresses lists the IP addresses that have actually been + bound to the Gateway. These addresses may differ from the addresses + in the Spec, e.g. if the Gateway automatically assigns an address + from a reserved pool. + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + enum: + - IPAddress + - Hostname + - NamedAddress + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: "Conditions describe the current conditions of the Gateway. + \n 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. \n Known condition types are: \n * \"Scheduled\" + * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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. + 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. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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. + \n 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 + 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: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + creationTimestamp: null + 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: v1alpha2 + 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 hostname that should match + against the HTTP Host header to select a HTTPRoute to process the + request. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 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. \n 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: + \n * 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, `test.example.com` and `*.example.com` would both match. + On the other hand, `example.com` and `test.example.net` would + not match. \n 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. \n 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. \n 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: \n 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. \n 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`). + \n 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 + 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. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n 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." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n 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. \n 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: gateway.networking.k8s.io + description: "Group is the group of the referent. \n 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. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n 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. \n + 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 + 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: "If unspecified or invalid (refers to a non-existent + resource or a Service with no endpoints), the rule performs + no forwarding. If there are also no filters specified that + would result in a response being sent, a HTTP 503 status code + is returned. 503 responses must be sent so that the overall + weight is respected; if an invalid backend is requested to + have 80% of requests, then 80% of requests must get a 503 + instead. \n Support: Core for Kubernetes Service Support: + Custom for any other resource \n Support for weight: Core" + items: + description: HTTPBackendRef defines how a HTTPRoute should + forward an HTTP request. + 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. \n Support: Custom (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. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (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. \n + 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. \n Input: GET /foo + HTTP/1.1 my-header: foo \n Config: add: + \ - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: + foo 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). + \n 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). + \n Input: GET /foo HTTP/1.1 my-header1: + foo my-header2: bar my-header3: baz \n + Config: remove: [\"my-header1\", \"my-header3\"] + \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n 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). + \n 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. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n 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. \n If there is + a cross-namespace reference to an *existing* + object that is not allowed by a ReferencePolicy, + 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. \n In either error case, the + Message of the `ResolvedRefs` Condition should + be used to provide more detail about the problem. + \n Support: Extended for Kubernetes Service + Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When + unspecified (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 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 + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace is specified, a ReferencePolicy + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferencePolicy + documentation for details. \n 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. 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 + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n 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 + of the request is used. \n 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 port to be used in + the value of the `Location` header in the + response. When empty, port (if specified) + of the request is used. \n 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. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: 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. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n 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: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. 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. \n + 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. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - 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. \n Specifying + a core filter multiple times has unspecified or custom conformance. + \n 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. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (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. \n 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. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + foo 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). + \n 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). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n Output: + \ GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + \ set: - name: \"my-header\" value: \"bar\" + \n 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). + \n 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. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n 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. \n If + there is a cross-namespace reference to an *existing* + object that is not allowed by a ReferencePolicy, + 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. \n + In either error case, the Message of the `ResolvedRefs` + Condition should be used to provide more detail + about the problem. \n Support: Extended for Kubernetes + Service Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (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 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 + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace is + specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferencePolicy + documentation for details. \n 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. 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 + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter + that responds to the request with an HTTP redirection. + \n 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 of the request is used. + \n 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 port to be used in the value + of the `Location` header in the response. When empty, + port (if specified) of the request is used. \n 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. \n + Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to + be used in response. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n + - Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, + e.g. \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: 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. \n + Implementers are encouraged to define custom implementation + types to extend the core API with implementation-specific + behavior. \n 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: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - ExtensionRef + type: string + required: + - type + type: object + maxItems: 16 + type: array + 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. \n For example, take the following matches configuration: + \n ``` matches: - path: value: \"/foo\" headers: - + name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" + ``` \n For a request to match against this rule, a request + must satisfy EITHER of the two conditions: \n - path prefixed + with `/foo` AND contains the header `version: v2` - path prefix + of `/v2/foo` \n See the documentation for HTTPRouteMatch on + how to specify multiple match conditions that should be ANDed + together. \n If no matches are specified, the default is a + prefix path match on \"/\", which has the effect of matching + every HTTP request. \n Proxy or Load Balancer routing configuration + generated from HTTPRoutes MUST prioritize rules based on the + following criteria, continuing on ties. Precedence must be + given to the the Rule with the largest number of: \n * Characters + in a matching non-wildcard hostname. * Characters in a matching + hostname. * Characters in a matching path. * Header matches. + * Query param matches. \n If ties still exist across multiple + Routes, matching precedence MUST be determined in order of + the following criteria, continuing on ties: \n * The oldest + Route based on creation timestamp. * The Route appearing first + in alphabetical order by \"/\". \n 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: "HTTPRouteMatch 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. \n For example, the match + below will match a HTTP request only if its path starts + with `/foo` AND it contains the `version: v1` header: \n + ``` match: path: value: \"/foo\" headers: - name: + \"version\" value \"v1\" ```" + 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). + \n 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. + \n 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. \n Support: Core (Exact) + \n Support: Custom (RegularExpression) \n Since + RegularExpression HeaderMatchType has custom 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. \n 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. \n Support: Core (Exact, PathPrefix) + \n Support: Custom (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified query + parameters to select the route. + 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). + maxLength: 256 + minLength: 1 + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the query parameter. \n Support: + Extended (Exact) \n Support: Custom (RegularExpression) + \n Since RegularExpression QueryParamMatchType + has custom conformance, implementations can support + POSIX, PCRE or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + 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. + \n 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. \n 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. \n 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. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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. \n Example: + \"example.net/gateway-controller\". \n 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)." + 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. \n 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. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n 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. \n 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: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + 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-sigs/gateway-api/pull/891 + creationTimestamp: null + name: tcproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TCPRoute + listKind: TCPRouteList + plural: tcproutes + singular: tcproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: TCPRoute provides a way to route TCP requests. When combined + with a Gateway listener, it can be used to forward connections on the port + specified by the listener to a set of backends specified by the TCPRoute. + 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 TCPRoute. + properties: + 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. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n 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." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n 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. \n 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: gateway.networking.k8s.io + description: "Group is the group of the referent. \n 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. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n 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. \n + 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 + rules: + description: Rules are a list of TCP matchers and actions. + items: + description: TCPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the underlying implementation MUST actively reject connection + attempts to this backend. Connection rejections must respect + weight; if an invalid backend is requested to have 80% of + connections, then 80% of connections must be rejected instead. + \n Support: Core for Kubernetes Service Support: Custom for + any other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace is specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferencePolicy documentation + for details." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. 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. \n + 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. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TCPRoute. + 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. + \n 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. \n 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. \n 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. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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. \n Example: + \"example.net/gateway-controller\". \n 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)." + 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. \n 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. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n 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. \n 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: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + 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-sigs/gateway-api/pull/891 + creationTimestamp: null + name: tlsroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: TLSRoute + listKind: TLSRouteList + plural: tlsroutes + singular: tlsroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "The TLSRoute resource is similar to TCPRoute, but can be configured + to match against TLS-specific metadata. This allows more flexibility in + matching streams for a given TLS listener. \n If you need to forward traffic + to a single target for a TLS listener, you could choose to use a TCPRoute + with a TLS listener." + 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 TLSRoute. + properties: + hostnames: + description: "Hostnames defines a set of SNI names that should match + against the SNI attribute of TLS ClientHello message in TLS handshake. + This matches the RFC 1123 definition of a hostname with 2 notable + exceptions: \n 1. IPs are not allowed in SNI names per RFC 6066. + 2. A hostname may be prefixed with a wildcard label (`*.`). The + wildcard label must appear by itself as the first label. \n If + a hostname is specified by both the Listener and TLSRoute, there + must be at least one intersecting hostname for the TLSRoute to be + attached to the Listener. For example: \n * A Listener with `test.example.com` + as the hostname matches TLSRoutes 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 TLSRoutes 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. \n If both the Listener and TLSRoute have specified + hostnames, any TLSRoute hostnames that do not match the Listener + hostname MUST be ignored. For example, if a Listener specified `*.example.com`, + and the TLSRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. \n If both + the Listener and TLSRoute have specified hostnames, and none match + with the criteria above, then the TLSRoute is not accepted. The + implementation must raise an 'Accepted' Condition with a status + of `False` in the corresponding RouteParentStatus. \n 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: \n 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. \n 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`). + \n 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 + 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. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n 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." + items: + description: "ParentRef identifies an API object (usually a Gateway) + that can be considered a parent of this resource (usually a route). + The only kind of parent resource with \"Core\" support is Gateway. + This API may be extended in the future to support additional kinds + of parent resources, such as HTTPRoute. \n 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. \n 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: gateway.networking.k8s.io + description: "Group is the group of the referent. \n 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. \n Support: Core + (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified (or empty string), this refers to the local namespace + of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name + \n Implementations MAY choose to support attaching Routes + to other resources. If that is the case, they MUST clearly + document how SectionName is interpreted. \n 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. \n + 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 + rules: + description: Rules are a list of TLS matchers and actions. + items: + description: TLSRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the rule performs no forwarding; if no filters are specified + that would result in a response being sent, the underlying + implementation must actively reject request attempts to this + backend, by rejecting the connection or returning a 503 status + code. Request rejections must respect weight; if an invalid + backend is requested to have 80% of requests, then 80% of + requests must be rejected instead. \n Support: Core for Kubernetes + Service Support: Custom for any other resource \n Support + for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace is specified, a ReferencePolicy object is required + in the referent namespace to allow that namespace's owner + to accept the reference. See the ReferencePolicy documentation + for details." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (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 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 + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferencePolicy + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferencePolicy documentation for details. \n 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. 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. \n + 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. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TLSRoute. + 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. + \n 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. \n 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. \n 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. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + 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. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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. \n Example: + \"example.net/gateway-controller\". \n 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)." + 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. \n 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. \n Support: + Core (Gateway) Support: Custom (Other Resources)" + 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. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified (or empty string), this refers to the + local namespace of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name \n Implementations MAY choose to support attaching + Routes to other resources. If that is the case, they MUST + clearly document how SectionName is interpreted. \n 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. \n 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: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] \ No newline at end of file diff --git a/infra/modules/eks/addons/manifests/gateway_system.yaml b/infra/modules/eks/addons/manifests/gateway_system.yaml new file mode 100644 index 00000000..bb3fdb2e --- /dev/null +++ b/infra/modules/eks/addons/manifests/gateway_system.yaml @@ -0,0 +1,240 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: gateway-system +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: gateway-api-admission +webhooks: +- name: validate.gateway.networking.k8s.io + matchPolicy: Equivalent + rules: + - operations: [ "CREATE" , "UPDATE" ] + apiGroups: [ "gateway.networking.k8s.io" ] + apiVersions: [ "v1alpha2", "v1beta1" ] + resources: [ "gateways", "gatewayclasses", "httproutes" ] + failurePolicy: Fail + sideEffects: None + admissionReviewVersions: + - v1 + clientConfig: + service: + name: gateway-api-admission-server + namespace: gateway-system + path: "/validate" +--- +apiVersion: v1 +kind: Service +metadata: + labels: + name: gateway-api-webhook-server + name: gateway-api-admission-server + namespace: gateway-system +spec: + type: ClusterIP + ports: + - name: https-webhook + port: 443 + targetPort: 8443 + selector: + name: gateway-api-admission-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway-api-admission-server + namespace: gateway-system + labels: + name: gateway-api-admission-server +spec: + replicas: 1 + selector: + matchLabels: + name: gateway-api-admission-server + template: + metadata: + name: gateway-api-admission-server + labels: + name: gateway-api-admission-server + spec: + containers: + - name: webhook + image: registry.k8s.io/gateway-api/admission-server:v0.7.0 + imagePullPolicy: Always + args: + - -logtostderr + - --tlsCertFile=/etc/certs/cert + - --tlsKeyFile=/etc/certs/key + - -v=10 + - 2>&1 + ports: + - containerPort: 8443 + name: webhook + resources: + limits: + memory: 50Mi + cpu: 100m + requests: + memory: 50Mi + cpu: 100m + volumeMounts: + - name: webhook-certs + mountPath: /etc/certs + readOnly: true + securityContext: + readOnlyRootFilesystem: true + volumes: + - name: webhook-certs + secret: + secretName: gateway-api-admission +--- +# +# config/webhook/certificate_config.yaml +# +apiVersion: v1 +kind: ServiceAccount +metadata: + name: gateway-api-admission + labels: + name: gateway-api-webhook + namespace: gateway-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gateway-api-admission + labels: + name: gateway-api +rules: +- apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + verbs: + - get + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: gateway-api-admission + annotations: + labels: + name: gateway-api-webhook +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: gateway-api-admission +subjects: +- kind: ServiceAccount + name: gateway-api-admission + namespace: gateway-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: gateway-api-admission + annotations: + labels: + name: gateway-api-webhook + namespace: gateway-system +rules: +- apiGroups: + - '' + resources: + - secrets + verbs: + - get + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: gateway-api-admission + annotations: + labels: + name: gateway-api-webhook + namespace: gateway-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: gateway-api-admission +subjects: +- kind: ServiceAccount + name: gateway-api-admission + namespace: gateway-system +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: gateway-api-admission + annotations: + labels: + name: gateway-api-webhook + namespace: gateway-system +spec: + template: + metadata: + name: gateway-api-admission-create + labels: + name: gateway-api-webhook + spec: + containers: + - name: create + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.1.1 + imagePullPolicy: IfNotPresent + args: + - create + - --host=gateway-api-admission-server,gateway-api-admission-server.gateway-system.svc + - --namespace=gateway-system + - --secret-name=gateway-api-admission + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + restartPolicy: OnFailure + serviceAccountName: gateway-api-admission + securityContext: + runAsNonRoot: true + runAsUser: 2000 +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: gateway-api-admission-patch + labels: + name: gateway-api-webhook + namespace: gateway-system +spec: + template: + metadata: + name: gateway-api-admission-patch + labels: + name: gateway-api-webhook + spec: + containers: + - name: patch + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.1.1 + imagePullPolicy: IfNotPresent + args: + - patch + - --webhook-name=gateway-api-admission + - --namespace=gateway-system + - --patch-mutating=false + - --patch-validating=true + - --secret-name=gateway-api-admission + - --patch-failure-policy=Fail + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + restartPolicy: OnFailure + serviceAccountName: gateway-api-admission + securityContext: + runAsNonRoot: true + runAsUser: 2000 diff --git a/infra/modules/eks/addons/manifests/letsencrypt_issuer.yaml b/infra/modules/eks/addons/manifests/letsencrypt_issuer.yaml new file mode 100644 index 00000000..8d92c744 --- /dev/null +++ b/infra/modules/eks/addons/manifests/letsencrypt_issuer.yaml @@ -0,0 +1,18 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: 'smart.contracts@iohk.io' + privateKeySecretRef: + name: letsencrypt + solvers: + - http01: + gatewayHTTPRoute: + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: traefik-gateway + namespace: traefik diff --git a/infra/modules/eks/addons/outputs.tf b/infra/modules/eks/addons/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/infra/modules/eks/addons/variables.tf b/infra/modules/eks/addons/variables.tf new file mode 100644 index 00000000..2f44a3e7 --- /dev/null +++ b/infra/modules/eks/addons/variables.tf @@ -0,0 +1,28 @@ +variable "aws_profile" { + type = string +} + +variable "cluster_name" { + type = string +} + +variable "cluster_version" { + type = string +} + +variable "cluster_endpoint" { + type = string +} + +variable "cluster_certificate_authority_data" { + type = string +} + +variable "oidc_provider_arn" { + type = string +} + +variable "eks_addons" { + type = any + default = {} +} diff --git a/infra/modules/eks/locals.tf b/infra/modules/eks/locals.tf new file mode 100644 index 00000000..2d2167f9 --- /dev/null +++ b/infra/modules/eks/locals.tf @@ -0,0 +1,16 @@ +locals { + cluster_addons = { + # aws-ebs-csi-driver = { + # most_recent = true + # } + coredns = { + most_recent = true + } + kube-proxy = { + most_recent = true + } + vpc-cni = { + most_recent = true + } + } +} \ No newline at end of file diff --git a/infra/modules/eks/main.tf b/infra/modules/eks/main.tf new file mode 100644 index 00000000..8b0b027a --- /dev/null +++ b/infra/modules/eks/main.tf @@ -0,0 +1,39 @@ +provider "kubernetes" { + host = module.eks.cluster_endpoint + cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name, "--profile", var.aws_profile] + } +} + +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "19.17.2" + + cluster_name = var.cluster_name + cluster_version = var.cluster_version + cluster_endpoint_private_access = var.cluster_endpoint_private_access + cluster_endpoint_public_access = var.cluster_endpoint_public_access + + vpc_id = var.vpc_id + subnet_ids = var.subnet_ids + control_plane_subnet_ids = var.control_plane_subnet_ids + + node_security_group_additional_rules = var.node_security_group_additional_rules + + cluster_addons = local.cluster_addons + + eks_managed_node_group_defaults = var.eks_managed_node_group_defaults + eks_managed_node_groups = var.eks_managed_node_groups + + manage_aws_auth_configmap = var.manage_aws_auth_configmap + aws_auth_users = var.aws_auth_users + aws_auth_roles = var.aws_auth_roles + + kms_key_owners = var.kms_key_owners + kms_key_administrators = var.kms_key_administrators + + tags = var.tags +} diff --git a/infra/modules/eks/outputs.tf b/infra/modules/eks/outputs.tf new file mode 100644 index 00000000..1f6fc81a --- /dev/null +++ b/infra/modules/eks/outputs.tf @@ -0,0 +1,23 @@ +output "cluster_name" { + value = module.eks.cluster_name +} + +output "cluster_version" { + value = module.eks.cluster_version +} + +output "cluster_endpoint" { + value = module.eks.cluster_endpoint +} + +output "cluster_certificate_authority_data" { + value = module.eks.cluster_certificate_authority_data +} + +output "oidc_provider_arn" { + value = module.eks.oidc_provider_arn +} + +output "node_security_group_id" { + value = module.eks.node_security_group_id +} \ No newline at end of file diff --git a/infra/modules/eks/variables.tf b/infra/modules/eks/variables.tf new file mode 100644 index 00000000..5d358af8 --- /dev/null +++ b/infra/modules/eks/variables.tf @@ -0,0 +1,67 @@ +variable "aws_profile" { + type = string +} + +variable "cluster_name" { + type = string +} + +variable "cluster_version" { + type = string +} + +variable "cluster_endpoint_private_access" { + type = bool +} + +variable "cluster_endpoint_public_access" { + type = bool +} + +variable "vpc_id" { + type = string +} + +variable "subnet_ids" { + type = list(string) +} + +variable "control_plane_subnet_ids" { + type = list(string) +} + +variable "node_security_group_additional_rules" { + type = any +} + +variable "eks_managed_node_group_defaults" { + type = any +} + +variable "eks_managed_node_groups" { + type = any +} + +variable "manage_aws_auth_configmap" { + type = bool +} + +variable "aws_auth_users" { + type = any +} + +variable "aws_auth_roles" { + type = any +} + +variable "kms_key_owners" { + type = any +} + +variable "kms_key_administrators" { + type = any +} + +variable "tags" { + type = any +} diff --git a/infra/modules/kubevela-addons/addons.tf b/infra/modules/kubevela-addons/addons.tf new file mode 100644 index 00000000..474ea40c --- /dev/null +++ b/infra/modules/kubevela-addons/addons.tf @@ -0,0 +1,8 @@ +data "kubectl_file_documents" "otel-operator" { + content = file("${path.module}/otel-operator.yaml") +} + +resource "kubectl_manifest" "otel-operator" { + for_each = data.kubectl_file_documents.otel-operator.manifests + yaml_body = each.value +} diff --git a/infra/modules/kubevela-addons/cardano.tf b/infra/modules/kubevela-addons/cardano.tf new file mode 100644 index 00000000..7bf4f82f --- /dev/null +++ b/infra/modules/kubevela-addons/cardano.tf @@ -0,0 +1,7 @@ +resource "helm_release" "cardano" { + name = "cardano" + + chart = "./cardano" + namespace = var.namespace +} + diff --git a/infra/modules/kubevela/cardano/Chart.yaml b/infra/modules/kubevela-addons/cardano/Chart.yaml similarity index 100% rename from infra/modules/kubevela/cardano/Chart.yaml rename to infra/modules/kubevela-addons/cardano/Chart.yaml diff --git a/infra/modules/kubevela/cardano/templates/cardano-node.yaml b/infra/modules/kubevela-addons/cardano/templates/cardano-node.yaml similarity index 100% rename from infra/modules/kubevela/cardano/templates/cardano-node.yaml rename to infra/modules/kubevela-addons/cardano/templates/cardano-node.yaml diff --git a/infra/modules/kubevela/cardano/values.yaml b/infra/modules/kubevela-addons/cardano/values.yaml similarity index 100% rename from infra/modules/kubevela/cardano/values.yaml rename to infra/modules/kubevela-addons/cardano/values.yaml diff --git a/infra/modules/kubevela/definitions.tf b/infra/modules/kubevela-addons/definitions.tf similarity index 85% rename from infra/modules/kubevela/definitions.tf rename to infra/modules/kubevela-addons/definitions.tf index 484ee018..5e61b12c 100644 --- a/infra/modules/kubevela/definitions.tf +++ b/infra/modules/kubevela-addons/definitions.tf @@ -1,12 +1,12 @@ resource "kubernetes_manifest" "traitdefinition_https_route" { manifest = { "apiVersion" = "core.oam.dev/v1beta1" - "kind" = "TraitDefinition" + "kind" = "TraitDefinition" "metadata" = { "annotations" = { "definition.oam.dev/description" = "defines HTTPS rules for mapping requests from a Gateway to Application." } - "name" = "https-route" + "name" = "https-route" "namespace" = var.namespace } "spec" = { @@ -27,12 +27,12 @@ resource "kubernetes_manifest" "traitdefinition_https_route" { resource "kubernetes_manifest" "traitdefinition_http_route" { manifest = { "apiVersion" = "core.oam.dev/v1beta1" - "kind" = "TraitDefinition" + "kind" = "TraitDefinition" "metadata" = { "annotations" = { "definition.oam.dev/description" = "defines HTTP rules for mapping requests from a Gateway to Application." } - "name" = "http-route" + "name" = "http-route" "namespace" = var.namespace } "spec" = { @@ -54,12 +54,12 @@ resource "kubectl_manifest" "traitdefinition_resource" { force_new = true yaml_body = yamlencode({ "apiVersion" = "core.oam.dev/v1beta1" - "kind" = "TraitDefinition" + "kind" = "TraitDefinition" "metadata" = { "annotations" = { "definition.oam.dev/description" = "Add resource requests and limits on K8s pod for your workload which follows the pod spec in path 'spec.template." } - "name" = "resource" + "name" = "resource" "namespace" = var.namespace } "spec" = { @@ -81,14 +81,14 @@ resource "kubectl_manifest" "workflowtdefinition_build_nix_image" { force_new = true yaml_body = yamlencode({ "apiVersion" = "core.oam.dev/v1beta1" - "kind" = "WorkflowStepDefinition" + "kind" = "WorkflowStepDefinition" "metadata" = { "annotations" = { "custom.definition.oam.dev/category" = "CI Integration" - "definition.oam.dev/alias" = "" - "definition.oam.dev/description" = "Build and push image with nix flake URIs" + "definition.oam.dev/alias" = "" + "definition.oam.dev/description" = "Build and push image with nix flake URIs" } - "name" = "build-nix-image" + "name" = "build-nix-image" "namespace" = var.namespace } "spec" = { @@ -103,8 +103,8 @@ resource "kubectl_manifest" "workflowtdefinition_build_nix_image" { resource "kubectl_manifest" "componentdefinition_helmrelease" { - force_new = true - yaml_body = file("${path.module}/definitions/helm.yaml") + force_new = true + yaml_body = file("${path.module}/definitions/helm.yaml") override_namespace = var.namespace } diff --git a/infra/modules/kubevela/definitions/build-nix-image.cue b/infra/modules/kubevela-addons/definitions/build-nix-image.cue similarity index 100% rename from infra/modules/kubevela/definitions/build-nix-image.cue rename to infra/modules/kubevela-addons/definitions/build-nix-image.cue diff --git a/infra/modules/kubevela/definitions/helm.yaml b/infra/modules/kubevela-addons/definitions/helm.yaml similarity index 100% rename from infra/modules/kubevela/definitions/helm.yaml rename to infra/modules/kubevela-addons/definitions/helm.yaml diff --git a/infra/modules/kubevela/definitions/helmrelease.cue b/infra/modules/kubevela-addons/definitions/helmrelease.cue similarity index 100% rename from infra/modules/kubevela/definitions/helmrelease.cue rename to infra/modules/kubevela-addons/definitions/helmrelease.cue diff --git a/infra/modules/kubevela/definitions/http-route.cue b/infra/modules/kubevela-addons/definitions/http-route.cue similarity index 98% rename from infra/modules/kubevela/definitions/http-route.cue rename to infra/modules/kubevela-addons/definitions/http-route.cue index edd71184..033b8579 100644 --- a/infra/modules/kubevela/definitions/http-route.cue +++ b/infra/modules/kubevela-addons/definitions/http-route.cue @@ -14,7 +14,7 @@ outputs: { if parameter.gatewayName == _|_ { name: "traefik-gateway" } - namespace: "vela-system" + namespace: "traefik" if parameter.listenerName != _|_ { sectionName: parameter.listenerName } diff --git a/infra/modules/kubevela/definitions/https-route.cue b/infra/modules/kubevela-addons/definitions/https-route.cue similarity index 100% rename from infra/modules/kubevela/definitions/https-route.cue rename to infra/modules/kubevela-addons/definitions/https-route.cue diff --git a/infra/modules/kubevela/definitions/resource.cue b/infra/modules/kubevela-addons/definitions/resource.cue similarity index 100% rename from infra/modules/kubevela/definitions/resource.cue rename to infra/modules/kubevela-addons/definitions/resource.cue diff --git a/infra/modules/kubevela/otel-operator.yaml b/infra/modules/kubevela-addons/otel-operator.yaml similarity index 100% rename from infra/modules/kubevela/otel-operator.yaml rename to infra/modules/kubevela-addons/otel-operator.yaml diff --git a/infra/modules/kubevela/secretUI.cue b/infra/modules/kubevela-addons/secretUI.cue similarity index 100% rename from infra/modules/kubevela/secretUI.cue rename to infra/modules/kubevela-addons/secretUI.cue diff --git a/infra/modules/kubevela-addons/variables.tf b/infra/modules/kubevela-addons/variables.tf new file mode 100644 index 00000000..b2fe2a10 --- /dev/null +++ b/infra/modules/kubevela-addons/variables.tf @@ -0,0 +1,17 @@ +variable "namespace" { + description = "Set the namespace that kubevela is deployed to" + type = string + default = "vela-system" +} + +variable "helm_defaults" { + description = "Customize default Helm behavior" + type = any + default = {} +} + +variable "cluster-name" { + description = "Name of the Kubernetes cluster" + default = "sample-cluster" + type = string +} diff --git a/infra/modules/kubevela-addons/versions.tf b/infra/modules/kubevela-addons/versions.tf new file mode 100644 index 00000000..cb6cee36 --- /dev/null +++ b/infra/modules/kubevela-addons/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + helm = "~> 2.0" + kubernetes = "~> 2.0, != 2.12" + kubectl = { + source = "gavinbunney/kubectl" + version = "~> 1.0" + } + kustomization = { + source = "kbst/kustomize" + version = "0.2.0-beta.3" + } + } +} diff --git a/infra/modules/kubevela/addons.tf b/infra/modules/kubevela/addons.tf deleted file mode 100644 index ad9dd586..00000000 --- a/infra/modules/kubevela/addons.tf +++ /dev/null @@ -1,17 +0,0 @@ -data "kubectl_file_documents" "postgres-operator" { - content = file("${path.module}/postgres-operator.yaml") -} - -resource "kubectl_manifest" "postgres-operator" { - for_each = data.kubectl_file_documents.postgres-operator.manifests - yaml_body = each.value -} - -data "kubectl_file_documents" "otel-operator" { - content = file("${path.module}/otel-operator.yaml") -} - -resource "kubectl_manifest" "otel-operator" { - for_each = data.kubectl_file_documents.otel-operator.manifests - yaml_body = each.value -} diff --git a/infra/modules/kubevela/cardano.tf b/infra/modules/kubevela/cardano.tf deleted file mode 100644 index d8604a6e..00000000 --- a/infra/modules/kubevela/cardano.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "helm_release" "cardano" { - name = "cardano" - - chart = "./cardano" - namespace = kubernetes_namespace.vela-system.metadata[0].name -} - diff --git a/infra/modules/kubevela/definitions/postgres.cue b/infra/modules/kubevela/definitions/postgres.cue deleted file mode 100644 index 8f2cabb1..00000000 --- a/infra/modules/kubevela/definitions/postgres.cue +++ /dev/null @@ -1,168 +0,0 @@ -output: { - kind: "postgresql" - apiVersion: "acid.zalan.do/v1" - metadata: { - name: context.name - namespace: context.namespace - // default namespace will be "prod" - } - spec: { - dockerImage: parameter.image //ghcr.io/zalando/spilo-15:2.1-p9 - numberOfInstances: parameter.replicas //By default it's 2 - teamId: parameter.teamId - postgresql: parameter.postgresql - databases: parameter.databases - preparedDatabases: parameter.preparedDatabases - users: parameter.users - enableMasterLoadBalancer: parameter.enableMasterLoadBalancer - enableReplicaLoadBalancer: parameter.enableReplicaLoadBalancer - enableConnectionPooler: parameter.enableConnectionPooler - enableReplicaConnectionPooler: parameter.enableReplicaConnectionPooler - enableMasterPoolerLoadBalancer: parameter.enableReplicaConnectionPooler - enableReplicaPoolerLoadBalancer: parameter.enableReplicaPoolerLoadBalancer - allowedSourceRanges: [ // load balancers' source ranges for both master and replica services - "127.0.0.1/32" - ] - volume: parameter.volume - additionalVolumes: [ - { - name: "empty" - mountPath: "/opt/empty" - targetContainers: [ - "all" - ] - volumeSource: { - emptyDir: {} - } - } - ] - enableShmVolume: parameter.enableShmVolume - resources: parameter.resources - patroni: parameter.patroni - ttl: parameter.ttl - loop_wait: parameter.loopWait - retry_timeout: parameter.retryTimeout - synchronous_mode: parameter.synchronousMode - synchronous_mode_strict: parameter.synchronousModeStrict - synchronous_node_count: parameter.synchronousNodeCount - maximum_lag_on_failover: 33554432 - initContainers: [ - { - name: "date" - image: "busybox" - command: [ "/bin/date" ] - } - ] - // Custom TLS certificate. Disabled unless tls.secretName has a value. - tls: parameter.tls - } -} -parameter: { - //+usage=configure postgresql. - postgresql: { - //+usage=the version of the postgresql to be used. - version: *"15" | string - parameters: { - // Expert section - shared_buffers: *"32MB" | string - max_connections: *"10" | string - log_statement: *"all" | string - } - } - //+usage=the size of the postgres cluster. - replicas: *2 | int - //+usage=set team Id. - teamId: *"acid" | string - //+usage=the image of the spilo. - image: *"ghcr.io/zalando/spilo-15:2.1-p9" | string - //+usage=configure volume. - volume: { - //+usage=the size of the volume used of postgres. - size: *"1Gi" | string - } - //+usage=define databases to be used. - databases: *{ - foo: "zalando" // dbname: owner - } | {...} - //+usage=configure created databases. - preparedDatabases: *{ - bar: { - defaultUsers: true - extensions: { - pg_partman: "public" - pgcrypto: "public" - } - schemas: { - data: {} - history: { - defaultRoles: true - defaultUsers: false - } - } - } - } | {...} - //+usage=configure users for the databases. - users: *{ - zalando: ["superuser", "createdb"] - foo_user: [] - } | {...} - //+usage=configure patroni. - patroni: { - failsafe_mode: *false | bool - initdb: { - encoding: *"UTF8" | string - locale: *"en_US.UTF-8" | string - "data-checksums": *"true" | string - } - } - //+usage=enable SHM volume if set true. - enableShmVolume: *true | bool - //+usage=enable master as load balancer if set true. - enableMasterLoadBalancer: *false | bool - //+usage=enable replica as load balancer if set true. - enableReplicaLoadBalancer: *false | bool - //+usage=enable/disable connection pooler deployment. - enableConnectionPooler: *false | bool - //+usage=set to enable connection pooler for replica service. - enableReplicaConnectionPooler: *false | bool - //+usage=set to enable master pooler as load balancer. - enableMasterPoolerLoadBalancer: *false | bool - //+usage=set to enable replica pooler as load balancer. - enableReplicaPoolerLoadBalancer: *false | bool - //+usage=set ttl(Time to live) by dedault it's 30 days. - ttl: *30 | int - //+usage=set loop wait time by dedault it's 10. - loopWait: *10 | int - //+usage=set retry timeout by dedault it's 10. - retryTimeout: *10 | int - //+usage=set to enable synchronous mode. - synchronousMode: *false | bool - //+usage=set to enable synchronous mode strictly. - synchronousModeStrict: *false | bool - //+usage=set how many nodes to be synchronized. - synchronousNodeCount: *1 | int - //+usage=configure resources. - resources: { - requests: { - cpu: *"10m" | string - memory: *"100Mi" | string - } - limits: { - cpu: *"500m" | string - memory: *"500Mi" | string - } - } - //+usage=configure custom TLS. - tls: { - //+usage=sets custom TLS secret name, It should correspond to a Kubernetes Secret resource to load. - secretName: *"" | string - //+usage=sets custom TLS certificate file. - certificateFile: *"tls.crt" | string - //+usage=sets custom TLS private key file. - privateKeyFile: *"tls.key" | string - //+usage=optionally configure Postgres with a CA certificate. - caFile: *"" | string - //+usage=optionally the ca.crt can come from this secret instead. - caSecretName: *"" | string - } - } diff --git a/infra/modules/kubevela/outputs.tf b/infra/modules/kubevela/outputs.tf index e69de29b..369bdaed 100644 --- a/infra/modules/kubevela/outputs.tf +++ b/infra/modules/kubevela/outputs.tf @@ -0,0 +1,3 @@ +output "namespace" { + value = var.namespace +} diff --git a/infra/modules/kubevela/postgres-operator.yaml b/infra/modules/kubevela/postgres-operator.yaml deleted file mode 100644 index 059f9905..00000000 --- a/infra/modules/kubevela/postgres-operator.yaml +++ /dev/null @@ -1,124 +0,0 @@ -apiVersion: core.oam.dev/v1beta1 -kind: Application -metadata: - annotations: - addon.oam.dev/componentDefinitions: postgres-cluster - creationTimestamp: null - labels: - addons.oam.dev/name: postgres-operator - addons.oam.dev/registry: experimental - addons.oam.dev/version: 1.0.0 - name: addon-postgres-operator - namespace: vela-system -spec: - components: - - name: ns-postgres-operator - properties: - objects: - - apiVersion: v1 - kind: Namespace - metadata: - name: postgres-operator - type: k8s-objects - - name: postgres-operator - properties: - chart: postgres-operator - repoType: helm - url: https://opensource.zalando.com/postgres-operator/charts/postgres-operator - version: 1.9.0 - type: helm - policies: - - name: postgres-operator-ns - properties: - rules: - - selector: - resourceTypes: - - Namespace - type: shared-resource - - name: deploy-postgres-operator - properties: - clusterLabelSelector: {} - namespace: postgres-operator - type: topology -status: {} - ---- -apiVersion: core.oam.dev/v1beta1 -kind: ComponentDefinition -metadata: - annotations: - definition.oam.dev/alias: "" - definition.oam.dev/description: postgres cluster component - labels: {} - name: postgres-cluster - namespace: vela-system -spec: - schematic: - cue: - template: "output: {\n\tkind: \"postgresql\"\n\tapiVersion: \"acid.zalan.do/v1\"\n\tmetadata: - {\n\t\tname: context.name\n\t\tnamespace: context.namespace\n\t\t// default - namespace will be \"prod\"\n\t}\n\tspec: {\n\t\tdockerImage: parameter.image - \ //ghcr.io/zalando/spilo-15:2.1-p9\n\t\tnumberOfInstances: parameter.replicas - //By default it's 2\n\t\tteamId: parameter.teamId\n\t\tpostgresql: - \ parameter.postgresql\n\t\tdatabases: parameter.databases\n\t\tpreparedDatabases: - \ parameter.preparedDatabases\n\t\tusers: parameter.users\n\t\tenableMasterLoadBalancer: - \ parameter.enableMasterLoadBalancer\n\t\tenableReplicaLoadBalancer: - \ parameter.enableReplicaLoadBalancer\n\t\tenableConnectionPooler: parameter.enableConnectionPooler\n\t\tenableReplicaConnectionPooler: - \ parameter.enableReplicaConnectionPooler\n\t\tenableMasterPoolerLoadBalancer: - \ parameter.enableReplicaConnectionPooler\n\t\tenableReplicaPoolerLoadBalancer: - parameter.enableReplicaPoolerLoadBalancer\n\t\tallowedSourceRanges: [ // load - balancers' source ranges for both master and replica services\n\t\t\t\t\t\"127.0.0.1/32\",\n\t\t]\n\t\tvolume: - parameter.volume\n\t\tadditionalVolumes: [\n\t\t\t{\n\t\t\t\tname: \"empty\"\n\t\t\t\tmountPath: - \"/opt/empty\"\n\t\t\t\ttargetContainers: [\n\t\t\t\t\t\"all\",\n\t\t\t\t]\n\t\t\t\tvolumeSource: - emptyDir: {}\n\t\t\t},\n\t\t]\n\t\tenableShmVolume: parameter.enableShmVolume\n\t\tresources: - \ parameter.resources\n\t\tpatroni: parameter.patroni\n\t\tttl: - \ parameter.ttl\n\t\tloop_wait: parameter.loopWait\n\t\tretry_timeout: - \ parameter.retryTimeout\n\t\tsynchronous_mode: parameter.synchronousMode\n\t\tsynchronous_mode_strict: - parameter.synchronousModeStrict\n\t\tsynchronous_node_count: parameter.synchronousNodeCount\n\t\tmaximum_lag_on_failover: - 33554432\n\t\tinitContainers: [\n\t\t\t{\n\t\t\t\tname: \"date\"\n\t\t\t\timage: - \"busybox\"\n\t\t\t\tcommand: [ \"/bin/date\"]\n\t\t\t},\n\t\t]\n\t\t// Custom - TLS certificate. Disabled unless tls.secretName has a value.\n\t\ttls: parameter.tls\n\t}\n}\nparameter: - {\n\t//+usage=configure postgresql.\n\tpostgresql: {\n\t\t//+usage=the version - of the postgresql to be used.\n\t\tversion: *\"15\" | string\n\t\tparameters: - {\n\t\t\t// Expert section\n\t\t\tshared_buffers: *\"32MB\" | string\n\t\t\tmax_connections: - *\"10\" | string\n\t\t\tlog_statement: *\"all\" | string\n\t\t}\n\t}\n\t//+usage=the - size of the postgres cluster.\n\treplicas: *2 | int\n\t//+usage=set team Id.\n\tteamId: - *\"acid\" | string\n\t//+usage=the image of the spilo.\n\timage: *\"ghcr.io/zalando/spilo-15:2.1-p9\" - | string\n\t//+usage=configure volume.\n\tvolume: {\n\t\t//+usage=the size - of the volume used of postgres.\n\t\tsize: *\"1Gi\" | string\n\t}\n\t//+usage=define - databases to be used.\n\tdatabases: *{\n\t\tfoo: \"zalando\" // dbname: owner\n\t} - | {...}\n\t//+usage=configure created databases.\n\tpreparedDatabases: *{\n\t\tbar: - {\n\t\t\tdefaultUsers: true\n\t\t\textensions: {\n\t\t\t\tpg_partman: \"public\"\n\t\t\t\tpgcrypto: - \ \"public\"\n\t\t\t}\n\t\t\tschemas: {\n\t\t\t\tdata: {}\n\t\t\t\thistory: - {\n\t\t\t\t\tdefaultRoles: true\n\t\t\t\t\tdefaultUsers: false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} - | {...}\n\t//+usage=configure users for the databases.\n\tusers: *{\n\t\tzalando: - [\"superuser\", \"createdb\"]\n\t\tfoo_user: []\n\t} | {...}\n\t//+usage=configure - patroni.\n\tpatroni: {\n\t\tfailsafe_mode: *false | bool\n\t\tinitdb: {\n\t\t\tencoding: - \ *\"UTF8\" | string\n\t\t\tlocale: *\"en_US.UTF-8\" | string\n\t\t\t\"data-checksums\": - *\"true\" | string\n\t\t}\n\t}\n\t//+usage=enable SHM volume if set true. - \ \n\tenableShmVolume: *true | bool\n\t//+usage=enable master - as load balancer if set true.\n\tenableMasterLoadBalancer: *false | bool\n\t//+usage=enable - replica as load balancer if set true.\n\tenableReplicaLoadBalancer: *false - | bool\n\t//+usage=enable/disable connection pooler deployment.\n\tenableConnectionPooler: - *false | bool\n\t//+usage=set to enable connection pooler for replica service.\n\tenableReplicaConnectionPooler: - *false | bool\n\t//+usage=set to enable master pooler as load balancer.\n\tenableMasterPoolerLoadBalancer: - *false | bool\n\t//+usage=set to enable replica pooler as load balancer.\n\tenableReplicaPoolerLoadBalancer: - *false | bool\n\t//+usage=set ttl(Time to live) by dedault it's 30 days.\n\tttl: - *30 | int\n\t//+usage=set loop wait time by dedault it's 10.\n\tloopWait: - *10 | int\n\t//+usage=set retry timeout by dedault it's 10.\n\tretryTimeout: - *10 | int\n\t//+usage=set to enable synchronous mode.\n\tsynchronousMode: - *false | bool\n\t//+usage=set to enable synchronous mode strictly.\n\tsynchronousModeStrict: - *false | bool\n\t//+usage=set how many nodes to be synchronized.\n\tsynchronousNodeCount: - *1 | int\n\t//+usage=configure resources.\n\tresources: {\n\t\trequests: {\n\t\t\tcpu: - \ *\"10m\" | string\n\t\t\tmemory: *\"100Mi\" | string\n\t\t}\n\t\tlimits: - {\n\t\t\tcpu: *\"500m\" | string\n\t\t\tmemory: *\"500Mi\" | string\n\t\t}\n\t}\n\t//+usage=configure - custom TLS.\n\ttls: {\n\t\t//+usage=sets custom TLS secret name, It should - correspond to a Kubernetes Secret resource to load.\n\t\tsecretName: *\"\" - | string\n\t\t//+usage=sets custom TLS certificate file.\n\t\tcertificateFile: - *\"tls.crt\" | string\n\t\t//+usage=sets custom TLS private key file.\n\t\tprivateKeyFile: - *\"tls.key\" | string\n\t\t//+usage=optionally configure Postgres with a CA - certificate.\n\t\tcaFile: *\"\" | string\n\t\t//+usage=optionally the ca.crt - can come from this secret instead.\n\t\tcaSecretName: *\"\" | string\n\t}\n}\n" - workload: - type: autodetects.core.oam.dev - diff --git a/infra/prod-us-east-1/k8s/rds-postgres/bastion/terragrunt.hcl b/infra/prod-us-east-1/k8s/rds-postgres/bastion/terragrunt.hcl new file mode 100644 index 00000000..3dd0df57 --- /dev/null +++ b/infra/prod-us-east-1/k8s/rds-postgres/bastion/terragrunt.hcl @@ -0,0 +1,57 @@ +locals { + + # Automatically load environment-level variables + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + + # Extract out common variables for reuse + project = local.account_vars.locals.project + app = "marlowe-runtime" + + bastion_name = "${local.project}-${local.app}-database-bastion" + + subnet_id = "subnet-087617570cd189b3e" + + tags = { + organization = "iog" + tribe = "smart-contracts" + environment = "prod" + function = "bastion" + Environment = "prod" + Terraform = "true" + Project = local.project + Resource = local.bastion_name + } + +} + +terraform { + source = "github.com/terraform-aws-modules/terraform-aws-ec2-instance//.?ref=v5.3.1" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +dependency "key_pair" { + config_path = "../key-pair" +} + +dependency "vpc" { + config_path = "../../../vpc" +} + +dependency "security_group" { + config_path = "../security-group" +} + +inputs = { + name = local.bastion_name + instance_type = "t2.micro" + key_name = dependency.key_pair.outputs.key_pair_name + + subnet_id = dependency.vpc.outputs.public_subnets[0] + vpc_security_group_ids = [dependency.security_group.outputs.security_group_id] + + tags = local.tags +} diff --git a/infra/prod-us-east-1/k8s/rds-postgres/key-pair/bastion-key-enc.yaml b/infra/prod-us-east-1/k8s/rds-postgres/key-pair/bastion-key-enc.yaml new file mode 100644 index 00000000..60dc332f --- /dev/null +++ b/infra/prod-us-east-1/k8s/rds-postgres/key-pair/bastion-key-enc.yaml @@ -0,0 +1,16 @@ +bastion-key: ENC[AES256_GCM,data:iAKayBo0pSyln0PMr9y9dlItjp/1Ob2LYTEyL1fMSDBMKbN0y5rAiIaQ+0/Zk8i3zbGkkNIzrVdIUX1rPgj2rkEBRye6MWfFDBWk/X2JA4UKKhZkbYF+bR6zcGZ3/nRa0qoj30AFDfOHDJgGjC24lSqsOIcOeex30SgHPmWmr8Up+Ux1TSjhoSJ6KsQZcpg9Eix7S5g0DzdTB07GQqD0EpFRFcncDw5ZBxrAip16zujHuOOmoh8YZipL9OdL1VqfZ7+TbUN78xV4j7HBh8NIFqiSXCypqkoub8ZvTL66MTpzlS9bjtDbh763pZrN66Bv/ES4FIqqGjgccmuZLmvtKL1xHb9JnLO0NQ5kGDCOnpKinS967YveNMxOS2Q63VEixBuhA9XelwnuUbbWqSGmLlE/qyMqiv918bgfONtwyvrLqDsCQssnY0kN0HsYnZD82V9ip5qvs/EiYG8/6zTK1oAYHH2uHih9aDKjljvMm3JSlUyVmQPSiMrDIC97SzxADvFoYHKvJGM6q/E7ev0jNRsV/xvuVxWXC/zdHIVAZuYedrm2ALBtZ/vORGV35+4na8myiqULYmNmiANmVlKyIeM57Qp1lXWvnbZSDvUvuIU1iySq99HawI/fvTnXP/z0/APeh+V3aVzAyQ8g3TDeHeG0teDssvouDtb+EEqQftZ2Y8Ca+DVWk8Jbr94oaHENXzpsa/xmz47QtdNhxpSnOLysHWrHjmzOj8aI/ZW08IRA0CxqefK36HRHE4Q6s1/fC50kBPBNe5YY8iGfYDkArBhAKuCy/IVhyh3lrZ/hrgTn2ISapDyIQkBovXw+sDWhZssVj7jgm4ogTg50FCyeEahWjuTCWAITCe+v9hYxXMY1ApDKlXDhRsSZDVAwTqjHPlkUw7gnVhOOPGnKwCtbuipogYv+baWmm7Kk6Z9n2TS5O0f5A8gblCJNhExpEpb5EOjPKSEpIOWebaETuTjz30PnviX8iy2c9ZGzhJB9x9pdz4ofR8Ib6z7BWkzrBt4efRzS3GcrMpTG4kG5fJCrh1vhv4eSyVW2ENJSBhckMGEcUUiaJy+auHjoRaQr4UyQKG2N8g+KcVka41x4PgEOnE768i/pADFDp0VaWd169kHAaAN435JcBmHeHeqKHOn4dU9JCmQtooypk2wtu0GTrJ+29Deg1W79zB2Q9wuzL+4gMYm5mzXX61Tc0a+tfNr4btu1VkkzL2+T8/EBSU9q0mFm1GMguhl3BJbevxGyKJXiRieq3QkbYhDmckIJHNY7yIVYqHBHTwJKOhbsGk715PUj/XQnyaJJ2pnD31m7NvQXuiYui8CInK2CwjqjAGcBco9klfo8Il/6SUOUJNyKzWkSEM686xRbCMzp9qPvvaMucr1kXUukl3q4BY//NaOLZk9mWCBQ2CdEIcKAZfdWOICp0cZtz0geUs7SfZ86YSQlpRZYRfAa8bn2Y5gpAk1fgdALyga8dfD0teRHq28ivvAUNa9kagQxhXE4JevLovcW06ifP48qMrmMuwz2KeQLWPJ9MS//1S/tfQG+LorUsmzwgb9s2K8P3E/6xgAqCI1dVg91Db+1KaTRRj96PAw4Rttrw2me/Ce+4i6ABVGBRanGGbgJlIqLGyyp7xpOjmCX3BNuHKqP/+FqoOW9Kc7l8OLnr+EFJDMRyO3GtMjx/gUYuSVPcs3BCu28ibZ/Q9L41pjigaJh0qjHzpDwv2oN/VNJRnV7SrOVCWlRxOpXu6oRbyGaJFLtvVEok/GPa14JkX0/YUw59HJ06RmgNKLacZjfWHdhiTZ1/jF9TpLkT8sZR/CnI7+6r1L/cAQJA1N27afanmzMbJCt/wh0h7zd+lilPKWf0dhPvzQ7KWcoVxaiK20BDjOvzLcPXyKZZKbZ2qDm8poeqU/2DOwygnweP63FpjsGlax5CIrlt1/WbUluZH6HSnQGAEvb4zupR/BHSUUK1njbxlF8INmmGoK72qbAdL94d0zD4xU8kj25hF5KjTHqYq0r+AuNTct5200m0HrWS8B/Hs2ADNpgXoC18ufI/82t8G8xt/FrX0eqhB8/fFAYTEh9/ctzGE82TWMd2Iyel4nXvLmT6lXvG3IKwT+MsBW1K3NBs8Z5AXaMRI+5JjjOottKvBA4x8tCvcvMfoZpzWsmzsyKrxWHI7jBz+Ai+gk5DwqckJ2lnVeCcUz2QIJgFBFImhxuAf6hBcATzanSq6HVofph/G9o57oxtnsUJ6+ZDAtvwdQsLGIYHq7XmojNyyl2wQ18UHbeo7lZgTntuaHUYJaXIP8+dSdmBBpYEKteRpIo8Vy88xhFEWBXB7U2b1Zm7/OMTY5mkutIu2eiDsFv3FmuV4OPqTjO2hgbNPOJzw/5IlOcXGvcvTHxC21a0n4ai00vREj7yncG2x3TMoQPnJ55aGFOnuKHuEsGo4Zd52yrDDuX+HVMmE08Ihl6cThOzC/LP+2yX3+bXi9n3CkccqA/KGHhuafG+jN27b9UYjbt5UbfNCqY9yGZoVzYbX7kGRLYlC5ZmG2LTGSbr1hdYAxq78q1s7tPjC6mlKCul7rqsskTnMjKbmliQUMdEpfmC4eppo6z4rDXTnz5w8RFT4V2Jr18l+QnIOjPs/9BpVjECoOGQJD/yc4hPXvF2bxFtWwfU/m3bY4PClUhRDeIq53mWRlcP/HCtmVeY39qjJGVv5lpbveG4oT0zY4FnAloWXn+sedkYvke0F4ZcRiU5LU+cZXoRnES1rUjMkTWWOqDIf+F8NXDqxEQES351TAN02UMuqb4TTBhqQ/Jdbu/sSoHEjVIJF/xeNOYGS82RQPcEsKE8ipq2CJIJUAqvxHMDvRUK7Gr5c65xQvPNtvMEByeEIfuXhVBJ3cDPom+pmqVZoDWCayVfPUQfPmW+12uSpqdI9H13Zm0MwyB7Df3hiMeROsahPn1/t7Y74Pxpuxuq4aVbz3c4QiOcdmZWpAF6Vru+3nACCkZkAb5oSdmIci+VDqBaISQV18abBJV/Wm6zyIJe6RP/WFGNMqnZxQeP2ITFHoie+3H0zN+nBqeFUGVgGMzntxB5gtSi7dmn17oC/CrWiSHyyvMf4QZpQvWrBWHTbDOP4rGeCW13+r1Tud8ws9y+U14uw6aZ+pEkfMShwtJd4uPN0JJ8qvAGPbXM9g0nc483KCG985xGzLA5XybljJglaLtRBmDcP9LpdKZ0HHepZg7IpgIiz8uSdqYF4uEp/VHR0A7HZnpnfrg3vSdUkqNYyBA7dyQpV8+1ImPD6HX5YfFIss3SgrlaEHtTZsPH3gtj43K9y4/yZ1S5ZrhjvAKpecLqhW+8nP1AeIuGb10E+3VeDKouuX8nGdMms8Sc9jsGJQTxAJWImQdaHy15RSgi/wTB20Aw91Fqy5rnJheDj9D0yKwtRoHdErhLIcJvK9hgTVSMHupVNVTbrMf8+Aqwwmc4qv9c9ST2hNIFSycsOoWap0bcSu4VRdwyYsPb6vwzsYa/lkCXyJ2nChkIjsQv8OM5Nrt1a2sTZWaUHF8JX6MKk0Z8i2iAftu16zkaqWnmKUWU29waRv4hx6+Irnv/dV6YKAYkrqcrbbr1yurzqijTEndeigQs/dbsXfFvqERrUS8GitIp5wwkqV64IRryF4xMJHEfFW6t+v8KPqRUBSiua6kFXC22A/WoCTd2TZglWnb4MggKVMv83AUadFJ7rjc8mDw7uV5mL1m4FeVmxMWJ/1somtMmSfhq7cRBLnvd9BHHiymhz8YttDh/H9SioP+xTiSB4C8n7ZGznTcvALEFrCf+pxBd8EgC8iR3Lrcslz+QTEkQjHX8m/RWYE2/QvfHxHRe+DBtC8HTXzysK+DuaXYg0cIFBPb5OOlUbX9fmnb6lLJEGpKg7rTZrf8F3YYSpwiwN84UFWRtGWpO5j6poiIFop+zkNhK4sWAlCRJLTF4Yd9tk+G//+oPaJ9spUWofyw8kjFKutPBgeHMcXPTfLzKQUs/Js+syYn7KEDD2dgF+LNE/yOZkc0+tWa8pAZrTw4JUb4NEFVoYX42O5BKultO4W1k7a6T7QDcgZMgtdqnsD30Uq5X94XX85PGuxmu6udiur7//YCZ7QUr59qeMnXipoefAmZlPsk75QB0NZ8F6B9f0CoSY03TDcQiCxWJRwGVcVF8bBvwfLdjgGzcb4MrC4w9ILv0ZghtKb89llB0+KXwsjm05JdF7JyI4CcFQ//v1MNoza3MLSTK+7UY0NBSlbXihpPpy0OnfCb2QMYNMFpOZKhS0zGjdBDEJWh5f09STW/vKNdBNmIcRcOgWACrRFPhsetWLaf7PE8gQZLjBQN4PFtobDt+e+Tgizv5Eee+mWSQ7cAPTA29dNjf9a+IyRfJFYa41rZZew5i7xzrbVHOBv0CJp+R0lv54v61waNVB6UB42RVqDSjkWxZkKn8vqc3BYl4oP9gUB7f8uctd8IMdfN8ku6llH1To/bEA==,iv:iK5K7WVKmhPpyNO9l5H4YwkEa5ePKTi4m9MJj1bzaVQ=,tag:oD32o3052HynUQydKomiwQ==,type:str] +sops: + kms: + - arn: arn:aws:kms:us-east-1:677160962006:key/fa4d1d08-ad00-4014-97d2-5ff14e00e1b1 + created_at: "2023-08-26T20:53:30Z" + enc: AQICAHgpALcUCbJ6IXIyoNVBg1oTqujiOETypdzUT4DiWJC8RwEbm4g9bd0WdDQeqO61+Xs6AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM4n+JH1wmrfuFdH+ZAgEQgDtQiJL1fG5xBrQURRiGl8KI1cZdopLTVXsUO7SmDn8rClUDMy5I5uH9gHXETQVJ3coMlbsOxKN7jk6XuQ== + aws_profile: "" + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-08-26T20:53:30Z" + mac: ENC[AES256_GCM,data:HfhfEnl7qei2gTqgr17cW50y6uyj1rosKpyzeE8sZTbgpYzD4KAHQtJTM7yKdDyTJ7S6ekwkio7rYoE/Ruyd123mN8Tj6QC9sb355TGwj4/w1LfH5QYnKBells3bqfZMyOL/9g0eep/pWGQ3MDyjeiOrJg/dbLeU7/Dz5gv3vJw=,iv:fMQ6WwQwWoTPpivlU7qZlebe7O/Wvl9en1N8dDArzqs=,tag:i31pvfzUEFw0DSgD/F4R8w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 diff --git a/infra/prod-us-east-1/k8s/rds-postgres/key-pair/terragrunt.hcl b/infra/prod-us-east-1/k8s/rds-postgres/key-pair/terragrunt.hcl new file mode 100644 index 00000000..00668932 --- /dev/null +++ b/infra/prod-us-east-1/k8s/rds-postgres/key-pair/terragrunt.hcl @@ -0,0 +1,41 @@ +locals { + + # Automatically load environment-level variables + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + + # Extract out common variables for reuse + project = local.account_vars.locals.project + app = "marlowe-runtime" + + bastion_name = "${local.project}-${local.app}-bastion" + bastion_key_pair_name = "${local.project}-${local.app}-db-bastion-kp" + + tags = { + organization = "iog" + tribe = "smart-contracts" + environment = "prod" + function = "bastion-key-pair" + App = "marlowe-runtime" + Environment = "prod" + Terraform = "true" + Project = local.project + Resource = local.bastion_name + } + +} + +terraform { + source = "github.com/terraform-aws-modules/terraform-aws-key-pair//.?ref=v2.0.2" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +inputs = { + key_name = local.bastion_key_pair_name + create_private_key = true + + tags = local.tags +} diff --git a/infra/prod-us-east-1/k8s/rds-postgres/rds/terragrunt.hcl b/infra/prod-us-east-1/k8s/rds-postgres/rds/terragrunt.hcl new file mode 100644 index 00000000..6bd66e59 --- /dev/null +++ b/infra/prod-us-east-1/k8s/rds-postgres/rds/terragrunt.hcl @@ -0,0 +1,64 @@ +locals { + + # Automatically load environment-level variables + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + + # Extract out common variables for reuse + project = local.account_vars.locals.project + app = "marlowe-runtime" + + database_name = "${local.project}-${local.app}-database" + snapshot_identifier = "rds:dapps-marlowe-runtime-database-2023-08-26-08-06" + + vpc_subnet_group_name = "default-vpc-0a68a5d196ce5e1d1" + vpc_security_group_ids = ["sg-0c2ff87114e5f6ec1"] + + tags = { + organization = "iog" + tribe = "smart-contracts" + environment = "prod" + function = "database" + Environment = "prod" + Terraform = "true" + Project = local.project + Resource = local.database_name + } + +} + +terraform { + source = "github.com/terraform-aws-modules/terraform-aws-rds//.?ref=v6.1.1" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +inputs = { + identifier = local.database_name + instance_class = "db.m5d.2xlarge" + multi_az = true + max_allocated_storage = 3000 + + db_subnet_group_name = local.vpc_subnet_group_name + vpc_security_group_ids = local.vpc_security_group_ids + + engine = "postgres" + major_engine_version = "15" + family = "postgres15" + + snapshot_identifier = local.snapshot_identifier + skip_final_snapshot = false + copy_tags_to_snapshot = true + backup_retention_period = 21 + + performance_insights_enabled = true + performance_insights_retention_period = 31 + + ca_cert_identifier = "rds-ca-rsa2048-g1" + + apply_immediately = true + + tags = local.tags +} diff --git a/infra/prod-us-east-1/k8s/rds-postgres/security-group/terragrunt.hcl b/infra/prod-us-east-1/k8s/rds-postgres/security-group/terragrunt.hcl new file mode 100644 index 00000000..fb8f829b --- /dev/null +++ b/infra/prod-us-east-1/k8s/rds-postgres/security-group/terragrunt.hcl @@ -0,0 +1,46 @@ +locals { + + # Automatically load environment-level variables + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + + # Extract out common variables for reuse + project = local.account_vars.locals.project + app = "marlowe-runtime" + + bastion_name = "${local.project}-${local.app}-bastion" + bastion_key_pair_name = "${local.project}-${local.app}-db-bastion-kp" + + tags = { + organization = "iog" + tribe = "smart-contracts" + environment = "prod" + function = "bastion-key-pair" + App = "marlowe-runtime" + Environment = "prod" + Terraform = "true" + Project = local.project + Resource = local.bastion_name + } + +} + +terraform { + source = "github.com/terraform-aws-modules/terraform-aws-security-group//.?ref=v5.1.0/modules/ssh" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +dependency "vpc" { + config_path = "../../../vpc" +} + +inputs = { + vpc_id = dependency.vpc.outputs.vpc_id + + computed_ingress_cidr_blocks = ["0.0.0.0/0"] + ingress_cidr_blocks = ["0.0.0.0/0"] + tags = local.tags +} diff --git a/infra/prod-us-east-1/k8s/rds-postgres/terragrunt.hcl b/infra/prod-us-east-1/k8s/rds-postgres/terragrunt.hcl deleted file mode 100644 index 8a8de620..00000000 --- a/infra/prod-us-east-1/k8s/rds-postgres/terragrunt.hcl +++ /dev/null @@ -1,44 +0,0 @@ -locals { - - # Automatically load environment-level variables - account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) - - # Extract out common variables for reuse - project = local.account_vars.locals.project - app = "marlowe-runtime" - database_name = "${local.project}-${local.app}-database" - - tags = { - Environment = "prod" - Terraform = "true" - Project = local.project - Resource = local.database_name - } - -} - -terraform { - source = "github.com/terraform-aws-modules/terraform-aws-rds/modules/db_instance" -} - -inputs = { - identifier = local.database_name - instance_class = "db.m5d.2xlarge" - multi_az = true - max_allocated_storage = 3000 - - db_subnet_group_name = "default-vpc-0a68a5d196ce5e1d1" - vpc_security_group_ids = ["sg-0c2ff87114e5f6ec1"] - - snapshot_identifier = "rds:runtime-database-1-2023-08-22-08-02" - skip_final_snapshot = false - copy_tags_to_snapshot = true - backup_retention_period = 21 - - performance_insights_enabled = true - performance_insights_retention_period = 31 - - apply_immediately = true - - tags = local.tags -} diff --git a/infra/prod-us-east-1/vpc/terragrunt.hcl b/infra/prod-us-east-1/vpc/terragrunt.hcl index 186d94c8..73683679 100644 --- a/infra/prod-us-east-1/vpc/terragrunt.hcl +++ b/infra/prod-us-east-1/vpc/terragrunt.hcl @@ -12,7 +12,7 @@ locals { # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the # working directory, into a temporary folder, and execute your Terraform commands in that folder. terraform { - source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git//.?ref=tags/v3.14.4" + source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git//.?ref=v5.1.1" } # Include all settings from the root terragrunt.hcl file @@ -47,6 +47,11 @@ inputs = { "kubernetes.io/role/internal-elb" = 1 } + map_public_ip_on_launch = true + manage_default_network_acl = false + manage_default_route_table = false + manage_default_security_group = false + tags = { Terraform = "true" Environment = local.env diff --git a/infra/provider-configs/k8s.hcl b/infra/provider-configs/k8s.hcl index aa8b0d50..8ec86415 100644 --- a/infra/provider-configs/k8s.hcl +++ b/infra/provider-configs/k8s.hcl @@ -4,9 +4,9 @@ locals { } generate "k8s_provider" { - path = "k8s_provider.tf" + path = "k8s_provider.tf" if_exists = "overwrite" - contents = <<-EOF + contents = <<-EOF provider "kubernetes" { host = data.aws_eks_cluster.cluster.endpoint cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data) diff --git a/infra/secrets.yaml b/infra/secrets.yaml new file mode 100644 index 00000000..1352b121 --- /dev/null +++ b/infra/secrets.yaml @@ -0,0 +1,17 @@ +grafana-api-key: + secret: ENC[AES256_GCM,data:zTck1eMIPRP4bnuZW3Lb8lMQl7/3GLKmKEqtzKZLrLZl2HwXz3V4HGe7uBu2tSvI0ZFFnZ19toIy/kqAQyNX32A8woKGoQ7fkEnjZ7AEZK0uVDxYY/OhuB3V1jMJRpFAsvGt2tgFc4l13EYqUEDjamyrNDs=,iv:0We5lZRKoa1X7vyDb5QNRrF4H3tCR06UaG3SULQr0BY=,tag:a7M3oeI/l/AlqwkEc/YCiQ==,type:str] +sops: + kms: + - arn: arn:aws:kms:us-east-1:677160962006:key/fa4d1d08-ad00-4014-97d2-5ff14e00e1b1 + created_at: "2023-06-30T15:11:50Z" + enc: AQICAHgpALcUCbJ6IXIyoNVBg1oTqujiOETypdzUT4DiWJC8RwFsLaAQpL8wBMz9YUGdIE7/AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM30YhEbBXCQbpWtoZAgEQgDt99sUCVeKhG1QKLVmL7paPEgCa5H2yz16s0s3DcqxYXM0wEMJy7AOXxWoF8UMXf8J2CA5oGk0P1tdaMw== + aws_profile: "" + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2023-06-30T15:11:50Z" + mac: ENC[AES256_GCM,data:ElMlntlM3hao9114uzL32/PYhBsXvqrIqwz1sXKwz02ZMaIDzLQarNT4w2zY5YMkK0JPxNBgw5KehTI7rojVBbaTBxjG0hthYN83ykmBIN2QfPLhVi+aVvEpJDFrYAtYAH8dGR6OMM/lTrYkPEAnZIFnl3/40XXb8wn9N1b9eFI=,iv:yj/NlCbkOEnuf+8hWnOJ0P5vZzEy/7R9PPiUS/9msbw=,tag:hm0qye2Y+GOoPXpHb5MxgA==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.7.3 \ No newline at end of file diff --git a/infra/terragrunt.hcl b/infra/terragrunt.hcl index 9fdf558d..f07c9a4a 100644 --- a/infra/terragrunt.hcl +++ b/infra/terragrunt.hcl @@ -41,7 +41,10 @@ locals { account_name = local.account_vars.locals.account_name account_id = local.account_vars.locals.aws_account_id aws_profile = local.account_vars.locals.aws_profile + tribe = local.account_vars.locals.tribe aws_region = local.environment_vars.locals.aws_region + env = local.environment_vars.locals.environment + project = local.environment_vars.locals.project } # Generate an AWS provider block @@ -58,7 +61,16 @@ generate "provider" { # role_arn = "arn:aws:iam::${local.account_id}:role/terragrunt" # } # Only these AWS Account IDs may be operated on by this template -} + default_tags { + tags = { + Environment = "${local.env}" + Project = "${local.project}" + Tribe = "${local.tribe}" + Organization = "iog" + Terraform = "true" + } + } + } EOF } diff --git a/infra/us-east-1/prod/eks/blue/cluster.hcl b/infra/us-east-1/prod/eks/blue/cluster.hcl new file mode 100644 index 00000000..fb75b218 --- /dev/null +++ b/infra/us-east-1/prod/eks/blue/cluster.hcl @@ -0,0 +1,12 @@ +# Set common variables for the Kubernetes cluster. This is automatically pulled in in the root terragrunt.hcl configuration to +# feed forward to the child modules. +locals { + env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + namespaces = ["preprod-prod", "mainnet-prod"] + version = "1.26" + name = "blue" + clustername = "${local.env_vars.locals.project}-${local.env_vars.locals.environment}-${local.env_vars.locals.aws_region}-${local.name}" + + # This will generate A records for these domains pointing to Traefik's ELB + hostnames = ["*.test.scdev.aws.iohkdev.io"] +} diff --git a/infra/us-east-1/prod/eks/blue/eks-addons/terragrunt.hcl b/infra/us-east-1/prod/eks/blue/eks-addons/terragrunt.hcl new file mode 100755 index 00000000..9a8b90e5 --- /dev/null +++ b/infra/us-east-1/prod/eks/blue/eks-addons/terragrunt.hcl @@ -0,0 +1,113 @@ +locals { + # Automatically load environment-level variables + environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + # Extract out common variables for reuse + env = local.environment_vars.locals.environment + region = local.environment_vars.locals.aws_region + hostnames = local.environment_vars.locals.hostnames + profile = local.account_vars.locals.aws_profile + + # Hosted Zone ARN for scdev-test.aws.iohkdev.io + hostedzone_arn = "arn:aws:route53:::hostedzone/Z10147571DRRDCJXSER5Y" +} + +include { + path = find_in_parent_folders() +} + +terraform { + source = "github.com/input-output-hk/sc-dev-platform.git//infra/modules/eks/addons?ref=2e8c2caa6e500cf8077e04c5d99355512284ccad" +} + +dependency "eks" { + config_path = "../eks" +} + +inputs = { + + aws_profile = local.profile + cluster_name = dependency.eks.outputs.cluster_name + cluster_version = dependency.eks.outputs.cluster_version + cluster_endpoint = dependency.eks.outputs.cluster_endpoint + cluster_certificate_authority_data = dependency.eks.outputs.cluster_certificate_authority_data + oidc_provider_arn = dependency.eks.outputs.oidc_provider_arn + + eks_addons = { + + # Cluster Autoscaler + cluster_autoscaler = { + set = [{ + name = "extraArgs.scale-down-utilization-threshold" + value = "0.7" + }] + } + + # External-DNS + enable_external_dns = true + external_dns_route53_zone_arns = [local.hostedzone_arn] + external_dns = { + values = [ + <<-EOT + env: + # Don't change anything, useful for debugging purposes. + - name: EXTERNAL_DNS_DRY_RUN + value: "0" + txtOwnerId: "${dependency.eks.outputs.cluster_name}" + EOT + ] + } + + # Cert-Manager + enable_cert_manager = true + cert_manager = { + chart_version = "v1.9.1" #FIXME + values = [ + <<-EOT + ingressShim: + defaultIssuerName: letsencrypt + defaultIssuerKind: ClusterIssuer + defaultIssuerGroup: cert-manager.io + + extraArgs: + - --feature-gates=ExperimentalGatewayAPISupport=true + EOT + ] + } + + # Traefik Load Balancer + enable_traefik_load_balancer = true + traefik_load_balancer = { + values = [ + <<-EOT + image: + tag: "v3.0" + + experimental: + kubernetesGateway: + enabled: true + namespacePolicy: All + + ports: + web: + redirectTo: + port: websecure + priority: 10 + + service: + annotations: + "service.beta.kubernetes.io/aws-load-balancer-type": "external" + "service.beta.kubernetes.io/aws-load-balancer-nlb-target-type": "instance" + "service.beta.kubernetes.io/aws-load-balancer-name": "traefik" + "service.beta.kubernetes.io/aws-load-balancer-scheme": "internet-facing" + "external-dns.alpha.kubernetes.io/hostname": "${join(",", local.hostnames)}" + "external-dns.alpha.kubernetes.io/aws-weight": "100" + "external-dns.alpha.kubernetes.io/set-identifier": "traefik-blue" + EOT + ] + } + + # KubeVela Controller + enable_kubevela_controller = true + } +} diff --git a/infra/us-east-1/prod/eks/blue/eks/terragrunt.hcl b/infra/us-east-1/prod/eks/blue/eks/terragrunt.hcl new file mode 100755 index 00000000..cb66510a --- /dev/null +++ b/infra/us-east-1/prod/eks/blue/eks/terragrunt.hcl @@ -0,0 +1,204 @@ +locals { + # Automatically load environment-level variables + environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + + # Extract out common variables for reuse + env = local.environment_vars.locals.environment + region = local.environment_vars.locals.aws_region + profile = local.account_vars.locals.aws_profile + aws_account_id = local.account_vars.locals.aws_account_id + users = local.account_vars.locals.users + tribe = local.account_vars.locals.tribe + project = local.account_vars.locals.project + name = "${local.project}-${local.env}-${local.region}-blue" + + list_users = [for user in local.users : + "arn:aws:iam::${local.aws_account_id}:user/${user}" + ] + + map_users = [for user in local.users : { + userarn = "arn:aws:iam::${local.aws_account_id}:user/${user}" + username = user + groups = ["system:masters"] + }] + + asg_tags = { + "k8s.io/cluster-autoscaler/${local.name}" = "owned" + "k8s.io/cluster-autoscaler/enabled" = true + } + + tags = {} +} + +# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the +# working directory, into a temporary folder, and execute your Terraform commands in that folder. +terraform { + source = "github.com/input-output-hk/sc-dev-platform.git//infra/modules/eks?ref=2e8c2caa6e500cf8077e04c5d99355512284ccad" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +# VPC as dependency +dependency "vpc" { + config_path = "../../../vpc" +} + +# These are the variables we have to pass in to use the module specified in the terragrunt configuration above +inputs = { + cluster_name = local.name + cluster_version = "1.26" + + cluster_endpoint_private_access = true + cluster_endpoint_public_access = true + + vpc_id = dependency.vpc.outputs.vpc_id + subnet_ids = concat(dependency.vpc.outputs.private_subnets, dependency.vpc.outputs.public_subnets) + control_plane_subnet_ids = dependency.vpc.outputs.intra_subnets + + node_security_group_additional_rules = { + ingress_self_all = { + from_port = 0 + to_port = 0 + protocol = "-1" + type = "ingress" + self = true + } + ingress_cluster_all = { + from_port = 0 + to_port = 0 + protocol = "-1" + type = "ingress" + source_cluster_security_group = true + } + ingress_node_port_tcp_1 = { + from_port = 1025 + to_port = 5472 # Exclude calico-typha port 5473 + protocol = "tcp" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + ingress_node_port_tcp_2 = { + from_port = 5474 + to_port = 10249 # Exclude kubelet port 10250 + protocol = "tcp" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + ingress_node_port_tcp_3 = { + from_port = 10251 + to_port = 10255 # Exclude kube-proxy HCHK port 10256 + protocol = "tcp" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + ingress_node_port_tcp_4 = { + from_port = 10257 + to_port = 61677 # Exclude aws-node port 61678 + protocol = "tcp" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + ingress_node_port_tcp_5 = { + from_port = 61679 + to_port = 65535 + protocol = "tcp" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + ingress_node_port_udp = { + from_port = 1025 + to_port = 65535 + protocol = "udp" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + egress_all = { + from_port = 0 + to_port = 0 + protocol = "-1" + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } + } + + # EKS managed node groups + eks_managed_node_group_defaults = { + tags = local.asg_tags + desired_size = 3 + min_size = 3 + max_size = 12 + capacity_type = "ON_DEMAND" + platform = "bottlerocket" + ami_release_version = "1.15.1-264e294c" + iam_role_additional_policies = { + AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + } + ebs_optimized = true + update_config = { + max_unavailable_percentage = 33 + } + block_device_mappings = { + root = { + device_name = "/dev/xvda" + ebs = { + volume_size = 2 + volume_type = "gp3" + delete_on_termination = true + encrypted = true + } + } + containers = { + device_name = "/dev/xvdb" + ebs = { + volume_size = 50 + volume_type = "gp3" + delete_on_termination = true + encrypted = true + } + } + } + } + + eks_managed_node_groups = { + "worker" = { + ami_type = "BOTTLEROCKET_x86_64" + instance_types = ["t3a.xlarge"] + subnet_ids = dependency.vpc.outputs.private_subnets + labels = { + network = "private" + } + } + "worker-memory" = { + ami_type = "BOTTLEROCKET_x86_64" + min_size = 3 + max_size = 6 + instance_types = ["t3a.2xlarge"] + subnet_ids = dependency.vpc.outputs.private_subnets + labels = { + network = "private" + } + } + } + + # aws-auth configmap + manage_aws_auth_configmap = true + aws_auth_users = local.map_users + aws_auth_roles = [] + + kms_key_owners = local.list_users + kms_key_administrators = local.list_users + + tags = local.tags + +} \ No newline at end of file diff --git a/infra/us-east-1/prod/eks/blue/grafana-agent/terragrunt.hcl b/infra/us-east-1/prod/eks/blue/grafana-agent/terragrunt.hcl new file mode 100644 index 00000000..d5c1c9c1 --- /dev/null +++ b/infra/us-east-1/prod/eks/blue/grafana-agent/terragrunt.hcl @@ -0,0 +1,40 @@ +include "root" { + path = find_in_parent_folders() +} + +locals { + # Get provider configs + k8s = read_terragrunt_config("${get_parent_terragrunt_dir()}/provider-configs/k8s.hcl") + helm = read_terragrunt_config("${get_parent_terragrunt_dir()}/provider-configs/helm.hcl") + + environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + dapps_namespaces = local.environment_vars.locals.namespaces + + secret_vars = yamldecode(sops_decrypt_file(find_in_parent_folders("secrets.yaml"))) + grafana-password = local.secret_vars.grafana-api-key.secret +} + +# Generate provider blocks +generate = merge(local.k8s.generate, local.helm.generate) + +terraform { + source = "../../../modules/grafana-agent" +} + +dependency "eks" { + config_path = "../eks" + + mock_outputs = { + cluster_name = "cluster-name" + cluster_oidc_issuer_url = "https://oidc.eks.eu-west-3.amazonaws.com/id/0000000000000000" + } +} + +inputs = { + # cluster-name = local.cluster + cluster-name = dependency.eks.outputs.cluster_name + k8s-cluster-name = dependency.eks.outputs.cluster_name # for provider block + namespace = "grafana-agent" + grafana-username = "379443" + grafana-password = local.grafana-password +} diff --git a/infra/us-east-1/prod/eks/blue/kubevela-addons/terragrunt.hcl b/infra/us-east-1/prod/eks/blue/kubevela-addons/terragrunt.hcl new file mode 100644 index 00000000..bc24702a --- /dev/null +++ b/infra/us-east-1/prod/eks/blue/kubevela-addons/terragrunt.hcl @@ -0,0 +1,40 @@ +include "root" { + path = find_in_parent_folders() +} + +locals { + # Get provider configs + k8s = read_terragrunt_config("${get_parent_terragrunt_dir()}/provider-configs/k8s.hcl") + helm = read_terragrunt_config("${get_parent_terragrunt_dir()}/provider-configs/helm.hcl") + kubectl = read_terragrunt_config("${get_parent_terragrunt_dir()}/provider-configs/kubectl.hcl") + + environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + dapps_namespaces = local.environment_vars.locals.namespaces +} + +# Generate provider blocks +generate = merge(local.k8s.generate, local.helm.generate, local.kubectl.generate) + +terraform { + source = "../../../modules/kubevela-addons" +} + +dependency "eks" { + config_path = "../eks" + + mock_outputs = { + cluster_id = "cluster-name" + cluster_oidc_issuer_url = "https://oidc.eks.eu-west-3.amazonaws.com/id/0000000000000000" + } +} + +dependency "kubevela" { + config_path = "../kubevela" +} + +inputs = { + # cluster-name = local.cluster + cluster-name = dependency.eks.outputs.cluster_name + k8s-cluster-name = dependency.eks.outputs.cluster_name # for provider block + namespace = dependency.kubevela.outputs.namespace +} diff --git a/infra/us-east-1/prod/env.hcl b/infra/us-east-1/prod/env.hcl new file mode 100644 index 00000000..877a442d --- /dev/null +++ b/infra/us-east-1/prod/env.hcl @@ -0,0 +1,10 @@ +# Set common variables for the environment. This is automatically pulled in in the root terragrunt.hcl configuration to +# feed forward to the child modules. +locals { + aws_region = "us-east-1" + environment = "prod" + project = "scde" + # This will generate A records for these domains pointing to Traefik's ELB + hostnames = ["*.test.scdev.aws.iohkdev.io"] + cidr_prefix = "10.30" +} diff --git a/infra/us-east-1/prod/rds/prod-marlowe-runtime-db/terragrunt.hcl b/infra/us-east-1/prod/rds/prod-marlowe-runtime-db/terragrunt.hcl new file mode 100644 index 00000000..94c8b9ea --- /dev/null +++ b/infra/us-east-1/prod/rds/prod-marlowe-runtime-db/terragrunt.hcl @@ -0,0 +1,71 @@ +locals { + # Automatically load environment-level variables + environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + + # Extract out common variables for reuse + project = local.account_vars.locals.project + env = local.environment_vars.locals.environment + app = "marlowe-runtime" + + database_name = "${local.env}-${local.app}-db" + + tags = {} + +} + +dependency "vpc" { + config_path = "../../vpc" +} + +dependency "eks" { + config_path = "../../eks/blue/eks" +} + +terraform { + source = "github.com/terraform-aws-modules/terraform-aws-rds//.?ref=v6.1.1" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +inputs = { + identifier = local.database_name + instance_class = "db.m6g.2xlarge" + multi_az = true + storage_type = "gp3" + allocated_storage = 1500 + max_allocated_storage = 3000 + domain = "" + publicly_accessible = false + monitoring_interval = 60 + monitoring_role_arn = "arn:aws:iam::${local.account_vars.locals.aws_account_id}:role/rds-monitoring-role" + + username = "postgres" + + create_db_subnet_group = true + subnet_ids = dependency.vpc.outputs.intra_subnets + + vpc_security_group_ids = [dependency.eks.outputs.node_security_group_id] + + engine = "postgres" + major_engine_version = "15" + family = "postgres15" + + skip_final_snapshot = false + copy_tags_to_snapshot = true + backup_retention_period = 21 + + performance_insights_enabled = true + performance_insights_retention_period = 31 + + ca_cert_identifier = "rds-ca-rsa2048-g1" + + auto_minor_version_upgrade = false + apply_immediately = true + deletion_protection = true + + tags = local.tags +} \ No newline at end of file diff --git a/infra/us-east-1/prod/vpc/terragrunt.hcl b/infra/us-east-1/prod/vpc/terragrunt.hcl new file mode 100644 index 00000000..01c4f9aa --- /dev/null +++ b/infra/us-east-1/prod/vpc/terragrunt.hcl @@ -0,0 +1,59 @@ +locals { + # Automatically load environment-level variables + environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl")) + # Extract out common variables for reuse + env = local.environment_vars.locals.environment + region = local.environment_vars.locals.aws_region + cidr_prefix = local.environment_vars.locals.cidr_prefix + project = local.environment_vars.locals.project + tribe = local.account_vars.locals.tribe + name = "${local.project}-${local.env}-${local.region}" +} + +# Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the +# working directory, into a temporary folder, and execute your Terraform commands in that folder. +terraform { + source = "git::https://github.com/terraform-aws-modules/terraform-aws-vpc.git//.?ref=v5.1.1" +} + +# Include all settings from the root terragrunt.hcl file +include { + path = find_in_parent_folders() +} + +# These are the variables we have to pass in to use the module specified in the terragrunt configuration above +inputs = { + name = local.name + cidr = "${local.cidr_prefix}.0.0/16" + + azs = ["${local.region}a", "${local.region}b", "${local.region}c"] + private_subnets = ["${local.cidr_prefix}.48.0/20", "${local.cidr_prefix}.64.0/20", "${local.cidr_prefix}.80.0/20"] # /20 will allow 4096 ips per subnet + public_subnets = ["${local.cidr_prefix}.0.0/20", "${local.cidr_prefix}.16.0/20", "${local.cidr_prefix}.32.0/20"] # /20 will allow 4096 ips per subnet + intra_subnets = ["${local.cidr_prefix}.96.0/22", "${local.cidr_prefix}.100.0/22", "${local.cidr_prefix}.104.0/22"] # /22 will allow 1024 ips per subnet + + enable_nat_gateway = true + single_nat_gateway = false + one_nat_gateway_per_az = true + + enable_dns_hostnames = true + enable_dns_support = true + + public_subnet_tags = { + "kubernetes.io/cluster/${local.name}-blue" = "shared" + "kubernetes.io/cluster/${local.name}-green" = "shared" + "kubernetes.io/role/elb" = 1 + } + + private_subnet_tags = { + "kubernetes.io/cluster/${local.name}-blue" = "shared" + "kubernetes.io/cluster/${local.name}-green" = "shared" + "kubernetes.io/role/internal-elb" = 1 + } + + map_public_ip_on_launch = true + manage_default_network_acl = false + manage_default_route_table = false + manage_default_security_group = false + +} diff --git a/packages/kubevela.nix b/packages/kubevela.nix index 64799a55..fa856009 100644 --- a/packages/kubevela.nix +++ b/packages/kubevela.nix @@ -1,14 +1,17 @@ -{ buildGoModule, fetchFromGitHub }: +{ + buildGoModule, + fetchFromGitHub, +}: buildGoModule { pname = "kubevela"; - version = "v1.7.4"; + version = "v1.9.6"; src = fetchFromGitHub { owner = "kubevela"; repo = "kubevela"; - rev = "v1.7.4"; - sha256 = "sha256-y9i23YpiN0LeygKUDJ/du+jnjA79i1buVamusdS+oUk="; + rev = "v1.9.6"; + sha256 = "sha256-eRlJP7TREtg/gDMDJUFuVwIIfyY40uFQA9Ua/o24hwg="; }; - vendorHash = "sha256-pumANncR9/QV6EXqrCCe9vjJEumhZhk+vqMFU9cHQ7Y="; + vendorHash = "sha256-UOq3iHi9aJD0veYiz6THdLJhXhK0Y6hwoViC3ma2cqM="; postInstall = '' cd $out/bin for f in * ; do mv -- "$f" "vela-$f" ; done