← back to Cf Dns Migration

__pycache__/stage.cpython-314.pyc

95 lines

+
hj�(��*�Rt^RIt^RIt^RIt^RIt^RIt^RIt]PPR4t
Rt]!]
4t]PR4t]PR4t]PR4t]'dR]2MR]R	]2t]PR
4;'g+]PR4;'g]PR4t0RmtR
0tRRltRRltRtRR]2RR/tRtRtRtRtRtRtR RltRt ]!R8Xd
] !4R#R#)!u�
Phase-2 CF-DNS staging engine.

For each domain: read its LIVE records from GoDaddy, ensure a Cloudflare zone
exists, and replicate the records into that zone idempotently. NOTHING cuts over
here — the domain keeps its GoDaddy nameservers until a human does the NS-swap,
so a staged CF zone is dormant/safe. The point is that when the swap happens the
zone is already a faithful copy, so there's zero downtime.

  python3 stage.py --dry-run homesonspec.com          # show what would happen
  python3 stage.py homesonspec.com foo.com            # stage specific domains
  python3 stage.py --from worklist.csv --limit 5      # stage first 5 from worklist
  python3 stage.py --from worklist.csv                # stage the whole worklist

Records are replicated DNS-only (grey cloud) to mirror GoDaddy exactly; enable
the CF proxy per-site later if wanted. NS/SOA and GoDaddy-proprietary
`_domainconnect` records are never copied.
Nz~/Projects/secrets-manager/.envc�P�/p\VRRR7F�pVP4pV'gKVPR4'dK6RV9gK?VPR^4wr4VP4PR4PR4WP4&K�	V#)zutf-8�ignore)�encoding�errors�#�=�"�')�open�strip�
startswith�split)�path�e�line�k�vs&    �4/Users/macstudio3/Projects/cf-dns-migration/stage.py�load_envrs~��
�A��T�G�H�=���z�z�|���4�����,�,�����:�:�c�1�%�D�A��7�7�9�?�?�3�/�5�5�c�:�A�g�g�i�L�	>�

