Compare commits

..

5 Commits

Author SHA1 Message Date
IamTheFij 650e2e488d Only build master
continuous-integration/drone/push Build is passing Details
2019-03-10 18:07:36 -07:00
IamTheFij ba60619521 Add drone pipeline
continuous-integration/drone/push Build is passing Details
2019-03-10 18:01:31 -07:00
IamTheFij 2944ffb8c8 Updated 2019-03-08 16:44:47 -08:00
IamTheFij 701027cc9c Total WIP 2019-03-08 21:25:08 +00:00
IamTheFij b7d77120b1 Add build-arg for base repo 2019-03-07 13:49:06 -08:00
8 changed files with 254 additions and 83 deletions

View File

@ -1,16 +1,19 @@
---
kind: pipeline kind: pipeline
name: linux-amd64 name: linux-amd64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps: steps:
- name: get qemu
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y make wget
- make build/qemu-x86_64-static
when:
branch:
- master
event:
- push
- tag
- name: build - name: build
image: plugins/docker image: plugins/docker
@ -22,20 +25,30 @@ steps:
from_secret: docker_username from_secret: docker_username
password: password:
from_secret: docker_password from_secret: docker_password
when:
branch:
- master
event:
- push
- tag
--- ---
kind: pipeline kind: pipeline
name: linux-arm name: linux-arm
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps: steps:
- name: get qemu
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y make wget
- make build/qemu-arm-static
when:
branch:
- master
event:
- push
- tag
- name: build - name: build
image: plugins/docker image: plugins/docker
@ -49,21 +62,31 @@ steps:
from_secret: docker_password from_secret: docker_password
build_args: build_args:
- ARCH=arm - ARCH=arm
- REPO=arm32v7 - REPO=arm32v6
when:
branch:
- master
event:
- push
- tag
--- ---
kind: pipeline kind: pipeline
name: linux-arm64 name: linux-arm64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps: steps:
- name: get qemu
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y make wget
- make build/qemu-aarch64-static
when:
branch:
- master
event:
- push
- tag
- name: build - name: build
image: plugins/docker image: plugins/docker
@ -78,6 +101,12 @@ steps:
build_args: build_args:
- ARCH=aarch64 - ARCH=aarch64
- REPO=arm64v8 - REPO=arm64v8
when:
branch:
- master
event:
- push
- tag
--- ---
kind: pipeline kind: pipeline
@ -88,14 +117,6 @@ depends_on:
- linux-arm - linux-arm
- linux-arm64 - linux-arm64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps: steps:
- name: publish manifest - name: publish manifest
image: plugins/manifest image: plugins/manifest
@ -107,3 +128,10 @@ steps:
from_secret: docker_username from_secret: docker_username
password: password:
from_secret: docker_password from_secret: docker_password
when:
branch:
- master
event:
- push
- tag

View File

@ -1,28 +1,19 @@
ARG REPO=library ARG REPO=library
FROM ${REPO}/python:3-alpine
FROM multiarch/qemu-user-static:4.2.0-2 as qemu-user-static
# Make sure a dummy x86_64 file exists so that the copy command doesn't error
# RUN touch /usr/bin/qemu-x86_64-fake
FROM ${REPO}/python:3.8-alpine
# Copy mutliarch file to run builds on x86_64
ARG ARCH=x86_64 ARG ARCH=x86_64
COPY --from=qemu-user-static /usr/bin/qemu-* /usr/bin/ COPY ./build/qemu-${ARCH}-static /usr/bin/
# COPY --from=qemu-user-static /usr/bin/qemu-${ARCH}-* /usr/bin/
RUN mkdir -p /src RUN mkdir -p /src
WORKDIR /src WORKDIR /src
# Get Cloudflare example script COPY ./requirements.txt ./
ENV CF_VERSION=2.6.0 RUN pip install -r ./requirements.txt
ADD https://raw.githubusercontent.com/cloudflare/python-cloudflare/$CF_VERSION/examples/example_update_dynamic_dns.py ./update_ddns.py
RUN chmod +rx ./update_ddns.py
RUN python -m pip install --no-cache-dir cloudflare==$CF_VERSION COPY ./start.sh ./
COPY ./update_ddns.py ./update_ddns.py
ENV DOMAIN="" ENV DOMAIN=""
USER nobody CMD [ "/src/start.sh" ]
ENTRYPOINT [ "/src/update_ddns.py" ]

