Skip to content

Commit

Permalink
Merge pull request #6 from davidnoyes/4-feature-cname-management
Browse files Browse the repository at this point in the history
CNAME management
  • Loading branch information
davidnoyes authored Dec 6, 2023
2 parents 03b14c6 + cb06e6f commit d966647
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ docker_build:

.PHONY: docker_run
docker_run:
@$(DOCKER_CMD) run -d --name $(APP_NAME) --restart=unless-stopped -e DPD_PIHOLE_URL=$(DPD_PIHOLE_URL) -e DPD_DOCKER_HOST_IP=$(DPD_DOCKER_HOST_IP) -e DPD_PIHOLE_API_TOKEN=$(DPD_PIHOLE_API_TOKEN) $(APP_NAME):$(VERSION)
@$(DOCKER_CMD) run -d --name $(APP_NAME) --restart=unless-stopped -e DPC_PIHOLE_URL=$(DPC_PIHOLE_URL) -e DPC_DEFAULT_TARGET_IP=$(DPC_DEFAULT_TARGET_IP) -e DPC_PIHOLE_API_TOKEN=$(DPC_PIHOLE_API_TOKEN) $(APP_NAME):$(VERSION)

.PHONY: update_modules
update_modules:
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ docker pull download.noyes.uk/davidnoyes/docker-pihole-customdns:latest
## Docker Usage

```shell
docker run --name docker-pihole-customdns -d --restart=unless-stopped -v /var/run/docker.sock:/var/run/docker.sock:ro -e DPC_PIHOLE_URL=http://pi.hole -e DPC_DOCKER_HOST_IP=198.51.100.0 -e DPC_PIHOLE_API_TOKEN=abcdefghijklmnopqrstuvwxyz
docker run --name docker-pihole-customdns -d --restart=unless-stopped -v /var/run/docker.sock:/var/run/docker.sock:ro -e DPC_PIHOLE_URL=http://pi.hole -e DPC_DEFAULT_TARGET_IP=198.51.100.0 -e DPC_PIHOLE_API_TOKEN=abcdefghijklmnopqrstuvwxyz
```

Replace the values for `DPC_PIHOLE_URL`, `DPC_DOCKER_HOST_IP` & `DPC_PIHOLE_API_TOKEN` as appropriate
Replace the values for `DPC_PIHOLE_URL`, `DPC_DEFAULT_TARGET_IP` & `DPC_PIHOLE_API_TOKEN` as appropriate

## Docker Label

Expand Down Expand Up @@ -58,7 +58,7 @@ services:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- DPC_PIHOLE_API_TOKEN=abcdefghijklmnopqrstuvwxyz
- DPC_DOCKER_HOST_IP=198.51.100.0
- DPC_DEFAULT_TARGET_IP=198.51.100.0
- DPC_PIHOLE_URL=http://pi.hole
```
Expand All @@ -68,7 +68,7 @@ services:
|-|-|
| `DPC_PIHOLE_API_TOKEN` | Pi-hole API Token. |
| `DPC_PIHOLE_API_TOKEN_2` | Second Pi-hole API Token (Optional)
| `DPC_DOCKER_HOST_IP` | Docker host IP address. The IP address used by the http proxy for all docker services on the host. |
| `DPC_DEFAULT_TARGET_IP` | Default target IP address for the Docker host. The IP address used by the http proxy for all docker services on the host. |
| `DPC_PIHOLE_URL` | Pi-hole URL (e.g. http://pi-hole) |
| `DPC_PIHOLE_URL_2` | Second Pi-hole URL (optional) |

Expand All @@ -80,12 +80,12 @@ Usage of ./docker-pihole-customdns:
Pi-hole API token
-apitoken2 string
Second Pi-hole API token (Optional)
-hostip string
Docker host IP address
-targetip string
Default target IP address for the Docker host
-piholeurl string
Pi-hole URL (e.g. http://pi.hole)
-piholeurl2 string
Second Pi-hole URL (optional e.g. http://pi.hole)
Second Pi-hole URL (Optional e.g. http://pi.hole)
```


