sqitchers / sqitch

Sensible database change management
https://sqitch.org
MIT License
2.78k stars 215 forks source link

Can’t call method “gecos” on an undefined value #459

Closed ferdinandsalis closed 5 years ago

ferdinandsalis commented 5 years ago

This currently happens in my ci pipleline (semaphore) which used to work.

Sqitch: 0.9999 Environment: Ubuntu 18.04 LTS https://docs.semaphoreci.com/article/32-ubuntu-1804-image

$ sqitch deploy --cd ./state/schema -t insure_test_local
--
  | Adding registry tables to insure_test_local
  | Use of uninitialized value $gid in getgrgid at /usr/share/perl5/PgCommon.pm line 783.
  | Use of uninitialized value $gid in getgrgid at /usr/share/perl5/PgCommon.pm line 783.
  | Use of uninitialized value $gid in getgrgid at /usr/share/perl5/PgCommon.pm line 783.
  | Use of uninitialized value $gid in getgrgid at /usr/share/perl5/PgCommon.pm line 783.
  | Can't call method "gecos" on an undefined value at /bin/../lib/perl5/App/Sqitch.pm line 96.

Using a prior version of sqitch (0.9996) yields no errors.

theory commented 5 years ago

What's the output of

perl -Ilib -MApp::Sqitch -E 'say App::Sqitch->new->sysuser'

And is the output username a valid username on your system?

ferdinandsalis commented 5 years ago

This is the output

perl -Ilib -MApp::Sqitch -E 'say App::Sqitch->new->sysuser'
Can't locate App/Sqitch.pm in @INC (you may need to install the App::Sqitch module) (@INC contains: lib /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.26.1 /usr/local/share/perl/5.26.1 /usr/lib/x86_64-linux-gnu/perl5/5.26 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.26 /usr/share/perl/5.26 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base).
BEGIN failed--compilation aborted.

This is when I install sqitch via docker. However when I install via apt (installs 0.9996) it outputs semaphore which is a valid username on the system.

theory commented 5 years ago

How are you running the Docker image? Are you using the shell script? If so, what is the output of

getent passwd $user | cut -d: -f5 | cut -d, -f1

?

sijad commented 5 years ago

I have same issue with docker image using docker-sqitch.sh script.

this is the output of getent passwd $user | cut -d: -f5 | cut -d, -f1 in my host:


Nobody
System Message Bus
systemd Journal Remote
systemd Network Management
systemd Resolver
systemd Time Synchronization
systemd Core Dumper

git daemon user

Avahi mDNS/DNS-SD daemon
Color management daemon
PolicyKit daemon
usbmux user
Geoinformation service
RealtimeKit
MariaDB
PostgreSQL user
unbound
Redis in-memory data structure store

Dynamic User

in docker the outputs is usernames (does not include my host username)

I've changed docker-sqitch.sh to use .env file instead of mounting my home directory:

https://gist.github.com/sijad/829b3c0eef527015ae635d8ae3b62f87

theory commented 5 years ago

Uh, okay. I got the code from this SO answer, but maybe it needs to be different. What we want is the full name of the current user.

theory commented 5 years ago

Wait, the reason it failed for you is because $user isn't set (of course). Try

user=${USER-$(whoami)}; getent passwd "$user"

That should output something like:

sijad:*:1048:411:Sajjad Hashemian:/home/sijad:/bin/bash
sijad commented 5 years ago

you're right but my host username does not exists in docker container and I guess that's why I get this error.

grzegorzk commented 5 years ago

I have seen this error when running sqitch from docker container. I fixed it by mounting my /etc/passwd into /etc/passwd within container with readonly flag.

This is what I added to docker-sqitch:

    docker run -it --rm --network host \
        (...)
        --mount type=bind,src="/etc/passwd",dst="/etc/passwd",readonly \
        (...)

Also (not really related but taking advantage of opportunity...) docker-sqitch script defines homedst=/home, but later users home is mounted within/home/user_name` which was resulting in errors.

theory commented 5 years ago

Yes, but if you run docker-sqitch.sh, it should get the full username from your host system, not from inside the docker container, and set the $SQITCH_ORIG_FULLNAME environment variable, which, when set, prevents Sqitch from calling gecos. It also generally won't be called if you have user.name set in your Sqitch configuration file.

If you're running Sqitch from inside another Docker container as @grzegorzk describes, you can mount /etc/passwd, as they did, though it's a pretty ugly hack. I'm pretty surprised that any Docker container runs without any username at all. Anyway, you can get around it by setting the $SQITCH_ORIG_FULLNAME environment variable some other way; the purpose of the *ORIG* environment variables is to copy values from a host system to a contained system, as described in sqitch help environment.

At any rate, perhaps I need to update the code in Sqitch itself to detect when gecos returns no value and set the full name to "Anonymous" or "Unknown Name" or some such.