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/zabbix_user.py
""" Management of Zabbix users. :codeauthor: Jiri Kotlin <jiri.kotlin@ultimum.io> """ import logging from copy import deepcopy import salt.utils.json from salt.exceptions import SaltException from salt.utils.versions import Version log = logging.getLogger(__name__) def __virtual__(): """ Only make these states available if Zabbix module is available. """ if "zabbix.user_create" in __salt__: return True return (False, "zabbix module could not be loaded") def admin_password_present(name, password=None, **kwargs): """ Initial change of Zabbix Admin password to password taken from one of the sources (only the most prioritized one): 1. 'password' parameter 2. '_connection_password' parameter 3. pillar 'zabbix.password' setting 1) Tries to log in as Admin with password found in state password parameter or _connection_password or pillar or default zabbix password in this precise order, if any of them is present. 2) If one of above passwords matches, it tries to change the password to the most prioritized one. 3) If not able to connect with any password then it fails. :param name: Just a name of state :param password: Optional - desired password for Admin to be set :param _connection_user: Optional - Ignored in this state (always assumed 'Admin') :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring) :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring) .. code-block:: yaml # password taken from pillar or _connection_password zabbix-admin-password: zabbix_user.admin_password_present # directly set password zabbix-admin-password: zabbix_user.admin_password_present: - password: SECRET_PASS """ login_error_messages = [ "Login name or password is incorrect", "Incorrect user name or password", ] dry_run = __opts__["test"] default_zabbix_user = "Admin" default_zabbix_password = "zabbix" ret = {"name": name, "changes": {}, "result": False, "comment": ""} passwords = [] connection_args = {} connection_args["_connection_user"] = default_zabbix_user if "_connection_url" in kwargs: connection_args["_connection_url"] = kwargs["_connection_url"] config_password = __salt__["config.option"]("zabbix.password", None) if config_password: passwords.append(config_password) if "_connection_password" in kwargs: passwords.append(kwargs["_connection_password"]) if password: passwords.append(password) # get unique list in preserved order and reverse it seen = set() unique_passwords = [str(x) for x in passwords if x not in seen and not seen.add(x)] unique_passwords.reverse() if not unique_passwords: ret["comment"] = ( "Could not find any Zabbix Admin password setting! See documentation." ) return ret else: desired_password = unique_passwords[0] unique_passwords.append(default_zabbix_password) for pwd in unique_passwords: connection_args["_connection_password"] = pwd try: user_get = __salt__["zabbix.user_get"]( default_zabbix_user, **connection_args ) except SaltException as err: if all([x not in str(err) for x in login_error_messages]): raise user_get = False if user_get: if pwd == desired_password: ret["result"] = True ret["comment"] = "Admin password is correct." return ret else: break if user_get: if not dry_run: user_update = __salt__["zabbix.user_update"]( user_get[0]["userid"], passwd=desired_password, **connection_args ) if user_update: ret["result"] = True ret["changes"]["passwd"] = "changed to '" + str(desired_password) + "'" else: ret["result"] = None ret["comment"] = ( "Password for user " + str(default_zabbix_user) + " updated to '" + str(desired_password) + "'" ) return ret def present(alias, passwd, usrgrps, medias=None, password_reset=False, **kwargs): """ Ensures that the user exists, eventually creates new user. NOTE: use argument firstname instead of name to not mess values with name from salt sls. .. versionadded:: 2016.3.0 :param alias: user alias :param passwd: user's password :param usrgrps: user groups to add the user to :param medias: Optional - user's medias to create :param password_reset: whether or not to reset password at update :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring) :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring) :param firstname: string with firstname of the user, use 'firstname' instead of 'name' parameter to not mess \ with value supplied from Salt sls file. .. code-block:: yaml make_user: zabbix_user.present: - alias: George - passwd: donottellanyonE@456x - password_reset: True - usrgrps: - 13 - 7 - medias: - me@example.com: - mediatype: mail - period: '1-7,00:00-24:00' - severity: NIWAHD - make_jabber: - active: true - mediatype: jabber - period: '1-5,08:00-19:00' - sendto: jabbera@example.com - text_me_morning_disabled: - active: false - mediatype: sms - period: '1-5,09:30-10:00' - severity: D - sendto: '+42032132588568' """ if medias is None: medias = [] usrgrps = [int(x) for x in usrgrps] connection_args = {} if "_connection_user" in kwargs: connection_args["_connection_user"] = kwargs["_connection_user"] if "_connection_password" in kwargs: connection_args["_connection_password"] = kwargs["_connection_password"] if "_connection_url" in kwargs: connection_args["_connection_url"] = kwargs["_connection_url"] ret = {"name": alias, "changes": {}, "result": False, "comment": ""} # Comment and change messages comment_user_created = f"User {alias} created." comment_user_updated = f"User {alias} updated." comment_user_notcreated = f"Unable to create user: {alias}. " comment_user_exists = f"User {alias} already exists." changes_user_created = { alias: { "old": f"User {alias} does not exist.", "new": f"User {alias} created.", } } def _media_format(medias_data): """ Formats medias from SLS file into valid JSON usable for zabbix API. Completes JSON with default values. :param medias_data: list of media data from SLS file """ if not medias_data: return list() medias_json = salt.utils.json.loads(salt.utils.json.dumps(medias_data)) medias_attr = ("active", "mediatype", "period", "severity", "sendto") media_type = {"mail": 1, "jabber": 2, "sms": 3} media_severities = ("D", "H", "A", "W", "I", "N") medias_dict = dict() for media in medias_json: for med in media: medias_dict[med] = dict() for medattr in media[med]: for key, value in medattr.items(): if key in medias_attr: medias_dict[med][key] = value medias_list = list() for key, value in medias_dict.items(): # Load media values or default values active = "0" if str(value.get("active", "true")).lower() == "true" else "1" mediatype_sls = str(value.get("mediatype", "mail")).lower() mediatypeid = str(media_type.get(mediatype_sls, 1)) period = value.get("period", "1-7,00:00-24:00") sendto = value.get("sendto", key) severity_sls = value.get("severity", "HD") severity_bin = "" for sev in media_severities: if sev in severity_sls: severity_bin += "1" else: severity_bin += "0" severity = str(int(severity_bin, 2)) medias_list.append( { "active": active, "mediatypeid": mediatypeid, "period": period, "sendto": sendto, "severity": severity, } ) return medias_list user_exists = __salt__["zabbix.user_exists"](alias, **connection_args) zabbix_version = __salt__["zabbix.apiinfo_version"](**connection_args) if user_exists: user = __salt__["zabbix.user_get"](alias, **connection_args)[0] userid = user["userid"] update_usrgrps = False update_medias = False usergroups = deepcopy(user.get("usrgrps", [])) cur_usrgrps = list() for usergroup in usergroups: cur_usrgrps.append(int(usergroup["usrgrpid"])) if set(cur_usrgrps) != set(usrgrps): update_usrgrps = True user_medias = user.get("medias", []) medias_formated = _media_format(medias) log.debug(user_medias) log.debug(medias_formated) if user_medias: user_medias_copy = deepcopy(user_medias) for user_med in user_medias_copy: user_med.pop("userid") user_med.pop("mediaid") media_diff = [x for x in medias_formated if x not in user_medias_copy] + [ y for y in user_medias_copy if y not in medias_formated ] if media_diff: update_medias = True elif not user_medias and medias: update_medias = True # Dry run, test=true mode if __opts__["test"]: if user_exists: if update_usrgrps or password_reset or update_medias: ret["result"] = None ret["comment"] = comment_user_updated else: ret["result"] = True ret["comment"] = comment_user_exists else: ret["result"] = None ret["comment"] = comment_user_created error = [] if user_exists: ret["result"] = True if update_usrgrps or password_reset or update_medias: ret["comment"] = comment_user_updated if Version(zabbix_version) > Version("3.4"): updates = deepcopy(connection_args) if update_usrgrps: updates["usrgrps"] = usrgrps if password_reset: updates["passwd"] = passwd if update_medias: updates["medias"] = medias_formated result = __salt__["zabbix.user_update"](userid, **updates) new_user = __salt__["zabbix.user_get"](alias, **connection_args)[0] if "error" in result: error.append(result["error"]) else: if update_usrgrps: ret["changes"]["usrgrps"] = str(new_user["usrgrps"]) if update_medias: ret["changes"]["medias"] = str(medias_formated) if password_reset: ret["changes"]["passwd"] = "updated" cur_usrgrps = list() for usergroup in new_user["usrgrps"]: cur_usrgrps.append(int(usergroup["usrgrpid"])) usrgrp_diff = list(set(usrgrps) - set(cur_usrgrps)) if usrgrp_diff and update_usrgrps: error.append(f"Unable to update group(s): {usrgrp_diff}") else: if update_usrgrps: __salt__["zabbix.user_update"]( userid, usrgrps=usrgrps, **connection_args ) updated_groups = __salt__["zabbix.usergroup_get"]( userids=userid, **connection_args ) cur_usrgrps = list() for usergroup in updated_groups: cur_usrgrps.append(int(usergroup["usrgrpid"])) usrgrp_diff = list(set(usrgrps) - set(cur_usrgrps)) if usrgrp_diff: error.append(f"Unable to update group(s): {usrgrp_diff}") ret["changes"]["usrgrps"] = str(updated_groups) if password_reset: updated_password = __salt__["zabbix.user_update"]( userid, passwd=passwd, **connection_args ) if "error" in updated_password: error.append(updated_groups["error"]) else: ret["changes"]["passwd"] = "updated" if update_medias: for user_med in user_medias: deletedmed = __salt__["zabbix.user_deletemedia"]( user_med["mediaid"], **connection_args ) if "error" in deletedmed: error.append(deletedmed["error"]) for media in medias_formated: updatemed = __salt__["zabbix.user_addmedia"]( userids=userid, active=media["active"], mediatypeid=media["mediatypeid"], period=media["period"], sendto=media["sendto"], severity=media["severity"], **connection_args, ) if "error" in updatemed: error.append(updatemed["error"]) ret["changes"]["medias"] = str(medias_formated) else: ret["comment"] = comment_user_exists else: user_create = __salt__["zabbix.user_create"](alias, passwd, usrgrps, **kwargs) if "error" not in user_create: ret["result"] = True ret["comment"] = comment_user_created ret["changes"] = changes_user_created else: ret["result"] = False ret["comment"] = comment_user_notcreated + str(user_create["error"]) # error detected if error: ret["changes"] = {} ret["result"] = False ret["comment"] = str(error) return ret def absent(name, **kwargs): """ Ensures that the user does not exist, eventually delete user. .. versionadded:: 2016.3.0 :param name: user alias :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring) :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring) .. code-block:: yaml George: zabbix_user.absent """ connection_args = {} if "_connection_user" in kwargs: connection_args["_connection_user"] = kwargs["_connection_user"] if "_connection_password" in kwargs: connection_args["_connection_password"] = kwargs["_connection_password"] if "_connection_url" in kwargs: connection_args["_connection_url"] = kwargs["_connection_url"] ret = {"name": name, "changes": {}, "result": False, "comment": ""} # Comment and change messages comment_user_deleted = f"USer {name} deleted." comment_user_notdeleted = f"Unable to delete user: {name}. " comment_user_notexists = f"User {name} does not exist." changes_user_deleted = { name: { "old": f"User {name} exists.", "new": f"User {name} deleted.", } } user_get = __salt__["zabbix.user_get"](name, **connection_args) # Dry run, test=true mode if __opts__["test"]: if not user_get: ret["result"] = True ret["comment"] = comment_user_notexists else: ret["result"] = None ret["comment"] = comment_user_deleted ret["changes"] = changes_user_deleted if not user_get: ret["result"] = True ret["comment"] = comment_user_notexists else: try: userid = user_get[0]["userid"] user_delete = __salt__["zabbix.user_delete"](userid, **connection_args) except KeyError: user_delete = False if user_delete and "error" not in user_delete: ret["result"] = True ret["comment"] = comment_user_deleted ret["changes"] = changes_user_deleted else: ret["result"] = False ret["comment"] = comment_user_notdeleted + str(user_delete["error"]) return ret