Closed jonasbadstuebner closed 1 year ago
Did the table networks
exist in your DB prior to upgrading?
It didn't. And I dropped the whole database and tried again, still the same issue. The networks table is created, but right after the migration fails.
That sounds like there's an operational problem, for example multiple migrations running at the same time or something.
I had the previous version of hydra running, but this should not break the migration, right? I removed my hydra deployment and will try to deploy the v2.0.2 manually.
This did not change anything. Only the v2.0.2 pod ran the automigration, nothing else was accessing hydras database. Still - this did not work. Can you tell me, how the migrations are done? Are they only taken from the migrations/
folder?
What can I do to find the source of this issue?
Are you using mariadb?
Yes - and I know that it is not officially supported - but can you tell me where it breaks? Since This execution should work the exact same no matter if I'm using MySQL or MariaDB...right?
If you give me this information, I am going to write docs and a PR to give basic MariaDB-Support. But I cannot do that, if I don't know where it breaks it's neck or why it is not just creating a table.
I found out that RANDOM_BYTES
is not existent for MariaDB prior to version 10.10.0.
So for the migrations to work on MariaDB, this function would have to be replaced, but would not break the functionality on MySQL.
As the author of the new "breaking" migrations wrote here, the stackoverflow thread contains a generic SQL solution, ready to be copy pasted from below.
I have the "working parts" of the failing migrations commented out.
-- Create the table
--CREATE TABLE `networks` (
-- `id` char(36) NOT NULL,
-- PRIMARY KEY(`id`),
-- `created_at` DATETIME NOT NULL,
-- `updated_at` DATETIME NOT NULL
--);
-- Insert first network with random ID
INSERT INTO networks (id, created_at, updated_at) VALUES (
(SELECT LOWER(CONCAT(
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
'4',
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
HEX(FLOOR(RAND() * 4 + 8)),
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'))))
, '2013-10-07 08:23:19', '2013-10-07 08:23:19');
-- to skip the migration in the future:
INSERT INTO `schema_migration` (`version`, `version_self`) VALUES ('20150101000001000000', '0');
There are more failing migrations, the fixes are similar: 20211004110001000000_change_client_primary_key
-- ALTER TABLE hydra_client CHANGE COLUMN pk pk_deprecated INT UNSIGNED;
-- ALTER TABLE hydra_client ADD COLUMN pk CHAR(36);
-- UUIDv4 generation based on https://stackoverflow.com/a/66868340/12723442
UPDATE hydra_client SET pk = (
SELECT LOWER(CONCAT(
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
'4',
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
HEX(FLOOR(RAND() * 4 + 8)),
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0')))
);
-- previously skipped commands (because of failure)
ALTER TABLE hydra_client DROP PRIMARY KEY, ADD PRIMARY KEY (pk);
ALTER TABLE hydra_client ADD KEY (pk_deprecated);
ALTER TABLE hydra_client CHANGE COLUMN pk_deprecated pk_deprecated INT UNSIGNED;
-- to skip the migration in the future:
INSERT INTO `schema_migration` (`version`, `version_self`) VALUES ('20211004110001000000', '0');
20211011000001000000_change_jwk_primary_key
-- ALTER TABLE hydra_jwk CHANGE COLUMN pk pk_deprecated INT UNSIGNED;
-- ALTER TABLE hydra_jwk ADD COLUMN pk CHAR(36);
-- UUIDv4 generation based on https://stackoverflow.com/a/66868340/12723442
UPDATE hydra_jwk SET pk = (
SELECT LOWER(CONCAT(
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'), '-',
'4',
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
HEX(FLOOR(RAND() * 4 + 8)),
LPAD(HEX(FLOOR(RAND() * 0x0fff)), 3, '0'), '-',
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0'),
LPAD(HEX(FLOOR(RAND() * 0xffff)), 4, '0')))
);
-- previously skipped commands (because of failure)
ALTER TABLE hydra_jwk ALTER pk DROP DEFAULT;
ALTER TABLE hydra_jwk DROP PRIMARY KEY, ADD PRIMARY KEY (pk);
ALTER TABLE hydra_jwk ADD KEY (pk_deprecated);
ALTER TABLE hydra_jwk CHANGE COLUMN pk_deprecated pk_deprecated INT UNSIGNED AUTO_INCREMENT;
-- to skip the migration in the future:
INSERT INTO `schema_migration` (`version`, `version_self`) VALUES ('20211011000001000000', '0');
MariaDB handles JSON differently than MySQL does. So here we need some other workaround: 20220513000001000001_string_slice_json.mysql.up.sql
UPDATE hydra_client SET redirect_uris_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(redirect_uris,'|','","') , '"]')),'$.tmp') WHERE redirect_uris <> '';
UPDATE hydra_client SET grant_types_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(grant_types,'|','","') , '"]')),'$.tmp') WHERE grant_types <> '';
UPDATE hydra_client SET response_types_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(response_types,'|','","') , '"]')),'$.tmp') WHERE response_types <> '';
UPDATE hydra_client SET audience_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(audience,'|','","') , '"]')),'$.tmp') WHERE audience <> '';
UPDATE hydra_client SET allowed_cors_origins_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(allowed_cors_origins,'|','","') , '"]')),'$.tmp') WHERE allowed_cors_origins <> '';
UPDATE hydra_client SET contacts_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(contacts,'|','","') , '"]')),'$.tmp') WHERE contacts <> '';
UPDATE hydra_client SET request_uris_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(request_uris,'|','","') , '"]')),'$.tmp') WHERE request_uris <> '';
UPDATE hydra_client SET post_logout_redirect_uris_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(post_logout_redirect_uris,'|','","') , '"]')),'$.tmp') WHERE post_logout_redirect_uris <> '';
-- to skip the migration in the future:
INSERT INTO `schema_migration` (`version`, `version_self`) VALUES ('20220513000001000001', '0');
20220513000001000007_string_slice_json.mysql.up.sql
UPDATE hydra_oauth2_flow SET requested_scope_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(requested_scope,'|','","') , '"]')),'$.tmp') WHERE requested_scope <> ('[]');
UPDATE hydra_oauth2_flow SET requested_at_audience_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(requested_at_audience,'|','","') , '"]')),'$.tmp') WHERE requested_at_audience <> ('[]');
UPDATE hydra_oauth2_flow SET amr_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(amr,'|','","') , '"]')),'$.tmp') WHERE amr <> ('[]');
UPDATE hydra_oauth2_flow SET granted_scope_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(granted_scope,'|','","') , '"]')),'$.tmp') WHERE granted_scope <> ('[]');
UPDATE hydra_oauth2_flow SET granted_at_audience_json = JSON_VALUE(json_object('tmp',concat('["' , REPLACE(granted_at_audience,'|','","') , '"]')),'$.tmp') WHERE granted_at_audience <> ('[]');
-- to skip the migration in the future:
INSERT INTO `schema_migration` (`version`, `version_self`) VALUES ('20220513000001000007', '0');
After every block of SQL queries, just restart the deployment and the init-container should break at the next of the blocks I provided. Check that with kubectl logs -f -n ory deployments/hydra -c hydra-automigrate
.
After all of that, you should see Successfully applied migrations!
and Hydra is starting.
I close this, since MariaDB is not officially supported. And if needed, I open and link more issues regarding MariaDB in the future, until maybe I open a PR to support MariaDB. I would volunteer to own that part of the code then.
I'm getting this exact issue in mysql 8.0 upgrading from 1.10.6 to 2.0.3 in my dev build
Preflight checklist
Describe the bug
Hydra v2.0.2 automigration fails with
I dropped the table but this did not work, since the automigration creates it twice, I think. When this error is thrown, the table exists again already. I looked into the failing migration but I'm missing the background information if there was any change to the migrations ("last pushed 3 months ago"). Maybe we could add an
IF NOT EXISTS
ref to theCREATE TABLE
statement? This would be an easy fix, but I don't know if this is desired behaviour then. This would give a warning, if the table exists, but would not fail.Reproducing the bug
Relevant log output
Relevant configuration
No response
Version
v2.0.2
On which operating system are you observing this issue?
Linux
In which environment are you deploying?
Kubernetes with Helm
Additional Context
No response