diff --git a/requirements.txt b/requirements.txt index 3372ca8..8132c74 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,34 +1,34 @@ -anyio==4.0.0; python_full_version > "3.8.0" and python_version < "4.0" \ - --hash=sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f \ - --hash=sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a -certifi==2023.7.22; python_full_version > "3.8.0" and python_version < "4.0" \ - --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ - --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 +anyio==3.7.0 ; python_full_version > "3.8.0" and python_version < "4.0" \ + --hash=sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce \ + --hash=sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0 +certifi==2023.5.7 ; python_full_version > "3.8.0" and python_version < "4.0" \ + --hash=sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7 \ + --hash=sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716 envyaml==1.10.211231 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:88f8a076159e3c317d3450a5f404132b6ac91aecee4934ea72eac65f911f1244 \ --hash=sha256:8d7a7a6be12587cc5da32a587067506b47b849f4643981099ad148015a72de52 -exceptiongroup==1.1.3; python_full_version > "3.8.0" and python_version < "3.11" \ - --hash=sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9 \ - --hash=sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3 +exceptiongroup==1.1.1 ; python_full_version > "3.8.0" and python_version < "3.11" \ + --hash=sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e \ + --hash=sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785 h11==0.14.0 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 -httpcore==0.18.0; python_full_version > "3.8.0" and python_version < "4.0" \ - --hash=sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9 \ - --hash=sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced -httpx==0.25.0; python_full_version > "3.8.0" and python_version < "4.0" \ - --hash=sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100 \ - --hash=sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875 +httpcore==0.17.2 ; python_full_version > "3.8.0" and python_version < "4.0" \ + --hash=sha256:125f8375ab60036db632f34f4b627a9ad085048eef7cb7d2616fea0f739f98af \ + --hash=sha256:5581b9c12379c4288fe70f43c710d16060c10080617001e6b22a3b6dbcbefd36 +httpx==0.24.1 ; python_full_version > "3.8.0" and python_version < "4.0" \ + --hash=sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd \ + --hash=sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd idna==3.4 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 jinja2==3.1.2 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 -lightkube-models==1.28.1.4; python_full_version > "3.8.0" and python_version < "4.0" \ - --hash=sha256:5d640979bd54653824a217622504eabf18e1ec65d23e97b160cc160818839517 \ - --hash=sha256:6b7a0b519d636ebd302c62811d4967b533a6c74f401e6a26c4840d9a32816d4d -lightkube==0.14.0; python_full_version > "3.8.0" and python_version < "4.0" \ +lightkube-models==1.27.1.4 ; python_full_version > "3.8.0" and python_version < "4.0" \ + --hash=sha256:206abb6d184a07ed84c20fbabe494847e892de2c38ed302f39a87b4ed1f7bcd9 \ + --hash=sha256:5caa97ed46bde5ae8a4313ebf3fa3d0135388d0aea0752261d4720e24d982fb0 +lightkube==0.14.0 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:448926ce667d18f9e07e9a600c7db0d0424447883f1873be31e60d9e86176d71 \ --hash=sha256:9c0a8e7543debded4494ae42606d73b775561eb0950504bd735f565b25ef8dc2 markupsafe==2.1.3 ; python_full_version > "3.8.0" and python_version < "4.0" \ @@ -36,8 +36,11 @@ markupsafe==2.1.3 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \ --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \ + --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \ --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ @@ -45,6 +48,7 @@ markupsafe==2.1.3 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \ --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ @@ -53,6 +57,7 @@ markupsafe==2.1.3 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \ --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ @@ -60,9 +65,12 @@ markupsafe==2.1.3 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \ --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \ --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \ --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ @@ -81,48 +89,50 @@ markupsafe==2.1.3 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ - --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 -PyYAML==6.0.1; python_full_version > "3.8.0" and python_version < "4.0" \ - --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ - --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ - --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ - --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ - --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ - --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ - --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ - --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ - --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ - --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ - --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ - --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ - --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ - --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ - --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ - --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ - --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ - --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ - --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ - --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ - --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ - --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ - --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ - --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ - --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ - --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ - --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ - --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ - --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ - --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ - --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ - --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ - --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ - --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ - --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ - --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ - --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ - --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ - --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ - --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f + --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \ + --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11 +pyyaml==6.0 ; python_full_version > "3.8.0" and python_version < "4.0" \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 sniffio==1.3.0 ; python_full_version > "3.8.0" and python_version < "4.0" \ --hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \ --hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384 diff --git a/spark8t/services.py b/spark8t/services.py index 07145a5..79adbe5 100644 --- a/spark8t/services.py +++ b/spark8t/services.py @@ -30,8 +30,10 @@ from spark8t.exceptions import AccountNotFound, FormatError, K8sResourceNotFound from spark8t.literals import MANAGED_BY_LABELNAME, PRIMARY_LABELNAME, SPARK8S_LABEL from spark8t.utils import ( + PercentEncodingSerializer, WithLogging, environ, + execute_command_output, filter_none, listify, parse_yaml_shell_output, @@ -725,9 +727,7 @@ def exec( return ( parse_yaml_shell_output(base_cmd) if (output is None) or (output == "yaml") - else subprocess.check_output( - base_cmd, shell=True, stderr=subprocess.STDOUT - ).decode("utf-8") + else execute_command_output(base_cmd) ) def get_service_account( @@ -1045,6 +1045,8 @@ def get(self, account_id: str) -> Optional[ServiceAccount]: class K8sServiceAccountRegistry(AbstractServiceAccountRegistry): """Class implementing a ServiceAccountRegistry, based on K8s.""" + _kubernetes_key_serializer = PercentEncodingSerializer("_") + def __init__(self, kube_interface: AbstractKubeInterface): self.kube_interface = kube_interface @@ -1074,7 +1076,12 @@ def _retrieve_account_configurations( except Exception: return PropertyFile.empty() - return PropertyFile(secret) + return PropertyFile( + { + self._kubernetes_key_serializer.deserialize(key): value + for key, value in secret.items() + } + ) def _build_service_account_from_raw(self, metadata: Dict[str, Any]): name = metadata["name"] @@ -1217,7 +1224,12 @@ def _create_account_configuration(self, service_account: ServiceAccount): f"Spark dynamic props available for reference at {t.name}\n" ) - service_account.extra_confs.write(t.file) + PropertyFile( + { + self._kubernetes_key_serializer.serialize(key): value + for key, value in service_account.extra_confs.props.items() + } + ).write(t.file) t.flush() diff --git a/spark8t/utils.py b/spark8t/utils.py index 0d64c0e..3d30b40 100644 --- a/spark8t/utils.py +++ b/spark8t/utils.py @@ -22,6 +22,7 @@ TypeVar, Union, ) +from urllib.parse import quote, unquote import yaml from envyaml import EnvYAML @@ -256,15 +257,36 @@ def parse_yaml_shell_output(cmd: str) -> Union[Dict[str, Any], str]: dictionary representing the output of the command """ with io.StringIO() as buffer: - buffer.write( - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT).decode( - "utf-8" - ) - ) + buffer.write(execute_command_output(cmd)) buffer.seek(0) return yaml.safe_load(buffer) +def execute_command_output(cmd: str) -> str: + """ + Execute command and return the output. + + Args: + cmd: string with bash command + + Raises: + CalledProcessError: when the bash command fails and exits with code other than 0 + + Returns: + output of the command + """ + try: + output = subprocess.check_output( + cmd, shell=True, stderr=subprocess.STDOUT + ).decode("utf-8") + except subprocess.CalledProcessError as e: + print(e.stderr) + print(e.stdout) + raise e + + return output + + @contextmanager def environ(*remove, **update): """ @@ -298,3 +320,36 @@ def environ(*remove, **update): def listify(value: Any) -> List[str]: return [str(v) for v in value] if isinstance(value, list) else [str(value)] + + +class PercentEncodingSerializer: + """This class provides a way to serialize and de-serialize keys to be stored in k8s. + + Keys in kubernetes need to comply with some format (described by the regex '[-._a-zA-Z0-9]+'). + In order to extend the range of keys that can be stored, we use a serialization based on + percent encoding, where % is replaced by _. Underscores are still supported but transformed + into a double underscore + """ + + _SPECIAL = "§" + + def __init__(self, percent_char: str = "_"): + self.percent_char = percent_char + + @property + def _double_percent_char(self) -> str: + return "".join([self.percent_char] * 2) + + def serialize(self, input_string: str) -> str: + return ( + quote(input_string) + .replace(self.percent_char, self._double_percent_char) + .replace("%", self.percent_char) + ) + + def deserialize(self, input_string: str) -> str: + return unquote( + input_string.replace(self._double_percent_char, self._SPECIAL) + .replace(self.percent_char, "%") + .replace(self._SPECIAL, self.percent_char) + ) diff --git a/tests/integration/test_registry.py b/tests/integration/test_registry.py index e3f3312..c7c1c5c 100644 --- a/tests/integration/test_registry.py +++ b/tests/integration/test_registry.py @@ -28,7 +28,9 @@ def test_registry_io(kubeinterface_name, kuberegistry_name, namespace, user, req namespace, kubeinterface.api_server, primary=True, - extra_confs=PropertyFile({"my-key": "my-value"}), + extra_confs=PropertyFile( + {"my-key": "my-value", "my-strange-key_*.@.%.$": "my-strange-value_*.@.%.$"} + ), ) registry.create(service_account) diff --git a/tests/unittest/test_utils.py b/tests/unittest/test_utils.py new file mode 100644 index 0000000..51c28d7 --- /dev/null +++ b/tests/unittest/test_utils.py @@ -0,0 +1,36 @@ +import re + +import pytest + +from spark8t.utils import PercentEncodingSerializer + +requirement = re.compile(r"[-._a-zA-Z0-9]+") + + +def check_compliance(input_string: str) -> bool: + if match := requirement.match(input_string): + return match.group() == input_string + return False + + +@pytest.fixture +def serializer(): + return PercentEncodingSerializer() + + +@pytest.mark.parametrize( + "input_string", + [ + "spark.*.property", + "spark_property", + "spark%property", + "spark__property", + "spark§property", + "spark property", + "spark%_property", + ], +) +def test_serializer(serializer, input_string): + serialized = serializer.serialize(input_string) + assert check_compliance(serialized) + assert serializer.deserialize(serialized) == input_string