Re: [PATCH] Find additional connection service files in pg_service.conf.d directory

From: Andres Freund <andres(at)anarazel(dot)de>
To: Curt Tilmes <curt(at)tilmes(dot)org>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: [PATCH] Find additional connection service files in pg_service.conf.d directory
Date: 2018-03-01 08:53:25
Message-ID: 20180301085325.k2r6i546t37pbmf5@alap3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On 2018-01-12 09:53:51 -0500, Curt Tilmes wrote:
> I love centralizing connection service definitions in
> <sysconfdir>/pg_service.conf, but for a
> large enterprise, sometimes we have multiple sets of connection
> service definitions
> independently managed.
>
> The convention widely adopted for this type of thing is to allow
> multiple config files to be in
> a directory, usually the '.d' version of the config filename. See, for example:
>
> What do you think?

Seems like a reasonable idea to me.

> @@ -4492,10 +4493,14 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
> {
> const char *service = conninfo_getval(options, "service");
> char serviceFile[MAXPGPATH];
> + char serviceDirPath[MAXPGPATH];
> char *env;
> bool group_found = false;
> int status;
> struct stat stat_buf;
> + DIR *serviceDir;
> + struct dirent *direntry;
> +
>
> /*
> * We have to special-case the environment variable PGSERVICE here, since
> @@ -4539,21 +4544,45 @@ next_file:
> snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
> getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
> if (stat(serviceFile, &stat_buf) != 0)
> + goto conf_dir;
> +
> + status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
> + if (group_found || status != 0)
> + return status;
> +
> +conf_dir:
> +

This is already pretty crufty, can't we make this look a bit prettier,
rather than extending this approach?

> + /*
> + * Try every file in pg_service.conf.d/*
> + */
> + snprintf(serviceDirPath, MAXPGPATH, "%s/pg_service.conf.d",
> + getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
> +
> + if (stat(serviceDirPath, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode) ||
> + (serviceDir = opendir(serviceDirPath)) == NULL)
> goto last_file;

This looks a bit ugly.

> - status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
> - if (status != 0)
> - return status;
> + while ((direntry = readdir(serviceDir)) != NULL)

So there's no really well defined order in which we parse these?

> + {
> + snprintf(serviceFile, MAXPGPATH, "%s/%s", serviceDirPath, direntry->d_name);
> +

In my experience with such .conf.d directories it's very useful to
filter names not matching a common pattern. Otherwise you end up with
editor tempfiles and such being used, which gets confusing.

> + if (stat(serviceFile, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode) ||
> + access(serviceFile, R_OK))
> + continue;

This doesn't look particularly pretty, but ...

Greetings,

Andres Freund

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2018-03-01 08:57:44 Re: PATCH: pgbench - break out timing data for initialization phases
Previous Message Andres Freund 2018-03-01 08:34:04 Re: PATCH: pgbench - option to build using ppoll() for larger connection counts