View File

@ -1,5 +1,4 @@
DOCKER_TAG ?= cloudflare-ddns-dev-${USER} DOCKER_TAG ?= cloudflare-ddns-dev-${USER}
.PHONY: clean
.PHONY: default .PHONY: default
default: test default: test
@ -8,25 +7,35 @@ default: test
test: test:
@echo ok @echo ok
.PHONY: update
update:
curl -o update_ddns.py https://raw.githubusercontent.com/cloudflare/python-cloudflare/master/examples/example_update_dynamic_dns.py
chmod +x update_ddns.py
.PHONY: build .PHONY: build
build: build: build/qemu-x86_64-static
docker build . -t ${DOCKER_TAG} docker build . -t ${DOCKER_TAG}
build/qemu-arm-static:
./get_qemu.sh arm
build/qemu-x86_64-static:
./get_qemu.sh x86_64
build/qemu-aarch64-static:
./get_qemu.sh aarch64
.PHONY: cross-build-arm .PHONY: cross-build-arm
cross-build-arm: cross-build-arm: build/qemu-arm-static
docker build --build-arg REPO=arm32v7 --build-arg ARCH=arm . -t ${DOCKER_TAG}-linux-arm docker build --build-arg REPO=arm32v6 --build-arg ARCH=arm . -t ${DOCKER_TAG}-linux-arm
.PHONY: cross-build-arm64 .PHONY: cross-build-arm
cross-build-arm64: cross-build-arm64: build/qemu-aarch64-static
docker build --build-arg REPO=arm64v8 --build-arg ARCH=aarch64 . -t ${DOCKER_TAG}-linux-arm64 docker build --build-arg REPO=arm64v8 --build-arg ARCH=aarch64 . -t ${DOCKER_TAG}-linux-arm64
.PHONY: all
all: build cross-build-arm cross-build-arm64
.PHONY: run .PHONY: run
run: build run: build
docker run --rm \ docker run --rm -e DOMAIN=${DOMAIN} \
-e CF_API_EMAIL=${CF_API_EMAIL} \ -e CF_API_EMAIL=${CF_API_EMAIL} \
-e CF_API_KEY=${CF_API_KEY} \ -e CF_API_KEY=${CF_API_KEY} \
${DOCKER_TAG} \ ${DOCKER_TAG}
"${DOMAIN}"

View File

