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/azurearm_dns.py
""" Azure (ARM) DNS State Module .. versionadded:: 3000 .. warning:: This cloud provider will be removed from Salt in version 3007 in favor of the `saltext.azurerm Salt Extension <https://github.com/salt-extensions/saltext-azurerm>`_ :maintainer: <devops@eitr.tech> :maturity: new :depends: * `azure <https://pypi.python.org/pypi/azure>`_ >= 2.0.0 * `azure-common <https://pypi.python.org/pypi/azure-common>`_ >= 1.1.8 * `azure-mgmt <https://pypi.python.org/pypi/azure-mgmt>`_ >= 1.0.0 * `azure-mgmt-compute <https://pypi.python.org/pypi/azure-mgmt-compute>`_ >= 1.0.0 * `azure-mgmt-dns <https://pypi.python.org/pypi/azure-mgmt-dns>`_ >= 1.0.1 * `azure-mgmt-network <https://pypi.python.org/pypi/azure-mgmt-network>`_ >= 1.7.1 * `azure-mgmt-resource <https://pypi.python.org/pypi/azure-mgmt-resource>`_ >= 1.1.0 * `azure-mgmt-storage <https://pypi.python.org/pypi/azure-mgmt-storage>`_ >= 1.0.0 * `azure-mgmt-web <https://pypi.python.org/pypi/azure-mgmt-web>`_ >= 0.32.0 * `azure-storage <https://pypi.python.org/pypi/azure-storage>`_ >= 0.34.3 * `msrestazure <https://pypi.python.org/pypi/msrestazure>`_ >= 0.4.21 :platform: linux :configuration: This module requires Azure Resource Manager credentials to be passed as a dictionary of keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication parameters are sensitive, it's recommended to pass them to the states via pillar. Required provider parameters: if using username and password: * ``subscription_id`` * ``username`` * ``password`` if using a service principal: * ``subscription_id`` * ``tenant`` * ``client_id`` * ``secret`` Optional provider parameters: **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: Possible values: * ``AZURE_PUBLIC_CLOUD`` (default) * ``AZURE_CHINA_CLOUD`` * ``AZURE_US_GOV_CLOUD`` * ``AZURE_GERMAN_CLOUD`` Example Pillar for Azure Resource Manager authentication: .. code-block:: yaml azurearm: user_pass_auth: subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 username: fletch password: 123pass mysubscription: subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 tenant: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF client_id: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF secret: XXXXXXXXXXXXXXXXXXXXXXXX cloud_environment: AZURE_PUBLIC_CLOUD Example states using Azure Resource Manager authentication: .. code-block:: none {% set profile = salt['pillar.get']('azurearm:mysubscription') %} Ensure DNS zone exists: azurearm_dns.zone_present: - name: contoso.com - resource_group: my_rg - tags: how_awesome: very contact_name: Elmer Fudd Gantry - connection_auth: {{ profile }} Ensure DNS record set exists: azurearm_dns.record_set_present: - name: web - zone_name: contoso.com - resource_group: my_rg - record_type: A - ttl: 300 - arecords: - ipv4_address: 10.0.0.1 - tags: how_awesome: very contact_name: Elmer Fudd Gantry - connection_auth: {{ profile }} Ensure DNS record set is absent: azurearm_dns.record_set_absent: - name: web - zone_name: contoso.com - resource_group: my_rg - record_type: A - connection_auth: {{ profile }} Ensure DNS zone is absent: azurearm_dns.zone_absent: - name: contoso.com - resource_group: my_rg - connection_auth: {{ profile }} """ import logging from functools import wraps import salt.utils.azurearm __virtualname__ = "azurearm_dns" log = logging.getLogger(__name__) def __virtual__(): """ Only make this state available if the azurearm_dns module is available. """ if "azurearm_dns.zones_list_by_resource_group" in __salt__: return __virtualname__ return (False, "azurearm_dns module could not be loaded") def _deprecation_message(function): """ Decorator wrapper to warn about azurearm deprecation """ @wraps(function) def wrapped(*args, **kwargs): salt.utils.versions.warn_until( "Chlorine", "The 'azurearm' functionality in Salt has been deprecated and its " "functionality will be removed in version 3007 in favor of the " "saltext.azurerm Salt Extension. " "(https://github.com/salt-extensions/saltext-azurerm)", category=FutureWarning, ) ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) return ret return wrapped @_deprecation_message def zone_present( name, resource_group, etag=None, if_match=None, if_none_match=None, registration_virtual_networks=None, resolution_virtual_networks=None, tags=None, zone_type="Public", connection_auth=None, **kwargs, ): """ .. versionadded:: 3000 Ensure a DNS zone exists. :param name: Name of the DNS zone (without a terminating dot). :param resource_group: The resource group assigned to the DNS zone. :param etag: The etag of the zone. `Etags <https://docs.microsoft.com/en-us/azure/dns/dns-zones-records#etags>`_ are used to handle concurrent changes to the same resource safely. :param if_match: The etag of the DNS zone. Omit this value to always overwrite the current zone. Specify the last-seen etag value to prevent accidentally overwritting any concurrent changes. :param if_none_match: Set to '*' to allow a new DNS zone to be created, but to prevent updating an existing zone. Other values will be ignored. :param registration_virtual_networks: A list of references to virtual networks that register hostnames in this DNS zone. This is only when zone_type is Private. (requires `azure-mgmt-dns <https://pypi.python.org/pypi/azure-mgmt-dns>`_ >= 2.0.0rc1) :param resolution_virtual_networks: A list of references to virtual networks that resolve records in this DNS zone. This is only when zone_type is Private. (requires `azure-mgmt-dns <https://pypi.python.org/pypi/azure-mgmt-dns>`_ >= 2.0.0rc1) :param tags: A dictionary of strings can be passed as tag metadata to the DNS zone object. :param zone_type: The type of this DNS zone (Public or Private). Possible values include: 'Public', 'Private'. Default value: 'Public' (requires `azure-mgmt-dns <https://pypi.python.org/pypi/azure-mgmt-dns>`_ >= 2.0.0rc1) :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. Example usage: .. code-block:: yaml Ensure DNS zone exists: azurearm_dns.zone_present: - name: contoso.com - resource_group: my_rg - zone_type: Private - registration_virtual_networks: - /subscriptions/{{ sub }}/resourceGroups/my_rg/providers/Microsoft.Network/virtualNetworks/test_vnet - tags: how_awesome: very contact_name: Elmer Fudd Gantry - connection_auth: {{ profile }} """ ret = {"name": name, "result": False, "comment": "", "changes": {}} if not isinstance(connection_auth, dict): ret["comment"] = ( "Connection information must be specified via connection_auth dictionary!" ) return ret zone = __salt__["azurearm_dns.zone_get"]( name, resource_group, azurearm_log_level="info", **connection_auth ) if "error" not in zone: tag_changes = __utils__["dictdiffer.deep_diff"]( zone.get("tags", {}), tags or {} ) if tag_changes: ret["changes"]["tags"] = tag_changes # The zone_type parameter is only accessible in azure-mgmt-dns >=2.0.0rc1 if zone.get("zone_type"): if zone.get("zone_type").lower() != zone_type.lower(): ret["changes"]["zone_type"] = { "old": zone["zone_type"], "new": zone_type, } if zone_type.lower() == "private": # The registration_virtual_networks parameter is only accessible in azure-mgmt-dns >=2.0.0rc1 if registration_virtual_networks and not isinstance( registration_virtual_networks, list ): ret["comment"] = ( "registration_virtual_networks must be supplied as a list of" " VNET ID paths!" ) return ret reg_vnets = zone.get("registration_virtual_networks", []) remote_reg_vnets = sorted( vnet["id"].lower() for vnet in reg_vnets if "id" in vnet ) local_reg_vnets = sorted( vnet.lower() for vnet in registration_virtual_networks or [] ) if local_reg_vnets != remote_reg_vnets: ret["changes"]["registration_virtual_networks"] = { "old": remote_reg_vnets, "new": local_reg_vnets, } # The resolution_virtual_networks parameter is only accessible in azure-mgmt-dns >=2.0.0rc1 if resolution_virtual_networks and not isinstance( resolution_virtual_networks, list ): ret["comment"] = ( "resolution_virtual_networks must be supplied as a list of VNET" " ID paths!" ) return ret res_vnets = zone.get("resolution_virtual_networks", []) remote_res_vnets = sorted( vnet["id"].lower() for vnet in res_vnets if "id" in vnet ) local_res_vnets = sorted( vnet.lower() for vnet in resolution_virtual_networks or [] ) if local_res_vnets != remote_res_vnets: ret["changes"]["resolution_virtual_networks"] = { "old": remote_res_vnets, "new": local_res_vnets, } if not ret["changes"]: ret["result"] = True ret["comment"] = f"DNS zone {name} is already present." return ret if __opts__["test"]: ret["result"] = None ret["comment"] = f"DNS zone {name} would be updated." return ret else: ret["changes"] = { "old": {}, "new": { "name": name, "resource_group": resource_group, "etag": etag, "registration_virtual_networks": registration_virtual_networks, "resolution_virtual_networks": resolution_virtual_networks, "tags": tags, "zone_type": zone_type, }, } if __opts__["test"]: ret["comment"] = f"DNS zone {name} would be created." ret["result"] = None return ret zone_kwargs = kwargs.copy() zone_kwargs.update(connection_auth) zone = __salt__["azurearm_dns.zone_create_or_update"]( name=name, resource_group=resource_group, etag=etag, if_match=if_match, if_none_match=if_none_match, registration_virtual_networks=registration_virtual_networks, resolution_virtual_networks=resolution_virtual_networks, tags=tags, zone_type=zone_type, **zone_kwargs, ) if "error" not in zone: ret["result"] = True ret["comment"] = f"DNS zone {name} has been created." return ret ret["comment"] = "Failed to create DNS zone {}! ({})".format( name, zone.get("error") ) return ret @_deprecation_message def zone_absent(name, resource_group, connection_auth=None): """ .. versionadded:: 3000 Ensure a DNS zone does not exist in the resource group. :param name: Name of the DNS zone. :param resource_group: The resource group assigned to the DNS zone. :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. """ ret = {"name": name, "result": False, "comment": "", "changes": {}} if not isinstance(connection_auth, dict): ret["comment"] = ( "Connection information must be specified via connection_auth dictionary!" ) return ret zone = __salt__["azurearm_dns.zone_get"]( name, resource_group, azurearm_log_level="info", **connection_auth ) if "error" in zone: ret["result"] = True ret["comment"] = f"DNS zone {name} was not found." return ret elif __opts__["test"]: ret["comment"] = f"DNS zone {name} would be deleted." ret["result"] = None ret["changes"] = { "old": zone, "new": {}, } return ret deleted = __salt__["azurearm_dns.zone_delete"]( name, resource_group, **connection_auth ) if deleted: ret["result"] = True ret["comment"] = f"DNS zone {name} has been deleted." ret["changes"] = {"old": zone, "new": {}} return ret ret["comment"] = f"Failed to delete DNS zone {name}!" return ret @_deprecation_message def record_set_present( name, zone_name, resource_group, record_type, if_match=None, if_none_match=None, etag=None, metadata=None, ttl=None, arecords=None, aaaa_records=None, mx_records=None, ns_records=None, ptr_records=None, srv_records=None, txt_records=None, cname_record=None, soa_record=None, caa_records=None, connection_auth=None, **kwargs, ): """ .. versionadded:: 3000 Ensure a record set exists in a DNS zone. :param name: The name of the record set, relative to the name of the zone. :param zone_name: Name of the DNS zone (without a terminating dot). :param resource_group: The resource group assigned to the DNS zone. :param record_type: The type of DNS record in this record set. Record sets of type SOA can be updated but not created (they are created when the DNS zone is created). Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' :param if_match: The etag of the record set. Omit this value to always overwrite the current record set. Specify the last-seen etag value to prevent accidentally overwritting any concurrent changes. :param if_none_match: Set to '*' to allow a new record set to be created, but to prevent updating an existing record set. Other values will be ignored. :param etag: The etag of the record set. `Etags <https://docs.microsoft.com/en-us/azure/dns/dns-zones-records#etags>`__ are used to handle concurrent changes to the same resource safely. :param metadata: A dictionary of strings can be passed as tag metadata to the record set object. :param ttl: The TTL (time-to-live) of the records in the record set. Required when specifying record information. :param arecords: The list of A records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.arecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param aaaa_records: The list of AAAA records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.aaaarecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param mx_records: The list of MX records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.mxrecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param ns_records: The list of NS records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.nsrecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param ptr_records: The list of PTR records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.ptrrecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param srv_records: The list of SRV records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.srvrecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param txt_records: The list of TXT records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.txtrecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param cname_record: The CNAME record in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.cnamerecord?view=azure-python>`__ to create a dictionary representing the record object. :param soa_record: The SOA record in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.soarecord?view=azure-python>`__ to create a dictionary representing the record object. :param caa_records: The list of CAA records in the record set. View the `Azure SDK documentation <https://docs.microsoft.com/en-us/python/api/azure.mgmt.dns.models.caarecord?view=azure-python>`__ to create a list of dictionaries representing the record objects. :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. Example usage: .. code-block:: yaml Ensure record set exists: azurearm_dns.record_set_present: - name: web - zone_name: contoso.com - resource_group: my_rg - record_type: A - ttl: 300 - arecords: - ipv4_address: 10.0.0.1 - metadata: how_awesome: very contact_name: Elmer Fudd Gantry - connection_auth: {{ profile }} """ ret = {"name": name, "result": False, "comment": "", "changes": {}} record_vars = [ "arecords", "aaaa_records", "mx_records", "ns_records", "ptr_records", "srv_records", "txt_records", "cname_record", "soa_record", "caa_records", ] if not isinstance(connection_auth, dict): ret["comment"] = ( "Connection information must be specified via connection_auth dictionary!" ) return ret rec_set = __salt__["azurearm_dns.record_set_get"]( name, zone_name, resource_group, record_type, azurearm_log_level="info", **connection_auth, ) if "error" not in rec_set: metadata_changes = __utils__["dictdiffer.deep_diff"]( rec_set.get("metadata", {}), metadata or {} ) if metadata_changes: ret["changes"]["metadata"] = metadata_changes for record_str in record_vars: # pylint: disable=eval-used record = eval(record_str) if record: if not ttl: ret["comment"] = ( "TTL is required when specifying record information!" ) return ret if not rec_set.get(record_str): ret["changes"] = {"new": {record_str: record}} continue if record_str[-1] != "s": if not isinstance(record, dict): ret["comment"] = ( "{} record information must be specified as a dictionary!".format( record_str ) ) return ret for k, v in record.items(): if v != rec_set[record_str].get(k): ret["changes"] = {"new": {record_str: record}} elif record_str[-1] == "s": if not isinstance(record, list): ret["comment"] = ( "{} record information must be specified as a list of" " dictionaries!".format(record_str) ) return ret local, remote = ( sorted(config) for config in (record, rec_set[record_str]) ) for val in local: for key in val: local_val = val[key] remote_val = remote.get(key) if isinstance(local_val, str): local_val = local_val.lower() if isinstance(remote_val, str): remote_val = remote_val.lower() if local_val != remote_val: ret["changes"] = {"new": {record_str: record}} if not ret["changes"]: ret["result"] = True ret["comment"] = f"Record set {name} is already present." return ret if __opts__["test"]: ret["result"] = None ret["comment"] = f"Record set {name} would be updated." return ret else: ret["changes"] = { "old": {}, "new": { "name": name, "zone_name": zone_name, "resource_group": resource_group, "record_type": record_type, "etag": etag, "metadata": metadata, "ttl": ttl, }, } for record in record_vars: # pylint: disable=eval-used if eval(record): # pylint: disable=eval-used ret["changes"]["new"][record] = eval(record) if __opts__["test"]: ret["comment"] = f"Record set {name} would be created." ret["result"] = None return ret rec_set_kwargs = kwargs.copy() rec_set_kwargs.update(connection_auth) rec_set = __salt__["azurearm_dns.record_set_create_or_update"]( name=name, zone_name=zone_name, resource_group=resource_group, record_type=record_type, if_match=if_match, if_none_match=if_none_match, etag=etag, ttl=ttl, metadata=metadata, arecords=arecords, aaaa_records=aaaa_records, mx_records=mx_records, ns_records=ns_records, ptr_records=ptr_records, srv_records=srv_records, txt_records=txt_records, cname_record=cname_record, soa_record=soa_record, caa_records=caa_records, **rec_set_kwargs, ) if "error" not in rec_set: ret["result"] = True ret["comment"] = f"Record set {name} has been created." return ret ret["comment"] = "Failed to create record set {}! ({})".format( name, rec_set.get("error") ) return ret @_deprecation_message def record_set_absent(name, zone_name, resource_group, connection_auth=None): """ .. versionadded:: 3000 Ensure a record set does not exist in the DNS zone. :param name: Name of the record set. :param zone_name: Name of the DNS zone. :param resource_group: The resource group assigned to the DNS zone. :param connection_auth: A dict with subscription and authentication parameters to be used in connecting to the Azure Resource Manager API. """ ret = {"name": name, "result": False, "comment": "", "changes": {}} if not isinstance(connection_auth, dict): ret["comment"] = ( "Connection information must be specified via connection_auth dictionary!" ) return ret rec_set = __salt__["azurearm_dns.record_set_get"]( name, zone_name, resource_group, azurearm_log_level="info", **connection_auth ) if "error" in rec_set: ret["result"] = True ret["comment"] = "Record set {} was not found in zone {}.".format( name, zone_name ) return ret elif __opts__["test"]: ret["comment"] = f"Record set {name} would be deleted." ret["result"] = None ret["changes"] = { "old": rec_set, "new": {}, } return ret deleted = __salt__["azurearm_dns.record_set_delete"]( name, zone_name, resource_group, **connection_auth ) if deleted: ret["result"] = True ret["comment"] = f"Record set {name} has been deleted." ret["changes"] = {"old": rec_set, "new": {}} return ret ret["comment"] = f"Failed to delete record set {name}!" return ret