Yes. You are right. Even the postgresql-13-setup script from postgresql does it with runuser -l.
But by now, it seems we have found the reason and a potential workaround.
Looking the last katello.log on my server I see this line:
[configure] /Stage[main]/Postgresql::Server::Initdb/Postgresql::Server::Instance::Initdb[main]/Exec[postgresql_initdb_instance_main]: '/usr/bin/initdb --pgdata '/var/lib/pgsql/data' --username 'postgres' ' won't be executed because of failed check 'creates'
This looks to me as if foreman-installer initializes the database as user root, calling initdb directly, which probably means in that step the current userās locale applies.
The upgrade runs through runuser -l which uses the system locale.
Both together would suggest that foreman-installer causes this, because it doesnāt use runuser -l for initdb (and doesnāt use postgresql-setup --initdb either). So this would make it a foreman-installer bug, because it relies on the system locale being used by the user running foreman-installer.
I would say it would be good if foreman-installer would check the locale of the database and the system locale and would raise an error if it finds an inconsistency. That would be better than people trying to find the right log file with the right piece of information pointing to the cause of the problemā¦
I think for most Puppet users this isnāt a problem because Puppet runs as a daemon with the system locale, but our installer is different. Iām wondering if it would be better to let the installer ensure Puppet runs with the system locale.
Please do not do that! Never do that! That is very dangerous! Technically your database is corrupted after that because you just told postgresql that the main postgres database has a different collation and ctype from what it actually does. It may just work for you because you are coming from C.UTF-8 and thus any strings in the database should directly map to en_US.UTF-8 without modification.
For someone else coming from a different collation it may cause serious issues.
But again: technically itās corrupted! Do not attempt it. String may be broken. Indexes may be broken. Anything string related may be broken. You may not even notice where itās broken until much later when you cannot find the texts you are looking for or worse itās causes internal crashes/exceptions because a text cannot be interpreted as itās the wrong locale.
Anything supported to be changed, can be changed through ALTER commands. Messing in the tables in postgres database can have serious effects.
The only supported way to āchangeā the collation or ctype is by dumping the database and restoring the dump into a new database created with the correct locale.
Otherwise, change the system locale to match and do the upgrade of the database. After that, it doesnāt matter. This is a bug of the redhat postgresql-setup script. Donāt break the database as workaround to this bugā¦
Only a postgresql developer might know that. Itās an inconsistent state. I donāt know where the information in the pg_database table is used. But itās not a trivial change otherwise there would probably an ALTER DATABASE option for that.
You can only revert to a snapshot before the upgrade or check a backup to find out the locale before. But even then, itās not safe to assume that simply changing it back would bring it into a consistent state again. You have changed it in postgresql 12 and upgraded to 13 with this. Even if I would guess that itās not an issue because the system postgres database will hopefully hold mostly ascii strings, unless someone know exactly the implications of these two columns in the pg_database table itās impossible to predict. Chances are it doesnāt matter.
To be safe, revert to a snapshot or backup before the upgrade and upgrade again.
Iāve taken your suggestion and I developed a different solution where I dump the old database and create a new database with the appropriate locales
/* create db */
create database postgres_new with owner=postgres encoding='UTF-8' lc_collate='en_US.UTF-8'
alter database postgres_new with allow_connections=true;
/* dump old db and restore in new db */
pg_dump -d postgres > /tmp/postgresbak.sql
psql -d postgres_new < /tmp/postgresbak.sql
/* drop old db */
lc_ctype='en_US.UTF-8' template template0;
alter database postgres rename to postgres_old;
alter database postgres_new rename to postgres;
drop database postgres_old
This solution also worked for me however Iām trying to understand how this is any different than my original solution when we have always used the en_US.UTF-8 locales.
Whatever changed in the recent version of this package to cause the locales to be set to C.UTF-8 for all users seems to be done in the interest of ensuring everyone has a POSIX standard locale that will be compatible for upgrade but this only seems to have created a mismatch for every user. What is the philosophy behind this?
I donāt think that is any better than messing with the postgres internal table. The database postgres is the internal table. I wouldnāt mess with it. I am surprised that this is working at all because when you rename the database you donāt have a database postgres for a moment. It wonder how it works at all.
Did you check after the drop database if there are still old database files opened which have been deleted. Did you restart the postgresql server since then? My guess would be that it wrote the information into files which were already openā¦
If you dump and restore to change the locale of the whole database, you have to dump all databases on the server, run initdb with the correct locale options and then restore.
I can only repeat: set the correct locale for the upgrade. Itās a bug of the postgresql-setup that it doesnāt use the current database locale for the inplace upgrade. With the correct locale set, at least for the duration of the upgrade, itāll work. Donāt try to change something internally which isnāt broken only because something else is broken.
With your change you never know what the impact may be. As far as I understand postgresql initializes the postgres, template0 and template1 database with the same locale. Possibly with your change, youāll end up with a database which cannot be upgraded anymore because those three arenāt matching. Or whatever.
Donāt try to tweak internals to work around an issue, which can be handled by setting the correct locale while running the database upgrade, until the upgrade script has been fixed by redhat to handle this case correctly.
I donāt understand why you donāt want to set the locale but rather mess with internals for which you donāt understand the consequences.
This was not expected but I am pretty sure it happened because that is the locale on my laptop and I SSH in to install the proxy so the remote shell inherited my environments.
I used sudo -i which keeps some of these environment as well.
Here is how I did it:
Took a VM snapshot.
sudo foreman-maintain service stop --exclude postgresql
sudo su - postgres # donāt use sudo -i as it will inherit remote locale
So for me the fix was to revert to snapshot before my failed upgrade attempt, and then re-do the upgrade after switching system locale to match the postgres database: