mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 06:23:00 +00:00
304 lines
9.0 KiB
Go
304 lines
9.0 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestValidateToken_Success(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Header.Get("Authorization") != "Bearer test-token" {
|
|
t.Errorf("unexpected auth header: %s", r.Header.Get("Authorization"))
|
|
}
|
|
w.WriteHeader(200)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"servers": []interface{}{}})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
if err := client.ValidateToken(); err != nil {
|
|
t.Errorf("ValidateToken() error = %v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateToken_InvalidToken(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(401)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"error": map[string]string{
|
|
"code": "unauthorized",
|
|
"message": "unable to authenticate",
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "bad-token")
|
|
if err := client.ValidateToken(); err == nil {
|
|
t.Error("ValidateToken() expected error for invalid token")
|
|
}
|
|
}
|
|
|
|
func TestCreateServer(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" || r.URL.Path != "/v1/servers" {
|
|
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}
|
|
|
|
var req CreateServerRequest
|
|
json.NewDecoder(r.Body).Decode(&req)
|
|
|
|
if req.Name != "sbx-test-1" {
|
|
t.Errorf("unexpected server name: %s", req.Name)
|
|
}
|
|
if req.ServerType != "cx22" {
|
|
t.Errorf("unexpected server type: %s", req.ServerType)
|
|
}
|
|
|
|
w.WriteHeader(201)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"server": map[string]interface{}{
|
|
"id": 12345,
|
|
"name": req.Name,
|
|
"status": "initializing",
|
|
"public_net": map[string]interface{}{
|
|
"ipv4": map[string]string{"ip": "1.2.3.4"},
|
|
},
|
|
"labels": req.Labels,
|
|
"server_type": map[string]string{"name": "cx22"},
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
server, err := client.CreateServer(CreateServerRequest{
|
|
Name: "sbx-test-1",
|
|
ServerType: "cx22",
|
|
Image: "ubuntu-24.04",
|
|
Location: "fsn1",
|
|
SSHKeys: []int64{1},
|
|
Labels: map[string]string{"orama-sandbox": "test"},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("CreateServer() error = %v", err)
|
|
}
|
|
if server.ID != 12345 {
|
|
t.Errorf("server ID = %d, want 12345", server.ID)
|
|
}
|
|
if server.Name != "sbx-test-1" {
|
|
t.Errorf("server name = %s, want sbx-test-1", server.Name)
|
|
}
|
|
if server.PublicNet.IPv4.IP != "1.2.3.4" {
|
|
t.Errorf("server IP = %s, want 1.2.3.4", server.PublicNet.IPv4.IP)
|
|
}
|
|
}
|
|
|
|
func TestDeleteServer(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "DELETE" || r.URL.Path != "/v1/servers/12345" {
|
|
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}
|
|
w.WriteHeader(200)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
if err := client.DeleteServer(12345); err != nil {
|
|
t.Errorf("DeleteServer() error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestListServersByLabel(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Query().Get("label_selector") != "orama-sandbox=test" {
|
|
t.Errorf("unexpected label_selector: %s", r.URL.Query().Get("label_selector"))
|
|
}
|
|
w.WriteHeader(200)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"servers": []map[string]interface{}{
|
|
{"id": 1, "name": "sbx-test-1", "status": "running", "public_net": map[string]interface{}{"ipv4": map[string]string{"ip": "1.1.1.1"}}, "server_type": map[string]string{"name": "cx22"}},
|
|
{"id": 2, "name": "sbx-test-2", "status": "running", "public_net": map[string]interface{}{"ipv4": map[string]string{"ip": "2.2.2.2"}}, "server_type": map[string]string{"name": "cx22"}},
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
servers, err := client.ListServersByLabel("orama-sandbox=test")
|
|
if err != nil {
|
|
t.Fatalf("ListServersByLabel() error = %v", err)
|
|
}
|
|
if len(servers) != 2 {
|
|
t.Errorf("got %d servers, want 2", len(servers))
|
|
}
|
|
}
|
|
|
|
func TestWaitForServer_AlreadyRunning(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(200)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"server": map[string]interface{}{
|
|
"id": 1,
|
|
"name": "test",
|
|
"status": "running",
|
|
"public_net": map[string]interface{}{
|
|
"ipv4": map[string]string{"ip": "1.1.1.1"},
|
|
},
|
|
"server_type": map[string]string{"name": "cx22"},
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
server, err := client.WaitForServer(1, 5*time.Second)
|
|
if err != nil {
|
|
t.Fatalf("WaitForServer() error = %v", err)
|
|
}
|
|
if server.Status != "running" {
|
|
t.Errorf("server status = %s, want running", server.Status)
|
|
}
|
|
}
|
|
|
|
func TestAssignFloatingIP(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" || r.URL.Path != "/v1/floating_ips/100/actions/assign" {
|
|
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}
|
|
|
|
var body map[string]int64
|
|
json.NewDecoder(r.Body).Decode(&body)
|
|
if body["server"] != 200 {
|
|
t.Errorf("unexpected server ID: %d", body["server"])
|
|
}
|
|
|
|
w.WriteHeader(200)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"action": map[string]interface{}{"id": 1, "status": "running"}})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
if err := client.AssignFloatingIP(100, 200); err != nil {
|
|
t.Errorf("AssignFloatingIP() error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUploadSSHKey(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" || r.URL.Path != "/v1/ssh_keys" {
|
|
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}
|
|
w.WriteHeader(201)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"ssh_key": map[string]interface{}{
|
|
"id": 42,
|
|
"name": "orama-sandbox",
|
|
"fingerprint": "aa:bb:cc:dd",
|
|
"public_key": "ssh-ed25519 AAAA...",
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
key, err := client.UploadSSHKey("orama-sandbox", "ssh-ed25519 AAAA...")
|
|
if err != nil {
|
|
t.Fatalf("UploadSSHKey() error = %v", err)
|
|
}
|
|
if key.ID != 42 {
|
|
t.Errorf("key ID = %d, want 42", key.ID)
|
|
}
|
|
}
|
|
|
|
func TestCreateFirewall(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" || r.URL.Path != "/v1/firewalls" {
|
|
t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path)
|
|
}
|
|
w.WriteHeader(201)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"firewall": map[string]interface{}{
|
|
"id": 99,
|
|
"name": "orama-sandbox",
|
|
},
|
|
})
|
|
}))
|
|
defer srv.Close()
|
|
|
|
client := newTestClient(srv, "test-token")
|
|
fw, err := client.CreateFirewall("orama-sandbox", SandboxFirewallRules(), map[string]string{"orama-sandbox": "infra"})
|
|
if err != nil {
|
|
t.Fatalf("CreateFirewall() error = %v", err)
|
|
}
|
|
if fw.ID != 99 {
|
|
t.Errorf("firewall ID = %d, want 99", fw.ID)
|
|
}
|
|
}
|
|
|
|
func TestSandboxFirewallRules(t *testing.T) {
|
|
rules := SandboxFirewallRules()
|
|
if len(rules) != 6 {
|
|
t.Errorf("got %d rules, want 6", len(rules))
|
|
}
|
|
|
|
expectedPorts := map[string]bool{"22": false, "53": false, "80": false, "443": false, "51820": false}
|
|
for _, r := range rules {
|
|
expectedPorts[r.Port] = true
|
|
if r.Direction != "in" {
|
|
t.Errorf("rule %s direction = %s, want in", r.Port, r.Direction)
|
|
}
|
|
}
|
|
for port, seen := range expectedPorts {
|
|
if !seen {
|
|
t.Errorf("missing firewall rule for port %s", port)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseHetznerError(t *testing.T) {
|
|
body := `{"error":{"code":"uniqueness_error","message":"server name already used"}}`
|
|
err := parseHetznerError([]byte(body), 409)
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
expected := "hetzner API error (HTTP 409): uniqueness_error — server name already used"
|
|
if err.Error() != expected {
|
|
t.Errorf("error = %q, want %q", err.Error(), expected)
|
|
}
|
|
}
|
|
|
|
// newTestClient creates a HetznerClient pointing at a test server.
|
|
func newTestClient(ts *httptest.Server, token string) *HetznerClient {
|
|
client := NewHetznerClient(token)
|
|
// Override the base URL by using a custom transport
|
|
client.httpClient = ts.Client()
|
|
// We need to override the base URL — wrap the transport
|
|
origTransport := client.httpClient.Transport
|
|
client.httpClient.Transport = &testTransport{
|
|
base: origTransport,
|
|
testURL: ts.URL,
|
|
}
|
|
return client
|
|
}
|
|
|
|
// testTransport rewrites requests to point at the test server.
|
|
type testTransport struct {
|
|
base http.RoundTripper
|
|
testURL string
|
|
}
|
|
|
|
func (t *testTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
// Rewrite the URL to point at the test server
|
|
req.URL.Scheme = "http"
|
|
req.URL.Host = t.testURL[len("http://"):]
|
|
if t.base != nil {
|
|
return t.base.RoundTrip(req)
|
|
}
|
|
return http.DefaultTransport.RoundTrip(req)
|
|
}
|