Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

New connector migration logic to support SQL moving to extension #1132

Merged
merged 2 commits into from
Mar 18, 2022

Conversation

jgpruitt
Copy link
Contributor

@jgpruitt jgpruitt commented Feb 9, 2022

Description

Make the extension required and delegate migrations to the extension

This PR makes the promscale extension required, while the timescaledb extension remains optional.
The minimum timescaledb version supported is now 2.6.0

The extension now handles applying database migrations. The connector's migration logic was updated accordingly.

If this is a fresh install, the connector will

  1. install the extension at the latest version

If promscale is installed at a database version prior to 0.5.0, the connector will

  1. apply any pending migrations from the old way of doing migrations
  2. drop the old version of the extension if it exists
  3. install the extension at 0.0.0 which will do some "takeover" logic
  4. update the extension to 0.5.0 (or whatever the latest version of the extension is)

If promscale is installed at database version 0.5.0 or greater, the connector will

  1. update the extension to 0.5.0 (or whatever the latest version of the extension is)

Merge requirements

Please take into account the following non-code changes that you may need to make with your PR:

  • CHANGELOG entry for user-facing changes
  • Updated the relevant documentation

@jgpruitt jgpruitt self-assigned this Feb 9, 2022
@jgpruitt jgpruitt added the Feature New features label Feb 9, 2022
@jgpruitt jgpruitt requested review from cevian and removed request for cevian February 9, 2022 19:46
@jgpruitt jgpruitt changed the title reorganizing a bit to prep for refactor New migration logic Feb 9, 2022
Copy link
Contributor

@cevian cevian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good progress. Some comments.

The error need more context because Golang is stupid in that it doesn't output stack traces with errors. I put in some examples, but there are more places in the code to fix

pkg/pgmodel/common/extension/extension.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/runner/client.go Outdated Show resolved Hide resolved
pkg/tests/end_to_end_tests/main_test.go Show resolved Hide resolved
if err == nil {
t.Errorf("Expected error in CheckDependencies")
}
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this seems like a key part of the test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping on this

pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
@JamesGuthrie
Copy link
Contributor

Also, can you rebase against current master, or merge master into extension-refactor, so that we can get this change: #1139

@jgpruitt
Copy link
Contributor Author

Also, can you rebase against current master, or merge master into extension-refactor, so that we can get this change: #1139

Done. Rebased extension-refactor on master and then this branch on it.

@JamesGuthrie
Copy link
Contributor

There's a minor change that we need to make with how Promscale handles schema generation. Here's the patch that I've been using to test it. It also adds some logging around the install/upgrade process which I found helpful to understand what's going on.

