When attempting to upgrade to TAS 4.x, the Cloud Controller pre-start script fails with the following error:
[2024-05-04 09:57:48+0000] Sequel::ForeignKeyConstraintViolation: Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails (`ccdb`.`buildpack_lifecycle_buildpacks`, CONSTRAINT `fk_blbuildpack_bldata_guid` FOREIGN KEY (`buildpack_lifecycle_data_guid`) REFERENCES `buildpack_lifecycle_data` (`guid`) ON DELETE RESTRICT) (Sequel::ForeignKeyConstraintViolation)
Tanzu Application Services 4.x
This is caused by orphaned entries in the buildpack_lifecycle_data table in the cloud controller database. The migration that attempts to delete these entries is here:
https://github.com/cloudfoundry/cloud_controller_ng/blob/ad9b5a1f29526df1307edf4644a0e733bbbb8bcb/db/migrations/20240115163000_add_delete_cascade_to_foreign_keys.rb#L11-L12
Note: Before performing these steps, please ensure you take a backup of the cloud controller database using the Backup and Restore procedure
First, connect to the Cloud Controller database:
Once connected, we need to confirm the entries to be deleted from the buildpack_lifecycle_data table:
SELECT * FROM buildpack_lifecycle_data WHERE (build_guid NOT IN (SELECT guid FROM builds));
These are orphaned entries that the migration was attempting to delete, but was failing due to the foreign key constraint.
Next, we need to check on the entries in the buildpack_lifecycle_buildpacks, which is the other side of the foreign key constraint.
SELECT * FROM buildpack_lifecycle_buildpacks WHERE buildpack_lifecycle_data_guid in (SELECT guid FROM buildpack_lifecycle_data WHERE (build_guid NOT IN (SELECT guid FROM builds)));
Once you have verified these entries, we need run the delete queries. First, we will attempt the same DELETE used by the migration. We should see the same error as in the cloud controller logs at this stage:
DELETE FROM buildpack_lifecycle_data WHERE (build_guid NOT IN (SELECT guid FROM builds));
Next is the DELETE to remove the orphaned entries in the buildpack_lifecycle_buildpacks table. This should unblock the migration attempt:
DELETE FROM buildpack_lifecycle_buildpacks where buildpack_lifecycle_data_guid in (SELECT guid FROM buildpack_lifecycle_data WHERE (build_guid NOT IN (SELECT guid FROM builds)));
We can then re-run the migration DELETE. This should now succeed.
DELETE FROM buildpack_lifecycle_data WHERE (build_guid NOT IN (SELECT guid FROM builds));
Finally, confirm that there are no longer any orphaned entries:
SELECT * FROM buildpack_lifecycle_data WHERE (build_guid NOT IN (SELECT guid FROM builds));
(should be zero rows)
The upgrade should now succeed on the next attempt.