From 27e74ef277fc28d186fa8957681fd62d6a030fa5 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Tue, 7 May 2024 11:41:45 +0000 Subject: [PATCH] Add DB migration test Signed-off-by: Gabriel Adrian Samfira --- database/sql/github_test.go | 140 ++++++++++++++++++++++++++++++++++++ testdata/db/v0.1.4/garm.db | Bin 0 -> 245760 bytes 2 files changed, 140 insertions(+) create mode 100644 testdata/db/v0.1.4/garm.db diff --git a/database/sql/github_test.go b/database/sql/github_test.go index b7621ec9..101ac411 100644 --- a/database/sql/github_test.go +++ b/database/sql/github_test.go @@ -15,7 +15,9 @@ package sql import ( + "bytes" "context" + "encoding/json" "fmt" "os" "testing" @@ -24,6 +26,7 @@ import ( runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" + "github.com/cloudbase/garm/config" "github.com/cloudbase/garm/database/common" garmTesting "github.com/cloudbase/garm/internal/testing" "github.com/cloudbase/garm/params" @@ -738,3 +741,140 @@ func TestGithubTestSuite(t *testing.T) { t.Parallel() suite.Run(t, new(GithubTestSuite)) } + +func TestCredentialsAndEndpointMigration(t *testing.T) { + cfg := garmTesting.GetTestSqliteDBConfig(t) + + // Copy the sample DB + data, err := os.ReadFile("../../testdata/db/v0.1.4/garm.db") + if err != nil { + t.Fatalf("failed to read test data: %s", err) + } + + if cfg.SQLite.DBFile == "" { + t.Fatalf("DB file not set") + } + if err := os.WriteFile(cfg.SQLite.DBFile, data, 0o600); err != nil { + t.Fatalf("failed to write test data: %s", err) + } + + // define some credentials + credentials := []config.Github{ + { + Name: "test-creds", + Description: "test creds", + AuthType: config.GithubAuthTypePAT, + PAT: config.GithubPAT{ + OAuth2Token: "test", + }, + }, + { + Name: "ghes-test", + Description: "ghes creds", + APIBaseURL: testAPIBaseURL, + UploadBaseURL: testUploadBaseURL, + BaseURL: testBaseURL, + AuthType: config.GithubAuthTypeApp, + App: config.GithubApp{ + AppID: 1, + InstallationID: 99, + PrivateKeyPath: "../../testdata/certs/srv-key.pem", + }, + }, + } + // Set the config credentials in the cfg. This is what happens in the main function. + // of GARM as well. + cfg.MigrateCredentials = credentials + + db, err := NewSQLDatabase(context.Background(), cfg) + if err != nil { + t.Fatalf("failed to create db connection: %s", err) + } + + // We expect that 2 endpoints will exist in the migrated DB and 2 credentials. + ctx := garmTesting.ImpersonateAdminContext(context.Background(), db, t) + + endpoints, err := db.ListGithubEndpoints(ctx) + if err != nil { + t.Fatalf("failed to list endpoints: %s", err) + } + if len(endpoints) != 2 { + t.Fatalf("expected 2 endpoints, got %d", len(endpoints)) + } + if endpoints[0].Name != defaultGithubEndpoint { + t.Fatalf("expected default endpoint to exist, got %s", endpoints[0].Name) + } + if endpoints[1].Name != "example.com" { + t.Fatalf("expected example.com endpoint to exist, got %s", endpoints[1].Name) + } + if endpoints[1].UploadBaseURL != testUploadBaseURL { + t.Fatalf("expected upload base URL to be %s, got %s", testUploadBaseURL, endpoints[1].UploadBaseURL) + } + if endpoints[1].BaseURL != testBaseURL { + t.Fatalf("expected base URL to be %s, got %s", testBaseURL, endpoints[1].BaseURL) + } + if endpoints[1].APIBaseURL != testAPIBaseURL { + t.Fatalf("expected API base URL to be %s, got %s", testAPIBaseURL, endpoints[1].APIBaseURL) + } + + creds, err := db.ListGithubCredentials(ctx) + if err != nil { + t.Fatalf("failed to list credentials: %s", err) + } + if len(creds) != 2 { + t.Fatalf("expected 2 credentials, got %d", len(creds)) + } + if creds[0].Name != "test-creds" { + t.Fatalf("expected test-creds to exist, got %s", creds[0].Name) + } + if creds[1].Name != "ghes-test" { + t.Fatalf("expected ghes-test to exist, got %s", creds[1].Name) + } + if creds[0].Endpoint.Name != defaultGithubEndpoint { + t.Fatalf("expected test-creds to be associated with default endpoint, got %s", creds[0].Endpoint.Name) + } + if creds[1].Endpoint.Name != "example.com" { + t.Fatalf("expected ghes-test to be associated with example.com endpoint, got %s", creds[1].Endpoint.Name) + } + + if creds[0].AuthType != params.GithubAuthTypePAT { + t.Fatalf("expected test-creds to have PAT auth type, got %s", creds[0].AuthType) + } + if creds[1].AuthType != params.GithubAuthTypeApp { + t.Fatalf("expected ghes-test to have App auth type, got %s", creds[1].AuthType) + } + if len(creds[0].CredentialsPayload) == 0 { + t.Fatalf("expected test-creds to have credentials payload, got empty") + } + + var pat params.GithubPAT + if err := json.Unmarshal(creds[0].CredentialsPayload, &pat); err != nil { + t.Fatalf("failed to unmarshal test-creds credentials payload: %s", err) + } + if pat.OAuth2Token != "test" { + t.Fatalf("expected test-creds to have PAT token test, got %s", pat.OAuth2Token) + } + + var app params.GithubApp + if err := json.Unmarshal(creds[1].CredentialsPayload, &app); err != nil { + t.Fatalf("failed to unmarshal ghes-test credentials payload: %s", err) + } + if app.AppID != 1 { + t.Fatalf("expected ghes-test to have app ID 1, got %d", app.AppID) + } + if app.InstallationID != 99 { + t.Fatalf("expected ghes-test to have installation ID 99, got %d", app.InstallationID) + } + if app.PrivateKeyBytes == nil { + t.Fatalf("expected ghes-test to have private key bytes, got nil") + } + + certBundle, err := credentials[1].App.PrivateKeyBytes() + if err != nil { + t.Fatalf("failed to read CA cert bundle: %s", err) + } + + if !bytes.Equal(app.PrivateKeyBytes, certBundle) { + t.Fatalf("expected ghes-test private key to be equal to the CA cert bundle") + } +} diff --git a/testdata/db/v0.1.4/garm.db b/testdata/db/v0.1.4/garm.db new file mode 100644 index 0000000000000000000000000000000000000000..7308e31f413bb5fceea4fd1e0848195a44df2d68 GIT binary patch literal 245760 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 literal 0 HcmV?d00001