update dns update ip job to update technitium via api
This commit is contained in:
parent
8f7ece5dac
commit
543fca5dbb
5 changed files with 222 additions and 33 deletions
48
cli/main.go
48
cli/main.go
|
|
@ -195,30 +195,32 @@ func run() error {
|
|||
return nil
|
||||
}
|
||||
// Send notification as glue records can't be modified programatically for godaddy :/
|
||||
err = notifyForIPChange(publicDNSIp, dynamicDNSIp)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to notify for ip change. this must succeed otherwise the glue records won't be updated")
|
||||
}
|
||||
defer notifyForIPChange(publicDNSIp, dynamicDNSIp)
|
||||
// setup git repo
|
||||
gitFs, err := NewGitFS(repository)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to initialize git fs")
|
||||
}
|
||||
worktree, err := gitFs.repo.Worktree()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get worktree")
|
||||
}
|
||||
err = updatePublicIP(gitFs, publicDNSIp, dynamicDNSIp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update public ip: %w", err)
|
||||
}
|
||||
// // commit changes
|
||||
if _, err = worktree.Commit("Update public ip and ns records", &git.CommitOptions{All: true, Author: &object.Signature{Name: "Webhook Handler Bot"}}); err != nil {
|
||||
return errors.Wrapf(err, "failed to commit")
|
||||
}
|
||||
if err = gitFs.Push(); err != nil {
|
||||
return errors.Wrapf(err, "failed to push changes")
|
||||
}
|
||||
// Old, code-as-infra based approach
|
||||
// gitFs, err := NewGitFS(repository)
|
||||
// if err != nil {
|
||||
// return errors.Wrapf(err, "failed to initialize git fs")
|
||||
// }
|
||||
// worktree, err := gitFs.repo.Worktree()
|
||||
// if err != nil {
|
||||
// return errors.Wrapf(err, "failed to get worktree")
|
||||
// }
|
||||
// err = updatePublicIP(gitFs, publicDNSIp, dynamicDNSIp)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to update public ip: %w", err)
|
||||
// }
|
||||
// // // commit changes
|
||||
// if _, err = worktree.Commit("Update public ip and ns records", &git.CommitOptions{All: true, Author: &object.Signature{Name: "Webhook Handler Bot"}}); err != nil {
|
||||
// return errors.Wrapf(err, "failed to commit")
|
||||
// }
|
||||
// if err = gitFs.Push(); err != nil {
|
||||
// return errors.Wrapf(err, "failed to push changes")
|
||||
// }
|
||||
username := os.Getenv("TECHNITIUM_USERNAME")
|
||||
password := os.Getenv("TECHNITIUM_PASSWORD")
|
||||
// dynamicDNSIp = net.ParseIP("6.9.6.9")
|
||||
return UpdatePublicIPViaTechnitiumAPI(dynamicDNSIp, username, password)
|
||||
default:
|
||||
err = errors.New(fmt.Sprintf("unsupported use case: %s", *useCase))
|
||||
}
|
||||
|
|
|
|||
167
cli/update_viktorbarzin_me_technitium.go
Normal file
167
cli/update_viktorbarzin_me_technitium.go
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type CreateTokenResponse struct {
|
||||
Username string `json:"username"`
|
||||
TokenName string `json:"tokenName"`
|
||||
Token string `json:"token"`
|
||||
Status string `json:"status"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
type GetRecordsResponse struct {
|
||||
Response struct {
|
||||
Zone struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Internal bool `json:"internal"`
|
||||
DnssecStatus string `json:"dnssecStatus"`
|
||||
Disabled bool `json:"disabled"`
|
||||
} `json:"zone"`
|
||||
Records []struct {
|
||||
Disabled bool `json:"disabled"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Ttl int64 `json:"ttl"`
|
||||
RData struct {
|
||||
IpAddress string `json:"ipAddress"`
|
||||
// there's more fields that we don't use atm
|
||||
} `json:"rData"`
|
||||
// RData interface{} `json:"rData"`
|
||||
DnsSecStatus string `json:"dnsSecStatus"`
|
||||
} `json:"records"`
|
||||
} `json:"response"`
|
||||
}
|
||||
type UpdateRecordResponse struct {
|
||||
Status string `json:"status"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
// const TECHNITIUM_HOST = "technitium-web.technitium"
|
||||
|
||||
const TECHNITIUM_HOST = "localhost"
|
||||
|
||||
func UpdatePublicIPViaTechnitiumAPI(newIp net.IP, username string, password string) error {
|
||||
token, err := createTechnitiumToken(username, password)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get technitium token")
|
||||
}
|
||||
for _, ns := range []string{"ns1", "ns2"} {
|
||||
nsRecordName := ns + ".viktorbarzin.me"
|
||||
currIpStr, err := getRecordValue(token, nsRecordName, "A")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get A record for ns server")
|
||||
}
|
||||
currIp := net.ParseIP(currIpStr)
|
||||
fmt.Printf("updating record %s to %s\n", nsRecordName, newIp.String())
|
||||
err = UpdateTechnitiumNSARecord(token, nsRecordName, currIp, newIp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to update NS A record")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateTechnitiumNSARecord(token, domain string, currIp, newIp net.IP) error {
|
||||
baseURL := fmt.Sprintf("http://%s:5380/api/zones/records/update", TECHNITIUM_HOST)
|
||||
params := map[string]string{
|
||||
"token": token,
|
||||
"domain": domain,
|
||||
"type": "A",
|
||||
"newIpAddress": newIp.String(),
|
||||
"ipAddress": currIp.String(),
|
||||
}
|
||||
resp, err := sendTechnitiumAPIRequest(baseURL, params)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to update record")
|
||||
}
|
||||
var parsedResponse UpdateRecordResponse
|
||||
err = json.NewDecoder(strings.NewReader(resp)).Decode(&parsedResponse)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to decode json response when updating record")
|
||||
}
|
||||
if parsedResponse.Status == "error" {
|
||||
return fmt.Errorf("received error status when updating record: %s", parsedResponse.ErrorMessage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createTechnitiumToken(username string, password string) (string, error) {
|
||||
baseURL := fmt.Sprintf("http://%s:5380/api/user/createToken", TECHNITIUM_HOST)
|
||||
params := map[string]string{
|
||||
"user": username,
|
||||
"pass": password,
|
||||
"tokenName": "infra-cli-token",
|
||||
}
|
||||
resp, err := sendTechnitiumAPIRequest(baseURL, params)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to fetch token")
|
||||
}
|
||||
var tokenResponse CreateTokenResponse
|
||||
// println(resp)
|
||||
err = json.NewDecoder(strings.NewReader(resp)).Decode(&tokenResponse)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to decode json response")
|
||||
}
|
||||
if tokenResponse.Status != "ok" {
|
||||
return "", fmt.Errorf("received error status when fetching token: %s, error: %s", tokenResponse.Status, tokenResponse.ErrorMessage)
|
||||
}
|
||||
return tokenResponse.Token, nil
|
||||
}
|
||||
|
||||
func getRecordValue(token, domain, recordType string) (string, error) {
|
||||
baseURL := fmt.Sprintf("http://%s:5380/api/zones/records/get", TECHNITIUM_HOST)
|
||||
params := map[string]string{
|
||||
"token": token,
|
||||
"domain": domain,
|
||||
}
|
||||
resp, err := sendTechnitiumAPIRequest(baseURL, params)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to fetch record values for domain %s", domain)
|
||||
}
|
||||
|
||||
var response GetRecordsResponse
|
||||
err = json.NewDecoder(strings.NewReader(resp)).Decode(&response)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to decode json response when getting all zone records")
|
||||
}
|
||||
for _, record := range response.Response.Records {
|
||||
if record.Type == recordType {
|
||||
return record.RData.IpAddress, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("failed to find record for name %s and type %s", domain, recordType)
|
||||
}
|
||||
|
||||
func sendTechnitiumAPIRequest(baseURL string, params map[string]string) (string, error) {
|
||||
url, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create base url")
|
||||
}
|
||||
// Encode the URL parameters
|
||||
query := url.Query()
|
||||
for key, value := range params {
|
||||
query.Add(key, value)
|
||||
}
|
||||
url.RawQuery = query.Encode()
|
||||
|
||||
resp, err := http.Get(url.String())
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to create token")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return string(body), err
|
||||
}
|
||||
6
main.tf
6
main.tf
|
|
@ -44,6 +44,8 @@ variable "webhook_handler_fb_verify_token" {}
|
|||
variable "webhook_handler_fb_page_token" {}
|
||||
variable "webhook_handler_fb_app_secret" {}
|
||||
variable "webhook_handler_git_user" {}
|
||||
variable "technitium_username" {}
|
||||
variable "technitium_password" {}
|
||||
variable "webhook_handler_git_token" {}
|
||||
variable "webhook_handler_ssh_key" {}
|
||||
variable "monitoring_idrac_username" {}
|
||||
|
|
@ -344,6 +346,10 @@ module "kubernetes_cluster" {
|
|||
resume_database_url = var.resume_database_url
|
||||
|
||||
frigate_valchedrym_camera_credentials = var.frigate_valchedrym_camera_credentials
|
||||
|
||||
// updating technitium records
|
||||
technitium_username = var.technitium_username
|
||||
technitium_password = var.technitium_password
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
# Module to run some infra-specific things like updating the public ip
|
||||
variable git_user {}
|
||||
variable git_token {}
|
||||
variable "git_user" {}
|
||||
variable "git_token" {}
|
||||
variable "technitium_username" {}
|
||||
variable "technitium_password" {}
|
||||
|
||||
|
||||
resource "kubernetes_cron_job_v1" "update-public-ip" {
|
||||
|
|
@ -23,21 +25,29 @@ resource "kubernetes_cron_job_v1" "update-public-ip" {
|
|||
spec {
|
||||
priority_class_name = "system-cluster-critical"
|
||||
container {
|
||||
name = "update-public-ip"
|
||||
image = "viktorbarzin/infra"
|
||||
name = "update-public-ip"
|
||||
image = "viktorbarzin/infra"
|
||||
command = ["./infra_cli"]
|
||||
args = ["-use-case", "update-public-ip"]
|
||||
|
||||
env {
|
||||
name = "GIT_USER"
|
||||
name = "GIT_USER"
|
||||
value = var.git_user
|
||||
}
|
||||
env {
|
||||
name = "GIT_TOKEN"
|
||||
name = "GIT_TOKEN"
|
||||
value = var.git_token
|
||||
}
|
||||
env {
|
||||
name = "TECHNITIUM_USERNAME"
|
||||
value = var.technitium_username
|
||||
}
|
||||
env {
|
||||
name = "TECHNITIUM_PASSWORD"
|
||||
value = var.technitium_password
|
||||
}
|
||||
}
|
||||
restart_policy = "Never"
|
||||
restart_policy = "Never"
|
||||
# service_account_name = "descheduler-sa"
|
||||
# volume {
|
||||
# name = "policy-volume"
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ variable "webhook_handler_fb_app_secret" {}
|
|||
variable "webhook_handler_git_user" {}
|
||||
variable "webhook_handler_git_token" {}
|
||||
variable "webhook_handler_ssh_key" {}
|
||||
variable "technitium_username" {}
|
||||
variable "technitium_password" {}
|
||||
variable "idrac_username" {}
|
||||
variable "idrac_password" {}
|
||||
variable "alertmanager_slack_api_url" {}
|
||||
|
|
@ -285,9 +287,11 @@ module "excalidraw" {
|
|||
}
|
||||
|
||||
module "infra-maintenance" {
|
||||
source = "./infra-maintenance"
|
||||
git_user = var.webhook_handler_git_user
|
||||
git_token = var.webhook_handler_git_token
|
||||
source = "./infra-maintenance"
|
||||
git_user = var.webhook_handler_git_user
|
||||
git_token = var.webhook_handler_git_token
|
||||
technitium_username = var.technitium_username
|
||||
technitium_password = var.technitium_password
|
||||
}
|
||||
|
||||
module "travel_blog" {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue