Open stevecrozz opened 8 months ago
Yeah, I'd like that as well! Not passing in a schedule should do a one-shot run.
I have k8s handle the scheduling for me. The way I handle this today is like this:
apiVersion: v1
metadata:
name: r53creds
data:
HOSTED_ZONE_ID:
RECORD_NAME:
AWS_ACCESS_KEY_ID:
AWS_SECRET_ACCESS_KEY:
AWS_DEFAULT_REGION:
kind: Secret
type: Opaque
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ddns
spec:
schedule: "*/15 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: ddns
image: alpine
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: r53creds
command: ["/bin/sh", "-c"]
args:
- |-
apk add aws-cli curl jq --no-cache && \
RECORD_TYPE="A" && \
TTL=300 && \
NEW_IP_ADDRESS=$(curl https://ipv4.icanhazip.com/) && \
# Define the JSON in a multi-line variable
CHANGE_BATCH=$(cat <<EOF
{
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "${RECORD_NAME}",
"Type": "${RECORD_TYPE}",
"TTL": ${TTL},
"ResourceRecords": [
{"Value": "${NEW_IP_ADDRESS}"}
]
}
}
]
}
EOF
)
aws route53 change-resource-record-sets \
--hosted-zone-id "$HOSTED_ZONE_ID" \
--change-batch "$CHANGE_BATCH" | jq -r '.ChangeInfo.Status'
Which works, but is less pretty ;-)
I experimented a bit yesterday and found ddns-route53 already does behave the way I want. It seems ddns-route53 does run in a one-shot mode when a schedule is not provided. I updated the issue title and description to indicate this is a documentation task.
Can you include a quick example? Then I'll happily open a pull request tomorrow.
Sure. Looking at how it works, it seems the program runs one time right away, and then if there is no schedule, the program exits.
I think I would start with a note here in the online --help menu: https://github.com/crazy-max/ddns-route53/blob/eae4181d45d514eb4ac9cc7a8b96a8067fc950f0/docs/usage/cli.md?plain=1#L22
- --schedule=STRING CRON expression format ($SCHEDULE).
+ --schedule=STRING CRON expression format ($SCHEDULE). Leave empty to run once and exit.
Ok I have adopted this in k8s. Works like a charm:
apiVersion: batch/v1
kind: CronJob
metadata:
name: ddns-route53
spec:
schedule: "*/15 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: ddns-route53
image: crazymax/ddns-route53:latest
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: "Europe/Amsterdam"
- name: LOG_LEVEL
value: info
- name: LOG_JSON
value: "false"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/ddns-route53.yml"
subPath: ddns-route53.yml
volumes:
- name: secret-volume
secret:
secretName: route-53-credentials-ddns
My secret:
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: route-53-credentials-ddns
namespace: default
data:
ddns-route53.yml: <removed>
If you want to load this secret from AWS Secrets Manger through external secrets consider this:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: external-route-53-credentials-ddns
namespace: default
spec:
dataFrom:
- extract:
key: k8s-route-53-credentials
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: aws-secretsmanager
target:
creationPolicy: Owner
name: route-53-credentials-ddns
template:
data:
ddns-route53.yml: |
credentials:
accessKeyID: "{{ .AWS_ACCESS_KEY_ID }}"
secretAccessKey: "{{ .AWS_SECRET_ACCESS_KEY }}"
route53:
hostedZoneID: "{{ .HOSTED_ZONE_ID }}"
recordsSet:
- name: "{{ .RECORD_NAME }}"
type: "A"
ttl: 300
mergePolicy: Replace
Description
Update the documentation so that readers will know that the program does not need to run as a daemon. That it runs in a one-shot mode when schedule is not provided.