Expand Down
113 changes: 99 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ type ExistingDNSResponse struct {
Data [][]string `json:"data"`
}

var hostIP string
var defaultTargetIP string
var defaultTargetDomain string
var authCode string
var pihole_url string
var authCode2 string
Expand All @@ -57,15 +58,20 @@ func main() {
}

func loadArguments() {
flag.StringVar(&hostIP, "hostip", "", "Docker host IP address")
flag.StringVar(&defaultTargetIP, "targetip", "", "Default target IP address for the Docker host")
flag.StringVar(&defaultTargetDomain, "targetdomain", "", "Default target domain address for the Docker host")
flag.StringVar(&authCode, "apitoken", "", "Pi-hole API token")
flag.StringVar(&pihole_url, "piholeurl", "", "Pi-hole URL (http://pi.hole)")
flag.StringVar(&authCode2, "apitoken2", "", "Second Pi-hole API token")
flag.StringVar(&pihole_url2, "piholeurl2", "", "Second Pi-hole URL (http://pi.hole)")
flag.Parse()

if hostIP == "" {
hostIP = os.Getenv("DPC_DOCKER_HOST_IP")
if defaultTargetIP == "" {
defaultTargetIP = os.Getenv("DPC_DEFAULT_TARGET_IP")
}

if defaultTargetDomain == "" {
defaultTargetDomain = os.Getenv("DPC_DEFAULT_TARGET_DOMAIN")
}

if authCode == "" {
Expand All @@ -84,8 +90,10 @@ func loadArguments() {
pihole_url2 = os.Getenv("DPC_PIHOLE_URL_2")
}

if hostIP == "" {
log.Fatal("Docker host IP is not provided. Set it using the -hostip flag or DPC_DOCKER_HOST_IP environment variable.")
if defaultTargetIP == "" && defaultTargetDomain == "" {
log.Fatal("Default Docker host target IP or target domain are not provided. Set either using the -targetip flag (DPC_DEFAULT_TARGET_IP) or -targetdomain (DPC_DEFAULT_TARGET_DOMAIN).")
} else if defaultTargetIP != "" && defaultTargetDomain != "" {
log.Fatal("Both default target IP and target domain are set. Only one default can be used.")
}

if authCode == "" {
Expand Down Expand Up @@ -192,15 +200,15 @@ func checkExistingContainers(pihole_url string, cli *client.Client, existingDNS
if found && isDNSMissing(labelValue, existingDNS) {
// Strip off the "/" prefix from the container name
containerName := strings.TrimPrefix(container.Names[0], "/")
createDNS(pihole_url, containerName, labelValue, hostIP)
createDNSRecord(pihole_url, containerName, labelValue)
}
}
}

func isDNSMissing(labelValue string, existingDNS [][]string) bool {
// Check if the DNS entry already exists
for _, existing := range existingDNS {
if len(existing) == 2 && existing[0] == labelValue && existing[1] == hostIP {
if len(existing) == 2 && existing[0] == labelValue && existing[1] == defaultTargetIP {
return false
}
}
Expand All @@ -222,14 +230,14 @@ func watchContainers(ctx context.Context, cli *client.Client) {
relevant, action, label := isRelevantEvent(event)
if relevant {
if action == CreateAction {
createDNS(pihole_url, event.Actor.Attributes["name"], label, hostIP)
createDNSRecord(pihole_url, event.Actor.Attributes["name"], label)
if pihole_url2 != "" {
createDNS(pihole_url2, event.Actor.Attributes["name"], label, hostIP)
createDNSRecord(pihole_url2, event.Actor.Attributes["name"], label)
}
} else if action == RemoveAction {
removeDNS(pihole_url, event.Actor.Attributes["name"], label, hostIP)
removeDNSRecord(pihole_url, event.Actor.Attributes["name"], label)
if pihole_url2 != "" {
removeDNS(pihole_url2, event.Actor.Attributes["name"], label, hostIP)
removeDNSRecord(pihole_url2, event.Actor.Attributes["name"], label)
}
}

Expand All @@ -251,7 +259,23 @@ func isRelevantEvent(event events.Message) (bool, Action, string) {
return false, "", ""
}

func createDNS(pihole_url string, containerName string, domainName string, ipAddress string) {
func createDNSRecord(pihole_url string, containerName string, domainName string) {
if defaultTargetIP != "" {
createARecord(pihole_url, containerName, domainName, defaultTargetIP)
} else {
createCNAMERecord(pihole_url, containerName, domainName, defaultTargetDomain)
}
}

func removeDNSRecord(pihole_url string, containerName string, domainName string) {
if defaultTargetIP != "" {
removeARecord(pihole_url, containerName, domainName, defaultTargetIP)
} else {
removeCNAMERecord(pihole_url, containerName, domainName, defaultTargetDomain)
}
}

func createARecord(pihole_url string, containerName string, domainName string, ipAddress string) {

// Make the API request with the required parameters
apiURL := pihole_url + "?customdns"
Expand Down Expand Up @@ -282,7 +306,7 @@ func createDNS(pihole_url string, containerName string, domainName string, ipAdd
}
}

func removeDNS(pihole_url string, containerName string, domainName string, ipAddress string) {
func removeARecord(pihole_url string, containerName string, domainName string, ipAddress string) {
// Make the API request with the required parameters
apiURL := pihole_url + "?customdns"
apiURL += "&auth=" + authCode
Expand Down Expand Up @@ -311,3 +335,64 @@ func removeDNS(pihole_url string, containerName string, domainName string, ipAdd
log.Printf("API for %s delete request failed for container %s - %s: %s", pihole_url, containerName, domainName, apiResponse.Message)
}
}

func createCNAMERecord(pihole_url string, containerName string, domainName string, targetName string) {

// Make the API request with the required parameters
apiURL := pihole_url + "?customcname"
apiURL += "&auth=" + authCode
apiURL += "&action=add"
apiURL += "&target=" + targetName
apiURL += "&domain=" + domainName

resp, err := http.Get(apiURL)
if err != nil {
log.Printf("Error making API request: %v", err)
return
}
defer resp.Body.Close()

// Decode the JSON response
var apiResponse APIResponse
if err := json.NewDecoder(resp.Body).Decode(&apiResponse); err != nil {
log.Printf("Error decoding JSON response: %v", err)
return
}

// Check the "success" attribute in the response
if apiResponse.Success {
log.Printf("API for %s add request successful for container %s - %s", pihole_url, containerName, domainName)
} else {
log.Printf("API for %s add request failed for container %s - %s: %s", pihole_url, containerName, domainName, apiResponse.Message)
}
}

func removeCNAMERecord(pihole_url string, containerName string, domainName string, targetName string) {
// Make the API request with the required parameters
apiURL := pihole_url + "?customcname"
apiURL += "&auth=" + authCode
apiURL += "&action=delete"
apiURL += "&target=" + targetName
apiURL += "&domain=" + domainName

resp, err := http.Get(apiURL)
if err != nil {
log.Printf("Error making API request: %v", err)
return
}
defer resp.Body.Close()

// Decode the JSON response
var apiResponse APIResponse
if err := json.NewDecoder(resp.Body).Decode(&apiResponse); err != nil {
log.Printf("Error decoding JSON response: %v", err)
return
}

// Check the "success" attribute in the response
if apiResponse.Success {
log.Printf("API for %s delete request successful for container %s - %s", pihole_url, containerName, domainName)
} else {
log.Printf("API for %s delete request failed for container %s - %s: %s", pihole_url, containerName, domainName, apiResponse.Message)
}
}

0 comments on commit d966647

Please sign in to comment.