Files
encapic/main_test.go
T
benvin 7f8ca8046e
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Check error returns to satisfy errcheck lint
2026-07-25 10:00:07 +10:00

129 lines
3.7 KiB
Go

package main
import (
"bytes"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"time"
)
// cobblerWire is the exact cobbler-wire document encapi serves for a node with
// a single role in the develop environment.
const cobblerWire = "classes:\n" +
" roles::infra::storage::vault: {}\n" +
"environment: develop\n" +
"parameters: {}\n"
// goldenENC is the reshaped ENC document the previous python script produced
// from cobblerWire (verified byte-for-byte against uv/python yaml.dump).
const goldenENC = "classes:\n" +
"- roles::infra::storage::vault\n" +
"environment: develop\n" +
"parameters:\n" +
" enc_env: develop\n" +
" enc_role:\n" +
" - roles::infra::storage::vault\n"
func TestRunGoldenOutput(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/cblr/svc/op/puppet/hostname/host.example" {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/x-yaml")
_, _ = w.Write([]byte(cobblerWire))
}))
defer srv.Close()
t.Setenv("ENCAPI_URL", srv.URL)
var out bytes.Buffer
if err := run([]string{"encapic", "host.example"}, &out); err != nil {
t.Fatalf("run returned error: %v", err)
}
if out.String() != goldenENC {
t.Errorf("output mismatch\n--- want ---\n%s\n--- got ---\n%s", goldenENC, out.String())
}
}
func TestRun404FailsNonZero(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, `{"error":"not found"}`, http.StatusNotFound)
}))
defer srv.Close()
t.Setenv("ENCAPI_URL", srv.URL)
var out bytes.Buffer
err := run([]string{"encapic", "ghost.example"}, &out)
if err == nil {
t.Fatalf("expected error on 404, got nil")
}
if out.Len() != 0 {
t.Errorf("expected no stdout on failure, got %q", out.String())
}
if !strings.Contains(err.Error(), "404") {
t.Errorf("error should mention 404, got %v", err)
}
}
func TestRun500FailsNonZero(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "boom", http.StatusInternalServerError)
}))
defer srv.Close()
t.Setenv("ENCAPI_URL", srv.URL)
var out bytes.Buffer
if err := run([]string{"encapic", "host.example"}, &out); err == nil {
t.Fatalf("expected error on 500, got nil")
}
}
func TestFetchTimeout(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(200 * time.Millisecond)
_, _ = w.Write([]byte(cobblerWire))
}))
defer srv.Close()
// Use a client with a tiny timeout to exercise the timeout path quickly.
client := &http.Client{Timeout: 20 * time.Millisecond}
resp, err := client.Get(srv.URL + "/cblr/svc/op/puppet/hostname/host.example")
if err == nil {
_ = resp.Body.Close()
t.Fatalf("expected timeout error, got none")
}
}
func TestRunUsage(t *testing.T) {
var out bytes.Buffer
if err := run([]string{"encapic"}, &out); err == nil {
t.Fatalf("expected usage error with no args")
}
if err := run([]string{"encapic", "a", "b"}, &out); err == nil {
t.Fatalf("expected usage error with too many args")
}
}
func TestRunVersion(t *testing.T) {
var out bytes.Buffer
if err := run([]string{"encapic", "--version"}, &out); err != nil {
t.Fatalf("version returned error: %v", err)
}
if !strings.Contains(out.String(), "encapic") {
t.Errorf("version output = %q", out.String())
}
}
func TestDefaultBaseURLCompiledIn(t *testing.T) {
// Guard against accidental changes to the in-cluster default.
if err := os.Unsetenv("ENCAPI_URL"); err != nil {
t.Fatalf("unsetenv: %v", err)
}
if defaultBaseURL != "http://encapi.encapi.svc.cluster.local" {
t.Errorf("defaultBaseURL = %q", defaultBaseURL)
}
}