diff --git a/main.go b/main.go index e573270..b43ffa4 100644 --- a/main.go +++ b/main.go @@ -38,12 +38,15 @@ func handleContainer(container container.Summary, piholeClient *pihole.Client, n msg += ". In dry run mode, not doing anything." log.Println(msg) } else { - msg += ", adding entries to pi-hole and nginx proxy mananger." + msg += ", adding entries to Pi-Hole and Nginx Proxy Manager." log.Println(msg) - piholeClient.AddDNSHostEntry(url, ip) + err := piholeClient.AddDNSHostEntry(url, ip) + if err != nil { + log.Printf("ERROR failed to add entry to Pi-Hole: %v", err) + } - npmClient.AddProxyHost(npm.ProxyHost{ + err = npmClient.AddProxyHost(npm.ProxyHost{ DomainNames: []string{url}, ForwardScheme: "http", ForwardHost: ip, @@ -51,6 +54,9 @@ func handleContainer(container container.Summary, piholeClient *pihole.Client, n Locations: []npm.Location{}, Meta: map[string]any{}, }) + if err != nil { + log.Printf("ERROR failed to add entry to Nginx Proxy Manager: %v", err) + } } } @@ -88,7 +94,7 @@ func main() { piHolePassword := envVars["PIHOLE_PASSWORD"] err = piholeClient.Login(piHolePassword) if err != nil { - log.Fatal(err) + log.Fatalf("ERROR failed to login to Pi-Hole: %v", err) } npmHost := envVars["NGINX_PROXY_MANAGER_HOST"] @@ -97,7 +103,7 @@ func main() { npmClient := npm.NewClient(npmHost, npmUser, npmPassword) err = npmClient.Login() if err != nil { - log.Fatal(err) + log.Fatalf("ERROR failed to login to Nginx Proxy Manager: %v", err) } dockerClient, err := docker.NewClient() diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 6602cdf..57e6970 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -11,7 +11,7 @@ type f struct { var flags f = f{} func ParseFlags() f { - flag.BoolVarP(&flags.DryRun, "dry-run", "d", false, "Simulates the process of adding DNS records and proxy hosts without making any actual changes to Pi-hole or Nginx Proxy Manager.") + flag.BoolVarP(&flags.DryRun, "dry-run", "d", false, "Simulates the process of adding DNS records and proxy hosts without making any actual changes to Pi-Hole or Nginx Proxy Manager.") flag.Parse() return flags } diff --git a/pkg/clients/common.go b/pkg/clients/common.go index e078eb3..426ed68 100644 --- a/pkg/clients/common.go +++ b/pkg/clients/common.go @@ -2,7 +2,6 @@ package clients import ( "io" - "log" "net/http" "strings" ) @@ -13,84 +12,78 @@ func setHeaders(req *http.Request, headers map[string]string) { } } -func Post(client *http.Client, path string, headers map[string]string, data *string) (string, int) { +func Post(client *http.Client, path string, headers map[string]string, data *string) (string, int, error) { req, err := http.NewRequest( http.MethodPost, path, strings.NewReader(*data), ) if err != nil { - log.Fatal(err) + return "", 0, err } setHeaders(req, headers) resp, err := client.Do(req) if err != nil { - log.Fatal(err) + return "", 0, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - log.Fatal(err) + return "", 0, err } - return string(body), resp.StatusCode + return string(body), resp.StatusCode, nil } -func Get(client *http.Client, path string, headers map[string]string) (string, int) { +func Get(client *http.Client, path string, headers map[string]string) (string, int, error) { req, err := http.NewRequest( http.MethodGet, path, nil, ) if err != nil { - log.Fatal(err) + return "", 0, err } setHeaders(req, headers) resp, err := client.Do(req) if err != nil { - log.Fatal(err) - } - if resp.StatusCode >= 400 { - log.Fatal(resp.StatusCode) + return "", 0, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - log.Fatal(err) + return "", 0, err } - return string(body), resp.StatusCode + return string(body), resp.StatusCode, nil } -func Patch(client *http.Client, path string, headers map[string]string, data string) (string, int) { +func Patch(client *http.Client, path string, headers map[string]string, data string) (string, int, error) { req, err := http.NewRequest( http.MethodPatch, path, strings.NewReader(data), ) if err != nil { - log.Fatal(err) + return "", 0, nil } setHeaders(req, headers) resp, err := client.Do(req) if err != nil { - log.Fatal(err) - } - if resp.StatusCode >= 400 { - log.Fatal(resp.StatusCode) + return "", 0, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - log.Fatal(err) + return "", 0, err } - return string(body), resp.StatusCode + return string(body), resp.StatusCode, nil } diff --git a/pkg/clients/npm/npm.go b/pkg/clients/npm/npm.go index d4a024d..ecdf8bf 100644 --- a/pkg/clients/npm/npm.go +++ b/pkg/clients/npm/npm.go @@ -2,6 +2,7 @@ package npm import ( "encoding/json" + "errors" "fmt" "log" "net/http" @@ -37,14 +38,20 @@ func (n *Client) Login() error { } payloadBytes, err := json.Marshal(loginPayload) if err != nil { - log.Fatal(err) + return err } payloadString := string(payloadBytes) - loginResponseString, statusCode := clients.Post(&n.Client, n.baseURL+"/tokens", headers, &payloadString) + loginResponseString, statusCode, err := clients.Post(&n.Client, n.baseURL+"/tokens", headers, &payloadString) + if err != nil { + return err + } + var resp Token - json.Unmarshal([]byte(loginResponseString), &resp) - if statusCode >= 400 || resp.Token == "" { - return fmt.Errorf("ERROR loging in to Nginx Proxy Manager: %v", loginResponseString) + err = json.Unmarshal([]byte(loginResponseString), &resp) + if statusCode >= 400 || err != nil || resp.Token == "" { + var loginError ErrorResponse + json.Unmarshal([]byte(loginResponseString), &loginError) + return errors.New(loginError.Error.Message) } n.token = resp.Token headers["authorization"] = "Bearer " + n.token @@ -52,9 +59,12 @@ func (n *Client) Login() error { } func (n *Client) getProxyHosts() (map[string]string, error) { - proxyHostsString, statusCode := clients.Get(&n.Client, n.baseURL+"/nginx/proxy-hosts", headers) - if statusCode >= 400 { - return nil, fmt.Errorf("ERROR getting proxy hosts from nginx proxy manager") + proxyHostsString, statusCode, err := clients.Get(&n.Client, n.baseURL+"/nginx/proxy-hosts", headers) + if statusCode == 401 { + n.refreshToken() + return n.getProxyHosts() + } else if statusCode >= 400 { + return nil, err } var proxyHosts []ProxyHost existingProxyHostsMap := map[string]string{} @@ -69,34 +79,45 @@ func (n *Client) getProxyHosts() (map[string]string, error) { return existingProxyHostsMap, nil } -func (n *Client) refreshToken() { - log.Println("Refreshing nginx proxy manager token") - if err := n.Login(); err != nil { - log.Fatal(err) - } +func (n *Client) refreshToken() error { + log.Println("Refreshing Nginx Proxy Manager token") + return n.Login() } -func (n *Client) AddProxyHost(host ProxyHost) { +func (n *Client) AddProxyHost(host ProxyHost) error { existingProxyHosts, err := n.getProxyHosts() if err != nil { - n.refreshToken() - existingProxyHosts, _ = n.getProxyHosts() + return err } - for _, domainName := range host.DomainNames { if _, exists := existingProxyHosts[domainName]; exists { - return + return nil } } payloadBytes, err := json.Marshal(host) if err != nil { - log.Fatal(err) + return err } + payloadString := string(payloadBytes) - _, statusCode := clients.Post(&n.Client, n.baseURL+"/nginx/proxy-hosts", headers, &payloadString) + resp, statusCode, err := clients.Post(&n.Client, n.baseURL+"/nginx/proxy-hosts", headers, &payloadString) + if err != nil { + return err + } if statusCode == 401 { - n.refreshToken() - clients.Post(&n.Client, n.baseURL+"/nginx/proxy-hosts", headers, &payloadString) + err := n.refreshToken() + if err != nil { + return err + } + _, _, err = clients.Post(&n.Client, n.baseURL+"/nginx/proxy-hosts", headers, &payloadString) + if err != nil { + return err + } + } else { + var errorResponse ErrorResponse + json.Unmarshal([]byte(resp), &errorResponse) + return errors.New(errorResponse.Error.Message) } + return nil } diff --git a/pkg/clients/npm/types.go b/pkg/clients/npm/types.go index d82994a..44e3662 100644 --- a/pkg/clients/npm/types.go +++ b/pkg/clients/npm/types.go @@ -5,6 +5,13 @@ type LoginRequest struct { Secret string `json:"secret"` } +type ErrorResponse struct { + Error struct { + Code int `json:"code"` + Message string `json:"message"` + } `json:"error"` +} + type Token struct { Token string `json:"token"` } diff --git a/pkg/clients/pihole/pihole.go b/pkg/clients/pihole/pihole.go index a660211..507531a 100644 --- a/pkg/clients/pihole/pihole.go +++ b/pkg/clients/pihole/pihole.go @@ -2,6 +2,7 @@ package pihole import ( "encoding/json" + "errors" "fmt" "log" "net/http" @@ -31,13 +32,15 @@ func NewClient(baseURL string) *Client { func (p *Client) Login(password string) error { loginPayload := fmt.Sprintf(`{"password": "%v"}`, password) - loginResponseString, statusCode := clients.Post(&p.Client, p.baseURL+"/auth", headers, &loginPayload) - + loginResponseString, statusCode, err := clients.Post(&p.Client, p.baseURL+"/auth", headers, &loginPayload) + if err != nil { + return err + } var resp loginResponse json.Unmarshal([]byte(loginResponseString), &resp) if statusCode >= 400 || resp.Session.Sid == "" { - return fmt.Errorf("ERROR loging in to Pi-Hole: %v", loginResponseString) + return fmt.Errorf(resp.Session.Message) } p.sid = resp.Session.Sid @@ -59,14 +62,16 @@ func dnsHostEntryToRawEntry(domain DomainName, ip IP) string { return fmt.Sprintf("%v %v", ip, domain) } -func (p *Client) getDNSHosts() DNSHostEntries { +func (p *Client) getDNSHosts() (DNSHostEntries, error) { if p.sid == "" { // TODO: log.Fatal("no SID") } headers["X-FTL-SID"] = p.sid - configResponseString, _ := clients.Get(&p.Client, p.baseURL+"/config", headers) - + configResponseString, _, err := clients.Get(&p.Client, p.baseURL+"/config", headers) + if err != nil { + return nil, err + } var resp configResponse json.Unmarshal([]byte(configResponseString), &resp) @@ -74,20 +79,23 @@ func (p *Client) getDNSHosts() DNSHostEntries { for _, rawDNSHostEntry := range resp.Config.DNS.Hosts { domain, ip, err := rawDNSHostRawEntryToEntry(rawDNSHostEntry) if err != nil { - log.Fatal(err) + return nil, err } dnsHostEntries[domain] = ip } - return dnsHostEntries + return dnsHostEntries, nil } -func (p *Client) AddDNSHostEntry(domain, ip string) { - existingEntries := p.getDNSHosts() +func (p *Client) AddDNSHostEntry(domain, ip string) error { + existingEntries, err := p.getDNSHosts() + if err != nil { + return err + } d := DomainName(domain) _, exists := existingEntries[d] if exists { - return + return nil } existingEntries[d] = IP(ip) @@ -102,7 +110,7 @@ func (p *Client) AddDNSHostEntry(domain, ip string) { payloadString, err := json.Marshal(payload) if err != nil { - log.Fatal(err) + return err } if p.sid == "" { @@ -110,8 +118,13 @@ func (p *Client) AddDNSHostEntry(domain, ip string) { log.Fatal("no SID") } headers["X-FTL-SID"] = p.sid - resp, _ := clients.Patch(&p.Client, p.baseURL+"/config", headers, string(payloadString)) + resp, statusCode, err := clients.Patch(&p.Client, p.baseURL+"/config", headers, string(payloadString)) + if err != nil { + return err + } + if statusCode >= 400 { + return errors.New(resp) + } - var r configResponse - json.Unmarshal([]byte(resp), &r) + return nil }