Add the good stuff
continuous-integration/drone/push Build is failing Details

This commit is contained in:
IamTheFij 2023-11-20 09:31:58 -08:00
parent bd093bb00f
commit 5f7d710404
5 changed files with 193 additions and 1 deletions

46
.drone.yml Normal file
View File

@ -0,0 +1,46 @@
---
kind: pipeline
name: publish
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps:
- name: Build and publish
image: woodpeckerci/plugin-docker-buildx
settings:
repo: iamthefij/unifi-traffic-routes
auto_tag: true
username:
from_secret: docker_username
password:
from_secret: docker_password
---
kind: pipeline
name: notify
depends_on:
- publish
trigger:
status:
- failure
steps:
- name: notify
image: drillster/drone-email
settings:
host:
from_secret: SMTP_HOST # pragma: whitelist secret
username:
from_secret: SMTP_USER # pragma: whitelist secret
password:
from_secret: SMTP_PASS # pragma: whitelist secret
from: drone@iamthefij.com

9
Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM python:3
COPY requirements.txt /src/
RUN pip install --no-cache-dir -r /src/requirements.txt
COPY main.py /src/
ENTRYPOINT ["/usr/local/bin/python"]
CMD ["/src/main.py"]

View File

@ -1,3 +1,16 @@
# unfifi-traffic-routes-domain-ip
Look up and set traffic route IPs based on domains for clients not using the UniFi DNS
## Configuration
Set the following as environment variables
| Variable | Description | Default |
| -------- | ----------- | ------- |
| `UNIFI_HOST` | Unifi network hostname | `192.168.1.1` |
| `UNIFI_PORT` | Unifi network port number | `443` |
| `UNIFI_USER` | Unifi username | |
| `UNIFI_PASS` | Unifi pass | |
The user must have access to Manage the Network application to update the Traffic Routes.

122
main.py Normal file
View File

@ -0,0 +1,122 @@
import asyncio
import logging
import os
import socket
from asyncio.timeouts import timeout
import aiohttp
import aiounifi
from aiounifi.controller import Controller
from aiounifi.models.configuration import Configuration
from aiounifi.models.traffic_route import IPAddress
from aiounifi.models.traffic_route import MatchingTarget
HOST = os.getenv("UNIFI_HOST", "192.168.1.1")
PORT = int(os.getenv("UNIFI_PORT", 443))
USERNAME = os.getenv("UNIFI_USER")
PASSWORD = os.getenv("UNIFI_PASSWORD")
LOGGER = logging.getLogger(__name__)
def get_configuration(session: aiohttp.ClientSession) -> Configuration:
return Configuration(
session,
HOST,
username=USERNAME,
password=PASSWORD,
port=PORT,
)
async def get_controller(config: Configuration) -> Controller | None:
controller = Controller(config)
try:
async with timeout(10):
await controller.login()
return controller
except aiounifi.LoginRequired:
LOGGER.error("Connected to UniFi at %s:%s but couldn't log in", config.host, config.port)
except aiounifi.Unauthorized:
LOGGER.error("Connected to UniFi at %s:%s but not registered", config.host, config.port)
except (asyncio.TimeoutError, aiounifi.RequestError):
LOGGER.exception("Error connecting to the UniFi controller at %s:%s", config.host, config.port)
except aiounifi.AiounifiException:
LOGGER.exception("Unknown UniFi communication error occurred")
return None
async def main():
session = aiohttp.ClientSession(cookie_jar=aiohttp.CookieJar(unsafe=True))
config = get_configuration(session)
controller = await get_controller(config)
if not controller:
LOGGER.error("Couldn't connect")
await session.close()
return
try:
await controller.initialize()
print("Initialized!!")
await controller.traffic_routes.update()
for item in controller.traffic_routes.values():
if item.domains and item.matching_target == MatchingTarget.IP:
print(item.description)
# Look up unique ip addresses
addresses = set()
for domain in item.domains:
print(domain["domain"])
addresses.update(
result[4][0]
for result in socket.getaddrinfo(
domain["domain"],
80,
type=socket.SOCK_STREAM,
proto=socket.IPPROTO_IP,
)
)
# Sort addresses by type and value
sorted_addresses = list(
sorted(
addresses, key=lambda a: f"{'ip4' if '.' in a else 'ip6'}-{a}"
)
)
print(sorted_addresses)
# Build addresses objects
ip_addresses = [
IPAddress(
ip_or_subnet=a,
ip_version="v4" if "." in a else "v6",
port_ranges=[],
ports=[],
)
for a in sorted_addresses
]
# Check for change
if ip_addresses == item.raw["ip_addresses"]:
print("already up to date")
continue
# Update while preserving current state
item.raw["ip_addresses"] = ip_addresses
result = await controller.traffic_routes.save(item)
print(result)
finally:
await session.close()
if __name__ == "__main__":
asyncio.run(main())

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
# aiounifi
git+https://github.com/ViViDboarder/aiounifi.git@traffic-routes