diff --git a/go.mod b/go.mod index c23f00f3..eed81e52 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( cloud.google.com/go/container v1.24.0 cloud.google.com/go/secretmanager v1.10.0 cloud.google.com/go/storage v1.29.0 + github.com/Masterminds/sprig/v3 v3.2.2 github.com/argoproj/argo-cd/v2 v2.6.7 github.com/argoproj/gitops-engine v0.7.3 github.com/atotto/clipboard v0.1.4 @@ -38,6 +39,7 @@ require ( github.com/rs/zerolog v1.29.1 github.com/segmentio/analytics-go v3.1.0+incompatible github.com/sirupsen/logrus v1.9.0 + github.com/stretchr/testify v1.8.4 github.com/swaggo/files v1.0.0 github.com/swaggo/gin-swagger v1.5.3 github.com/swaggo/swag v1.16.1 @@ -54,12 +56,20 @@ require ( ) require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect + github.com/alicebob/miniredis/v2 v2.23.1 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/go-resty/resty/v2 v2.11.0 // indirect - github.com/go-test/deep v1.0.4 // indirect - github.com/hashicorp/go-hclog v1.3.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect + github.com/go-test/deep v1.0.3 // indirect + github.com/huandu/xstrings v1.3.1 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gotest.tools/v3 v3.4.0 // indirect ) @@ -265,7 +275,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/yaml.v3 v3.0.1 k8s.io/apiextensions-apiserver v0.26.0 // indirect k8s.io/apiserver v0.24.2 // indirect k8s.io/cli-runtime v0.24.2 // indirect diff --git a/go.sum b/go.sum index 88cf6e46..7ba0d6e4 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,13 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= @@ -106,7 +111,9 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis/v2 v2.23.1 h1:jR6wZggBxwWygeXcdNyguCOCIjPsZyNUNlAkTx2fu0U= +github.com/alicebob/miniredis/v2 v2.23.1/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -367,7 +374,6 @@ github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8 github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= @@ -475,8 +481,8 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -627,8 +633,7 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy9do= -github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -666,11 +671,14 @@ github.com/hashicorp/vault/api v1.9.0/go.mod h1:lloELQP4EyhjnCQhF8agKvWIVTmxbpEJ github.com/heketi/heketi v10.3.0+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -775,13 +783,11 @@ github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GW github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -816,6 +822,8 @@ github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -830,6 +838,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= @@ -926,9 +936,8 @@ github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runc v1.1.1/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -1059,6 +1068,8 @@ github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1083,6 +1094,7 @@ github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -1121,11 +1133,11 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -1192,6 +1204,7 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ= +github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -1259,6 +1272,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -1445,6 +1459,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1472,7 +1487,6 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1533,7 +1547,6 @@ golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/controller/argocd.go b/internal/controller/argocd.go index db959d87..12eba020 100644 --- a/internal/controller/argocd.go +++ b/internal/controller/argocd.go @@ -10,7 +10,7 @@ import ( "context" "fmt" "os/exec" - "time" + "time" argocdapi "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned" awsext "github.com/kubefirst/kubefirst-api/extensions/aws" @@ -178,7 +178,7 @@ func (clctrl *ClusterController) DeployRegistryApplication() error { if err != nil { return err } - + log.Info().Msg("applying the registry application to argocd") registryURL, err := clctrl.GetRepoURL() @@ -221,11 +221,11 @@ func (clctrl *ClusterController) DeployRegistryApplication() error { } log.Info().Msgf("Error creating Argo CD application on attempt number #%d: %v\n", attempt, err) time.Sleep(5 * time.Second) - continue + continue } log.Info().Msgf("Argo CD application created successfully on attempt #%d: %s\n", attempt, app.Name) - break + break } diff --git a/internal/services/services.go b/internal/services/services.go index 96396d45..3c2b413a 100644 --- a/internal/services/services.go +++ b/internal/services/services.go @@ -163,7 +163,7 @@ func CreateService(cl *pkgtypes.Cluster, serviceName string, appDef *pkgtypes.Gi gitopsKubefirstTokens := utils.CreateTokensFromDatabaseRecord(cl, registryPath, secretStoreRef, project, clusterDestination, environment, clusterName) //Detokenize App Template - err = providerConfigs.DetokenizeGitGitops(catalogServiceFolder, gitopsKubefirstTokens, cl.GitProtocol, cl.CloudflareAuth.OriginCaIssuerKey != "") + err = providerConfigs.Detokenize(catalogServiceFolder, gitopsKubefirstTokens, cl.GitProtocol, cl.CloudflareAuth.OriginCaIssuerKey != "") if err != nil { return fmt.Errorf("cluster %s - error opening file: %s", clusterName, err) } diff --git a/internal/vultr/kubernetes.go b/internal/vultr/kubernetes.go index fca9d3ad..7c70efc4 100644 --- a/internal/vultr/kubernetes.go +++ b/internal/vultr/kubernetes.go @@ -90,7 +90,7 @@ func (c *VultrConfiguration) DeleteBlockStorage(blockStorage []govultr.BlockStor return nil } -func (c *VultrConfiguration) GetKubeconfig(clusterName string)(string, error) { +func (c *VultrConfiguration) GetKubeconfig(clusterName string) (string, error) { clusters, _, _, err := c.Client.Kubernetes.ListClusters(c.Context, &govultr.ListOptions{}) if err != nil { @@ -98,7 +98,7 @@ func (c *VultrConfiguration) GetKubeconfig(clusterName string)(string, error) { } var clusterId string - for _, cluster := range clusters { + for _, cluster := range clusters { if cluster.Label == clusterName { clusterId = cluster.ID continue @@ -112,7 +112,7 @@ func (c *VultrConfiguration) GetKubeconfig(clusterName string)(string, error) { kubeConfig, _, err := c.Client.Kubernetes.GetKubeConfig(c.Context, clusterId) if err != nil { - return "", err + return "", err } return kubeConfig.KubeConfig, nil diff --git a/pkg/providerConfigs/adjustDriver.go b/pkg/providerConfigs/adjustDriver.go index ef35bffe..d6e5277b 100644 --- a/pkg/providerConfigs/adjustDriver.go +++ b/pkg/providerConfigs/adjustDriver.go @@ -985,7 +985,7 @@ func PrepareGitRepositories( // DETOKENIZE //* detokenize the gitops repo - DetokenizeGitGitops(gitopsDir, gitopsTokens, gitProtocol, useCloudflareOriginIssuer) + err = Detokenize(gitopsDir, gitopsTokens, gitProtocol, useCloudflareOriginIssuer) if err != nil { return err } @@ -999,7 +999,7 @@ func PrepareGitRepositories( // DETOKENIZE //* detokenize the metaphor repo - DetokenizeGitMetaphor(metaphorDir, metaphorTokens) + err = Detokenize(metaphorDir, metaphorTokens, gitProtocol, useCloudflareOriginIssuer) if err != nil { return err } diff --git a/pkg/providerConfigs/config.go b/pkg/providerConfigs/config.go index 3c407f83..75a6b872 100644 --- a/pkg/providerConfigs/config.go +++ b/pkg/providerConfigs/config.go @@ -8,9 +8,8 @@ package providerConfigs import ( "fmt" - "os" - "github.com/rs/zerolog/log" + "os" ) type ProviderConfig struct { @@ -27,35 +26,32 @@ type ProviderConfig struct { VultrToken string CloudflareAPIToken string CloudflareOriginCaIssuerAPIToken string - - GithubToken string - GitlabToken string - - ArgoWorkflowsDir string - DestinationGitopsRepoHttpsURL string - DestinationGitopsRepoGitURL string - DestinationGitopsRepoURL string - DestinationMetaphorRepoHttpsURL string - DestinationMetaphorRepoGitURL string - DestinationMetaphorRepoURL string - GitopsDir string - GitProvider string - GitProtocol string - K1Dir string - Kubeconfig string - KubectlClient string - KubefirstBotSSHPrivateKey string - KubefirstConfig string - LogsDir string - MetaphorDir string - RegistryAppName string - RegistryYaml string - SSLBackupDir string - TerraformClient string - ToolsDir string - - GitopsDirectoryValues *GitopsDirectoryValues - MetaphorDirectoryValues *MetaphorTokenValues + GithubToken string + GitlabToken string + ArgoWorkflowsDir string + DestinationGitopsRepoHttpsURL string + DestinationGitopsRepoGitURL string + DestinationGitopsRepoURL string + DestinationMetaphorRepoHttpsURL string + DestinationMetaphorRepoGitURL string + DestinationMetaphorRepoURL string + GitopsDir string + GitProvider string + GitProtocol string + K1Dir string + Kubeconfig string + KubectlClient string + KubefirstBotSSHPrivateKey string + KubefirstConfig string + LogsDir string + MetaphorDir string + RegistryAppName string + RegistryYaml string + SSLBackupDir string + TerraformClient string + ToolsDir string + GitopsDirectoryValues *GitopsDirectoryValues + MetaphorDirectoryValues *MetaphorTokenValues } // GetConfig - load default values from kubefirst installer @@ -69,12 +65,10 @@ func GetConfig( cloudflareOriginCaIssuerAPIToken string, ) *ProviderConfig { config := ProviderConfig{} - homeDir, err := os.UserHomeDir() if err != nil { log.Fatal().Msgf("something went wrong getting home path: %s", err) } - // cGitHost describes which git host to use depending on gitProvider var cGitHost string switch gitProvider { @@ -83,7 +77,6 @@ func GetConfig( case "gitlab": cGitHost = GitlabHost } - config.DestinationGitopsRepoURL = fmt.Sprintf("https://%s/%s/gitops.git", cGitHost, gitOwner) config.DestinationGitopsRepoGitURL = fmt.Sprintf("git@%s:%s/gitops.git", cGitHost, gitOwner) config.DestinationMetaphorRepoURL = fmt.Sprintf("https://%s/%s/metaphor.git", cGitHost, gitOwner) @@ -105,6 +98,5 @@ func GetConfig( config.SSLBackupDir = fmt.Sprintf("%s/.k1/%s/ssl/%s", homeDir, clusterName, domainName) config.TerraformClient = fmt.Sprintf("%s/.k1/%s/tools/terraform", homeDir, clusterName) config.ToolsDir = fmt.Sprintf("%s/.k1/%s/tools", homeDir, clusterName) - return &config } diff --git a/pkg/providerConfigs/constants.go b/pkg/providerConfigs/constants.go index 09ccdea7..90a40d1b 100644 --- a/pkg/providerConfigs/constants.go +++ b/pkg/providerConfigs/constants.go @@ -19,8 +19,11 @@ const ( LocalhostOS = runtime.GOOS LocalhostArch = runtime.GOARCH TerraformClientVersion = "1.3.8" - ArgocdHelmChartVersion = "4.10.5" ArgocdPortForwardURL = runtimepkg.ArgocdPortForwardURL VaultPortForwardURL = runtimepkg.VaultPortForwardURL + + TokenRegexPattern = "<([A-Z_0-9-]+)>" + leftDelimiter = "<%" + rightDelimiter = "%>" ) diff --git a/pkg/providerConfigs/detokenize.go b/pkg/providerConfigs/detokenize.go index 358e6867..b50c4746 100644 --- a/pkg/providerConfigs/detokenize.go +++ b/pkg/providerConfigs/detokenize.go @@ -7,20 +7,53 @@ See the LICENSE file for more details. package providerConfigs import ( - "encoding/json" + "bytes" "fmt" - "io/ioutil" + "github.com/Masterminds/sprig/v3" + "io" "os" "path/filepath" - "strconv" + "reflect" + "regexp" "strings" - - log "github.com/rs/zerolog/log" + "text/template" ) -// DetokenizeGitGitops - Translate tokens by values on a given path -func DetokenizeGitGitops(path string, tokens *GitopsDirectoryValues, gitProtocol string, useCloudflareOriginIssuer bool) error { - err := filepath.Walk(path, detokenizeGitops(path, tokens, gitProtocol, useCloudflareOriginIssuer)) +// ToTemplateVars - converts a string to a template variable +func ToTemplateVars(input string, instance Tokens) string { + value := reflect.ValueOf(instance) + if value.Kind() == reflect.Ptr { + value = value.Elem() + } + sanitizer := strings.NewReplacer("<", "", "_", "", ">", "", "-", "") + + fields := value.Type() + normalizedName := strings.ToLower(sanitizer.Replace(input)) + for i := 0; i < fields.NumField(); i++ { + field := fields.Field(i) + val := value.Field(i) + + if normalizedName == strings.ToLower(field.Name) { + // If the field value is the zero value of the field template + // will add - to the template variable to clean up extra whitespace. + // We do not have any bool values in the tokens, so we should be ok. + // TODO: Find a better way to handle this. + if val.IsZero() { + return fmt.Sprintf("%s- .%s %s", leftDelimiter, field.Name, rightDelimiter) + } + // if field name matches return the correct formatted name + return fmt.Sprintf("%s .%s %s", leftDelimiter, field.Name, rightDelimiter) + } + } + + // If no match found, return so we can have a visual indication + // that the token was not found in the Token Struct without erroring out + return "" +} + +// Detokenize - Translate tokens by values on a given path +func Detokenize(path string, tokens Tokens, gitProtocol string, useCloudflareOriginIssuer bool) error { + err := filepath.Walk(path, detokenize(tokens, gitProtocol, useCloudflareOriginIssuer)) if err != nil { return err } @@ -28,287 +61,124 @@ func DetokenizeGitGitops(path string, tokens *GitopsDirectoryValues, gitProtocol return nil } -func detokenizeGitops(path string, tokens *GitopsDirectoryValues, gitProtocol string, useCloudflareOriginIssuer bool) filepath.WalkFunc { +func detokenize(tokens Tokens, gitProtocol string, useCloudflareOriginIssuer bool) filepath.WalkFunc { return filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error { if fi.IsDir() && fi.Name() == ".git" { return filepath.SkipDir } - if err != nil { - return err - } if fi.IsDir() { return nil } + // Incase there is a .gitignore or .gitkeep etc file in the directory, skip it. + if strings.Contains(fi.Name(), ".git") { + return nil + } - metaphorDevelopmentIngressURL := fmt.Sprintf("https://metaphor-development.%s", tokens.DomainName) - metaphorStagingIngressURL := fmt.Sprintf("https://metaphor-staging.%s", tokens.DomainName) - metaphorProductionIngressURL := fmt.Sprintf("https://metaphor-production.%s", tokens.DomainName) - - // var matched bool - matched, _ := filepath.Match("*", fi.Name()) - - if matched { - // ignore .git files - if !strings.Contains(path, "/.git/") { - - read, err := ioutil.ReadFile(path) - if err != nil { - return err - } - - var fullDomainName string - - if tokens.SubdomainName != "" { - fullDomainName = fmt.Sprintf("%s.%s", tokens.SubdomainName, tokens.DomainName) - } else { - fullDomainName = tokens.DomainName - } - - newContents := string(read) - newContents = strings.Replace(newContents, "", tokens.AlertsEmail, -1) - newContents = strings.Replace(newContents, "", tokens.AtlantisAllowList, -1) - newContents = strings.Replace(newContents, "", tokens.ClusterName, -1) - newContents = strings.Replace(newContents, "", tokens.CloudProvider, -1) - newContents = strings.Replace(newContents, "", tokens.CloudRegion, -1) - newContents = strings.Replace(newContents, "", tokens.ClusterId, -1) - newContents = strings.Replace(newContents, "", tokens.ClusterType, -1) - newContents = strings.Replace(newContents, "", tokens.ContainerRegistryURL, -1) - newContents = strings.Replace(newContents, "", fullDomainName, -1) - newContents = strings.Replace(newContents, "", tokens.KubeconfigPath, -1) - newContents = strings.Replace(newContents, "", tokens.KubefirstArtifactsBucket, -1) - newContents = strings.Replace(newContents, "", tokens.KubefirstStateStoreBucket, -1) - newContents = strings.Replace(newContents, "", tokens.KubefirstTeam, -1) - newContents = strings.Replace(newContents, "", os.Getenv("KUBEFIRST_TEAM_INFO"), -1) - newContents = strings.Replace(newContents, "", tokens.KubefirstVersion, -1) - newContents = strings.Replace(newContents, "", tokens.StateStoreBucketHostname, -1) - newContents = strings.Replace(newContents, "", tokens.WorkloadClusterTerraformModuleURL, -1) - newContents = strings.Replace(newContents, "", tokens.WorkloadClusterBootstrapTerraformModuleURL, -1) - newContents = strings.Replace(newContents, "", tokens.NodeType, -1) - newContents = strings.Replace(newContents, "", fmt.Sprint(tokens.NodeCount), -1) - - // AWS - newContents = strings.Replace(newContents, "", tokens.AwsAccountID, -1) - newContents = strings.Replace(newContents, "", tokens.AwsIamArnAccountRoot, -1) - newContents = strings.Replace(newContents, "", tokens.AwsNodeCapacityType, -1) - - // google - newContents = strings.Replace(newContents, "", tokens.GoogleProject, -1) - newContents = strings.Replace(newContents, "", tokens.ForceDestroy, -1) - newContents = strings.Replace(newContents, "", tokens.GoogleUniqueness, -1) - - if tokens.CloudProvider == "k3s" { - // k3s - newContents = strings.Replace(newContents, "", tokens.K3sServersPrivateIps[0], -1) - // TODO: this is a hack to get around - // need to be refactored into a single function with args - var terraformServersPrivateIpsList string - jsonBytes, err := json.Marshal(tokens.K3sServersPrivateIps) - if err != nil { - log.Fatal().Msgf("detokenise issue on %s", err) - } - terraformServersPrivateIpsList = string(jsonBytes) - newContents = strings.Replace(newContents, "", terraformServersPrivateIpsList, -1) - - var terraformServersPublicIpsList string - jsonBytes2, err := json.Marshal(tokens.K3sServersPublicIps) - if err != nil { - log.Fatal().Msgf("detokenise issue on %s", err) - } - terraformServersPublicIpsList = string(jsonBytes2) - newContents = strings.Replace(newContents, "", terraformServersPublicIpsList, -1) - - var terraformServersArgsList string - jsonBytes3, err := json.Marshal(tokens.K3sServersArgs) - if err != nil { - log.Fatal().Msgf("detokenise issue on %s", err) - } - terraformServersArgsList = string(jsonBytes3) - newContents = strings.Replace(newContents, "", terraformServersArgsList, -1) - - newContents = strings.Replace(newContents, "", tokens.SshUser, -1) - } - newContents = strings.Replace(newContents, "", tokens.ArgoCDIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.ArgoCDIngressNoHTTPSURL, -1) - newContents = strings.Replace(newContents, "", tokens.ArgoWorkflowsIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.ArgoWorkflowsIngressNoHTTPSURL, -1) - newContents = strings.Replace(newContents, "", tokens.AtlantisIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.AtlantisIngressNoHTTPSURL, -1) - newContents = strings.Replace(newContents, "", tokens.ChartMuseumIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.VaultIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.VaultIngressNoHTTPSURL, -1) - newContents = strings.Replace(newContents, "", tokens.VaultDataBucketName, -1) - newContents = strings.Replace(newContents, "", tokens.VouchIngressURL, -1) - - newContents = strings.Replace(newContents, "", tokens.GitDescription, -1) - newContents = strings.Replace(newContents, "", tokens.GitNamespace, -1) - newContents = strings.Replace(newContents, "", tokens.GitProvider, -1) - newContents = strings.Replace(newContents, "", gitProtocol, -1) - newContents = strings.Replace(newContents, "", tokens.GitRunner, -1) - newContents = strings.Replace(newContents, "", tokens.GitRunnerDescription, -1) - newContents = strings.Replace(newContents, "", tokens.GitRunnerNS, -1) - newContents = strings.Replace(newContents, "", tokens.GitURL, -1) // remove - - // GitHub - newContents = strings.Replace(newContents, "", tokens.GitHubHost, -1) - newContents = strings.Replace(newContents, "", strings.ToLower(tokens.GitHubOwner), -1) - newContents = strings.Replace(newContents, "", tokens.GitHubUser, -1) - - // GitLab - newContents = strings.Replace(newContents, "", tokens.GitlabHost, -1) - newContents = strings.Replace(newContents, "", tokens.GitlabOwner, -1) - newContents = strings.Replace(newContents, "", strconv.Itoa(tokens.GitlabOwnerGroupID), -1) - newContents = strings.Replace(newContents, "", tokens.GitlabUser, -1) - - newContents = strings.Replace(newContents, "", tokens.GitopsRepoAtlantisWebhookURL, -1) - newContents = strings.Replace(newContents, "", tokens.GitopsRepoNoHTTPSURL, -1) - - newContents = strings.Replace(newContents, "", metaphorDevelopmentIngressURL, -1) - newContents = strings.Replace(newContents, "", metaphorProductionIngressURL, -1) - newContents = strings.Replace(newContents, "", metaphorStagingIngressURL, -1) - - // external-dns optionality to provide cloudflare support regardless of cloud provider - newContents = strings.Replace(newContents, "", tokens.ExternalDNSProviderName, -1) - newContents = strings.Replace(newContents, "", tokens.ExternalDNSProviderTokenEnvName, -1) - newContents = strings.Replace(newContents, "", tokens.ExternalDNSProviderSecretName, -1) - newContents = strings.Replace(newContents, "", tokens.ExternalDNSProviderSecretKey, -1) - newContents = strings.Replace(newContents, "", tokens.DomainName, -1) - - // Catalog - newContents = strings.Replace(newContents, "", tokens.RegistryPath, -1) - newContents = strings.Replace(newContents, "", tokens.SecretStoreRef, -1) - newContents = strings.Replace(newContents, "", tokens.Project, -1) - newContents = strings.Replace(newContents, "", tokens.ClusterDestination, -1) - newContents = strings.Replace(newContents, "", tokens.Environment, -1) - - //origin issuer defines which annotations should be on ingresses - if useCloudflareOriginIssuer { - newContents = strings.Replace(newContents, "", "cert-manager.io/issuer: cloudflare-origin-issuer", -1) - newContents = strings.Replace(newContents, "", "cert-manager.io/issuer-kind: OriginIssuer", -1) - newContents = strings.Replace(newContents, "", "cert-manager.io/issuer-group: cert-manager.k8s.cloudflare.com", -1) - newContents = strings.Replace(newContents, "", "external-dns.alpha.kubernetes.io/cloudflare-proxied: \"true\"", -1) - } else { - newContents = strings.Replace(newContents, "", "cert-manager.io/cluster-issuer: \"letsencrypt-prod\"", -1) - newContents = strings.Replace(newContents, "", "", -1) - newContents = strings.Replace(newContents, "", "", -1) - newContents = strings.Replace(newContents, "", "", -1) - } - - newContents = strings.Replace(newContents, "", tokens.UseTelemetry, -1) - - // Switch the repo url based on https flag - newContents = strings.Replace(newContents, "", tokens.GitopsRepoURL, -1) - - // The fqdn is used by metaphor/argo to choose the appropriate url for cicd operations. - if gitProtocol == "https" { - newContents = strings.Replace(newContents, "", fmt.Sprintf("https://%v.com/", tokens.GitProvider), -1) - } else { - newContents = strings.Replace(newContents, "", fmt.Sprintf("git@%v.com:", tokens.GitProvider), -1) - } + var ( + newContentData []byte + ) + + switch tokenType := tokens.(type) { + case *GitopsDirectoryValues: + setGitOpsTokens(tokenType, gitProtocol, useCloudflareOriginIssuer) + tokens = tokenType + case *MetaphorTokenValues: + setMetaphorTokens(tokenType, gitProtocol) + tokens = tokenType + } - err = ioutil.WriteFile(path, []byte(newContents), 0) - if err != nil { - return err - } - } + newContentData, err = renderGoTemplating(path, tokens) + if err != nil { + return err } - return nil + return os.WriteFile(path, newContentData, 0644) + }) } -// DetokenizeAdditionalPath - Translate tokens by values on a given path -func DetokenizeAdditionalPath(path string, tokens *GitopsDirectoryValues) error { - err := filepath.Walk(path, detokenizeAdditionalPath(path, tokens)) - if err != nil { - return err - } +func setMetaphorTokens(tokens *MetaphorTokenValues, gitProtocol string) { + tokens.GitProtocol = gitProtocol + tokens.MetaphorDevelopmentIngressURL = fmt.Sprintf("https://metaphor-dev.%s", tokens.DomainName) + tokens.MetaphorProductionIngressURL = fmt.Sprintf("https://metaphor.%s", tokens.DomainName) + tokens.MetaphorStagingIngressURL = fmt.Sprintf("https://metaphor-stage.%s", tokens.DomainName) - return nil } -// detokenizeAdditionalPath temporary addition to handle detokenizing additional files -func detokenizeAdditionalPath(path string, tokens *GitopsDirectoryValues) filepath.WalkFunc { - return filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error { - if err != nil { - return err - } - - if !!fi.IsDir() { - return nil +func setGitOpsTokens(tokens *GitopsDirectoryValues, gitProtocol string, useCloudflareOriginIssuer bool) { + if tokens.SubdomainName != "" { + if !strings.Contains(tokens.DomainName, tokens.SubdomainName) { + tokens.DomainName = fmt.Sprintf("%s.%s", tokens.SubdomainName, tokens.DomainName) } + } + //origin issuer defines which annotations should be on ingresses + if useCloudflareOriginIssuer { + tokens.CertManagerIssuerAnnotation1 = "cert-manager.io/issuer: cloudflare-origin-issuer" + tokens.CertManagerIssuerAnnotation2 = "cert-manager.io/issuer-kind: OriginIssuer" + tokens.CertManagerIssuerAnnotation3 = "cert-manager.io/issuer-group: cert-manager.k8s.cloudflare.com" + tokens.CertManagerIssuerAnnotation4 = "external-dns.alpha.kubernetes.io/cloudflare-proxied: \"true\"" + } else { + tokens.CertManagerIssuerAnnotation1 = "cert-manager.io/cluster-issuer: \"letsencrypt-prod\"" + } - // var matched bool - matched, _ := filepath.Match("*", fi.Name()) - - if matched { - // ignore .git files - if !strings.Contains(path, "/.git/") { - read, err := ioutil.ReadFile(path) - if err != nil { - return err - } + if tokens.CloudProvider == "k3s" { + tokens.K3sEndpoint = tokens.K3sServersPrivateIps[0] + } - newContents := string(read) - newContents = strings.Replace(newContents, "", tokens.GitlabOwner, -1) + // The fqdn is used by metaphor/argo to choose the appropriate url for cicd operations. + if gitProtocol == "https" { + tokens.GitFqdn = fmt.Sprintf("https://%v.com/", tokens.GitProvider) + } else { + tokens.GitFqdn = fmt.Sprintf("git@%v.com:", tokens.GitProvider) + } +} - err = ioutil.WriteFile(path, []byte(newContents), 0) - if err != nil { - return err - } - } - } - return nil - }) +// renderGoTemplating - Renders the template with the given values +// it also includes the sprig GenericFuncMap functions listed here: https://masterminds.github.io/sprig/. +func parseTemplate(content string) (*template.Template, error) { + funcs := sprig.GenericFuncMap() + t := template.New("gitops-template"). + Funcs(funcs). + Delims(leftDelimiter, rightDelimiter) + return t.Parse(content) } -// DetokenizeGithubMetaphor - Translate tokens by values on a given path -func DetokenizeGitMetaphor(path string, tokens *MetaphorTokenValues) error { - err := filepath.Walk(path, detokenizeGitopsMetaphor(path, tokens)) - if err != nil { - return err +func executeTemplate(t *template.Template, writer io.Writer, tokens Tokens) error { + switch tmplTokens := tokens.(type) { + case *GitopsDirectoryValues: + return t.Execute(writer, tmplTokens) + case *MetaphorTokenValues: + // Handle tokens of type *MetaphorTokenValues + return t.Execute(writer, tmplTokens) + default: + return fmt.Errorf("invalid type for tokens: %T", tokens) } - return nil } -// DetokenizeDirectoryGithubMetaphor - Translate tokens by values on a directory level. -func detokenizeGitopsMetaphor(path string, tokens *MetaphorTokenValues) filepath.WalkFunc { - return filepath.WalkFunc(func(path string, fi os.FileInfo, err error) error { - if err != nil { - return err - } - - if !!fi.IsDir() { - return nil - } - - // var matched bool - matched, _ := filepath.Match("*", fi.Name()) +func replaceTemplateVariables(content string, regex *regexp.Regexp, tokens Tokens) string { + return regex.ReplaceAllStringFunc(content, tokens.ToTemplateVars) +} - if matched { - // ignore .git files - if !strings.Contains(path, "/.git/") { +// renderGoTemplating - Render a template with the given tokens. +func renderGoTemplating(path string, tokens Tokens) ([]byte, error) { + read, err := os.ReadFile(path) + if err != nil { + return nil, err + } + // Replace all tokens with their values + regex := regexp.MustCompile(TokenRegexPattern) + content := replaceTemplateVariables(string(read), regex, tokens) + buff := bytes.NewBufferString(content) - read, err := ioutil.ReadFile(path) - if err != nil { - return err - } + parsedTemplate, err := parseTemplate(buff.String()) + if err != nil { + return nil, err + } - // todo reduce to terraform tokens by moving to helm chart? - newContents := string(read) - newContents = strings.Replace(newContents, "", tokens.CloudRegion, -1) - newContents = strings.Replace(newContents, "", tokens.ClusterName, -1) - newContents = strings.Replace(newContents, "", tokens.ContainerRegistryURL, -1) // todo need to fix metaphor repo names - newContents = strings.Replace(newContents, "", tokens.DomainName, -1) - newContents = strings.Replace(newContents, "", tokens.MetaphorDevelopmentIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.MetaphorProductionIngressURL, -1) - newContents = strings.Replace(newContents, "", tokens.MetaphorStagingIngressURL, -1) + newBuff := bytes.NewBuffer([]byte{}) + if err = executeTemplate(parsedTemplate, newBuff, tokens); err != nil { + return nil, err + } - err = ioutil.WriteFile(path, []byte(newContents), 0) - if err != nil { - return err - } - } - } - return nil - }) + return newBuff.Bytes(), nil } diff --git a/pkg/providerConfigs/detokenize_test.go b/pkg/providerConfigs/detokenize_test.go new file mode 100644 index 00000000..ab3de9d6 --- /dev/null +++ b/pkg/providerConfigs/detokenize_test.go @@ -0,0 +1,321 @@ +package providerConfigs + +import ( + "context" + "fmt" + "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/argoproj/argo-cd/v2/test" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" + "io/fs" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/dynamic/fake" + "os" + "path/filepath" + "strings" + "testing" +) + +const ( + templateRepositoryURL = "https://github.com/kubefirst/gitops-template.git" + tempDir = "./" +) + +var ( + gitOpsDirList = []string{ + "akamai-github", + "aws-github", + "aws-gitlab", + "civo-github", + "civo-gitlab", + "digitalocean-github", + "digitalocean-gitlab", + "google-github", + "google-gitlab", + "vultr-github", + "vultr-gitlab", + } + + k3dDirList = []string{ + "k3d-github", + "k3d-gitlab", + "k3s-gitlab", + } +) + +func setGitopsDirectoryValues() *GitopsDirectoryValues { + return &GitopsDirectoryValues{ + AlertsEmail: "alerts@example.com", + AtlantisAllowList: "192.168.0.0/16", + CloudProvider: "aws", + CloudRegion: "us-east-1", + ClusterId: "test-cluster-id", + ClusterName: "test-cluster-name", + ClusterType: "eks", + ContainerRegistryURL: "https://container-registry.example.com", + CustomTemplateValues: map[string]interface{}{ + "repo_name": "testKubeFirstCustomTemplating", + "archive_on_destroy": false, + "clusters": map[string]string{ + "looper": "coolString", + }, + "example-cm": "example-cm-name", + "namespace": "test-namespace", + "exampleCmData": map[string]string{ + "key1": "value1", + "key2": "value2", + }, + }, + DomainName: "example.com", + SubdomainName: "test", + DNSProvider: "route53", + Kubeconfig: "kubeconfig-data", + KubeconfigPath: "/path/to/kubeconfig", + KubefirstArtifactsBucket: "kubefirst-artifacts-bucket", + KubefirstStateStoreBucket: "kubefirst-state-store-bucket", + KubefirstTeam: "test-team", + KubefirstVersion: "1.2.3", + StateStoreBucketHostname: "state-store-bucket.example.com", + NodeType: "m5.large", + NodeCount: 3, + ArgoCDIngressURL: "https://argocd.example.com", + ArgoCDIngressNoHTTPSURL: "http://argocd.example.com", + ArgoWorkflowsIngressURL: "https://argo-workflows.example.com", + ArgoWorkflowsIngressNoHTTPSURL: "http://argo-workflows.example.com", + ArgoWorkflowsDir: "/path/to/argo-workflows", + AtlantisIngressURL: "https://atlantis.example.com", + AtlantisIngressNoHTTPSURL: "http://atlantis.example.com", + AtlantisWebhookURL: "https://atlantis-webhook.example.com", + ChartMuseumIngressURL: "https://chart-museum.example.com", + VaultIngressURL: "https://vault.example.com", + VaultIngressNoHTTPSURL: "http://vault.example.com", + VaultDataBucketName: "vault-data-bucket", + VouchIngressURL: "https://vouch.example.com", + RegistryPath: "/path/to/registry", + SecretStoreRef: "secret-store-ref", + Project: "test-project", + ClusterDestination: "test-cluster-destination", + Environment: "test-environment", + AwsIamArnAccountRoot: "arn:aws:iam::123456789012:root", + AwsKmsKeyId: "1234abcd-12ab-34cd-56ef-123456789abc", + AwsNodeCapacityType: "ON_DEMAND", + AwsAccountID: "123456789012", + GoogleAuth: "google-auth-data", + GoogleProject: "test-google-project", + GoogleUniqueness: "test-google-uniqueness", + ForceDestroy: "true", + K3sServersPrivateIps: []string{"10.0.0.1", "10.0.0.2", "10.0.0.3"}, + K3sServersPublicIps: []string{"1.2.3.4", "5.6.7.8", "9.10.11.12"}, + K3sServersArgs: []string{"--arg1", "--arg2=value2", "--arg3"}, + SshUser: "test-user", + SshPrivateKey: "ssh-private-key-data", + GitDescription: "test-git-description", + GitNamespace: "test-git-namespace", + GitProvider: "github", + GitProtocol: "https", + GitopsRepoGitURL: "https://github.com/test-org/test-repo.git", + GitopsRepoURL: "https://github.com/test-org/test-repo", + GitRunner: "test-git-runner", + GitRunnerDescription: "test-git-runner-description", + GitRunnerNS: "test-git-runner-ns", + GitURL: "https://github.com", + GitFqdn: "github.com", + GitHubHost: "github.com", + GitHubOwner: "test-org", + GitHubUser: "test-user", + GitlabHost: "gitlab.com", + GitlabOwner: "test-org", + GitlabOwnerGroupID: 123, + GitlabUser: "test-user", + GitopsRepoAtlantisWebhookURL: "https://atlantis-webhook.example.com/test-repo", + GitopsRepoNoHTTPSURL: "http://github.com/test-org/test-repo", + WorkloadClusterTerraformModuleURL: "https://github.com/test-org/test-module.git", + WorkloadClusterBootstrapTerraformModuleURL: "https://github.com/test-org/test-bootstrap-module.git", + ExternalDNSProviderName: "route53", + ExternalDNSProviderTokenEnvName: "AWS_ACCESS_KEY_ID", + ExternalDNSProviderSecretName: "external-dns-provider-secret", + ExternalDNSProviderSecretKey: "access-key", + UseTelemetry: "true", + } +} + +type DetokenizeSuite struct { + k *fake.FakeDynamicClient + t *testing.T + templatesDirectory string + + GitopsTokens *GitopsDirectoryValues + MetaphorTokens *MetaphorTokenValues +} + +func createRepositoryTempDirs(t *testing.T, d *DetokenizeSuite) { + var err error + d.templatesDirectory, err = os.MkdirTemp(tempDir, "templates") + assert.NoError(t, err) +} + +func newFakeClient(t *testing.T, d *DetokenizeSuite) { + scheme := runtime.NewScheme() + schemeBuilder := runtime.SchemeBuilder{} + assert.NoError(t, schemeBuilder.AddToScheme(scheme)) + + // Create the mocked kubernetes client and add the ArgoCD Application scheme to it so that + // we can apply the rendered manifests to the fake client and check for errors. + d.k = fake.NewSimpleDynamicClient(scheme, + &v1alpha1.Application{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "argoproj.io/v1alpha1", + Kind: "Application", + }, + }) + + assert.NoError(t, v1alpha1.AddToScheme(scheme)) +} + +func setMetaphorTokenValues(d *DetokenizeSuite) *MetaphorTokenValues { + return &MetaphorTokenValues{ + CloudRegion: d.GitopsTokens.CloudRegion, + ClusterName: d.GitopsTokens.ClusterName, + ContainerRegistryURL: d.GitopsTokens.ContainerRegistryURL, + CustomTemplateValues: nil, + GitProtocol: d.GitopsTokens.GitProtocol, + DomainName: d.GitopsTokens.DomainName, + MetaphorDevelopmentIngressURL: fmt.Sprintf("https://metaphor-development.%s", d.GitopsTokens.DomainName), + MetaphorProductionIngressURL: fmt.Sprintf("https://metaphor.%s", d.GitopsTokens.DomainName), + MetaphorStagingIngressURL: fmt.Sprintf("https://metaphor-stage.%s", d.GitopsTokens.DomainName), + } +} + +func TestDetokenize(t *testing.T) { + d := SetupSuite(t) + + clean := os.Getenv("K1_TEST_CLEANUP") + + if clean == "true" || clean == "" { + defer t.Cleanup(d.TearDownSuite) + } + + t.Run("DetokenizeGitops", d.TestDetokenizeGitops) + t.Run("DetokenizeMetaphor", d.TestDetokenizeMetaphor) + t.Run("DetokenizeK3d", d.TestDetokenizeK3d) + t.Run("DetokenizeGitopsWithCustomTemplateValues", d.TestDetokenizeGitopsWithCustomTemplateValues) +} + +// SetupTest initializes the necessary dependencies and configurations for the DetokenizeSuite test suite. +func SetupSuite(t *testing.T) *DetokenizeSuite { + d := &DetokenizeSuite{t: t} + createRepositoryTempDirs(t, d) + newFakeClient(t, d) + d.GitopsTokens = setGitopsDirectoryValues() + d.MetaphorTokens = setMetaphorTokenValues(d) + + err := cloneRepo(templateRepositoryURL, d.templatesDirectory) + assert.NoError(t, err) + + return d +} + +func (d *DetokenizeSuite) TearDownSuite() { + err := os.RemoveAll(d.templatesDirectory) + assert.NoError(d.t, err) +} + +func (d *DetokenizeSuite) TestDetokenizeGitops(t *testing.T) { + for _, dir := range gitOpsDirList { + currentPath := filepath.Join(d.templatesDirectory, dir) + assert.NoError(t, Detokenize(currentPath, d.GitopsTokens, + "https", false)) + assert.NoError(t, filepath.Walk(currentPath, testManifestValidity(currentPath, d))) + } +} + +// TestDetokenizeK3d tests the detokenization of the k3d cluster-types directory. +// Leaving this separate from the other cluster-types directories because it is slightly different, +// and we may want to test it separately in the future. +func (d *DetokenizeSuite) TestDetokenizeK3d(t *testing.T) { + // Set CloudProvider to k3s to properly render the k3d TF + d.GitopsTokens.CloudProvider = "k3s" + for _, dir := range k3dDirList { + currentPath := filepath.Join(d.templatesDirectory, dir) + assert.NoError(t, Detokenize(currentPath, d.GitopsTokens, + "https", false)) + assert.NoError(t, filepath.Walk(currentPath, testManifestValidity(currentPath, d))) + } + // Reset cloud provider for remainder of tests + d.GitopsTokens.CloudProvider = "aws" +} + +func (d *DetokenizeSuite) TestDetokenizeMetaphor(t *testing.T) { + err := Detokenize(filepath.Join(d.templatesDirectory, "metaphor", ".argo"), d.MetaphorTokens, d.GitopsTokens.GitProtocol, false) + assert.NoError(t, err) +} + +func (d *DetokenizeSuite) TestDetokenizeGitopsWithCustomTemplateValues(t *testing.T) { + templatingDir := filepath.Join(d.templatesDirectory, "templating") + if _, err := os.Stat(templatingDir); os.IsNotExist(err) { + fmt.Println("Skipping TestDetokenizeGitopsWithCustomTemplateValues because the templating directory does not exist") + return + } + assert.NoError(t, Detokenize(filepath.Join(d.templatesDirectory, "templating"), + d.GitopsTokens, "https", false)) + + assert.NoError(t, filepath.Walk(templatingDir, testManifestValidity(templatingDir, d))) +} + +func cloneRepo(src string, dirPath string) error { + _, cloneErr := git.PlainClone(dirPath, false, &git.CloneOptions{ + URL: src, + SingleBranch: true, + ReferenceName: plumbing.NewBranchReferenceName("main"), + }) + + return cloneErr +} + +func applyFile(path string, k *fake.FakeDynamicClient) error { + f, err := os.ReadFile(path) + if err != nil { + return err + } + + us := test.YamlToUnstructured(string(f)) + + _, err = k.Resource(v1alpha1.SchemeGroupVersion.WithResource(us.GetResourceVersion())). + Namespace(us.GetNamespace()). + Create(context.Background(), us, metav1.CreateOptions{}) + + return err +} + +func delApp(path string, k *fake.FakeDynamicClient) error { + f, err := os.ReadFile(path) + if err != nil { + return err + } + app := &v1alpha1.Application{} + if err = yaml.Unmarshal(f, app); err != nil { + return err + } + + return k.Resource(v1alpha1.SchemeGroupVersion.WithResource("Application")).Namespace(app.Namespace). + DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app.kubernetes.io/instance=%s", app.Name), + }) +} + +func testManifestValidity(currentPath string, d *DetokenizeSuite) filepath.WalkFunc { + return func(path string, info fs.FileInfo, err error) error { + if !info.IsDir() { + if strings.Contains(info.Name(), ".yaml") { + // Apply the manifests to the fake client and check for errors. + assert.NoError(d.t, applyFile(path, d.k)) + } + // Delete the manifests from the fake client so that we don't get duplicate resource errors + return delApp(currentPath, d.k) + } + return filepath.SkipDir + } +} diff --git a/pkg/providerConfigs/types.go b/pkg/providerConfigs/types.go index 7c6f5f4f..6aa7cb3d 100644 --- a/pkg/providerConfigs/types.go +++ b/pkg/providerConfigs/types.go @@ -6,15 +6,28 @@ See the LICENSE file for more details. */ package providerConfigs +// Tokens - interface for all token values +type Tokens interface { + ToTemplateVars(s string) string + GetDomain() string + GetGitProtocol() string +} + type GitopsDirectoryValues struct { - AlertsEmail string - AtlantisAllowList string - CloudProvider string - CloudRegion string - ClusterId string - ClusterName string - ClusterType string + AlertsEmail string + AtlantisAllowList string + CloudProvider string + CloudRegion string + ClusterId string + ClusterName string + ClusterType string + // + CertManagerIssuerAnnotation1 string + CertManagerIssuerAnnotation2 string + CertManagerIssuerAnnotation3 string + CertManagerIssuerAnnotation4 string ContainerRegistryURL string + CustomTemplateValues map[string]interface{} DomainName string SubdomainName string DNSProvider string @@ -56,6 +69,7 @@ type GitopsDirectoryValues struct { GoogleUniqueness string ForceDestroy string + K3sEndpoint string K3sServersPrivateIps []string K3sServersPublicIps []string K3sServersArgs []string @@ -72,6 +86,7 @@ type GitopsDirectoryValues struct { GitRunnerDescription string GitRunnerNS string GitURL string + GitFqdn string GitHubHost string GitHubOwner string @@ -95,14 +110,40 @@ type GitopsDirectoryValues struct { UseTelemetry string } +func (g *GitopsDirectoryValues) ToTemplateVars(s string) string { + return ToTemplateVars(s, g) +} + +func (g *GitopsDirectoryValues) GetDomain() string { + return g.DomainName +} + +func (g *GitopsDirectoryValues) GetGitProtocol() string { + return g.GitProvider +} + type MetaphorTokenValues struct { CheckoutCWFTTemplate string CloudRegion string ClusterName string + GitProtocol string CommitCWFTTemplate string ContainerRegistryURL string + CustomTemplateValues map[string]interface{} DomainName string MetaphorDevelopmentIngressURL string MetaphorProductionIngressURL string MetaphorStagingIngressURL string } + +func (m *MetaphorTokenValues) ToTemplateVars(s string) string { + return ToTemplateVars(s, m) +} + +func (m *MetaphorTokenValues) GetDomain() string { + return m.DomainName +} + +func (m *MetaphorTokenValues) GetGitProtocol() string { + return m.GitProtocol +}