PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/saltstack/salt/lib/python3.10/site-packages/salt/states
Viewing File: /opt/saltstack/salt/lib/python3.10/site-packages/salt/states/kubernetes.py
""" Manage kubernetes resources as salt states ========================================== NOTE: This module requires the proper pillar values set. See salt.modules.kubernetesmod for more information. .. warning:: Configuration options will change in 2019.2.0. The kubernetes module is used to manage different kubernetes resources. .. code-block:: yaml my-nginx: kubernetes.deployment_present: - namespace: default metadata: app: frontend spec: replicas: 1 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 80 my-mariadb: kubernetes.deployment_absent: - namespace: default # kubernetes deployment as specified inside of # a file containing the definition of the the # deployment using the official kubernetes format redis-master-deployment: kubernetes.deployment_present: - name: redis-master - source: salt://k8s/redis-master-deployment.yml require: - pip: kubernetes-python-module # kubernetes service as specified inside of # a file containing the definition of the the # service using the official kubernetes format redis-master-service: kubernetes.service_present: - name: redis-master - source: salt://k8s/redis-master-service.yml require: - kubernetes.deployment_present: redis-master # kubernetes deployment as specified inside of # a file containing the definition of the the # deployment using the official kubernetes format # plus some jinja directives nginx-source-template: kubernetes.deployment_present: - source: salt://k8s/nginx.yml.jinja - template: jinja require: - pip: kubernetes-python-module # Kubernetes secret k8s-secret: kubernetes.secret_present: - name: top-secret data: key1: value1 key2: value2 key3: value3 .. versionadded:: 2017.7.0 """ import copy import logging log = logging.getLogger(__name__) def __virtual__(): """ Only load if the kubernetes module is available in __salt__ """ if "kubernetes.ping" in __salt__: return True return (False, "kubernetes module could not be loaded") def _error(ret, err_msg): """ Helper function to propagate errors to the end user. """ ret["result"] = False ret["comment"] = err_msg return ret def deployment_absent(name, namespace="default", **kwargs): """ Ensures that the named deployment is absent from the given namespace. name The name of the deployment namespace The name of the namespace """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} deployment = __salt__["kubernetes.show_deployment"](name, namespace, **kwargs) if deployment is None: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The deployment does not exist" return ret if __opts__["test"]: ret["comment"] = "The deployment is going to be deleted" ret["result"] = None return ret res = __salt__["kubernetes.delete_deployment"](name, namespace, **kwargs) if res["code"] == 200: ret["result"] = True ret["changes"] = {"kubernetes.deployment": {"new": "absent", "old": "present"}} ret["comment"] = res["message"] else: ret["comment"] = f"Something went wrong, response: {res}" return ret def deployment_present( name, namespace="default", metadata=None, spec=None, source="", template="", **kwargs, ): """ Ensures that the named deployment is present inside of the specified namespace with the given metadata and spec. If the deployment exists it will be replaced. name The name of the deployment. namespace The namespace holding the deployment. The 'default' one is going to be used unless a different one is specified. metadata The metadata of the deployment object. spec The spec of the deployment object. source A file containing the definition of the deployment (metadata and spec) in the official kubernetes format. template Template engine to be used to render the source file. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} if (metadata or spec) and source: return _error( ret, "'source' cannot be used in combination with 'metadata' or 'spec'" ) if metadata is None: metadata = {} if spec is None: spec = {} deployment = __salt__["kubernetes.show_deployment"](name, namespace, **kwargs) if deployment is None: if __opts__["test"]: ret["result"] = None ret["comment"] = "The deployment is going to be created" return ret res = __salt__["kubernetes.create_deployment"]( name=name, namespace=namespace, metadata=metadata, spec=spec, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"][f"{namespace}.{name}"] = {"old": {}, "new": res} else: if __opts__["test"]: ret["result"] = None return ret # TODO: improve checks # pylint: disable=fixme log.info("Forcing the recreation of the deployment") ret["comment"] = "The deployment is already present. Forcing recreation" res = __salt__["kubernetes.replace_deployment"]( name=name, namespace=namespace, metadata=metadata, spec=spec, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"] = {"metadata": metadata, "spec": spec} ret["result"] = True return ret def service_present( name, namespace="default", metadata=None, spec=None, source="", template="", **kwargs, ): """ Ensures that the named service is present inside of the specified namespace with the given metadata and spec. If the deployment exists it will be replaced. name The name of the service. namespace The namespace holding the service. The 'default' one is going to be used unless a different one is specified. metadata The metadata of the service object. spec The spec of the service object. source A file containing the definition of the service (metadata and spec) in the official kubernetes format. template Template engine to be used to render the source file. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} if (metadata or spec) and source: return _error( ret, "'source' cannot be used in combination with 'metadata' or 'spec'" ) if metadata is None: metadata = {} if spec is None: spec = {} service = __salt__["kubernetes.show_service"](name, namespace, **kwargs) if service is None: if __opts__["test"]: ret["result"] = None ret["comment"] = "The service is going to be created" return ret res = __salt__["kubernetes.create_service"]( name=name, namespace=namespace, metadata=metadata, spec=spec, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"][f"{namespace}.{name}"] = {"old": {}, "new": res} else: if __opts__["test"]: ret["result"] = None return ret # TODO: improve checks # pylint: disable=fixme log.info("Forcing the recreation of the service") ret["comment"] = "The service is already present. Forcing recreation" res = __salt__["kubernetes.replace_service"]( name=name, namespace=namespace, metadata=metadata, spec=spec, source=source, template=template, old_service=service, saltenv=__env__, **kwargs, ) ret["changes"] = {"metadata": metadata, "spec": spec} ret["result"] = True return ret def service_absent(name, namespace="default", **kwargs): """ Ensures that the named service is absent from the given namespace. name The name of the service namespace The name of the namespace """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} service = __salt__["kubernetes.show_service"](name, namespace, **kwargs) if service is None: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The service does not exist" return ret if __opts__["test"]: ret["comment"] = "The service is going to be deleted" ret["result"] = None return ret res = __salt__["kubernetes.delete_service"](name, namespace, **kwargs) if res["code"] == 200: ret["result"] = True ret["changes"] = {"kubernetes.service": {"new": "absent", "old": "present"}} ret["comment"] = res["message"] else: ret["comment"] = f"Something went wrong, response: {res}" return ret def namespace_absent(name, **kwargs): """ Ensures that the named namespace is absent. name The name of the namespace """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} namespace = __salt__["kubernetes.show_namespace"](name, **kwargs) if namespace is None: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The namespace does not exist" return ret if __opts__["test"]: ret["comment"] = "The namespace is going to be deleted" ret["result"] = None return ret res = __salt__["kubernetes.delete_namespace"](name, **kwargs) if ( res["code"] == 200 or (isinstance(res["status"], str) and "Terminating" in res["status"]) or (isinstance(res["status"], dict) and res["status"]["phase"] == "Terminating") ): ret["result"] = True ret["changes"] = {"kubernetes.namespace": {"new": "absent", "old": "present"}} if res["message"]: ret["comment"] = res["message"] else: ret["comment"] = "Terminating" else: ret["comment"] = f"Something went wrong, response: {res}" return ret def namespace_present(name, **kwargs): """ Ensures that the named namespace is present. name The name of the namespace. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} namespace = __salt__["kubernetes.show_namespace"](name, **kwargs) if namespace is None: if __opts__["test"]: ret["result"] = None ret["comment"] = "The namespace is going to be created" return ret res = __salt__["kubernetes.create_namespace"](name, **kwargs) ret["result"] = True ret["changes"]["namespace"] = {"old": {}, "new": res} else: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The namespace already exists" return ret def secret_absent(name, namespace="default", **kwargs): """ Ensures that the named secret is absent from the given namespace. name The name of the secret namespace The name of the namespace """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} secret = __salt__["kubernetes.show_secret"](name, namespace, **kwargs) if secret is None: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The secret does not exist" return ret if __opts__["test"]: ret["comment"] = "The secret is going to be deleted" ret["result"] = None return ret __salt__["kubernetes.delete_secret"](name, namespace, **kwargs) # As for kubernetes 1.6.4 doesn't set a code when deleting a secret # The kubernetes module will raise an exception if the kubernetes # server will return an error ret["result"] = True ret["changes"] = {"kubernetes.secret": {"new": "absent", "old": "present"}} ret["comment"] = "Secret deleted" return ret def secret_present( name, namespace="default", data=None, source=None, template=None, **kwargs ): """ Ensures that the named secret is present inside of the specified namespace with the given data. If the secret exists it will be replaced. name The name of the secret. namespace The namespace holding the secret. The 'default' one is going to be used unless a different one is specified. data The dictionary holding the secrets. source A file containing the data of the secret in plain format. template Template engine to be used to render the source file. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} if data and source: return _error(ret, "'source' cannot be used in combination with 'data'") secret = __salt__["kubernetes.show_secret"](name, namespace, **kwargs) if secret is None: if data is None: data = {} if __opts__["test"]: ret["result"] = None ret["comment"] = "The secret is going to be created" return ret res = __salt__["kubernetes.create_secret"]( name=name, namespace=namespace, data=data, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"][f"{namespace}.{name}"] = {"old": {}, "new": res} else: if __opts__["test"]: ret["result"] = None ret["comment"] = "The secret is going to be replaced" return ret # TODO: improve checks # pylint: disable=fixme log.info("Forcing the recreation of the service") ret["comment"] = "The secret is already present. Forcing recreation" res = __salt__["kubernetes.replace_secret"]( name=name, namespace=namespace, data=data, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"] = { # Omit values from the return. They are unencrypted # and can contain sensitive data. "data": list(res["data"]) } ret["result"] = True return ret def configmap_absent(name, namespace="default", **kwargs): """ Ensures that the named configmap is absent from the given namespace. name The name of the configmap namespace The namespace holding the configmap. The 'default' one is going to be used unless a different one is specified. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} configmap = __salt__["kubernetes.show_configmap"](name, namespace, **kwargs) if configmap is None: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The configmap does not exist" return ret if __opts__["test"]: ret["comment"] = "The configmap is going to be deleted" ret["result"] = None return ret __salt__["kubernetes.delete_configmap"](name, namespace, **kwargs) # As for kubernetes 1.6.4 doesn't set a code when deleting a configmap # The kubernetes module will raise an exception if the kubernetes # server will return an error ret["result"] = True ret["changes"] = {"kubernetes.configmap": {"new": "absent", "old": "present"}} ret["comment"] = "ConfigMap deleted" return ret def configmap_present( name, namespace="default", data=None, source=None, template=None, **kwargs ): """ Ensures that the named configmap is present inside of the specified namespace with the given data. If the configmap exists it will be replaced. name The name of the configmap. namespace The namespace holding the configmap. The 'default' one is going to be used unless a different one is specified. data The dictionary holding the configmaps. source A file containing the data of the configmap in plain format. template Template engine to be used to render the source file. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} if data and source: return _error(ret, "'source' cannot be used in combination with 'data'") elif data is None: data = {} configmap = __salt__["kubernetes.show_configmap"](name, namespace, **kwargs) if configmap is None: if __opts__["test"]: ret["result"] = None ret["comment"] = "The configmap is going to be created" return ret res = __salt__["kubernetes.create_configmap"]( name=name, namespace=namespace, data=data, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"][f"{namespace}.{name}"] = {"old": {}, "new": res} else: if __opts__["test"]: ret["result"] = None ret["comment"] = "The configmap is going to be replaced" return ret # TODO: improve checks # pylint: disable=fixme log.info("Forcing the recreation of the service") ret["comment"] = "The configmap is already present. Forcing recreation" res = __salt__["kubernetes.replace_configmap"]( name=name, namespace=namespace, data=data, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"] = {"data": res["data"]} ret["result"] = True return ret def pod_absent(name, namespace="default", **kwargs): """ Ensures that the named pod is absent from the given namespace. name The name of the pod namespace The name of the namespace """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} pod = __salt__["kubernetes.show_pod"](name, namespace, **kwargs) if pod is None: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The pod does not exist" return ret if __opts__["test"]: ret["comment"] = "The pod is going to be deleted" ret["result"] = None return ret res = __salt__["kubernetes.delete_pod"](name, namespace, **kwargs) if res["code"] == 200 or res["code"] is None: ret["result"] = True ret["changes"] = {"kubernetes.pod": {"new": "absent", "old": "present"}} if res["code"] is None: ret["comment"] = "In progress" else: ret["comment"] = res["message"] else: ret["comment"] = f"Something went wrong, response: {res}" return ret def pod_present( name, namespace="default", metadata=None, spec=None, source="", template="", **kwargs, ): """ Ensures that the named pod is present inside of the specified namespace with the given metadata and spec. If the pod exists it will be replaced. name The name of the pod. namespace The namespace holding the pod. The 'default' one is going to be used unless a different one is specified. metadata The metadata of the pod object. spec The spec of the pod object. source A file containing the definition of the pod (metadata and spec) in the official kubernetes format. template Template engine to be used to render the source file. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} if (metadata or spec) and source: return _error( ret, "'source' cannot be used in combination with 'metadata' or 'spec'" ) if metadata is None: metadata = {} if spec is None: spec = {} pod = __salt__["kubernetes.show_pod"](name, namespace, **kwargs) if pod is None: if __opts__["test"]: ret["result"] = None ret["comment"] = "The pod is going to be created" return ret res = __salt__["kubernetes.create_pod"]( name=name, namespace=namespace, metadata=metadata, spec=spec, source=source, template=template, saltenv=__env__, **kwargs, ) ret["changes"][f"{namespace}.{name}"] = {"old": {}, "new": res} else: if __opts__["test"]: ret["result"] = None return ret # TODO: fix replace_namespaced_pod validation issues ret["comment"] = ( "salt is currently unable to replace a pod without " "deleting it. Please perform the removal of the pod requiring " "the 'pod_absent' state if this is the desired behaviour." ) ret["result"] = False return ret ret["changes"] = {"metadata": metadata, "spec": spec} ret["result"] = True return ret def node_label_absent(name, node, **kwargs): """ Ensures that the named label is absent from the node. name The name of the label node The name of the node """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} labels = __salt__["kubernetes.node_labels"](node, **kwargs) if name not in labels: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The label does not exist" return ret if __opts__["test"]: ret["comment"] = "The label is going to be deleted" ret["result"] = None return ret __salt__["kubernetes.node_remove_label"](node_name=node, label_name=name, **kwargs) ret["result"] = True ret["changes"] = {"kubernetes.node_label": {"new": "absent", "old": "present"}} ret["comment"] = "Label removed from node" return ret def node_label_folder_absent(name, node, **kwargs): """ Ensures the label folder doesn't exist on the specified node. name The name of label folder node The name of the node """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} labels = __salt__["kubernetes.node_labels"](node, **kwargs) folder = name.strip("/") + "/" labels_to_drop = [] new_labels = [] for label in labels: if label.startswith(folder): labels_to_drop.append(label) else: new_labels.append(label) if not labels_to_drop: ret["result"] = True if not __opts__["test"] else None ret["comment"] = "The label folder does not exist" return ret if __opts__["test"]: ret["comment"] = "The label folder is going to be deleted" ret["result"] = None return ret for label in labels_to_drop: __salt__["kubernetes.node_remove_label"]( node_name=node, label_name=label, **kwargs ) ret["result"] = True ret["changes"] = { "kubernetes.node_label_folder_absent": {"old": list(labels), "new": new_labels} } ret["comment"] = "Label folder removed from node" return ret def node_label_present(name, node, value, **kwargs): """ Ensures that the named label is set on the named node with the given value. If the label exists it will be replaced. name The name of the label. value Value of the label. node Node to change. """ ret = {"name": name, "changes": {}, "result": False, "comment": ""} labels = __salt__["kubernetes.node_labels"](node, **kwargs) if name not in labels: if __opts__["test"]: ret["result"] = None ret["comment"] = "The label is going to be set" return ret __salt__["kubernetes.node_add_label"]( label_name=name, label_value=value, node_name=node, **kwargs ) elif labels[name] == value: ret["result"] = True ret["comment"] = "The label is already set and has the specified value" return ret else: if __opts__["test"]: ret["result"] = None ret["comment"] = "The label is going to be updated" return ret ret["comment"] = "The label is already set, changing the value" __salt__["kubernetes.node_add_label"]( node_name=node, label_name=name, label_value=value, **kwargs ) old_labels = copy.copy(labels) labels[name] = value ret["changes"][f"{node}.{name}"] = {"old": old_labels, "new": labels} ret["result"] = True return ret