�H��GODADDY_API_KEY�GODADDY_API_SECRET�GODADDY_PATzBearer zsso-key �:�CLOUDFLARE_API_TOKEN�CF_API_TOKEN�CLOUDFLARE_DNS_TOKEN�_domainconnectc�0�Ve%\P!V4P4MRp\PPYY;'g/R7p\PP
V^R7;_uu_4pVP\P!VP4P443uuRRR4# +'giR#;i \PPdxpTP\P!TP4P443uRp?# \d"TPR\T4/3uuRp?#i;iRp?i\dp^R\T4/3uRp?#Rp?ii;i)N)�data�method�headers)�timeout�error)�json�dumps�encode�urllib�request�Request�urlopen�status�loads�read�decoder#�	HTTPError�code�	Exception�str)�urlr r!�bodyr�r�resp�exs&&&&    r�reqr8)s��(,�(8�4�:�:�d��"�"�$�d�D������s�f�m�m�QS��T�A�%�
�^�^�
#�
#�A�r�
#�
2�
2�d��;�;��
�
�4�9�9�;�+=�+=�+?� @�@�3�
2�
2�
2���<�<�!�!�=��G�G�T�Z�Z����	�(8�(8�(:�;�;�
;���<����7�C��G�*<�!<�<�<���%��7�C��G�$�$�$��%�sr�)C�>C	�>
C�	C	�C�C�F�<=D?�9F�?$E+�#E.�$F�*E+�+E.�.F�;F�<F�
F�Fc	�b�\V4EFp\RVR2R\/R7wr4V^�8Xd\V\4'dVu#VR8Xg4V^8Xg-\V\
4'dzVP
R4R8Xdd^p\V\
4'd\VP
R^44p\P!\V^V^,,44K�\V\4'dVu#\P!R	4EK	.# \d^pLvi;i)
u�Read with backoff — GoDaddy throttles ~60 req/min and returns 429; the
earlier run's 135 'no records' were false empties from being throttled.z#https://api.godaddy.com/v1/domains/z/records�
Authorization�r!i�r0�TOO_MANY_REQUESTS�
retryAfterSecg�?)�ranger8�GD_AUTH�
isinstance�list�dict�get�intr1�time�sleep�max)�domain�tries�i�st�d�waits&&    r�
gd_recordsrN6s����5�\���9�&���J�,�g�6�8���
��9��A�t�,�,��H�
��9��a��J�q�$�$7�$7�A�E�E�&�M�M`�<`��D��!�T�"�"�����o�q� 9�:�T��J�J�s�4��a�!�e��-�.���a�����H��
�
�3����I��
!�*��$�*�s�D�
D.�-D.c���\V4PR4p\V4^8H;'d5\;QJdRV4F'dKR#	R#!RV44#)�.c3�"�TF;qP4;'d ^\V4u;8*;'d^�8*Mux�K=	R#5i)�N)�isdigitrD)�.0�xs& r�	<genexpr>�is_ipv4.<locals>.<genexpr>Ls0���M�1�a�y�y�{�A�A�q�C��F�/A�/A�c�/A�A�1�s
�A�(AFT)r2r
�len�all)�s�ps& r�is_ipv4r\JsM���A����S��A��q�6�Q�;�M�M�3�3�M�1�M�3�3�M�3�M�3�M�1�M�M�Mrr:zContent-Typezapplication/jsonc��\RV2\R7wrVPR4;'g.pV'd
V^,#R#)z0https://api.cloudflare.com/client/v4/zones?name=r;�resultN�r8�CF_HrC)rH�_rL�ress&   r�cf_zonercPs?���A�&��J�TX�Y�D�A�
�%�%��/�
�
�R�C��3�q�6�"�d�"rc	��\RR\RVRR/4wrVPR4'dVPR4#R#)z*https://api.cloudflare.com/client/v4/zones�POST�name�type�full�successr^Nr_)rHrarLs&  r�cf_create_zonerjTsB���;�V�T�����/�1�D�A��e�e�I�.�.�1�5�5��?�8�D�8rc��.^r!\RVRV2\R7wr4VPR4;'g.pW,
p\V4^d8dV#V^,
pK[)��+https://api.cloudflare.com/client/v4/zones/z/dns_records?per_page=100&page=r;r^)r8r`rCrX)�zid�out�pagerarLrbs&     r�
cf_recordsrqXse���A��
��@���Ed�ei�dj�k�uy�z����e�e�H�o�#�#����
���s�8�c�>�5��J�	
��	�rc�.�\RVR2R\V4#)rmz/dns_recordsre)r8r`)rn�recs&&r�cf_addrtas ���<�S�E��N�PV�X\�^a�b�brc�r�VPR4pVPRR4pVR9gV\9gVR9dR#VR8XdTMVR	V2pVPR
R4pVR8Xd
VR9dTpVR8Xd\V4'gR#VR8XdR\V49dR#RTRTR
TR\	\VPRR4;'gR4^<4RR/pVR8Xd;\VPR^
4;'g^
4VR&VP
RR4VR9dVP
RR4V#)zJMap a GoDaddy record to a Cloudflare dns_records payload, or None to skip.rgrf�@�A�AAAA�CNAME�MXNrPr�r�content�ttliX�proxiedF�priority)�NS�SOA�SRV)rwrxryrz�TXT�CAA)rvr{)r�r�r�)rC�
SKIP_NAMESr\r2rGrD�pop)rHr5�trf�fqdnrrss&&     r�gd_to_cfr�ds,��	���f�
�A��5�5����D�	� � �D�J�$6�!�Ch�:h���S�[�6���a��x�&8�D��5�5����D��G�|��	�)����C�x���
�
�d��F�{�s�#�d�)�+�D��1�f�d�I�t�U�C��A�E�E�%�QT�DU�D\�D\�Y\�@]�_a�<b�dm�ot�
u�C��D�y��a�e�e�J��3�9�9�r�:��J�����	�4� ��!�!����	�4� ��Jrc�t�WPR4\V4P4PR43#)rPr)�rstripr2r)r�rfr|s&&&r�rec_keyr�{s.��
�{�{�3���W��!3�!3�!5�!;�!;�C�!@�A�Arc�
�\V4pV'g
RVRRR^R^RR/#\V4pRpV'g2V'd	RR	R
R./pM!\V4pRpV'g
RVRR
R^R^RR/#VR,pVR	8Xd.M
\V4pVUu0uF.p\	VR,VR,VPRR44kK0	pp/p	\
4\
4r�VF�pVR,PR4pV	PV\
44PVR,4\VPRR44PR4P4p
VR,R8Xd)V
PR4'dV
PV4VR,R8XgK�V
PR4'gK�VPV4K�	^;r�VEFp\W4pV'gKVR,PR4p\VR,4PR4P4p
V	PV\
44pVR,R8XdV'dV^,
pK�VR,R8wdRV9dV^,
pK�VR,R8Xd)V
PR4'dW�9dV^,
pK�VR,R8Xd*V
PR4'dW�9d
V^,
pEK(\	VR,VR,VR,4pVV9d
V^,
pEK]V	PV\
44PVR,4VPV4VR,R8Xd)V
PR4'dV
PV4VR,R8Xd)V
PR4'dVPV4V'dF\RVR,R
RVR,R
R\VR,4R,24V^,
pM�\!VV4wppVPR4'dV^,
pMxVPR.4p\";QJdRV4F'gKRM	RM
!RV44'dV^,
pM"\R VR,RVR,R!V24\$P&!R"4EK	R#P)VPR
.4;'g.4pRTRV'gR$V'dR%MR,MR&RVRVRVR'V/#uupi)(rHr+zno-godaddy-records�added�existing�nsr{F�idz(would-create)�name_serversz(assigned-on-create)Tzcf-zone-create-failedrgrfr|rPrr�zv=dmarc1zv=spf1ryz    + �6� �34z -> :N�.Nrirc3�Z"�TF!pR\V4P49x�K#	R#5i)zalready existsN)r2�lower)rTrs& rrV�stage.<locals>.<genexpr>�s ���H�4�a�'�3�q�6�<�<�>�9�4�s�)+z    ! z: g�������?�,�stagedz+created�dry�zone_id)rNrcrjrqr�rC�setr��
setdefault�addr2rr�rr��printrt�anyrErF�join)rHr��gd�zone�createdrnr�r5�have�types_at�dmarc_at�spf_at�nm�cr��kept�payload�hererr0r6�errsr�s&&                     r�stager�~sj��	�F�	�B�
��&�(�,@�'�1�j�Z[�]a�ce�f�f��6�?�D��G����*�N�=S�<T�U�D�!�&�)�D��G�� �&�(�4K�W�VW�Yc�ef�hl�np�q�q�
�t�*�C��,�,�r�*�S�/�H�IQ�R��A�G�A�f�I�q��y�!�%�%�	�2�*>�?��D�R��H��u�c�e�f�
��
�v�Y�
�
�c�
"�����B���&�*�*�1�V�9�5�����i��$�%�+�+�C�0�6�6�8���V�9���!�,�,�z�":�":�H�L�L��<L��V�9���!�,�,�x�"8�"8�&�*�*�R�.����E�
���6�%����
�V�_�
#�
#�C�
(��c�'�)�2D�.E�.K�.K�C�.P�.V�.V�.X�!��|�|�B���&���6�?�g�%�$���	��8��6�?�g�%�'�T�/�4�1�9�4�h��6�?�e�#����Z�(@�(@�R�^�UY�]^�U^�UY�`h��6�?�e�#����X�(>�(>�2�<�QU�YZ�QZ�QU�\d��G�F�O�W�V�_�g�i�6H�I����9��A�I�D�x����B���&�*�*�7�6�?�;�T�X�X�a�[��6�?�e�#����Z�(@�(@�(�,�,�r�BR��6�?�e�#����X�(>�(>��
�
�2����F�7�6�?�1�-�Q�w�v��r�.B�$�s�7�S\�K]�G^�_b�Gc�Fd�e�f��Q�J�E���W�-�J�D�$��x�x�	�"�"�E�Q�J�E��x�x��"�-���3�H�4�H�3�3�3�H�4�H�H�H�$�RS�)�$��f�W�V�_�$5�Q�w�v��6G�r�$��P�Q��
�
�4��9�:

���$�(�(�>�2�.�4�4�"�	5�B��f�h�\_��7�Z�PR�)S�ej��U�J��d�B�	�3�H�H��SSs�4T>c
���\PR,pRV9qUu.uF
q"R8wgKVNK	ppRp.p^pV\V48d�W,R8Xd#\W^,,4q5^,
pK?W,R8XdU^RIpVP\
W^,,44FqtPVR,4K	V^,
pK�VPW,4V^,
pK�V'dVRVpV'g"\R4\P!^4\'d\'d
\'g"\R4\P!^4\V'dRMR	R
\V4R24.pVF�p	\RV	2R
R7\W�4p
VPV
4\RV
R,RV
R,RV
R,R2V
R,'d
RV
R,2MR,R
R7\P!R4K�	RpV'g�^RIp\
VRRR7;_uu_4pVP!V4q�P#.RO4VF3q�P#VR,VR,VR,VR,.4K5	RRR4\RVR24R#R#uupi +'giL(;i) :rlNNz	--dry-runNz--limitz--fromrHzJusage: stage.py [--dry-run] [--from worklist.csv] [--limit N] [domain ...]z<missing creds (GODADDY_API_KEY/SECRET, CLOUDFLARE_API_TOKEN)zDRY-RUN�STAGINGr�z domain(s)
u── T)�flushz   r+z: +r�z new, r�z already presentr�z | NS: r{gffffff�?zstaged-nameservers.csv�w)�newlineu
NS-swap worklist → z> (set each domain's GoDaddy nameservers to its cf_nameservers))rHr+r��cf_nameservers)�sys�argvrXrD�csv�
DictReaderr
�appendr��exit�GD_KEY�GD_SEC�CF_TOKENr�rErF�writer�writerow)�argsr��a�limit�domainsrJr��row�resultsrLrbro�fr�r5s               r�mainr��sA���8�8�B�<�D�
��
�C�$�&K�$�Q�{�:J�q�q�$�t�&K��E�B�'�	�A�
�c�$�i�-��7�i���T�A�#�Y���a���
�W��
 ���~�~�d�4�!��9�o�6����s�8�}�8U�6�
��F�A��n�n�T�W�%�q�A�v�q������g��
�Z�[�]`�]e�]e�fg�]h��F�v�v�(�(�
�L�M�s�x�x�XY�{�	�#�Y�9�-�Q�s�7�|�n�L�
I�J��G�
��
���s�m�4�(��A�m�����s��
��C��M�?�#�c�'�l�^�6�#�j�/�9J�JZ�[�*-�d�)�)�7�3�t�9�+�&��=�DH�	J��
�
�3��
�#�C���
�#�s�B�
'�
'�1��
�
�1�
�A�z�z�*Y�Z���j�j�!�H�+�q��{�A�g�J�PQ�RV�PW�)X�Y�W�(�	�'��u�,j�k�l���5'L�8(�
'�s�K�K�AK�K(	�__main__>rwrzr�r�r�rxry�NS_SUB)�GETNN)�)F)"�__doc__r$�osr�rE�urllib.requestr'�urllib.errorr�
expanduser�ENVr�ErCr�r��GD_PATr?r��
COPY_TYPESr�r8rNr\r`rcrjrqrtr�r�r�r��__name__�rr�<module>r�s+���$9�8�8��g�g���:�;��
�
�S�M��	
��� �	!��A�E�E�2F�,G�6�	
���}�	�� &�G�F�8�
�h�v�h�a��x�,H���5�5�'�(�b�b�A�E�E�.�,A�b�b�Q�U�U�Ka�Eb��
H�
��
�
�
%��(N�
	�7�8�*�-�~�?Q�R��#�9��c��.B�:H�x!m�F�z���F�r