diff --git a/pkg/pgmodel/common/extension/extension.go b/pkg/pgmodel/common/extension/extension.go
index 3c2beec..0be24cf 100644
--- a/pkg/pgmodel/common/extension/extension.go
+++ b/pkg/pgmodel/common/extension/extension.go
@@ -202,9 +202,18 @@ func MigrateExtension(conn *pgx.Conn, extName string, extSchemaName string, vali
 	}
 
 	if !isInstalled {
-		_, extErr := conn.Exec(context.Background(),
-			fmt.Sprintf("CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s VERSION '%s'",
-				extName, extSchemaName, getSqlVersion(*newVersion, extName)))
+		var query = ""
+		switch extName {
+		case "timescaledb":
+			query = fmt.Sprintf("CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s VERSION '%s'",
+				extName, extSchemaName, getSqlVersion(*newVersion, extName))
+		case "promscale":
+			query = fmt.Sprintf("CREATE EXTENSION IF NOT EXISTS %s VERSION '%s'",
+				extName, getSqlVersion(*newVersion, extName))
+		default:
+			return fmt.Errorf("unknown extension: %s", extName)
+		}
+		_, extErr := conn.Exec(context.Background(), query)
 		if extErr != nil {
 			return extErr
 		}
diff --git a/pkg/pgmodel/new_migrate.go b/pkg/pgmodel/new_migrate.go
index ec3eaa4..af945f5 100644
--- a/pkg/pgmodel/new_migrate.go
+++ b/pkg/pgmodel/new_migrate.go
@@ -46,6 +46,7 @@ func removeOldExtensionIfExists(db *pgx.Conn) error {
 	}
 
 	if installed && installedVersion.LT(semver.MustParse(transition)) {
+		log.Info("msg", "Dropping extension at version '"+installedVersion.String()+"'")
 		_, err := db.Exec(
 			context.Background(),
 			stmt,
@@ -59,6 +60,7 @@ func removeOldExtensionIfExists(db *pgx.Conn) error {
 }
 
 func installExtensionAllBalls(db *pgx.Conn) error {
+	log.Info("msg", "Installing extension at version '0.0.0'")
 	const stmt = "CREATE EXTENSION promscale SCHEMA _prom_ext VERSION '0.0.0'"
 	_, err := db.Exec(
 		context.Background(),

Copy link
Contributor

@cevian cevian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly looks good, but there are a few issues.

image = "timescaledev/timescaledb:nightly-" + PGTag
}
return image, nil
return "timescaledev/promscale-extension:0.5.0-ts2-pg14", nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this will have to wait for my changes in PR #1199

pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
if searchPath != expected {
t.Errorf("incorrect search path\nexpected\n\t%s\nfound\n\t%s", expected, searchPath)
}
// TODO (james): I'm not sure that we should be removing the search path modification, I've started a discussion.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what I think: I don't think we should be removing search path modifications but they should also probably NOT be done in the extension. Rather they should still be done by the connector.

Not sure about this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although our tests should mostly test without search_path modifications

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to leave for now. Tracked here: https://github.com/timescale/promscale/issues/1256

if err == nil {
t.Errorf("Expected error in CheckDependencies")
}
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping on this

if _, err := db.Exec(context.Background(), "SELECT prom_api.register_metric_view('prom_data', 'metric_view_in_data_schema')"); err == nil {
t.Fatal("Should not be able to register a metric view in data schema")
}
// TODO (james): It doesn't seem as though what this test is testing is still valid.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this not a valid test? Even a superuser shouldn't be able to do this...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

pkg/pgmodel/common/extension/extension.go Outdated Show resolved Hide resolved
pkg/pgmodel/common/extension/extension.go Outdated Show resolved Hide resolved
- {name: "W/O Promscale Extension", shortname: "wo-prom-ext", ext: false, tsdb: true, tsdb2: true, tsdboss: false, multi: false, pg: 14}
- {name: "Plain Postgres", shortname: "plain-pg", ext: false, tsdb: false, tsdb2: false, tsdboss: false, multi: false, pg: 14}
- {name: "TimescaleDB-OSS", shortname: "tsdb-oss", ext: false, tsdb: true, tsdb2: true, tsdboss: true, multi: false, pg: 14}
- {name: "Plain Postgres (12)", shortname: "plain-pg-12", ext: true, tsdb: false, tsdb2: false, tsdboss: false, multi: false, pg: 12}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait pending #1199

return err
}
return pgmodel.CheckSchemaVersion(ctx, conn, appVersion, false)
return util.GetSharedLease(ctx, conn, schema.LockID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we call extension.CheckVersions here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it wasn't necessary since we check on startup and then hold a schema lease lock, but I guess that might not be foolproof.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in 089d60e

@cevian cevian added this to the 0.11.0 milestone Mar 11, 2022
@cevian cevian changed the title New migration logic New connector migration logic to support SQL moving to extension Mar 11, 2022
@jgpruitt jgpruitt changed the base branch from extension-refactor to master March 11, 2022 17:32
@jgpruitt jgpruitt force-pushed the jp/migration-refactor3 branch 3 times, most recently from aed2de5 to 5a87893 Compare March 11, 2022 18:43
Copy link
Contributor

@cevian cevian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much better only a few comments

pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
return err
}
return pgmodel.CheckSchemaVersion(ctx, conn, appVersion, false)
return util.GetSharedLease(ctx, conn, schema.LockID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

if _, err := db.Exec(context.Background(), "SELECT prom_api.register_metric_view('prom_data', 'metric_view_in_data_schema')"); err == nil {
t.Fatal("Should not be able to register a metric view in data schema")
}
// TODO (james): It doesn't seem as though what this test is testing is still valid.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

if searchPath != expected {
t.Errorf("incorrect search path\nexpected\n\t%s\nfound\n\t%s", expected, searchPath)
}
// TODO (james): I'm not sure that we should be removing the search path modification, I've started a discussion.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

pkg/tests/end_to_end_tests/migrate_test.go Outdated Show resolved Hide resolved
pkg/tests/upgrade_tests/shapshot.go Outdated Show resolved Hide resolved
@@ -75,13 +75,40 @@ func getDBImages(extensionState testhelpers.ExtensionState) (prev string, clean
//but migration code that works in an older PG version should generally work in a newer one.
panic("Only use pg12 for upgrade tests")
}
return "timescaledev/promscale-extension:0.1.1-ts2-pg12", testhelpers.LatestDBWithPromscaleImageBase + ":latest-ts2-pg12"
return "timescaledev/promscale-extension:0.1.2-ts2-pg13", testhelpers.LatestDBWithPromscaleImageBase + ":latest-ts2-pg13"
// using pg13 until we deal with the lack of "trusted" support in pg12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a note to block merge on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracked in #1257

pkg/tests/upgrade_tests/upgrade_test.go Outdated Show resolved Hide resolved
@@ -425,7 +464,7 @@ func withNewDBAtCurrentVersion(t testing.TB, DBName string, extensionState testh
addNode2(t, *testDatabase)
}
defer func() { _ = closer.Close() }()
connectURL := testhelpers.PgConnectURL(*testDatabase, testhelpers.NoSuperuser)
connectURL := testhelpers.PgConnectURL(*testDatabase, testhelpers.Superuser)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in 5ce1a3c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is back to Superuser now?

pkg/tests/end_to_end_tests/main_test.go Outdated Show resolved Hide resolved
pkg/pgmodel/common/extension/extension.go Outdated Show resolved Hide resolved
pkg/version/version.go Outdated Show resolved Hide resolved
pkg/internal/testhelpers/postgres_container.go Outdated Show resolved Hide resolved
pkg/pgmodel/common/extension/extension.go Outdated Show resolved Hide resolved
pkg/tests/end_to_end_tests/migrate_test.go Show resolved Hide resolved
@JamesGuthrie
Copy link
Contributor

Can we also squash the commits down?

@jgpruitt jgpruitt force-pushed the jp/migration-refactor3 branch 2 times, most recently from 09ffc49 to 923826d Compare March 17, 2022 19:46
@jgpruitt jgpruitt marked this pull request as ready for review March 18, 2022 13:48
pkg/pgmodel/new_migrate.go Outdated Show resolved Hide resolved
if searchPath != expected {
t.Errorf("incorrect search path\nexpected\n\t%s\nfound\n\t%s", expected, searchPath)
}
// TODO (james): I'm not sure that we should be removing the search path modification, I've started a discussion.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to leave for now. Tracked here: https://github.com/timescale/promscale/issues/1256

@@ -75,13 +75,40 @@ func getDBImages(extensionState testhelpers.ExtensionState) (prev string, clean
//but migration code that works in an older PG version should generally work in a newer one.
panic("Only use pg12 for upgrade tests")
}
return "timescaledev/promscale-extension:0.1.1-ts2-pg12", testhelpers.LatestDBWithPromscaleImageBase + ":latest-ts2-pg12"
return "timescaledev/promscale-extension:0.1.2-ts2-pg13", testhelpers.LatestDBWithPromscaleImageBase + ":latest-ts2-pg13"
// using pg13 until we deal with the lack of "trusted" support in pg12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracked in #1257

@@ -425,7 +464,7 @@ func withNewDBAtCurrentVersion(t testing.TB, DBName string, extensionState testh
addNode2(t, *testDatabase)
}
defer func() { _ = closer.Close() }()
connectURL := testhelpers.PgConnectURL(*testDatabase, testhelpers.NoSuperuser)
connectURL := testhelpers.PgConnectURL(*testDatabase, testhelpers.Superuser)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is back to Superuser now?

@jgpruitt jgpruitt requested a review from a team as a code owner March 18, 2022 18:44
jgpruitt and others added 2 commits March 18, 2022 13:52
This PR makes the promscale extension required, while the timescaledb extension remains optional.
The minimum timescaledb version supported is now 2.6.0

The extension now handles applying database migrations. The connector's migration logic was updated accordingly.

If this is a fresh install, the connector will

1. install the extension at the latest version

If promscale is installed at a database version prior to 0.5.0, the connector will

1. apply any pending migrations from the old way of doing migrations
2. drop the old version of the extension if it exists
3. install the extension at 0.0.0 which will do some "takeover" logic
4. update the extension to 0.5.0 (or whatever the latest version of the extension is)

If promscale is installed at database version 0.5.0 or greater, the connector will

1. update the extension to 0.5.0 (or whatever the latest version of the extension is)

Co-authored-by: Matvey Arye <mat@timescale.com>
Co-authored-by: James Guthrie <jguthrie@timescale.com>
The main goal of this change (which is probably too large) is to ensure
that we can build the promscale connector against a version of the
promscale extension which contains all of the necessary bits.

This change is motivated by the fact that there is now a hard dependency
on the extension, and we need to be able to test in-progress changes
across repositories.

The basic mechanism is that for each open PR in the promscale_extension
repo, there will be a docker image built and pushed to the registry at:
`ghcr.io/timescale/dev_promscale_extension:<special-tag-here>`.

`<special-tag-here>` is constructed from the branch name from which the
PR originated. When a PR is opened in the promscale repository, we look
to see if there is already a docker image corresponding to the branch
name. If not, we fall back to the most recent docker image which was
built on the `develop` branch in the extension repository.

`<special-tag-here>` has the basic form of:

  `<extension-version>-<timescale-major>-<pg-version>`

Some examples are:
- `jg-ha-dockerfile-ts2-pg14`
- `develop-ts2-pg14`
- `0.5.0-ts2-pg14`

Local development is supported through two mechanisms:

1. When running e.g. `make docker-image-14` in the promscale_extension
   repo, the docker image is tagged as: `local/dev_promscale_extension`
   with the `<extension-version>` component of the tag set to `head`.
2. When running `make test` in the promscale repo, it first looks to see
   if a local image is available matching the `local/` prefix, then
   checks for a docker image derived from the current branch name, and
   then for built from the `develop` branch.

A number of things have changed tangentially as well:

- end_to_end tests now take the docker image which they should run
  against as an argument instead of using some magic to derive it
- `make test` was split into two components: `make unit` and `make e2e`
- multinode tests are being skipped because we broke them in the develop
  branch of the promscale extension
@jgpruitt jgpruitt enabled auto-merge (rebase) March 18, 2022 20:05
@jgpruitt jgpruitt dismissed JamesGuthrie’s stale review March 18, 2022 20:05

Addressed requests

@jgpruitt jgpruitt merged commit df8041a into master Mar 18, 2022
@jgpruitt jgpruitt deleted the jp/migration-refactor3 branch March 18, 2022 20:05
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Feature New features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants