Sync instances with harvester core-plugin - issues&fixes

Hi everyone!

This is a configuration/bugreport - what am I doing wrong? - kind of question and belongs in both categories, maintenance&development, probably.

I set up a secondary OpenBIS instance as described here (version 20.10.11, same as our production instance), but using podman: Quickstart — Python documentation
It runs fine so far but contains default data&types only, of course. Therefore, I’d like to mirror the contents of the production instance as far as my credentials allow. For this, I found the Harvester core-plugin: openBIS Sync — Python documentation

There were some technical complications with that. Issues #3 and especially #4 I’d like to discuss:

  1. I needed to add the custom TLS cert of the production instance to the keystore within the container - that’s rather straight forward

  2. When dry-running the harvester, I got errors about failed connections to localhost:5432 (postgres port). This is because the postgres DB runs in a different container which has a separate hostname. I could not easily find out where this comes from. I just set up port-forwarding in the application container (openbis-app) to the DB container:
    localhost:5432 → openbis-db:5432.

  3. During the initial dry-run of the Harvester, it stops at Update timestamps and users with an exception caused by the listAllUsers() function (trace below) and I wonder, why?
    After looking around for some time in the configuration and code, I came across the data-sources config in openbis-sync core-plugins/openbis-sync/2/dss/data-sources/openbis-db/plugin.properties. There, I added the config entries urlHostPart, scriptFolder, owner, password, adminUser and adminPassword as in the main dss/service.properties. Not all are necessary, I assume, but that made the error below disappear and finish the dry-run successfully. Is this the expected configuration? (‘cause its missing in the docs)

    2025-11-24 18:18:38,210 INFO  -------- monitoring started for 'Update timestamps and users'.
    2025-11-24 18:18:38,210 INFO  /-------------- Short Summary --------------
    2025-11-24 18:18:38,277 INFO  |      19 users ADDED
    2025-11-24 18:18:38,340 ERROR Sync (dry run) failed:
    org.springframework.jdbc.UncategorizedSQLException: listAllUsers; uncategorized SQLException for SQL [select id,user_id as userId from persons]; SQL state [null]; error code [0]; Cannot create PoolableConnectionFactory (The server requested SCRAM-based authentication, but the password is an empty string.); nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (The server requested SCRAM-based authentication, but the password is an empty string.)
            at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89)
            at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
            at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
            at ch.systemsx.cisd.openbis.common.spring.SpringEoDSQLExceptionTranslator.translateException(SpringEoDSQLExceptionTranslator.java:52)
            at net.lemnik.eodsql.impl.ExceptionTranslationUtils.translateException(Unknown Source)
            at net.lemnik.eodsql.impl.ExceptionTranslationUtils.translateException(Unknown Source)
            at net.lemnik.eodsql.impl.ExceptionTranslationUtils.translateException(Unknown Source)
            at net.lemnik.eodsql.impl.BaseQueryImpl.invoke(Unknown Source)
            at com.sun.proxy.$Proxy62.listAllUsers(Unknown Source)
            at ch.ethz.sis.openbis.generic.server.dss.plugins.sync.harvester.synchronizer.EntitySynchronizer.getUserTechIds(EntitySynchronizer.java:247)
            at ch.ethz.sis.openbis.generic.server.dss.plugins.sync.harvester.synchronizer.EntitySynchronizer.updateTimestampsAndUsers(EntitySynchronizer.java:234)
            at ch.ethz.sis.openbis.generic.server.dss.plugins.sync.harvester.synchronizer.EntitySynchronizer.synchronizeEntities(EntitySynchronizer.java:217)
            at ch.ethz.sis.openbis.generic.server.dss.plugins.sync.harvester.HarvesterMaintenanceTask.synchronize(HarvesterMaintenanceTask.java:236)
            at ch.ethz.sis.openbis.generic.server.dss.plugins.sync.harvester.HarvesterMaintenanceTask.execute(HarvesterMaintenanceTask.java:161)
    
  4. After a successful dry-run, it runs the synchronization for real, imports all the masterdata just fine. But stops when beginning to register the entities, sadly. It complains about unknown permId - but I wonder, isn’t that (restoring permIds) what the sync should do?

    2025-11-24 19:09:15,557 INFO  -------- monitoring started for 'Register entities'.
    2025-11-24 19:09:27,395 ERROR Sync failed:
    ch.systemsx.cisd.common.exceptions.UserFailureException: No sample could be found for perm id 20240925075946115-7310.
            at ch.systemsx.cisd.common.exceptions.UserFailureException.fromTemplate(UserFailureException.java:48)
    

Since the dry-run was successful, finally, I wonder what is wrong and how to get it to sync the entities as well? Is it designed to restore permIds? In my case, it’s for an object property of a custom PERSON type (responsible person for a measurement, here).
I’m out of ideas how to work around, since I can’t create objects with specific permIds with pyBIS, right? Are there other options?

About some insights about what to expect or even how to fix, I’d be very happy.

Thank you very much (also for reading so far)!
Best wishes
Ingo