fix: support postgres initial agent setup (#1410)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -12,7 +13,9 @@ import (
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
"github.com/kandev/kandev/internal/agent/registry"
|
||||
"github.com/kandev/kandev/internal/common/config"
|
||||
"github.com/kandev/kandev/internal/events/bus"
|
||||
"github.com/kandev/kandev/internal/testutil"
|
||||
)
|
||||
|
||||
@@ -62,6 +65,31 @@ func TestPostgresBootInitializesRepositories(t *testing.T) {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
agentRegistry, registryCleanup, err := registry.Provide(log)
|
||||
if err != nil {
|
||||
t.Fatalf("provide agent registry: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if registryCleanup != nil {
|
||||
_ = registryCleanup()
|
||||
}
|
||||
})
|
||||
services, agentSettingsController, err := provideServices(
|
||||
cfg,
|
||||
log,
|
||||
repos,
|
||||
pool,
|
||||
bus.NewMemoryEventBus(log),
|
||||
agentRegistry,
|
||||
"test-postgres-boot",
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("provide services with postgres: %v", err)
|
||||
}
|
||||
if err := runInitialAgentSetup(context.Background(), services.User, agentSettingsController, log); err != nil {
|
||||
t.Fatalf("run initial agent setup with postgres: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type postgresConnInfo struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/kandev/kandev/internal/testutil"
|
||||
@@ -13,3 +14,45 @@ func TestPostgresFreshSchemaInitializes(t *testing.T) {
|
||||
t.Fatalf("init fresh postgres schema: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostgresHasDeletedAgentProfilesHandlesMissingAgent(t *testing.T) {
|
||||
db := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
|
||||
repo, err := newSQLiteRepositoryWithDB(db, db, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("init fresh postgres schema: %v", err)
|
||||
}
|
||||
|
||||
hasDeleted, err := repo.HasDeletedAgentProfiles(context.Background(), "missing-agent")
|
||||
if err != nil {
|
||||
t.Fatalf("HasDeletedAgentProfiles: %v", err)
|
||||
}
|
||||
if hasDeleted {
|
||||
t.Fatal("HasDeletedAgentProfiles = true, want false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostgresHasDeletedAgentProfilesReturnsTrueForDeletedProfile(t *testing.T) {
|
||||
db := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
|
||||
repo, err := newSQLiteRepositoryWithDB(db, db, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("init fresh postgres schema: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
profileID := seedAgentProfile(t, repo, "postgres-deleted", "postgres-agent")
|
||||
profile, err := repo.GetAgentProfileIncludingDeleted(ctx, profileID)
|
||||
if err != nil {
|
||||
t.Fatalf("lookup profile: %v", err)
|
||||
}
|
||||
if err := repo.DeleteAgentProfile(ctx, profileID); err != nil {
|
||||
t.Fatalf("delete profile: %v", err)
|
||||
}
|
||||
|
||||
hasDeleted, err := repo.HasDeletedAgentProfiles(ctx, profile.AgentID)
|
||||
if err != nil {
|
||||
t.Fatalf("HasDeletedAgentProfiles: %v", err)
|
||||
}
|
||||
if !hasDeleted {
|
||||
t.Fatal("HasDeletedAgentProfiles = false, want true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,12 +860,15 @@ func (r *sqliteRepository) ListAgentProfiles(ctx context.Context, agentID string
|
||||
func (r *sqliteRepository) HasDeletedAgentProfiles(ctx context.Context, agentID string) (bool, error) {
|
||||
var exists int
|
||||
err := r.ro.QueryRowContext(ctx,
|
||||
r.ro.Rebind(`SELECT EXISTS(SELECT 1 FROM agent_profiles WHERE agent_id = ? AND deleted_at IS NOT NULL)`),
|
||||
r.ro.Rebind(`SELECT 1 FROM agent_profiles WHERE agent_id = ? AND deleted_at IS NOT NULL LIMIT 1`),
|
||||
agentID).Scan(&exists)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return exists == 1, nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// applyLegacyBackfill returns the profile with CLIFlags populated from the
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
"github.com/kandev/kandev/internal/db"
|
||||
"github.com/kandev/kandev/internal/db/dialect"
|
||||
)
|
||||
|
||||
// Store persists install-wide Kandev settings that are not scoped to a user,
|
||||
@@ -39,6 +40,10 @@ func (s *Store) initSchema() error {
|
||||
}
|
||||
|
||||
func (s *Store) migrateLegacySystemSettings() error {
|
||||
if dialect.IsPostgres(s.db.DriverName()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var exists int
|
||||
if err := s.db.QueryRow(`
|
||||
SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = 'system_settings'
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
|
||||
"github.com/kandev/kandev/internal/db"
|
||||
"github.com/kandev/kandev/internal/testutil"
|
||||
)
|
||||
|
||||
func TestStoreSaveAndGet(t *testing.T) {
|
||||
@@ -62,6 +63,26 @@ func TestStoreMigratesLegacySystemSettings(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreInitializesOnPostgres(t *testing.T) {
|
||||
conn := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
|
||||
store, err := NewStore(db.NewPool(conn, conn))
|
||||
if err != nil {
|
||||
t.Fatalf("new postgres store: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
if err := store.Save(ctx, "system_metrics", []byte(`{"interval_seconds":5}`)); err != nil {
|
||||
t.Fatalf("save postgres setting: %v", err)
|
||||
}
|
||||
value, found, err := store.Get(ctx, "system_metrics")
|
||||
if err != nil {
|
||||
t.Fatalf("get postgres setting: %v", err)
|
||||
}
|
||||
if !found || string(value) != `{"interval_seconds":5}` {
|
||||
t.Fatalf("postgres value = (%q, %v)", value, found)
|
||||
}
|
||||
}
|
||||
|
||||
func newTestStore(t *testing.T) *Store {
|
||||
t.Helper()
|
||||
conn := newSQLite(t)
|
||||
|
||||
Reference in New Issue
Block a user