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/client/ssh/wrapper
Viewing File: /opt/saltstack/salt/lib/python3.10/site-packages/salt/client/ssh/wrapper/state.py
""" Create ssh executor system """ import logging import os import time import salt.client.ssh.shell import salt.client.ssh.state import salt.defaults.exitcodes import salt.loader import salt.minion import salt.roster import salt.state import salt.utils.args import salt.utils.data import salt.utils.files import salt.utils.hashutils import salt.utils.jid import salt.utils.json import salt.utils.platform import salt.utils.state import salt.utils.thin from salt.exceptions import SaltInvocationError __func_alias__ = {"apply_": "apply"} log = logging.getLogger(__name__) def _ssh_state(chunks, st_kwargs, kwargs, pillar, test=False): """ Function to run a state with the given chunk via salt-ssh """ file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), __opts__.get("extra_filerefs", "") ), ) # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( __opts__["thin_dir"], test, trans_tar_sum, __opts__["hash_type"] ) single = salt.client.ssh.Single( __opts__, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(__opts__["thin_dir"])) stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.data.decode( salt.utils.json.loads(stdout, object_hook=salt.utils.data.encode_dict) ) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return salt.utils.data.decode(stdout) def _set_retcode(ret, highstate=None): """ Set the return code based on the data back from the state system """ # Set default retcode to 0 __context__["retcode"] = salt.defaults.exitcodes.EX_OK if isinstance(ret, list): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return if not salt.utils.state.check_result(ret, highstate=highstate): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_FAILURE def _check_pillar(kwargs, pillar=None): """ Check the pillar for errors, refuse to run the state if there are errors in the pillar and return the pillar errors """ if kwargs.get("force"): return True pillar_dict = pillar if pillar is not None else __pillar__.value() if "_errors" in pillar_dict: return False return True def _wait(jid): """ Wait for all previously started state jobs to finish running """ if jid is None: jid = salt.utils.jid.gen_jid(__opts__) states = _prior_running_states(jid) while states: time.sleep(1) states = _prior_running_states(jid) def _merge_extra_filerefs(*args): """ Takes a list of filerefs and returns a merged list """ ret = [] for arg in args: if isinstance(arg, str): if arg: ret.extend(arg.split(",")) elif isinstance(arg, list): if arg: ret.extend(arg) return ",".join(ret) def _cleanup_slsmod_low_data(low_data): """ Set "slsmod" keys to None to make low_data JSON serializable """ for i in low_data: if "slsmod" in i: i["slsmod"] = None def _cleanup_slsmod_high_data(high_data): """ Set "slsmod" keys to None to make high_data JSON serializable """ for i in high_data.values(): if "stateconf" in i: stateconf_data = i["stateconf"][1] if "slsmod" in stateconf_data: stateconf_data["slsmod"] = None def _parse_mods(mods): """ Parse modules. """ if isinstance(mods, str): mods = [item.strip() for item in mods.split(",") if item.strip()] return mods def sls(mods, saltenv="base", test=None, exclude=None, **kwargs): """ Create the seed file for a state.sls run """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) initial_pillar = _get_initial_pillar(opts) pillar_override = kwargs.get("pillar") with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() mods = _parse_mods(mods) high_data, errors = st_.render_highstate( {saltenv: mods}, context=__context__.value() ) if exclude: if isinstance(exclude, str): exclude = exclude.split(",") if "__exclude__" in high_data: high_data["__exclude__"].extend(exclude) else: high_data["__exclude__"] = exclude high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors high_data, req_in_errors = st_.state.requisite_in(high_data) errors += req_in_errors high_data = st_.state.apply_exclude(high_data) # Verify that the high data is structurally sound if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors # Compile and verify the raw chunks chunks = st_.state.compile_high_data(high_data) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", "") ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.json.loads(stdout) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return stdout def running(concurrent=False): """ Return a list of strings that contain state return data if a state function is already running. This function is used to prevent multiple state calls from being run at the same time. CLI Example: .. code-block:: bash salt '*' state.running """ ret = [] if concurrent: return ret active = __salt__["saltutil.is_running"]("state.*") for data in active: err = ( 'The function "{}" is running as PID {} and was started at {} ' "with jid {}".format( data["fun"], data["pid"], salt.utils.jid.jid_to_time(data["jid"]), data["jid"], ) ) ret.append(err) return ret def _prior_running_states(jid): """ Return a list of dicts of prior calls to state functions. This function is used to queue state calls so only one is run at a time. """ ret = [] active = __salt__["saltutil.is_running"]("state.*") for data in active: try: data_jid = int(data["jid"]) except ValueError: continue if data_jid < int(jid): ret.append(data) return ret def _check_queue(queue, kwargs): """ Utility function to queue the state run if requested and to check for conflicts in currently running states """ if queue: _wait(kwargs.get("__pub_jid")) else: conflict = running(concurrent=kwargs.get("concurrent", False)) if conflict: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return conflict def _get_initial_pillar(opts): return __pillar__.value() if opts["pillarenv"] == __opts__["pillarenv"] else None def low(data, **kwargs): """ Execute a single low data call This function is mostly intended for testing the state system CLI Example: .. code-block:: bash salt '*' state.low '{"state": "pkg", "fun": "installed", "name": "vi"}' """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() chunks = [data] with salt.client.ssh.state.SSHHighState( __opts__, None, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=__pillar__.value(), ) as st_: for chunk in chunks: chunk["__id__"] = ( chunk["name"] if not chunk.get("__id__") else chunk["__id__"] ) err = st_.state.verify_data(data) if err: return err file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), __opts__.get("extra_filerefs", "") ), ) roster = salt.roster.Roster(__opts__, __opts__.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, __pillar__.value(), st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__["hash_type"]) cmd = "state.pkg {}/salt_state.tgz pkg_sum={} hash_type={}".format( __opts__["thin_dir"], trans_tar_sum, __opts__["hash_type"] ) single = salt.client.ssh.Single( __opts__, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(__opts__["thin_dir"])) stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.json.loads(stdout) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return stdout def _get_test_value(test=None, **kwargs): """ Determine the correct value for the test flag. """ ret = True if test is None: if salt.utils.args.test_mode(test=test, **kwargs): ret = True else: ret = __opts__.get("test", None) else: ret = test return ret def high(data, **kwargs): """ Execute the compound calls stored in a single set of high data This function is mostly intended for testing the state system CLI Example: .. code-block:: bash salt '*' state.high '{"vim": {"pkg": ["installed"]}}' """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() chunks = st_.state.compile_high_data(data) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", "") ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz pkg_sum={} hash_type={}".format( opts["thin_dir"], trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.json.loads(stdout) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return stdout def apply_(mods=None, **kwargs): """ .. versionadded:: 2015.5.3 Apply states! This function will call highstate or state.sls based on the arguments passed in, state.apply is intended to be the main gateway for all state executions. CLI Example: .. code-block:: bash salt '*' state.apply salt '*' state.apply test salt '*' state.apply test,pkgs """ if mods: return sls(mods, **kwargs) return highstate(**kwargs) def request(mods=None, **kwargs): """ .. versionadded:: 2017.7.3 Request that the local admin execute a state run via `salt-call state.run_request` All arguments match state.apply CLI Example: .. code-block:: bash salt '*' state.request salt '*' state.request test salt '*' state.request test,pkgs """ kwargs["test"] = True ret = apply_(mods, **kwargs) notify_path = os.path.join(__opts__["cachedir"], "req_state.p") req = check_request() req.update( { kwargs.get("name", "default"): { "test_run": ret, "mods": mods, "kwargs": kwargs, } } ) with salt.utils.files.set_umask(0o077): try: if salt.utils.platform.is_windows(): # Make sure cache file isn't read-only __salt__["cmd.run"](f'attrib -R "{notify_path}"') with salt.utils.files.fopen(notify_path, "w+b") as fp_: salt.payload.dump(req, fp_) except OSError: log.error( "Unable to write state request file %s. Check permission.", notify_path ) return ret def check_request(name=None): """ .. versionadded:: 2017.7.3 Return the state request information, if any CLI Example: .. code-block:: bash salt '*' state.check_request """ notify_path = os.path.join(__opts__["cachedir"], "req_state.p") if os.path.isfile(notify_path): with salt.utils.files.fopen(notify_path, "rb") as fp_: # Not sure if this needs to be decoded since it is being returned, # and msgpack serialization will encode it to bytes anyway. req = salt.payload.load(fp_) if name: return req[name] return req return {} def clear_request(name=None): """ .. versionadded:: 2017.7.3 Clear out the state execution request without executing it CLI Example: .. code-block:: bash salt '*' state.clear_request """ notify_path = os.path.join(__opts__["cachedir"], "req_state.p") if not os.path.isfile(notify_path): return True if not name: try: os.remove(notify_path) except OSError: pass else: req = check_request() if name in req: req.pop(name) else: return False with salt.utils.files.set_umask(0o077): try: if salt.utils.platform.is_windows(): # Make sure cache file isn't read-only __salt__["cmd.run"](f'attrib -R "{notify_path}"') with salt.utils.files.fopen(notify_path, "w+b") as fp_: salt.payload.dump(req, fp_) except OSError: log.error( "Unable to write state request file %s. Check permission.", notify_path, ) return True def run_request(name="default", **kwargs): """ .. versionadded:: 2017.7.3 Execute the pending state request CLI Example: .. code-block:: bash salt '*' state.run_request """ req = check_request() if name not in req: return {} n_req = req[name] if "mods" not in n_req or "kwargs" not in n_req: return {} req[name]["kwargs"].update(kwargs) if "test" in n_req["kwargs"]: n_req["kwargs"].pop("test") if req: ret = apply_(n_req["mods"], **n_req["kwargs"]) try: os.remove(os.path.join(__opts__["cachedir"], "req_state.p")) except OSError: pass return ret return {} def highstate(test=None, **kwargs): """ Retrieve the state data from the salt master for this minion and execute it CLI Example: .. code-block:: bash salt '*' state.highstate salt '*' state.highstate exclude=sls_to_exclude salt '*' state.highstate exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() chunks = st_.compile_low_chunks(context=__context__.value()) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", "") ), ) # Check for errors for chunk in chunks: if not isinstance(chunk, dict): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return chunks roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.json.loads(stdout) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return stdout def top(topfn, test=None, **kwargs): """ Execute a specific top file instead of the default CLI Example: .. code-block:: bash salt '*' state.top reverse_top.sls salt '*' state.top reverse_top.sls exclude=sls_to_exclude salt '*' state.top reverse_top.sls exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.opts["state_top"] = os.path.join("salt://", topfn) st_.push_active() chunks = st_.compile_low_chunks(context=__context__.value()) # Check for errors for chunk in chunks: if not isinstance(chunk, dict): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return chunks file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", "") ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.json.loads(stdout) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return stdout def show_highstate(**kwargs): """ Retrieve the highstate data from the salt master and display it CLI Example: .. code-block:: bash salt '*' state.show_highstate """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() chunks = st_.compile_highstate(context=__context__.value()) # Check for errors if not isinstance(chunks, dict): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return chunks _cleanup_slsmod_high_data(chunks) return chunks def show_lowstate(**kwargs): """ List out the low data that will be applied to this minion CLI Example: .. code-block:: bash salt '*' state.show_lowstate """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) with salt.client.ssh.state.SSHHighState( opts, None, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=_get_initial_pillar(opts), ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err st_.push_active() chunks = st_.compile_low_chunks(context=__context__.value()) _cleanup_slsmod_low_data(chunks) return chunks def sls_id(id_, mods, test=None, queue=False, **kwargs): """ Call a single ID from the named module(s) and handle all requisites The state ID comes *before* the module ID(s) on the command line. id ID to call mods Comma-delimited list of modules to search for given id and its requisites .. versionadded:: 2017.7.3 saltenv : base Specify a salt fileserver environment to be used when applying states pillarenv Specify a Pillar environment to be used when applying states. This can also be set in the minion config file using the :conf_minion:`pillarenv` option. When neither the :conf_minion:`pillarenv` minion config option nor this CLI argument is used, all Pillar environments will be merged together. CLI Example: .. code-block:: bash salt '*' state.sls_id my_state my_module salt '*' state.sls_id my_state my_module,a_common_module """ st_kwargs = __salt__.kwargs conflict = _check_queue(queue, kwargs) if conflict is not None: return conflict orig_test = __opts__.get("test", None) opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) # Since this is running a specific ID within a specific SLS file, fall back # to the 'base' saltenv if none is configured and none was passed. if opts["saltenv"] is None: opts["saltenv"] = "base" pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( __opts__, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += __pillar__["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) split_mods = _parse_mods(mods) st_.push_active() high_, errors = st_.render_highstate( {opts["saltenv"]: split_mods}, context=__context__.value() ) errors += st_.state.verify_high(high_) # Apply requisites to high data high_, req_in_errors = st_.state.requisite_in(high_) if req_in_errors: # This if statement should not be necessary if there were no errors, # but it is required to get the unit tests to pass. errors.extend(req_in_errors) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors chunks = st_.state.compile_high_data(high_) chunk = [x for x in chunks if x.get("__id__", "") == id_] if not chunk: raise SaltInvocationError( "No matches for ID '{}' found in SLS '{}' within saltenv '{}'".format( id_, mods, opts["saltenv"] ) ) ret = _ssh_state(chunk, st_kwargs, kwargs, pillar, test=test) _set_retcode(ret, highstate=highstate) # Work around Windows multiprocessing bug, set __opts__['test'] back to # value from before this function was run. __opts__["test"] = orig_test return ret def show_sls(mods, saltenv="base", test=None, **kwargs): """ Display the state data from a specific sls or list of sls files on the master CLI Example: .. code-block:: bash salt '*' state.show_sls core,edit.vim dev """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() mods = _parse_mods(mods) high_data, errors = st_.render_highstate( {saltenv: mods}, context=__context__.value() ) high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors high_data, req_in_errors = st_.state.requisite_in(high_data) errors += req_in_errors high_data = st_.state.apply_exclude(high_data) # Verify that the high data is structurally sound if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors _cleanup_slsmod_high_data(high_data) return high_data def show_low_sls(mods, saltenv="base", test=None, **kwargs): """ Display the low state data from a specific sls or list of sls files on the master. .. versionadded:: 2016.3.2 CLI Example: .. code-block:: bash salt '*' state.show_low_sls core,edit.vim dev """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() mods = _parse_mods(mods) high_data, errors = st_.render_highstate( {saltenv: mods}, context=__context__.value() ) high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors high_data, req_in_errors = st_.state.requisite_in(high_data) errors += req_in_errors high_data = st_.state.apply_exclude(high_data) # Verify that the high data is structurally sound if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors ret = st_.state.compile_high_data(high_data) _cleanup_slsmod_low_data(ret) return ret def show_top(**kwargs): """ Return the top data that the minion will use for a highstate CLI Example: .. code-block:: bash salt '*' state.show_top """ __opts__["grains"] = __grains__ opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) with salt.client.ssh.state.SSHHighState( opts, None, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=_get_initial_pillar(opts), ) as st_: top_data = st_.get_top(context=__context__.value()) errors = [] errors += st_.verify_tops(top_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors matches = st_.top_matches(top_data) return matches def single(fun, name, test=None, **kwargs): """ .. versionadded:: 2015.5.0 Execute a single state function with the named kwargs, returns False if insufficient data is sent to the command By default, the values of the kwargs will be parsed as YAML. So, you can specify lists values, or lists of single entry key-value maps, as you would in a YAML salt file. Alternatively, JSON format of keyword values is also supported. CLI Example: .. code-block:: bash salt '*' state.single pkg.installed name=vim """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() # state.fun -> [state, fun] comps = fun.split(".") if len(comps) < 2: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return "Invalid function passed" # Create the low chunk, using kwargs as a base kwargs.update({"state": comps[0], "fun": comps[1], "__id__": name, "name": name}) opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) # Set test mode opts["test"] = _get_test_value(test, **kwargs) # Get the override pillar data # This needs to be removed from the kwargs, they are called # as a lowstate with one item, not a single chunk pillar_override = kwargs.pop("pillar", None) # Create the State environment st_ = salt.client.ssh.state.SSHState( opts, pillar_override, initial_pillar=_get_initial_pillar(opts) ) try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] # Verify the low chunk err = st_.verify_data(kwargs) if err: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return err # Must be a list of low-chunks chunks = [kwargs] # Retrieve file refs for the state run, so we can copy relevant files down # to the minion before executing the state file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", "") ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) # Create a hash so we can verify the tar on the target system trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) # We use state.pkg to execute the "state package" cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) # Create a salt-ssh Single object to actually do the ssh work single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) # Copy the tar down single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) # Run the state.pkg command on the target stdout, stderr, _ = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass # Read in the JSON data and return the data structure try: return salt.utils.json.loads(stdout) except Exception as e: # pylint: disable=broad-except log.error("JSON Render failed for: %s\n%s", stdout, stderr) log.error(str(e)) # If for some reason the json load fails, return the stdout return stdout def test(*args, **kwargs): """ .. versionadded:: 3001 Alias for `state.apply` with the kwarg `test` forced to `True`. This is a nicety to avoid the need to type out `test=True` and the possibility of a typo causing changes you do not intend. """ kwargs["test"] = True ret = apply_(*args, **kwargs) return ret