package secrets import ( "context" "encoding/json" "net/http" "net/http/httptest" "strings" "testing" ) func TestClientLoginAndFetchBranches(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch { case r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/auth/approle/login"): _ = json.NewEncoder(w).Encode(map[string]any{"auth": map[string]any{"client_token": "token"}}) case r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/secret/data/nodes/missing"): w.WriteHeader(http.StatusNotFound) case r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/secret/data/nodes/error"): http.Error(w, "boom", http.StatusInternalServerError) case r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/secret/data/nodes/node1"): _ = json.NewEncoder(w).Encode(map[string]any{ "data": map[string]any{ "data": map[string]any{"k3s_token": "abc", "cloud_init": "ci"}, }, }) default: http.NotFound(w, r) } })) defer srv.Close() cli := &Client{Addr: srv.URL, RoleID: "role", SecretID: "secret", Client: srv.Client()} if err := cli.LoginIfNeeded(context.Background()); err != nil { t.Fatalf("LoginIfNeeded: %v", err) } if cli.Token != "token" { t.Fatalf("expected token, got %q", cli.Token) } if got, err := cli.FetchNode(context.Background(), "missing"); err != nil || got == nil || got.K3sToken != "" { t.Fatalf("FetchNode missing = %#v err=%v", got, err) } if _, err := cli.FetchNode(context.Background(), "error"); err == nil { t.Fatal("expected FetchNode error") } if got, err := cli.FetchNode(context.Background(), "node1"); err != nil || got.K3sToken != "abc" { t.Fatalf("FetchNode node1 = %#v err=%v", got, err) } if cli.httpClient() == nil { t.Fatal("httpClient returned nil") } } func TestClientLoginAdditionalErrorBranches(t *testing.T) { cli := &Client{Addr: "://bad-vault", RoleID: "role", SecretID: "secret"} if err := cli.LoginIfNeeded(context.Background()); err == nil { t.Fatal("expected invalid login URL to fail") } cli = &Client{Addr: "http://127.0.0.1:1", RoleID: "role", SecretID: "secret"} if err := cli.LoginIfNeeded(context.Background()); err == nil { t.Fatal("expected login connection failure") } badJSON := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/auth/approle/login") { _, _ = w.Write([]byte(`{bad-json`)) return } http.NotFound(w, r) })) defer badJSON.Close() cli = &Client{Addr: badJSON.URL, RoleID: "role", SecretID: "secret", Client: badJSON.Client()} if err := cli.LoginIfNeeded(context.Background()); err == nil { t.Fatal("expected malformed login response to fail") } emptyToken := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/auth/approle/login") { _ = json.NewEncoder(w).Encode(map[string]any{"auth": map[string]any{}}) return } http.NotFound(w, r) })) defer emptyToken.Close() cli = &Client{Addr: emptyToken.URL, RoleID: "role", SecretID: "secret", Client: emptyToken.Client()} if err := cli.LoginIfNeeded(context.Background()); err == nil { t.Fatal("expected empty login token to fail") } } func TestClientFetchAdditionalErrorBranches(t *testing.T) { cli := &Client{Addr: "://bad-vault", Token: "token"} if _, err := cli.FetchNode(context.Background(), "node1"); err == nil { t.Fatal("expected invalid fetch URL to fail") } cli = &Client{Addr: "http://127.0.0.1:1", Token: "token"} if _, err := cli.FetchNode(context.Background(), "node1"); err == nil { t.Fatal("expected fetch connection failure") } badJSON := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/secret/data/nodes/node1") { _, _ = w.Write([]byte(`{bad-json`)) return } http.NotFound(w, r) })) defer badJSON.Close() cli = &Client{Addr: badJSON.URL, Token: "token", Client: badJSON.Client()} if _, err := cli.FetchNode(context.Background(), "node1"); err == nil { t.Fatal("expected malformed fetch response to fail") } }