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/win_dism.py
""" Installing of Windows features using DISM ========================================= Install windows features/capabilties with DISM .. code-block:: yaml Language.Basic~~~en-US~0.0.1.0: dism.capability_installed NetFx3: dism.feature_installed """ import logging import os import salt.utils.data import salt.utils.platform log = logging.getLogger(__name__) __virtualname__ = "dism" def __virtual__(): """ Only work on Windows where the DISM module is available """ if not salt.utils.platform.is_windows(): return False, "Module only available on Windows" return __virtualname__ def capability_installed( name, source=None, limit_access=False, image=None, restart=False ): """ Install a DISM capability Args: name (str): The capability to install source (str): The optional source of the capability limit_access (bool): Prevent DISM from contacting Windows Update for online images image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the install Example: Run ``dism.available_capabilities`` to get a list of available capabilities. This will help you get the proper name to use. .. code-block:: yaml install_dotnet35: dism.capability_installed: - name: NetFX3~~~~ """ ret = {"name": name, "result": True, "comment": "", "changes": {}} old = __salt__["dism.installed_capabilities"]() if name in old: ret["comment"] = f"The capability {name} is already installed" return ret if __opts__["test"]: ret["changes"]["capability"] = f"{name} will be installed" ret["result"] = None return ret # Install the capability status = __salt__["dism.add_capability"](name, source, limit_access, image, restart) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to install {}: {}".format(name, status["stdout"]) ret["result"] = False new = __salt__["dism.installed_capabilities"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Installed {name}" ret["changes"] = status ret["changes"]["capability"] = changes return ret def capability_removed(name, image=None, restart=False): """ Uninstall a DISM capability Args: name (str): The capability to uninstall image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the uninstall Example: Run ``dism.installed_capabilities`` to get a list of installed capabilities. This will help you get the proper name to use. .. code-block:: yaml remove_dotnet35: dism.capability_removed: - name: NetFX3~~~~ """ ret = {"name": name, "result": True, "comment": "", "changes": {}} old = __salt__["dism.installed_capabilities"]() if name not in old: ret["comment"] = f"The capability {name} is already removed" return ret if __opts__["test"]: ret["changes"]["capability"] = f"{name} will be removed" ret["result"] = None return ret # Remove the capability status = __salt__["dism.remove_capability"](name, image, restart) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to remove {}: {}".format(name, status["stdout"]) ret["result"] = False new = __salt__["dism.installed_capabilities"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Removed {name}" ret["changes"] = status ret["changes"]["capability"] = changes return ret def feature_installed( name, package=None, source=None, limit_access=False, enable_parent=False, image=None, restart=False, ): """ Install a DISM feature Args: name (str): The feature in which to install package (Optional[str]): The parent package for the feature. You do not have to specify the package if it is the Windows Foundation Package. Otherwise, use package to specify the parent package of the feature source (str): The optional source of the feature limit_access (bool): Prevent DISM from contacting Windows Update for online images enable_parent (Optional[bool]): True will enable all parent features of the specified feature image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the install Example: Run ``dism.available_features`` to get a list of available features. This will help you get the proper name to use. .. code-block:: yaml install_telnet_client: dism.feature_installed: - name: TelnetClient """ ret = {"name": name, "result": True, "comment": "", "changes": {}} old = __salt__["dism.installed_features"]() if name in old: ret["comment"] = f"The feature {name} is already installed" return ret if __opts__["test"]: ret["changes"]["feature"] = f"{name} will be installed" ret["result"] = None return ret # Install the feature status = __salt__["dism.add_feature"]( name, package, source, limit_access, enable_parent, image, restart ) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to install {}: {}".format(name, status["stdout"]) ret["result"] = False new = __salt__["dism.installed_features"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Installed {name}" ret["changes"] = status ret["changes"]["feature"] = changes return ret def feature_removed(name, remove_payload=False, image=None, restart=False): """ Disables a feature. Args: name (str): The feature to disable remove_payload (Optional[bool]): Remove the feature's payload. Must supply source when enabling in the future. image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the uninstall Example: Run ``dism.installed_features`` to get a list of installed features. This will help you get the proper name to use. .. code-block:: yaml remove_telnet_client: dism.feature_removed: - name: TelnetClient - remove_payload: True """ ret = {"name": name, "result": True, "comment": "", "changes": {}} old = __salt__["dism.installed_features"]() if name not in old: ret["comment"] = f"The feature {name} is already removed" return ret if __opts__["test"]: ret["changes"]["feature"] = f"{name} will be removed" ret["result"] = None return ret # Remove the feature status = __salt__["dism.remove_feature"](name, remove_payload, image, restart) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to remove {}: {}".format(name, status["stdout"]) ret["result"] = False new = __salt__["dism.installed_features"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Removed {name}" ret["changes"] = status ret["changes"]["feature"] = changes return ret def package_installed( name, ignore_check=False, prevent_pending=False, image=None, restart=False ): """ Install a package. Args: name (str): The package to install. Can be a .cab file, a .msu file, or a folder ignore_check (Optional[bool]): Skip installation of the package if the applicability checks fail prevent_pending (Optional[bool]): Skip the installation of the package if there are pending online actions image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the install Example: .. code-block:: yaml install_KB123123123: dism.package_installed: - name: C:\\Packages\\KB123123123.cab """ ret = {"name": name, "result": True, "comment": "", "changes": {}} # Fail if using a non-existent package path if "~" not in name and not os.path.exists(name): if __opts__["test"]: ret["result"] = None else: ret["result"] = False ret["comment"] = f"Package path {name} does not exist" return ret old = __salt__["dism.installed_packages"]() # Get package info so we can see if it's already installed package_info = __salt__["dism.package_info"](name) if package_info["Package Identity"] in old: ret["comment"] = "The package {} is already installed: {}".format( name, package_info["Package Identity"] ) return ret if __opts__["test"]: ret["changes"]["package"] = f"{name} will be installed" ret["result"] = None return ret # Install the package status = __salt__["dism.add_package"]( name, ignore_check, prevent_pending, image, restart ) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to install {}: {}".format(name, status["stdout"]) ret["result"] = False new = __salt__["dism.installed_packages"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Installed {name}" ret["changes"] = status ret["changes"]["package"] = changes return ret def package_removed(name, image=None, restart=False): """ Uninstall a package Args: name (str): The full path to the package. Can be either a .cab file or a folder. Should point to the original source of the package, not to where the file is installed. This can also be the name of a package as listed in ``dism.installed_packages`` image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the uninstall Example: .. code-block:: yaml # Example using source remove_KB1231231: dism.package_installed: - name: C:\\Packages\\KB1231231.cab # Example using name from ``dism.installed_packages`` remove_KB1231231: dism.package_installed: - name: Package_for_KB1231231~31bf3856ad364e35~amd64~~10.0.1.3 """ ret = {"name": name, "result": True, "comment": "", "changes": {}} # Fail if using a non-existent package path if "~" not in name and not os.path.exists(name): if __opts__["test"]: ret["result"] = None else: ret["result"] = False ret["comment"] = f"Package path {name} does not exist" return ret old = __salt__["dism.installed_packages"]() # Get package info so we can see if it's already removed package_info = __salt__["dism.package_info"](name) # If `Package Identity` isn't returned or if they passed a cab file, if # `Package Identity` isn't in the list of installed packages if ( "Package Identity" not in package_info or package_info["Package Identity"] not in old ): ret["comment"] = f"The package {name} is already removed" return ret if __opts__["test"]: ret["changes"]["package"] = f"{name} will be removed" ret["result"] = None return ret # Remove the package status = __salt__["dism.remove_package"](name, image, restart) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to remove {}: {}".format(name, status["stdout"]) ret["result"] = False new = __salt__["dism.installed_packages"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Removed {name}" ret["changes"] = status ret["changes"]["package"] = changes return ret def kb_removed(name, image=None, restart=False): """ Uninstall a KB package .. versionadded:: 3006.0 Args: name (str): The name of the KB. Can be with or without the KB at the beginning. image (Optional[str]): The path to the root directory of an offline Windows image. If `None` is passed, the running operating system is targeted. Default is None. restart (Optional[bool]): Reboot the machine if required by the uninstall Example: .. code-block:: yaml # Example using full KB name remove_KB1231231: dism.package_installed: - name: KB1231231 # Example using just he KB number remove_KB1231231: dism.package_installed: - name: 1231231 """ ret = {"name": name, "result": True, "comment": "", "changes": {}} pkg_name = __salt__["dism.get_kb_package_name"](kb=name, image=image) # If pkg_name is None, the package is not installed if pkg_name is None: ret["comment"] = f"{name} is not installed" return ret if __opts__["test"]: ret["changes"]["package"] = f"{name} will be removed" ret["result"] = None return ret # Fail if using a non-existent package path old = __salt__["dism.installed_packages"]() # Remove the package status = __salt__["dism.remove_kb"](kb=name, image=image, restart=restart) if status["retcode"] not in [0, 1641, 3010]: ret["comment"] = "Failed to remove {}: {}".format(name, status["stdout"]) ret["result"] = False return ret new = __salt__["dism.installed_packages"]() changes = salt.utils.data.compare_lists(old, new) if changes: ret["comment"] = f"Removed {name}" ret["changes"] = status ret["changes"]["package"] = changes return ret