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/modules
Viewing File: /opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/solarisipspkg.py
""" IPS pkg support for Solaris .. important:: If you feel that Salt should be using this module to manage packages on a minion, and it is using a different module (or gives an error similar to *'pkg.install' is not available*), see :ref:`here <module-provider-override>`. This module provides support for Solaris 11 new package management - IPS (Image Packaging System). This is the default pkg module for Solaris 11 (and later). If you want to use also other packaging module (e.g. pkgutil) together with IPS, you need to override the ``pkg`` provider in sls for each package: .. code-block:: yaml mypackage: pkg.installed: - provider: pkgutil Or you can override it globally by setting the :conf_minion:`providers` parameter in your Minion config file like this: .. code-block:: yaml providers: pkg: pkgutil Or you can override it globally by setting the :conf_minion:`providers` parameter in your Minion config file like this: .. code-block:: yaml providers: pkg: pkgutil """ import copy import logging import salt.utils.data import salt.utils.functools import salt.utils.path import salt.utils.pkg from salt.exceptions import CommandExecutionError # Define the module's virtual name __virtualname__ = "pkg" log = logging.getLogger(__name__) def __virtual__(): """ Set the virtual pkg module if the os is Solaris 11 """ if ( __grains__["os_family"] == "Solaris" and float(__grains__["kernelrelease"]) > 5.10 and salt.utils.path.which("pkg") ): return __virtualname__ return ( False, "The solarisips execution module failed to load: only available " "on Solaris >= 11.", ) ips_pkg_return_values = { 0: "Command succeeded.", 1: "An error occurred.", 2: "Invalid command line options were specified.", 3: "Multiple operations were requested, but only some of them succeeded.", 4: "No changes were made - nothing to do.", 5: "The requested operation cannot be performed on a live image.", 6: ( "The requested operation cannot be completed because the licenses for " "the packages being installed or updated have not been accepted." ), 7: "The image is currently in use by another process and cannot be modified.", } def _ips_get_pkgname(line): """ Extracts package name from "pkg list -v" output. Input: one line of the command output Output: pkg name (e.g.: "pkg://solaris/x11/library/toolkit/libxt") Example use: line = "pkg://solaris/x11/library/toolkit/libxt@1.1.3,5.11-0.175.1.0.0.24.1317:20120904T180030Z i--" name = _ips_get_pkgname(line) """ return line.split()[0].split("@")[0].strip() def _ips_get_pkgversion(line): """ Extracts package version from "pkg list -v" output. Input: one line of the command output Output: package version (e.g.: "1.1.3,5.11-0.175.1.0.0.24.1317:20120904T180030Z") Example use: line = "pkg://solaris/x11/library/toolkit/libxt@1.1.3,5.11-0.175.1.0.0.24.1317:20120904T180030Z i--" name = _ips_get_pkgversion(line) """ return line.split()[0].split("@")[1].strip() def refresh_db(full=False, **kwargs): """ Updates the remote repos database. full : False Set to ``True`` to force a refresh of the pkg DB from all publishers, regardless of the last refresh time. CLI Example: .. code-block:: bash salt '*' pkg.refresh_db salt '*' pkg.refresh_db full=True """ # Remove rtag file to keep multiple refreshes from happening in pkg states salt.utils.pkg.clear_rtag(__opts__) if full: return __salt__["cmd.retcode"]("/bin/pkg refresh --full") == 0 else: return __salt__["cmd.retcode"]("/bin/pkg refresh") == 0 def upgrade_available(name, **kwargs): """ Check if there is an upgrade available for a certain package Accepts full or partial FMRI. Returns all matches found. CLI Example: .. code-block:: bash salt '*' pkg.upgrade_available apache-22 """ version = None cmd = ["pkg", "list", "-Huv", name] lines = __salt__["cmd.run_stdout"](cmd).splitlines() if not lines: return {} ret = {} for line in lines: ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) return ret def list_upgrades(refresh=True, **kwargs): # pylint: disable=W0613 """ Lists all packages available for update. When run in global zone, it reports only upgradable packages for the global zone. When run in non-global zone, it can report more upgradable packages than ``pkg update -vn``, because ``pkg update`` hides packages that require newer version of ``pkg://solaris/entire`` (which means that they can be upgraded only from the global zone). If ``pkg://solaris/entire`` is found in the list of upgrades, then the global zone should be updated to get all possible updates. Use ``refresh=True`` to refresh the package database. refresh : True Runs a full package database refresh before listing. Set to ``False`` to disable running the refresh. .. versionchanged:: 2017.7.0 In previous versions of Salt, ``refresh`` defaulted to ``False``. This was changed to default to ``True`` in the 2017.7.0 release to make the behavior more consistent with the other package modules, which all default to ``True``. CLI Example: .. code-block:: bash salt '*' pkg.list_upgrades salt '*' pkg.list_upgrades refresh=False """ if salt.utils.data.is_true(refresh): refresh_db(full=True) upgrades = {} # awk is in core-os package so we can use it without checking lines = __salt__["cmd.run_stdout"]("/bin/pkg list -Huv").splitlines() for line in lines: upgrades[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) return upgrades def upgrade(refresh=False, **kwargs): """ Upgrade all packages to the latest possible version. When run in global zone, it updates also all non-global zones. In non-global zones upgrade is limited by dependency constrains linked to the version of pkg://solaris/entire. Returns a dictionary containing the changes: .. code-block:: python {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} When there is a failure, an explanation is also included in the error message, based on the return code of the ``pkg update`` command. CLI Example: .. code-block:: bash salt '*' pkg.upgrade """ if salt.utils.data.is_true(refresh): refresh_db() # Get a list of the packages before install so we can diff after to see # what got installed. old = list_pkgs() # Install or upgrade the package # If package is already installed cmd = ["pkg", "update", "-v", "--accept"] result = __salt__["cmd.run_all"](cmd, output_loglevel="trace", python_shell=False) __context__.pop("pkg.list_pkgs", None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if result["retcode"] != 0: raise CommandExecutionError( "Problem encountered upgrading packages", info={ "changes": ret, "retcode": ips_pkg_return_values[result["retcode"]], "result": result, }, ) return ret def _list_pkgs_from_context(versions_as_list): """ Use pkg list from __context__ """ if versions_as_list: return __context__["pkg.list_pkgs"] else: ret = copy.deepcopy(__context__["pkg.list_pkgs"]) __salt__["pkg_resource.stringify"](ret) return ret def list_pkgs(versions_as_list=False, **kwargs): """ List the currently installed packages as a dict:: {'<package_name>': '<version>'} CLI Example: .. code-block:: bash salt '*' pkg.list_pkgs """ # not yet implemented or not applicable if any( [salt.utils.data.is_true(kwargs.get(x)) for x in ("removed", "purge_desired")] ): return {} if "pkg.list_pkgs" in __context__ and kwargs.get("use_context", True): return _list_pkgs_from_context(versions_as_list) ret = {} cmd = "/bin/pkg list -Hv" lines = __salt__["cmd.run_stdout"](cmd).splitlines() # column 1 is full FMRI name in form pkg://publisher/class/name@version for line in lines: name = _ips_get_pkgname(line) version = _ips_get_pkgversion(line) __salt__["pkg_resource.add_pkg"](ret, name, version) __salt__["pkg_resource.sort_pkglist"](ret) __context__["pkg.list_pkgs"] = copy.deepcopy(ret) if not versions_as_list: __salt__["pkg_resource.stringify"](ret) return ret def version(*names, **kwargs): """ Common interface for obtaining the version of installed packages. Accepts full or partial FMRI. If called using pkg_resource, full FMRI is required. Partial FMRI is returned if the package is not installed. CLI Example: .. code-block:: bash salt '*' pkg.version vim salt '*' pkg.version foo bar baz salt '*' pkg_resource.version pkg://solaris/entire """ if not names: return "" cmd = ["/bin/pkg", "list", "-Hv"] cmd.extend(names) lines = __salt__["cmd.run_stdout"](cmd, ignore_retcode=True).splitlines() ret = {} for line in lines: ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) # Append package names which are not installed/found for name in names: if name not in ret: ret[name] = "" # Return a string if only one package name passed if len(names) == 1: try: return next(iter(ret.values())) except StopIteration: return "" return ret def latest_version(*names, **kwargs): """ The available version of packages in the repository. Accepts full or partial FMRI. Partial FMRI is returned if the full FMRI could not be resolved. If the latest version of a given package is already installed, an empty string will be returned for that package. Please use pkg.latest_version as pkg.available_version is being deprecated. .. versionchanged:: 2019.2.0 Support for multiple package names added. CLI Example: .. code-block:: bash salt '*' pkg.latest_version bash salt '*' pkg.latest_version pkg://solaris/entire salt '*' pkg.latest_version postfix sendmail """ if not names: return "" cmd = ["/bin/pkg", "list", "-Hnv"] cmd.extend(names) lines = __salt__["cmd.run_stdout"](cmd, ignore_retcode=True).splitlines() ret = {} for line in lines: ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line) installed = version(*names) if len(names) == 1: # Convert back our result in a dict if only one name is passed installed = {list(ret)[0] if ret else names[0]: installed} for name in ret: if name not in installed: continue if ret[name] == installed[name]: ret[name] = "" # Append package names which are not found for name in names: if name not in ret: ret[name] = "" # Return a string if only one package name passed if len(names) == 1: try: return next(iter(ret.values())) except StopIteration: return "" return ret # available_version is being deprecated available_version = salt.utils.functools.alias_function( latest_version, "available_version" ) def get_fmri(name, **kwargs): """ Returns FMRI from partial name. Returns empty string ('') if not found. In case of multiple match, the function returns list of all matched packages. CLI Example: .. code-block:: bash salt '*' pkg.get_fmri bash """ if name.startswith("pkg://"): # already full fmri return name cmd = ["/bin/pkg", "list", "-aHv", name] # there can be more packages matching the name lines = __salt__["cmd.run_stdout"](cmd).splitlines() if not lines: # empty string = package not found return "" ret = [] for line in lines: ret.append(_ips_get_pkgname(line)) return ret def normalize_name(name, **kwargs): """ Internal function. Normalizes pkg name to full FMRI before running pkg.install. In case of multiple matches or no match, it returns the name without modifications. CLI Example: .. code-block:: bash salt '*' pkg.normalize_name vim """ if name.startswith("pkg://"): # already full fmri return name cmd = ["/bin/pkg", "list", "-aHv", name] # there can be more packages matching the name lines = __salt__["cmd.run_stdout"](cmd).splitlines() # if we get more lines, it's multiple match (name not unique) # if we get zero lines, pkg is not installed # in both ways it's safer to return original (unmodified) name and let "pkg install" to deal with it if len(lines) != 1: return name # return pkg name return _ips_get_pkgname(lines[0]) def is_installed(name, **kwargs): """ Returns True if the package is installed. Otherwise returns False. Name can be full or partial FMRI. In case of multiple match from partial FMRI name, it returns True. CLI Example: .. code-block:: bash salt '*' pkg.is_installed bash """ cmd = ["/bin/pkg", "list", "-Hv", name] return __salt__["cmd.retcode"](cmd) == 0 def search(name, versions_as_list=False, **kwargs): """ Searches the repository for given pkg name. The name can be full or partial FMRI. All matches are printed. Globs are also supported. CLI Example: .. code-block:: bash salt '*' pkg.search bash """ ret = {} cmd = ["/bin/pkg", "list", "-aHv", name] out = __salt__["cmd.run_all"](cmd, ignore_retcode=True) if out["retcode"] != 0: # error = nothing found return {} # no error, processing pkg listing # column 1 is full FMRI name in form pkg://publisher/pkg/name@version for line in out["stdout"].splitlines(): name = _ips_get_pkgname(line) version = _ips_get_pkgversion(line) __salt__["pkg_resource.add_pkg"](ret, name, version) if not versions_as_list: __salt__["pkg_resource.stringify"](ret) return ret def install(name=None, refresh=False, pkgs=None, version=None, test=False, **kwargs): """ Install the named package using the IPS pkg command. Accepts full or partial FMRI. Returns a dict containing the new package names and versions:: {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} Multiple Package Installation Options: pkgs A list of packages to install. Must be passed as a python list. CLI Example: .. code-block:: bash salt '*' pkg.install vim salt '*' pkg.install pkg://solaris/editor/vim salt '*' pkg.install pkg://solaris/editor/vim refresh=True salt '*' pkg.install pkgs='["foo", "bar"]' """ if not pkgs: if is_installed(name): return {} if refresh: refresh_db(full=True) pkg2inst = "" if pkgs: # multiple packages specified pkg2inst = [] for pkg in pkgs: if getattr(pkg, "items", False): if list(pkg.items())[0][1]: # version specified pkg2inst.append( f"{list(pkg.items())[0][0]}@{list(pkg.items())[0][1]}" ) else: pkg2inst.append(list(pkg.items())[0][0]) else: pkg2inst.append(f"{pkg}") log.debug("Installing these packages instead of %s: %s", name, pkg2inst) else: # install single package if version: pkg2inst = f"{name}@{version}" else: pkg2inst = f"{name}" cmd = ["pkg", "install", "-v", "--accept"] if test: cmd.append("-n") # Get a list of the packages before install so we can diff after to see # what got installed. old = list_pkgs() # Install or upgrade the package # If package is already installed if isinstance(pkg2inst, str): cmd.append(pkg2inst) elif isinstance(pkg2inst, list): cmd = cmd + pkg2inst out = __salt__["cmd.run_all"](cmd, output_loglevel="trace") # Get a list of the packages again, including newly installed ones. __context__.pop("pkg.list_pkgs", None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if out["retcode"] != 0: raise CommandExecutionError( "Error occurred installing package(s)", info={ "changes": ret, "retcode": ips_pkg_return_values[out["retcode"]], "errors": [out["stderr"]], }, ) # No error occurred if test: return "Test succeeded." return ret def remove(name=None, pkgs=None, **kwargs): """ Remove specified package. Accepts full or partial FMRI. In case of multiple match, the command fails and won't modify the OS. name The name of the package to be deleted. Multiple Package Options: pkgs A list of packages to delete. Must be passed as a python list. The ``name`` parameter will be ignored if this option is passed. Returns a list containing the removed packages. CLI Example: .. code-block:: bash salt '*' pkg.remove <package name> salt '*' pkg.remove tcsh salt '*' pkg.remove pkg://solaris/shell/tcsh salt '*' pkg.remove pkgs='["foo", "bar"]' """ targets = salt.utils.args.split_input(pkgs) if pkgs else [name] if not targets: return {} if pkgs: log.debug("Removing these packages instead of %s: %s", name, targets) # Get a list of the currently installed pkgs. old = list_pkgs() # Remove the package(s) cmd = ["/bin/pkg", "uninstall", "-v"] + targets out = __salt__["cmd.run_all"](cmd, output_loglevel="trace") # Get a list of the packages after the uninstall __context__.pop("pkg.list_pkgs", None) new = list_pkgs() ret = salt.utils.data.compare_dicts(old, new) if out["retcode"] != 0: raise CommandExecutionError( "Error occurred removing package(s)", info={ "changes": ret, "retcode": ips_pkg_return_values[out["retcode"]], "errors": [out["stderr"]], }, ) return ret def purge(name, **kwargs): """ Remove specified package. Accepts full or partial FMRI. Returns a list containing the removed packages. CLI Example: .. code-block:: bash salt '*' pkg.purge <package name> """ return remove(name, **kwargs)