Skip to content

Commit

Permalink
Merge pull request #5907 from garlick/issue#5898
Browse files Browse the repository at this point in the history
add options for offline config file parsing
  • Loading branch information
mergify[bot] committed Apr 22, 2024
2 parents 60f3341 + 4042bd1 commit 63953d3
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 14 deletions.
16 changes: 16 additions & 0 deletions doc/man1/flux-config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ scripts.
*fsd* prints the value in its human-readable, string form. *fsd-integer*
and *fsd-real* print the value in integer and real seconds, respectively.

.. option:: -c, --config-path=PATH

Read configuration from PATH instead of fetching configuration from local
broker. If PATH is a directory, then read all TOML files from that
directory. If PATH is a file, then load configuration as JSON if the file
extension is ``.json``, otherwise load the file as TOML. As a special case,
``system``, ``security``, and ``imp`` may be used as shorthand for the
compiled-in paths to system configuration objects.


builtin
-------

Expand All @@ -76,6 +86,12 @@ configuration key names. This command is available to all users.
specific values if found to be in tree. This enables Flux testing without
requiring installation.

.. option:: --intree
Force :program:`flux config builtin` to return in-tree paths.

.. option:: --installed
Force :program:`flux config builtin` to return installed paths.

load
----

Expand Down
1 change: 1 addition & 0 deletions doc/test/spell.en.pws
Original file line number Diff line number Diff line change
Expand Up @@ -860,3 +860,4 @@ validators
hostpids
Xauth
dbus
intree
65 changes: 55 additions & 10 deletions src/cmd/builtin/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "src/common/libutil/read_all.h"
#include "src/common/libutil/tomltk.h"
#include "ccan/array_size/array_size.h"
#include "ccan/str/str.h"

#include "builtin.h"

Expand Down Expand Up @@ -122,8 +123,10 @@ static void print_config_item (json_t *o,
static int config_get (optparse_t *p, int ac, char *av[])
{
int optindex = optparse_option_index (p);
flux_t *h;
flux_t *h = NULL;
flux_future_t *f = NULL;
const char *config_path = NULL;
flux_conf_t *conf = NULL;
json_t *o;
const char *path = NULL;
const char *typestr;
Expand All @@ -136,12 +139,32 @@ static int config_get (optparse_t *p, int ac, char *av[])
optparse_print_usage (p);
exit (1);
}
if (!(h = builtin_get_flux_handle (p)))
log_err_exit ("flux_open");
if (!(f = flux_rpc (h, "config.get", NULL, FLUX_NODEID_ANY, 0))
|| flux_rpc_get_unpack (f, "o", &o) < 0)
log_msg_exit ("Error fetching config object: %s",
future_strerror (f, errno));
if ((config_path = optparse_get_str (p, "config-path", NULL))) {
char buf[1024];
flux_error_t error;

if (streq (config_path, "system")
|| streq (config_path, "security")
|| streq (config_path, "imp")) {
snprintf (buf,
sizeof (buf),
"%s/%s/conf.d",
FLUXCONFDIR,
config_path);
config_path = buf;
}
if (!(conf = flux_conf_parse (config_path, &error))
|| flux_conf_unpack (conf, &error, "o", &o) < 0)
log_msg_exit ("%s", error.text);
}
else {
if (!(h = builtin_get_flux_handle (p)))
log_err_exit ("flux_open");
if (!(f = flux_rpc (h, "config.get", NULL, FLUX_NODEID_ANY, 0))
|| flux_rpc_get_unpack (f, "o", &o) < 0)
log_msg_exit ("Error fetching config object: %s",
future_strerror (f, errno));
}
typestr = optparse_get_str (p, "type", "any");
if (parse_json_type (typestr, &type, &fsd_subtype) < 0)
log_msg_exit ("Unknown type: %s", typestr);
Expand All @@ -152,6 +175,7 @@ static int config_get (optparse_t *p, int ac, char *av[])
fsd_subtype,
p);

flux_conf_decref (conf);
flux_future_destroy (f);
flux_close (h);
return (0);
Expand All @@ -162,13 +186,21 @@ static int builtin_get (optparse_t *p, int ac, char *av[])
int optindex = optparse_option_index (p);
const char *name;
const char *value;
int flags;

if (optindex != ac - 1) {
optparse_print_usage (p);
exit (1);
}
if (optparse_hasopt (p, "installed"))
flags = FLUX_CONF_INSTALLED;
else if (optparse_hasopt (p, "intree"))
flags = FLUX_CONF_INTREE;
else
flags = FLUX_CONF_AUTO;

name = av[optindex];
value = flux_conf_builtin_get (name, FLUX_CONF_AUTO);
value = flux_conf_builtin_get (name, flags);
if (!value)
log_msg_exit ("%s is invalid", name);
printf ("%s\n", value);
Expand Down Expand Up @@ -260,6 +292,10 @@ int cmd_config (optparse_t *p, int ac, char *av[])
}

