feat: add internal cluster admin endpoints
This commit is contained in:
@@ -36,6 +36,7 @@ type StoredCluster struct {
|
||||
type Storage interface {
|
||||
Get(ctx context.Context, id string) (StoredCluster, bool, error)
|
||||
Upsert(ctx context.Context, cluster StoredCluster) (StoredCluster, error)
|
||||
SetStatus(ctx context.Context, id string, status string) (StoredCluster, bool, error)
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
@@ -120,6 +121,23 @@ func (r Repository) UpsertCluster(ctx context.Context, cluster Cluster) (Cluster
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r Repository) SetClusterStatus(ctx context.Context, id string, status string) (Cluster, bool, error) {
|
||||
stored, found, err := r.storage.SetStatus(ctx, strings.TrimSpace(id), strings.TrimSpace(status))
|
||||
if err != nil || !found {
|
||||
return Cluster{}, found, err
|
||||
}
|
||||
|
||||
return Cluster{
|
||||
ID: stored.ID,
|
||||
Name: stored.Name,
|
||||
APIEndpoint: stored.APIEndpoint,
|
||||
TLSFingerprint: stored.TLSFingerprint,
|
||||
TokenID: stored.TokenID,
|
||||
Status: stored.Status,
|
||||
CreatedAt: stored.CreatedAt,
|
||||
}, true, nil
|
||||
}
|
||||
|
||||
type SQLStorage struct {
|
||||
db *sql.DB
|
||||
}
|
||||
@@ -203,3 +221,30 @@ func (s SQLStorage) Upsert(ctx context.Context, cluster StoredCluster) (StoredCl
|
||||
|
||||
return stored, nil
|
||||
}
|
||||
|
||||
func (s SQLStorage) SetStatus(ctx context.Context, id string, status string) (StoredCluster, bool, error) {
|
||||
var stored StoredCluster
|
||||
err := s.db.QueryRowContext(ctx, `
|
||||
update public.clusters
|
||||
set status = $2
|
||||
where id = $1
|
||||
returning id::text, name, api_endpoint, tls_fingerprint, encrypted_token, token_id, status, created_at
|
||||
`, id, status).Scan(
|
||||
&stored.ID,
|
||||
&stored.Name,
|
||||
&stored.APIEndpoint,
|
||||
&stored.TLSFingerprint,
|
||||
&stored.EncryptedToken,
|
||||
&stored.TokenID,
|
||||
&stored.Status,
|
||||
&stored.CreatedAt,
|
||||
)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return StoredCluster{}, false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return StoredCluster{}, false, err
|
||||
}
|
||||
|
||||
return stored, true, nil
|
||||
}
|
||||
|
||||
@@ -83,6 +83,37 @@ func TestRepositoryReturnsErrorWhenStoredTokenUsesWrongKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositorySetsClusterStatusWithoutDecryptingToken(t *testing.T) {
|
||||
storage := newMemoryStorage()
|
||||
repository := NewRepositoryWithStorage(storage, testCipher(t, 1))
|
||||
|
||||
_, err := repository.UpsertCluster(context.Background(), Cluster{
|
||||
ID: "cluster-1",
|
||||
Name: "Lab",
|
||||
APIEndpoint: "https://pve.example.test:8006",
|
||||
TLSFingerprint: "AA:BB",
|
||||
TokenID: "root@pam!proxui",
|
||||
TokenSecret: "secret-token",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("UpsertCluster() error = %v", err)
|
||||
}
|
||||
|
||||
updated, found, err := repository.SetClusterStatus(context.Background(), "cluster-1", "disabled")
|
||||
if err != nil {
|
||||
t.Fatalf("SetClusterStatus() error = %v", err)
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("SetClusterStatus() found = false, want true")
|
||||
}
|
||||
if updated.Status != "disabled" {
|
||||
t.Fatalf("Status = %q, want disabled", updated.Status)
|
||||
}
|
||||
if updated.TokenSecret != "" {
|
||||
t.Fatal("SetClusterStatus() returned token secret")
|
||||
}
|
||||
}
|
||||
|
||||
func testCipher(t *testing.T, value byte) encryption.Cipher {
|
||||
t.Helper()
|
||||
|
||||
@@ -124,3 +155,13 @@ func (s *memoryStorage) Upsert(_ context.Context, cluster StoredCluster) (Stored
|
||||
s.records[cluster.ID] = cluster
|
||||
return cluster, nil
|
||||
}
|
||||
|
||||
func (s *memoryStorage) SetStatus(_ context.Context, id string, status string) (StoredCluster, bool, error) {
|
||||
cluster, ok := s.records[id]
|
||||
if !ok {
|
||||
return StoredCluster{}, false, nil
|
||||
}
|
||||
cluster.Status = status
|
||||
s.records[id] = cluster
|
||||
return cluster, true, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user