@ -1,34 +1,21 @@
# Docker Cloudfare DDNS # Docker Cloudfare DDNS
Simple Docker image that wraps an example script to dynamically update a Cloudflare DNS record. Simple Docker image to dynamically update a Cloudflare DNS record.
## Usage ## Usage
There are two things to configure. First, the domain that you wish to update needs to be provided as a command line argument. This can be done by adding it to the end of your run command (example in the Makefile) or by adding it as a command to your compose file. Eg: All parameters are passed to the script using env variables, so export the following:
ddns: DOMAIN=sub.example.com
image: IamTheFij/cloudflare-ddns CF_API_EMAIL=admin@example.com
command: ["example.com"]
Your Cloudflare credentials can be passed in any way that [python-cloudflare](https://github.com/cloudflare/python-cloudflare) allows. Generally, either via envioronment variables:
CF_API_EMAIL=admin@example.com # Do not set if using an API Token
CF_API_KEY=00000000000000000000 CF_API_KEY=00000000000000000000
CF_API_CERTKEY='v1.0-...'
Or by providing a file mounted to the working directory in the image, `/src/.cloudflare.cfg` that contains something like:
[CloudFlare]
emal = admin@example.com # Do not set if using an API Token
token = 00000000000000000000
certtoken = v1.0-...
Then run. To execute from this directory, you can use the convenient Make target. Then run. To execute from this directory, you can use the convenient Make target.
make run make run
## Source ## Development
Original source: https://git.iamthefij.com/iamthefij/docker-cloudflare-ddns The script is straight from the examples provided by Cloudflare on their Github. The latest version can be downloaded using:
Github mirror: https://github.com/iamthefij/docker-cloudflare-ddns make update

13
get_qemu.sh Executable file
View File

@ -0,0 +1,13 @@
#! /bin/bash
HOST_ARCH=x86_64
VERSION=v2.9.1-1
mkdir -p build
cd build
for target_arch in $*; do
wget -N https://github.com/multiarch/qemu-user-static/releases/download/$VERSION/${HOST_ARCH}_qemu-${target_arch}-static.tar.gz
tar -xvf ${HOST_ARCH}_qemu-${target_arch}-static.tar.gz
rm ${HOST_ARCH}_qemu-${target_arch}-static.tar.gz
done

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
cloudflare

3
start.sh Executable file
View File

@ -0,0 +1,3 @@
#! /bin/bash
exec /src/update_ddns.py $DOMAIN

139
update_ddns.py Executable file
View File

@ -0,0 +1,139 @@
#!/usr/bin/env python
"""Cloudflare API code - example"""
from __future__ import print_function
import os
import sys
import re
import json
import requests
sys.path.insert(0, os.path.abspath('..'))
import CloudFlare
def my_ip_address():
"""Cloudflare API code - example"""
# This list is adjustable - plus some v6 enabled services are needed
# url = 'http://myip.dnsomatic.com'
# url = 'http://www.trackip.net/ip'
# url = 'http://myexternalip.com/raw'
url = 'https://api.ipify.org'
try:
ip_address = requests.get(url).text
except:
exit('%s: failed' % (url))
if ip_address == '':
exit('%s: failed' % (url))
if ':' in ip_address:
ip_address_type = 'AAAA'
else:
ip_address_type = 'A'
return ip_address, ip_address_type
def do_dns_update(cf, zone_name, zone_id, dns_name, ip_address, ip_address_type):
"""Cloudflare API code - example"""
try:
params = {'name':dns_name, 'match':'all', 'type':ip_address_type}
dns_records = cf.zones.dns_records.get(zone_id, params=params)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones/dns_records %s - %d %s - api call failed' % (dns_name, e, e))
updated = False
# update the record - unless it's already correct
for dns_record in dns_records:
old_ip_address = dns_record['content']
old_ip_address_type = dns_record['type']
if ip_address_type not in ['A', 'AAAA']:
# we only deal with A / AAAA records
continue
if ip_address_type != old_ip_address_type:
# only update the correct address type (A or AAAA)
# we don't see this becuase of the search params above
print('IGNORED: %s %s ; wrong address family' % (dns_name, old_ip_address))
continue
if ip_address == old_ip_address:
print('UNCHANGED: %s %s' % (dns_name, ip_address))
updated = True
continue
# Yes, we need to update this record - we know it's the same address type
dns_record_id = dns_record['id']
dns_record = {
'name':dns_name,
'type':ip_address_type,
'content':ip_address
}
try:
dns_record = cf.zones.dns_records.put(zone_id, dns_record_id, data=dns_record)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones.dns_records.put %s - %d %s - api call failed' % (dns_name, e, e))
print('UPDATED: %s %s -> %s' % (dns_name, old_ip_address, ip_address))
updated = True
if updated:
return
# no exsiting dns record to update - so create dns record
dns_record = {
'name':dns_name,
'type':ip_address_type,
'content':ip_address
}
try:
dns_record = cf.zones.dns_records.post(zone_id, data=dns_record)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones.dns_records.post %s - %d %s - api call failed' % (dns_name, e, e))
print('CREATED: %s %s' % (dns_name, ip_address))
def main():
"""Cloudflare API code - example"""
try:
dns_name = sys.argv[1]
except IndexError:
exit('usage: example-update-dynamic-dns.py fqdn-hostname')
host_name, zone_name = dns_name.split('.', 1)
ip_address, ip_address_type = my_ip_address()
print('MY IP: %s %s' % (dns_name, ip_address))
cf = CloudFlare.CloudFlare()
# grab the zone identifier
try:
params = {'name':zone_name}
zones = cf.zones.get(params=params)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones %d %s - api call failed' % (e, e))
except Exception as e:
exit('/zones.get - %s - api call failed' % (e))
if len(zones) == 0:
exit('/zones.get - %s - zone not found' % (zone_name))
if len(zones) != 1:
exit('/zones.get - %s - api call returned %d items' % (zone_name, len(zones)))
zone = zones[0]
zone_name = zone['name']
zone_id = zone['id']
do_dns_update(cf, zone_name, zone_id, dns_name, ip_address, ip_address_type)
exit(0)
if __name__ == '__main__':
main()