Last active
April 10, 2018 15:54
-
-
Save gtmanfred/b2691c1d53a61b374f0a5d4cefa10e65 to your computer and use it in GitHub Desktop.
save ip of server to DO api if dhcp changes it for some reason
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import aiocron | |
import aiohttp | |
import asyncio | |
import fcntl | |
import json | |
import logging | |
import os | |
import socket | |
import struct | |
ENDPOINT = 'https://api.digitalocean.com/v2/' | |
TOKEN = '<DO token>' | |
INTERFACE = '<interface with ip>' | |
NAME = '<name for record>' | |
DOMAIN = '<domain for record>' | |
# Public ip or Private ip | |
# Public ip queries icanhazip.com | |
# Private ip looks for the first ip address on the INTERFACE | |
NETWORK_TYPE = '<public/private' | |
logging.basicConfig(level=logging.INFO) | |
log = logging.getLogger(__name__) | |
async def get_private_address(): | |
loop = asyncio.get_event_loop() | |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
fn_ = await loop.run_in_executor( | |
None, | |
fcntl.ioctl, | |
s.fileno(), | |
0x8915, # SIOCGIFADDR | |
struct.pack('256s', INTERFACE[:15].encode()) | |
) | |
return await loop.run_in_executor(None, socket.inet_ntoa, fn_[20:24]) | |
async def get_public_address(): | |
async with aiohttp.ClientSession() as session: | |
async with session.get('http://icanhazip.com') as resp: | |
data = await resp.text() | |
return data.strip() | |
get_ip_address = globals()[f'get_{NETWORK_TYPE}_address'] | |
async def api_call(path, payload=None, method='get'): | |
headers = {'Authorization': 'Bearer {0}'.format(TOKEN), | |
'Content-Type': 'application/json'} | |
kwargs = {'url': path} | |
if method in ('post', 'put'): | |
kwargs['json'] = payload | |
async with aiohttp.ClientSession(headers=headers) as session: | |
async with getattr(session, method)(**kwargs) as response: | |
response.raise_for_status() | |
return await response.json() | |
async def update(record_id): | |
payload = {'data': await get_ip_address()} | |
await api_call(os.path.join(ENDPOINT, 'domains', DOMAIN, 'records', f'{record_id}'), payload=payload, method='put') | |
async def create(): | |
payload = { | |
"type": "A", | |
"name": NAME, | |
"data": await get_ip_address(), | |
"priority": None, | |
"port": None, | |
"weight": None, | |
} | |
await api_call(os.path.join(ENDPOINT, 'domains', DOMAIN, 'records'), payload=payload, method='post') | |
@aiocron.crontab('* * * * *') | |
async def check(): | |
records = await api_call(os.path.join(ENDPOINT, 'domains', DOMAIN, 'records')) | |
for record in records['domain_records']: | |
if record['name'] == NAME: | |
if record['data'] == await get_ip_address(): | |
log.info('Current Record is correct.') | |
return | |
else: | |
log.info('Updating Record.') | |
await update(record['id']) | |
break | |
else: | |
log.info('Creating Record.') | |
await create() | |
if __name__ == '__main__': | |
log.info('Starting IO Loop') | |
asyncio.get_event_loop().run_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment