The solution involves checking if we are running as root. If so, try to create postgres user and group, pick out their id/pid, adopt the db directory and run the db server as that user.
The reasoning behind this: be able to run embedded-postgres inside a standard docker container (eg. for unit tests in CI).
Like in my other Issue, I ended up implementing this using patch-package:
constructor(options = {}) {
// Assign default options to options object
this.options = Object.assign({}, defaults, options);
instances.add(this);
this._spawnOptions = {};
}
async initialise() {
//...
// Check if we are running as root
const isRoot = os_1.userInfo().uid === 0;
if (isRoot) {
try {
child_process_1.execSync('groupadd postgres', {stdio: 'pipe'});
child_process_1.execSync('useradd -g postgres postgres', {stdio: 'pipe'});
this.options.on_log("Created user and group 'postgres'");
} catch(err) {
if (!err.message.includes('already exists')) {
this.options.on_error('Error while creating user/group:', err);
}
}
// Fetch the uid and gid of the newly created postgres user and group
let uid, gid;
try {
uid = parseInt(child_process_1.execSync('id -u postgres', {stdio: 'pipe'}).toString().trim());
gid = parseInt(child_process_1.execSync('id -g postgres', {stdio: 'pipe'}).toString().trim());
this.options.on_log("Postgres uid/gid: " + uid + "/" + gid);
} catch(err) {
this.options.on_error('Error while getting uid/gid:', err);
}
child_process_1.execSync('chown postgres:postgres ' + this.options.database_dir);
this.options.on_log("Postgres user is now the owner of " + this.options.database_dir);
this._spawnOptions = {
uid: uid,
gid: gid
};
}
// Initialize the database
await new Promise((resolve, reject) => {
const process = (0, child_process_1.spawn)(initdb, [
`--pgdata=${this.options.database_dir}`,
`--auth=${this.options.auth_method}`,
`--username=${this.options.user}`,
`--pwfile=${passwordFile}`,
], this._spawnOptions);
// ....
// Spawn a postgres server
this.process = (0, child_process_1.spawn)(postgres, [
'-D',
this.options.database_dir,
'-p',
this.options.port.toString(),
], this._spawnOptions);
This is very rough, using sync functions, etc. As in my other issue, the problem is I couldn't set up the project to work with real TS code. So I ended up hacking this together, that solves my use case.
The solution involves checking if we are running as root. If so, try to create
postgres
user and group, pick out their id/pid, adopt the db directory and run the db server as that user.The reasoning behind this: be able to run embedded-postgres inside a standard docker container (eg. for unit tests in CI).
Like in my other Issue, I ended up implementing this using patch-package:
This is very rough, using sync functions, etc. As in my other issue, the problem is I couldn't set up the project to work with real TS code. So I ended up hacking this together, that solves my use case.