feat: Implement configuration management and DNS provider integration
- Added configuration management using Viper in internal/config/config.go - Implemented ClientConfig, ServerConfig, TLSConfig, HetznerConfig, UpstreamConfig, and main Config struct. - Created LoadConfig function to read and validate configuration files. - Developed Hetzner DNS provider in internal/provider/hetzner/hetzner.go with methods for updating DNS records. - Added comprehensive unit tests for configuration loading and Hetzner provider functionality. - Established HTTP server with metrics and update endpoint in internal/server/server.go. - Implemented request handling, authorization, and error management in the server. - Created integration tests for the Hetzner provider API interactions. - Removed legacy dynamic DNS integration tests in favor of the new API-based approach.
This commit is contained in:
105
internal/server/server_router_test.go
Normal file
105
internal/server/server_router_test.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package server_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"git.cloonar.com/cloonar/updns/internal/config"
|
||||
"git.cloonar.com/cloonar/updns/internal/server"
|
||||
)
|
||||
|
||||
func newTestConfig(provider string) *config.Config {
|
||||
return &config.Config{
|
||||
Server: config.ServerConfig{
|
||||
BindAddress: ":0",
|
||||
TLS: config.TLSConfig{Enabled: false},
|
||||
},
|
||||
Upstream: config.UpstreamConfig{
|
||||
Provider: provider,
|
||||
Hetzner: config.HetznerConfig{APIToken: "token"},
|
||||
},
|
||||
Clients: map[string]config.ClientConfig{
|
||||
"client1": {
|
||||
Secret: "s3cr3t",
|
||||
Exact: []string{"a.example.com"},
|
||||
Wildcard: []string{"example.net"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsEndpoint(t *testing.T) {
|
||||
r := server.NewRouter(newTestConfig("unknown"))
|
||||
req := httptest.NewRequest("GET", "/metrics", nil)
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200 OK, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateInvalidJSON(t *testing.T) {
|
||||
r := server.NewRouter(newTestConfig("unknown"))
|
||||
req := httptest.NewRequest("POST", "/update", bytes.NewBufferString("{invalid"))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("expected 400 BadRequest, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUnauthorizedKey(t *testing.T) {
|
||||
r := server.NewRouter(newTestConfig("unknown"))
|
||||
body := map[string]string{"key": "bad", "secret": "x", "host": "a.example.com"}
|
||||
data, _ := json.Marshal(body)
|
||||
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusUnauthorized {
|
||||
t.Errorf("expected 401 Unauthorized, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateHostForbidden(t *testing.T) {
|
||||
r := server.NewRouter(newTestConfig("unknown"))
|
||||
body := map[string]string{"key": "client1", "secret": "s3cr3t", "host": "bad.example.com"}
|
||||
data, _ := json.Marshal(body)
|
||||
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusForbidden {
|
||||
t.Errorf("expected 403 Forbidden, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateProviderNotConfigured(t *testing.T) {
|
||||
r := server.NewRouter(newTestConfig("unknown"))
|
||||
body := map[string]string{"key": "client1", "secret": "s3cr3t", "host": "a.example.com"}
|
||||
data, _ := json.Marshal(body)
|
||||
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusInternalServerError {
|
||||
t.Errorf("expected 500 InternalServerError, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateSuccess(t *testing.T) {
|
||||
r := server.NewRouter(newTestConfig("hetzner"))
|
||||
body := map[string]string{"key": "client1", "secret": "s3cr3t", "host": "a.example.com", "ip": "1.2.3.4"}
|
||||
data, _ := json.Marshal(body)
|
||||
req := httptest.NewRequest("POST", "/update", bytes.NewBuffer(data))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusOK {
|
||||
t.Errorf("expected 200 OK, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user