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
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