static struct optparse_option get_opts[] = {
{ .name = "config-path", .key = 'c', .has_arg = 1,
.arginfo = "PATH|system|security|imp",
.usage = "Get broker config from PATH (default: use live config)"
},
{ .name = "type", .key = 't', .has_arg = 1, .arginfo = "TYPE",
.usage = "Set expected type (any, string, integer, real, boolean"
", object, array, fsd, fsd-integer, fsd-real)",
Expand All @@ -273,6 +309,15 @@ static struct optparse_option get_opts[] = {
OPTPARSE_TABLE_END
};

static struct optparse_option builtin_opts[] = {
{ .name = "intree", .has_arg = 0,
.usage = "Force in-tree paths to be used"
},
{ .name = "installed", .has_arg = 0,
.usage = "Force installed paths to be used",
},
OPTPARSE_TABLE_END
};

static struct optparse_subcommand config_subcmds[] = {
{ "load",
Expand All @@ -290,7 +335,7 @@ static struct optparse_subcommand config_subcmds[] = {
NULL,
},
{ "get",
"[--type=TYPE] [--quiet] [--default=VAL] [PATH]",
"[OPTIONS] [NAME]",
"Query broker configuration values",
config_get,
0,
Expand All @@ -301,7 +346,7 @@ static struct optparse_subcommand config_subcmds[] = {
"Print compiled-in Flux configuration values",
builtin_get,
0,
NULL,
builtin_opts,
},
OPTPARSE_SUBCMD_END
};
Expand Down
27 changes: 23 additions & 4 deletions src/cmd/flux-R.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,20 +847,39 @@ int cmd_parse_config (optparse_t *p, int argc, char **argv)
{
flux_error_t error;
json_t *o = NULL;
const char *path = NULL;
struct rlist *rl = NULL;
flux_conf_t *conf;

if (!(conf = flux_conf_parse (argv[1], &error)))
log_msg_exit ("flux_conf_parse: %s", error.text);

if (flux_conf_unpack (conf, &error,
"{s:{s:o}}",
"{s:{s?o s?s}}",
"resource",
"config", &o) < 0)
"config", &o,
"path", &path) < 0)
log_msg_exit ("Config file error: %s", error.text);

if (!(rl = rlist_from_config (o, &error)))
log_msg_exit ("Config file error: %s", error.text);
if (!o) {
json_error_t e;

if (!path) {
log_msg_exit ("Config file error:"
" resource.config or resource.path must be defined");
}
if (!(o = json_load_file (path, 0, &e))
|| !(rl = rlist_from_json (o, &e))) {
if (e.line == -1)
log_msg_exit ("%s: %s", path, e.text);
log_msg_exit ("%s: %s on line %d", path, e.text, e.line);
}
json_decref (o);
}
else {
if (!(rl = rlist_from_config (o, &error)))
log_msg_exit ("Config file error: %s", error.text);
}

rlist_puts (rl);

Expand Down
16 changes: 16 additions & 0 deletions t/t0026-flux-R.t
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,20 @@ test_expect_success 'flux R parse-config detects invalid property' '
test_must_fail flux R parse-config conf
'

test_expect_success 'flux R parse-config also works with resource.path' '
flux R encode -r 0-1 >R.path &&
cat <<-EOF >conf/resource.toml &&
resource.path = "R.path"
EOF
flux R parse-config conf
'
test_expect_success 'flux R parse-config fails when resource.path = bad R' '
echo "bad json" >R.path &&
test_must_fail flux R parse-config conf
'
test_expect_success 'flux R parse-config fails when resource.path = missing R' '
rm -f R.path &&
test_must_fail flux R parse-config conf
'

test_done
39 changes: 39 additions & 0 deletions t/t2806-config-cmd.t
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ test_description='Test flux config get'

. $(dirname $0)/sharness.sh

FLUXCONFDIR=$(dirname $(flux config builtin --installed rc1_path))
test -d $FLUXCONFDIR/system/conf.d || test_set_prereq NO_SYSTEM_CONF
test -d $FLUXCONFDIR/security/conf.d || test_set_prereq NO_SECURITY_CONF
test -d $FLUXCONFDIR/imp/conf.d || test_set_prereq NO_IMP_CONF


mkdir config
cat <<EOF >config/config.toml
[foo]
Expand Down Expand Up @@ -181,6 +187,15 @@ test_expect_success 'flux-config builtin fails on unknown key' '
test_expect_success 'flux-config builtin works on known key' '
flux config builtin rc1_path
'
test_expect_success 'flux-config builtin --intree works' '
flux config builtin --intree rc1_path >rc1_path_intree
'
test_expect_success 'flux-config builtin --installed works' '
flux config builtin --installed rc1_path >rc1_path_installed
'
test_expect_success 'flux-config builtin intree and installed return different values' '
test_must_fail test_cmp rc1_path_intree rc1_path_installed
'
test_expect_success 'flux-config get works as guest' '
runas_guest flux config get >obj
'
Expand All @@ -193,5 +208,29 @@ test_expect_success 'flux-config reload fails as guest' '
test_expect_success 'flux-config builtin works as guest' '
runas_guest flux config builtin rc1_path
'
test_expect_success 'flux-config get works when --config-path points to dir' '
mkdir -p altconfig &&
echo "flag = 99" >altconfig/foo.toml &&
flux config get --config-path=altconfig | jq -e .flag
'
test_expect_success 'flux-config get works when --config-path points to file' '
flux config get --config-path=altconfig/foo.toml | jq -e .flag
'
test_expect_success 'flux-config get fails when --config-path path is wrong' '
test_must_fail flux config get --config-path=/not/a/file
'
test_expect_success 'flux-config get fails when --config-path is invalid' '
echo "x x x" >badconf.toml &&
test_must_fail flux config get --config-path=badconf.toml
'
test_expect_success NO_SYSTEM_CONF 'flux-config get --config-path=system fails when missing' '
test_must_fail flux config get --config-path=system
'
test_expect_success NO_SECURITY_CONF 'flux-config get --config-path=security fails when missing' '
test_must_fail flux config get --config-path=security
'
test_expect_success NO_IMP_CONF 'flux-config get --config-path=imp fails when missing' '
test_must_fail flux config get --config-path=imp
'

test_done

0 comments on commit 63953d3

Please sign in to comment.