feat: mvp (#1)

MVP including features:
* Detect IP change
* Configurable/generic external IP provider
* Configurable/generic DNS provider
* Impl. of plain external IP provider
* Impl. of Ionos DNS provider

Reviewed-on: #1
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
This commit was merged in pull request #1.
This commit is contained in:
2024-04-01 11:50:27 +02:00
committed by t.behrendt
parent 90369bf147
commit 99361a5ccd
23 changed files with 1521 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
package externalIpProvider
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestNew(t *testing.T) {
t.Run("returns external ip provider", testNew())
t.Run("returns error when url is empty", testNewEmptyUrl())
}
func testNew() func(t *testing.T) {
return func(t *testing.T) {
provider, err := New(PlainExternalIpProviderConfig{
Url: "http://localhost",
})
if err != nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
if provider == nil {
t.Fatalf("NewPlain() returned nil provider")
}
}
}
func testNewEmptyUrl() func(t *testing.T) {
return func(t *testing.T) {
_, err := New(PlainExternalIpProviderConfig{})
if err == nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
}
}
func TestGetExternal(t *testing.T) {
t.Run("returns external ip", testGetExternalIp())
t.Run("returns error when unable to parse ip", testGetExternalIpUnparsableIp())
t.Run("returns error when unexpected status code", testGetExternalIpUnexpectedStatusCode())
t.Run("returns error when unable to parse url", testGetExternalIpUnableToParseUrl())
t.Run("returns error when unable to get", testGetExternalIpUnableToGet())
}
func testGetExternalIp() func(t *testing.T) {
return func(t *testing.T) {
mockServer := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("127.0.0.1"))
},
))
defer mockServer.Close()
provider, err := New(PlainExternalIpProviderConfig{
Url: mockServer.URL,
})
if err != nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
ip, err := provider.GetExternalIp()
if err != nil {
t.Fatalf("GetExternalIp() returned unexpected error: %v", err)
}
if ip.String() != "127.0.0.1" {
t.Fatalf("GetExternalIp() returned unexpected ip: %v instead of 127.0.0.1", ip)
}
}
}
func testGetExternalIpUnparsableIp() func(t *testing.T) {
return func(t *testing.T) {
mockServer := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("not an ip"))
},
))
defer mockServer.Close()
provider, err := New(PlainExternalIpProviderConfig{
Url: mockServer.URL,
})
if err != nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
_, err = provider.GetExternalIp()
if err == nil {
t.Fatalf("GetExternalIp() returned unexpected error: %v", err)
}
}
}
func testGetExternalIpUnexpectedStatusCode() func(t *testing.T) {
return func(t *testing.T) {
mockServer := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
},
))
defer mockServer.Close()
provider, err := New(PlainExternalIpProviderConfig{
Url: mockServer.URL,
})
if err != nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
_, err = provider.GetExternalIp()
if err == nil {
t.Fatalf("GetExternalIp() returned unexpected error: %v", err)
}
}
}
func testGetExternalIpUnableToParseUrl() func(t *testing.T) {
return func(t *testing.T) {
provider, err := New(PlainExternalIpProviderConfig{
Url: "not a url !'§%&",
})
if err != nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
_, err = provider.GetExternalIp()
if err == nil {
t.Fatalf("GetExternalIp() returned unexpected error: %v", err)
}
}
}
func testGetExternalIpUnableToGet() func(t *testing.T) {
return func(t *testing.T) {
// force error by using a non-responding url, beware of side effects
provider, err := New(PlainExternalIpProviderConfig{
Url: "http://localhost:1234",
})
if err != nil {
t.Fatalf("NewPlain() returned unexpected error: %v", err)
}
_, err = provider.GetExternalIp()
if err == nil {
t.Fatalf("GetExternalIp() returned unexpected error: %v", err)
}
}
}