diff --git a/doc/man1/flux-kvs.adoc b/doc/man1/flux-kvs.adoc index 49f9ba196909..78ce8fc573dd 100644 --- a/doc/man1/flux-kvs.adoc +++ b/doc/man1/flux-kvs.adoc @@ -39,20 +39,20 @@ their parent in the overlay network. Different KVS namespaces can be created in which kvs values can be read from/written to. By default, all KVS operations operate on the -default KVS namespace "primary". To use a different namespace, set -the environment variable FLUX_KVS_NAMESPACE to the namespace you wish -to use. When a KVS namespace is first created, it is only created on -the leader. Followers will initialize itself against a namespace the -first time it is used. When a namespace is removed, a namespace is -marked for removal on the leader and an event is multicast to -followers to similarly mark the namespace for removal. The namespace -will then be garbage collected in the background. There may be a -delay in the namespace being recognized as removed. Similar to -commits, it is "eventually consistent". +default KVS namespace "primary". An alternate namespace can be +specified via the '--namespace' option or the environment variable +FLUX_KVS_NAMESPACE. flux-kvs(1) runs a KVS 'COMMAND'. The possible commands and their arguments are described below. +COMMON OPTIONS +-------------- +*-N, --namespace*='name':: +Specify a namespace to be used in all KVS commands. A namespace +specified via this option overrides a namespace set in the environment +variable FLUX_KVS_NAMESPACE. + COMMANDS -------- *namespace-create* [-o owner] 'name' ['name...']:: diff --git a/doc/man3/Makefile.am b/doc/man3/Makefile.am index f8d1972f7c9a..6f83d916751c 100644 --- a/doc/man3/Makefile.am +++ b/doc/man3/Makefile.am @@ -45,7 +45,8 @@ MAN3_FILES_PRIMARY = \ flux_kvs_lookup.3 \ flux_kvs_commit.3 \ flux_kvs_txn_create.3 \ - flux_kvs_namespace_create.3 + flux_kvs_namespace_create.3 \ + flux_kvs_set_namespace.3 # These files are generated as roff .so includes of a primary page. # A2X handles this automatically if mentioned in NAME section @@ -141,7 +142,8 @@ MAN3_FILES_SECONDARY = \ flux_kvs_txn_symlink.3 \ flux_kvs_txn_put_raw.3 \ # flux_kvs_txn_put_treeobj.3 \ - flux_kvs_namespace_remove.3 + flux_kvs_namespace_remove.3 \ + flux_kvs_get_namespace.3 ADOC_FILES = $(MAN3_FILES_PRIMARY:%.3=%.adoc) XML_FILES = $(MAN3_FILES_PRIMARY:%.3=%.xml) @@ -257,6 +259,7 @@ flux_kvs_txn_symlink.3: flux_kvs_txn_create.3 flux_kvs_txn_put_raw.3: flux_kvs_txn_create.3 # flux_kvs_txn_put_treeobj.3: flux_kvs_txn_create.3 flux_kvs_namespace_remove.3: flux_kvs_namespace_create.3 +flux_kvs_get_namespace.3: flux_kvs_set_namespace.3 flux_open.3: topen.c flux_send.3: tsend.c diff --git a/doc/man3/flux_kvs_commit.adoc b/doc/man3/flux_kvs_commit.adoc index effda74d7baa..b98d780ea9c1 100644 --- a/doc/man3/flux_kvs_commit.adoc +++ b/doc/man3/flux_kvs_commit.adoc @@ -49,9 +49,9 @@ was successful, indicating the entire transaction was committed, or -1 on failure, indicating none of the transaction was committed. By default, both `flux_kvs_commit()` and `flux_kvs_fence()` operate on -the default KVS namespace. To use a different namespace, set the -environment variable FLUX_KVS_NAMESPACE to the namespace you wish to -use. +the default KVS namespace. To use a different namespace, see the +`flux_kvs_set_namespace()` function or set the environment variable +FLUX_KVS_NAMESPACE to the namespace you wish to use. FLAGS ----- @@ -112,4 +112,4 @@ include::COPYRIGHT.adoc[] SEE ALSO --------- -flux_future_then(3), flux_kvs_txn_create(3) +flux_future_then(3), flux_kvs_txn_create(3), flux_kvs_set_namespace(3) diff --git a/doc/man3/flux_kvs_lookup.adoc b/doc/man3/flux_kvs_lookup.adoc index e87b40c84b43..c5b82c5ade13 100644 --- a/doc/man3/flux_kvs_lookup.adoc +++ b/doc/man3/flux_kvs_lookup.adoc @@ -49,9 +49,9 @@ static set of content within the KVS, effectively a snapshot. See `flux_kvs_lookup_get_treeobj()` below. By default, both `flux_kvs_lookup()` and `flux_kvs_lookupat()` operate -on the default KVS namespace. To use a different namespace, set the -environment variable FLUX_KVS_NAMESPACE to the namespace you wish to -use. +on the default KVS namespace. To use a different namespace, see the +`flux_kvs_set_namespace()` function or set the environment variable +FLUX_KVS_NAMESPACE to the namespace you wish to use. All the functions below are variations on a common theme. First they complete the lookup RPC by blocking on the response, if not already received. @@ -170,6 +170,6 @@ include::COPYRIGHT.adoc[] SEE ALSO --------- -flux_rpc(3), flux_future_then(3) +flux_rpc(3), flux_future_then(3), flux_kvs_set_namespace(3) https://github.com/flux-framework/rfc/blob/master/spec_11.adoc[RFC 11: Key Value Store Tree Object Format v1] diff --git a/doc/man3/flux_kvs_set_namespace.adoc b/doc/man3/flux_kvs_set_namespace.adoc new file mode 100644 index 000000000000..3ab6a79a583e --- /dev/null +++ b/doc/man3/flux_kvs_set_namespace.adoc @@ -0,0 +1,67 @@ +flux_kvs_set_namespace(3) +========================= +:doctype: manpage + + +NAME +---- +flux_kvs_set_namespace, flux_kvs_get_namespace - set/get KVS namespace + + +SYNOPSIS +-------- + #include + + int flux_kvs_set_namespace (flux_t *h, const char *namespace); + + const char *flux_kvs_get_namespace (flux_t *h); + +DESCRIPTION +----------- + +`flux_kvs_set_namespace()` sets the KVS namespace to use for all +KVS operations within a flux handle. By setting a KVS namespace +in the flux handle, this namespace will override any KVS namespace +specified in the environment variable FLUX_KVS_NAMESPACE. + +`flux_kvs_get_namespace()` will determine the current namespace to +use, whether set via `flux_kvs_set_namespace()` or the environment +variable FLUX_KVS_NAMESPACE. If neither is set, the default +namespace of "primary" will be used. + + +RETURN VALUE +------------ + +`flux_kvs_set_namespace()` returns 0 on success, or -1 on failure. +`flux_kvs_get_namespace()` returns namespace on success, or NULL on +failure. + + +ERRORS +------ + +EINVAL:: +One of the arguments was invalid. + +ENOMEM:: +Out of memory. + +AUTHOR +------ +This page is maintained by the Flux community. + + +RESOURCES +--------- +Github: + + +COPYRIGHT +--------- +include::COPYRIGHT.adoc[] + + +SEE ALSO +--------- +flux_kvs_lookup(3), flux_kvs_commit(3) diff --git a/src/cmd/flux-kvs.c b/src/cmd/flux-kvs.c index 9c27a5c32e33..6c6aac475d32 100644 --- a/src/cmd/flux-kvs.c +++ b/src/cmd/flux-kvs.c @@ -60,6 +60,13 @@ static void dump_kvs_dir (const flux_kvsdir_t *dir, int maxcol, #define min(a,b) ((a)<(b)?(a):(b)) +static struct optparse_option global_opts[] = { + { .name = "namespace", .key = 'N', .has_arg = 1, + .usage = "Specify KVS namespace to use.", + }, + OPTPARSE_TABLE_END +}; + static struct optparse_option namespace_create_opts[] = { { .name = "owner", .key = 'o', .has_arg = 1, .usage = "Specify alternate namespace owner via userid", @@ -314,11 +321,15 @@ int main (int argc, char *argv[]) optparse_t *p; int optindex; int exitval; + const char *namespace; log_init ("flux-kvs"); p = optparse_create ("flux-kvs"); + if (optparse_add_option_table (p, global_opts) != OPTPARSE_SUCCESS) + log_msg_exit ("optparse_add_option_table() failed"); + /* Override help option for our own */ if (optparse_set (p, OPTPARSE_USAGE, cmdusage) != OPTPARSE_SUCCESS) log_msg_exit ("optparse_set (USAGE)"); @@ -338,7 +349,7 @@ int main (int argc, char *argv[]) exit (1); if ((argc - optindex == 0) - || !optparse_get_subcommand (p, argv[optind])) { + || !optparse_get_subcommand (p, argv[optindex])) { usage (p, NULL, NULL); exit (1); } @@ -346,6 +357,11 @@ int main (int argc, char *argv[]) if (!(h = flux_open (NULL, 0))) log_err_exit ("flux_open"); + if ((namespace = optparse_get_str (p, "namespace", NULL))) { + if (flux_kvs_set_namespace (h, namespace) < 0) + log_msg_exit ("flux_kvs_set_namespace"); + } + optparse_set_data (p, "flux_handle", h); if ((exitval = optparse_run_subcommand (p, argc, argv)) < 0) diff --git a/src/common/libkvs/Makefile.am b/src/common/libkvs/Makefile.am index 0ee2a77779cd..dd42edabf4e4 100644 --- a/src/common/libkvs/Makefile.am +++ b/src/common/libkvs/Makefile.am @@ -13,7 +13,6 @@ noinst_LTLIBRARIES = libkvs.la libkvs_la_SOURCES = \ kvs.c \ - kvs_private.h \ kvs_lookup.c \ kvs_dir.c \ kvs_dir_private.h \ @@ -39,6 +38,8 @@ TESTS = \ test_kvs_txn.t \ test_kvs_lookup.t \ test_kvs_dir.t \ + test_kvs_commit.t \ + test_kvs_watch.t \ test_treeobj.t check_PROGRAMS = \ @@ -75,6 +76,14 @@ test_kvs_dir_t_SOURCES = test/kvs_dir.c test_kvs_dir_t_CPPFLAGS = $(test_cppflags) test_kvs_dir_t_LDADD = $(test_ldadd) $(LIBDL) +test_kvs_commit_t_SOURCES = test/kvs_commit.c +test_kvs_commit_t_CPPFLAGS = $(test_cppflags) +test_kvs_commit_t_LDADD = $(test_ldadd) $(LIBDL) + +test_kvs_watch_t_SOURCES = test/kvs_watch.c +test_kvs_watch_t_CPPFLAGS = $(test_cppflags) +test_kvs_watch_t_LDADD = $(test_ldadd) $(LIBDL) + test_treeobj_t_SOURCES = test/treeobj.c test_treeobj_t_CPPFLAGS = $(test_cppflags) test_treeobj_t_LDADD = $(test_ldadd) $(LIBDL) diff --git a/src/common/libkvs/kvs.c b/src/common/libkvs/kvs.c index 9e70336c942a..97496d7ae10a 100644 --- a/src/common/libkvs/kvs.c +++ b/src/common/libkvs/kvs.c @@ -29,12 +29,7 @@ #include -const char *get_kvs_namespace (void) -{ - if (getenv ("FLUX_KVS_NAMESPACE")) - return getenv ("FLUX_KVS_NAMESPACE"); - return KVS_PRIMARY_NAMESPACE; -} +#define FLUX_HANDLE_KVS_NAMESPACE "kvsnamespace" flux_future_t *flux_kvs_namespace_create (flux_t *h, const char *namespace, uint32_t owner, int flags) @@ -64,13 +59,51 @@ flux_future_t *flux_kvs_namespace_remove (flux_t *h, const char *namespace) "namespace", namespace); } +int flux_kvs_set_namespace (flux_t *h, const char *namespace) +{ + char *str; + + if (!h || !namespace) { + errno = EINVAL; + return -1; + } + + if (!(str = strdup (namespace))) { + errno = ENOMEM; + return -1; + } + + flux_aux_set (h, FLUX_HANDLE_KVS_NAMESPACE, str, free); + return 0; +} + +const char *flux_kvs_get_namespace (flux_t *h) +{ + const char *namespace; + + if (!h) { + errno = EINVAL; + return NULL; + } + + if ((namespace = flux_aux_get (h, FLUX_HANDLE_KVS_NAMESPACE))) + return namespace; + + if ((namespace = getenv ("FLUX_KVS_NAMESPACE"))) + return namespace; + + return KVS_PRIMARY_NAMESPACE; +} + int flux_kvs_get_version (flux_t *h, int *versionp) { flux_future_t *f; - const char *namespace = get_kvs_namespace (); + const char *namespace; int version; int rc = -1; + if (!(namespace = flux_kvs_get_namespace (h))) + return -1; if (!(f = flux_rpc_pack (h, "kvs.getroot", FLUX_NODEID_ANY, 0, "{ s:s }", "namespace", namespace))) goto done; @@ -87,9 +120,11 @@ int flux_kvs_get_version (flux_t *h, int *versionp) int flux_kvs_wait_version (flux_t *h, int version) { flux_future_t *f; - const char *namespace = get_kvs_namespace (); + const char *namespace; int ret = -1; + if (!(namespace = flux_kvs_get_namespace (h))) + return -1; if (!(f = flux_rpc_pack (h, "kvs.sync", FLUX_NODEID_ANY, 0, "{ s:i s:s }", "rootseq", version, "namespace", namespace))) diff --git a/src/common/libkvs/kvs.h b/src/common/libkvs/kvs.h index 78ea23207292..927fba8759d6 100644 --- a/src/common/libkvs/kvs.h +++ b/src/common/libkvs/kvs.h @@ -36,6 +36,16 @@ flux_future_t *flux_kvs_namespace_create (flux_t *h, const char *namespace, uint32_t owner, int flags); flux_future_t *flux_kvs_namespace_remove (flux_t *h, const char *namespace); +/* Namespace Selection + * - configure a KVS namespace to use in all kvs operations using this + * handle. + * - if never set, the value from the environment variable + * FLUX_KVS_NAMESPACE is used. + * - if FLUX_KVS_NAMESPACE is not set, KVS_PRIMARY_NAMESPACE is assumed. + */ +int flux_kvs_set_namespace (flux_t *h, const char *namespace); +const char *flux_kvs_get_namespace (flux_t *h); + /* Synchronization: * Process A commits data, then gets the store version V and sends it to B. * Process B waits for the store version to be >= V, then reads data. diff --git a/src/common/libkvs/kvs_commit.c b/src/common/libkvs/kvs_commit.c index 893e0df0bc36..02ee9d3d8ded 100644 --- a/src/common/libkvs/kvs_commit.c +++ b/src/common/libkvs/kvs_commit.c @@ -29,14 +29,16 @@ #include #include -#include "kvs_private.h" #include "kvs_txn_private.h" #include "src/common/libutil/blobref.h" flux_future_t *flux_kvs_fence (flux_t *h, int flags, const char *name, int nprocs, flux_kvs_txn_t *txn) { - const char *namespace = get_kvs_namespace (); + const char *namespace; + + if (!(namespace = flux_kvs_get_namespace (h))) + return NULL; if (txn) { json_t *ops; diff --git a/src/common/libkvs/kvs_commit.h b/src/common/libkvs/kvs_commit.h index 90567748dfb8..14369aec5335 100644 --- a/src/common/libkvs/kvs_commit.h +++ b/src/common/libkvs/kvs_commit.h @@ -9,8 +9,6 @@ enum kvs_commit_flags { FLUX_KVS_NO_MERGE = 1, /* disallow commits to be mergeable with others */ }; -/* To use an alternate namespace, set environment variable FLUX_KVS_NAMESPACE */ - flux_future_t *flux_kvs_commit (flux_t *h, int flags, flux_kvs_txn_t *txn); flux_future_t *flux_kvs_fence (flux_t *h, int flags, const char *name, diff --git a/src/common/libkvs/kvs_lookup.c b/src/common/libkvs/kvs_lookup.c index c8d724f1e14e..84dc794a52a1 100644 --- a/src/common/libkvs/kvs_lookup.c +++ b/src/common/libkvs/kvs_lookup.c @@ -32,7 +32,6 @@ #include #include -#include "kvs_private.h" #include "kvs_dir_private.h" #include "kvs_lookup.h" #include "treeobj.h" @@ -100,12 +99,14 @@ flux_future_t *flux_kvs_lookup (flux_t *h, int flags, const char *key) { struct lookup_ctx *ctx; flux_future_t *f; - const char *namespace = get_kvs_namespace (); + const char *namespace; if (!h || !key || strlen (key) == 0 || validate_lookup_flags (flags) < 0) { errno = EINVAL; return NULL; } + if (!(namespace = flux_kvs_get_namespace (h))) + return NULL; if (!(ctx = alloc_ctx (h, flags, key))) return NULL; if (!(f = flux_rpc_pack (h, "kvs.get", FLUX_NODEID_ANY, 0, @@ -144,8 +145,10 @@ flux_future_t *flux_kvs_lookupat (flux_t *h, int flags, const char *key, } } else { - const char *namespace = get_kvs_namespace (); + const char *namespace; + if (!(namespace = flux_kvs_get_namespace (h))) + return NULL; if (!(ctx->atref = strdup (treeobj))) return NULL; if (!(obj = json_loads (treeobj, 0, NULL))) { diff --git a/src/common/libkvs/kvs_lookup.h b/src/common/libkvs/kvs_lookup.h index 3c3ca3cb2b43..30fd3ef52d44 100644 --- a/src/common/libkvs/kvs_lookup.h +++ b/src/common/libkvs/kvs_lookup.h @@ -5,8 +5,6 @@ extern "C" { #endif -/* To use an alternate namespace, set environment variable FLUX_KVS_NAMESPACE */ - flux_future_t *flux_kvs_lookup (flux_t *h, int flags, const char *key); flux_future_t *flux_kvs_lookupat (flux_t *h, int flags, const char *key, const char *treeobj); diff --git a/src/common/libkvs/kvs_private.h b/src/common/libkvs/kvs_private.h index 20367166884c..6e78d2885c2c 100644 --- a/src/common/libkvs/kvs_private.h +++ b/src/common/libkvs/kvs_private.h @@ -1,8 +1,6 @@ #ifndef _KVS_PRIVATE_H #define _KVS_PRIVATE_H -const char *get_kvs_namespace (void); - #endif /* !_KVS_PRIVATE_H */ /* diff --git a/src/common/libkvs/kvs_watch.c b/src/common/libkvs/kvs_watch.c index 0a919d09689a..1b7ed3d662d7 100644 --- a/src/common/libkvs/kvs_watch.c +++ b/src/common/libkvs/kvs_watch.c @@ -30,7 +30,6 @@ #include #include "treeobj.h" -#include "kvs_private.h" #include "kvs_dir_private.h" typedef enum { @@ -148,9 +147,11 @@ static kvs_watcher_t *lookup_watcher (flux_t *h, uint32_t matchtag) int flux_kvs_unwatch (flux_t *h, const char *key) { flux_future_t *f = NULL; - const char *namespace = get_kvs_namespace (); + const char *namespace; int rc = -1; + if (!(namespace = flux_kvs_get_namespace (h))) + goto done; if (!(f = flux_rpc_pack (h, "kvs.unwatch", FLUX_NODEID_ANY, 0, "{s:s s:s}", "key", key, @@ -236,10 +237,12 @@ static flux_future_t *kvs_watch_rpc (flux_t *h, const char *key, const char *json_str, int flags) { flux_future_t *f; - const char *namespace = get_kvs_namespace (); + const char *namespace; json_t *val = NULL; int saved_errno; + if (!(namespace = flux_kvs_get_namespace (h))) + goto error; if (!json_str) json_str = "null"; if (!(val = json_loads (json_str, JSON_DECODE_ANY, NULL))) { @@ -413,6 +416,10 @@ int flux_kvs_watch_once_dir (flux_t *h, flux_kvsdir_t **dirp, char *key; int rc; + if (!fmt) { + errno = EINVAL; + return -1; + } va_start (ap, fmt); rc = vasprintf (&key, fmt, ap); va_end (ap); @@ -480,6 +487,10 @@ int flux_kvs_watch_dir (flux_t *h, kvs_set_dir_f set, void *arg, char *key; int rc; + if (!fmt) { + errno = EINVAL; + return -1; + } va_start (ap, fmt); rc = vasprintf (&key, fmt, ap); va_end (ap); diff --git a/src/common/libkvs/kvs_watch.h b/src/common/libkvs/kvs_watch.h index a9b923fef1f7..a987038e4e54 100644 --- a/src/common/libkvs/kvs_watch.h +++ b/src/common/libkvs/kvs_watch.h @@ -40,7 +40,6 @@ typedef int (*kvs_set_dir_f)(const char *key, flux_kvsdir_t *dir, void *arg, * Callback is triggered once during registration to get the initial value. * Once the reactor is (re-)entered, it will then be called each time the * key changes. - * To use an alternate namespace, set environment variable FLUX_KVS_NAMESPACE */ int flux_kvs_watch (flux_t *h, const char *key, kvs_set_f set, void *arg); @@ -50,7 +49,6 @@ int flux_kvs_watch (flux_t *h, const char *key, kvs_set_f set, void *arg); * KVS's hash tree namespace organization, this function will be called * whenever any key under this directory changes, since that forces the * hash references to change on parents, all the way to the root. - * To use an alternate namespace, set environment variable FLUX_KVS_NAMESPACE */ int flux_kvs_watch_dir (flux_t *h, kvs_set_dir_f set, void *arg, const char *fmt, ...) @@ -58,7 +56,6 @@ int flux_kvs_watch_dir (flux_t *h, kvs_set_dir_f set, void *arg, /* Cancel a flux_kvs_watch(), freeing server-side state, and unregistering * any callback. Returns 0 on success, or -1 with errno set on error. - * To use an alternate namespace, set environment variable FLUX_KVS_NAMESPACE */ int flux_kvs_unwatch (flux_t *h, const char *key); @@ -73,8 +70,6 @@ int flux_kvs_unwatch (flux_t *h, const char *key); * * If 'key' initially exists, then is removed, the function fails with * ENOENT and the initial value is not freed. - * - * To use an alternate namespace, set environment variable FLUX_KVS_NAMESPACE */ int flux_kvs_watch_once (flux_t *h, const char *key, char **json_str); diff --git a/src/common/libkvs/test/kvs.c b/src/common/libkvs/test/kvs.c index 2df71b85f2d6..b83a4b927b3e 100644 --- a/src/common/libkvs/test/kvs.c +++ b/src/common/libkvs/test/kvs.c @@ -7,7 +7,6 @@ #include "src/common/libflux/flux.h" #include "kvs.h" -#include "kvs_private.h" #include "src/common/libtap/tap.h" void errors (void) @@ -21,24 +20,21 @@ void errors (void) errno = 0; ok (flux_kvs_namespace_remove (NULL, NULL) == NULL && errno == EINVAL, "flux_kvs_namespace_remove fails on bad input"); -} -void namespace (void) -{ - const char *str; - - ok (setenv ("FLUX_KVS_NAMESPACE", "FOOBAR", 1) == 0, - "setenv FLUX_KVS_NAMESPACE success"); - ok ((str = get_kvs_namespace ()) != NULL, - "get_kvs_namespace returns non-NULL"); - ok (!strcmp (str, "FOOBAR"), - "get_kvs_namespace returns correct non-default namespace"); - ok (unsetenv ("FLUX_KVS_NAMESPACE") == 0, - "unsetenv FLUX_KVS_NAMESPACE success"); - ok ((str = get_kvs_namespace ()) != NULL, - "get_kvs_namespace returns non-NULL"); - ok (!strcmp (str, KVS_PRIMARY_NAMESPACE), - "get_kvs_namespace returns correct default namespace"); + ok (flux_kvs_set_namespace (NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_set_namespace fails on bad input"); + + errno = 0; + ok (flux_kvs_get_namespace (NULL) == NULL && errno == EINVAL, + "flux_kvs_get_namespace fails on bad input"); + + errno = 0; + ok (flux_kvs_get_version (NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_get_version fails on bad input"); + + errno = 0; + ok (flux_kvs_wait_version (NULL, 0) < 0 && errno == EINVAL, + "flux_kvs_wait_version fails on bad input"); } int main (int argc, char *argv[]) @@ -47,7 +43,6 @@ int main (int argc, char *argv[]) plan (NO_PLAN); errors (); - namespace (); done_testing(); return (0); diff --git a/src/common/libkvs/test/kvs_commit.c b/src/common/libkvs/test/kvs_commit.c new file mode 100644 index 000000000000..675ef6f5fb8f --- /dev/null +++ b/src/common/libkvs/test/kvs_commit.c @@ -0,0 +1,39 @@ +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "src/common/libflux/flux.h" +#include "kvs_commit.h" +#include "src/common/libtap/tap.h" + +void errors (void) +{ + /* check simple error cases */ + + errno = 0; + ok (flux_kvs_fence (NULL, 0, NULL, 0, NULL) == NULL && errno == EINVAL, + "flux_kvs_fence fails on bad input"); + + errno = 0; + ok (flux_kvs_commit (NULL, 0, NULL) == NULL && errno == EINVAL, + "flux_kvs_commit fails on bad input"); +} + +int main (int argc, char *argv[]) +{ + + plan (NO_PLAN); + + errors (); + + done_testing(); + return (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ + diff --git a/src/common/libkvs/test/kvs_watch.c b/src/common/libkvs/test/kvs_watch.c new file mode 100644 index 000000000000..54cc3a4738ee --- /dev/null +++ b/src/common/libkvs/test/kvs_watch.c @@ -0,0 +1,51 @@ +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "src/common/libflux/flux.h" +#include "kvs_watch.h" +#include "src/common/libtap/tap.h" + +void errors (void) +{ + /* check simple error cases */ + + errno = 0; + ok (flux_kvs_unwatch (NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_unwatch fails on bad input"); + + errno = 0; + ok (flux_kvs_watch_once (NULL, NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_watch_once fails on bad input"); + + errno = 0; + ok (flux_kvs_watch (NULL, NULL, NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_watch fails on bad input"); + + errno = 0; + ok (flux_kvs_watch_once_dir (NULL, NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_watch_once_dir fails on bad input"); + + errno = 0; + ok (flux_kvs_watch_dir (NULL, NULL, NULL, NULL) < 0 && errno == EINVAL, + "flux_kvs_watch_dir fails on bad input"); +} + +int main (int argc, char *argv[]) +{ + + plan (NO_PLAN); + + errors (); + + done_testing(); + return (0); +} + +/* + * vi:tabstop=4 shiftwidth=4 expandtab + */ + diff --git a/t/kvs/fence_namespace_remove.c b/t/kvs/fence_namespace_remove.c index d77bdc3ce762..699d51600dc2 100644 --- a/t/kvs/fence_namespace_remove.c +++ b/t/kvs/fence_namespace_remove.c @@ -47,7 +47,7 @@ static char *prefix = NULL; static void usage (void) { - fprintf (stderr, "Usage: fence_namespace_remove prefix\n"); + fprintf (stderr, "Usage: fence_namespace_remove namespace prefix\n"); exit (1); } @@ -56,22 +56,29 @@ int main (int argc, char *argv[]) flux_t *h = NULL; uint32_t rank; char *key = NULL; + char *namespace = NULL; char *fence_name = NULL; flux_future_t *f = NULL; flux_kvs_txn_t *txn = NULL; log_init (basename (argv[0])); - if (argc != 2) + if (argc != 3) usage (); - prefix = argv[1]; + namespace = argv[1]; + prefix = argv[2]; if (!(h = flux_open (NULL, 0))) { log_err_exit ("flux_open"); goto done; } + if (flux_kvs_set_namespace (h, namespace) < 0) { + log_err_exit ("flux_kvs_set_namespace"); + goto done; + } + if (flux_get_rank (h, &rank) < 0) { log_err ("flux_get_rank"); goto done; diff --git a/t/kvs/kvs-helper.sh b/t/kvs/kvs-helper.sh index 128e404dd13a..fa6d4ac3382e 100755 --- a/t/kvs/kvs-helper.sh +++ b/t/kvs/kvs-helper.sh @@ -29,6 +29,15 @@ test_kvs_key() { test_cmp expected output } +# arg1 - namespace +# arg2 - key to retrieve +# arg3 - expected value +test_kvs_key_namespace() { + flux kvs --namespace="$1" get --json "$2" >output + echo "$3" >expected + test_cmp expected output +} + # arg1 - key to retrieve # arg2 - value to wait for wait_watch_put() { @@ -41,6 +50,17 @@ wait_watch_put() { return $(loophandlereturn $i) } +# arg1 - namespace +# arg2 - key to retrieve +# arg3 - value to wait for +wait_watch_put_namespace() { + export FLUX_KVS_NAMESPACE=$1 + wait_watch_put $2 $3 + exitvalue=$? + unset FLUX_KVS_NAMESPACE + return $exitvalue +} + # arg1 - key to retrieve wait_watch_empty() { i=0 diff --git a/t/t1004-kvs-namespace.t b/t/t1004-kvs-namespace.t index 44d7a61bddad..4590dcd52395 100755 --- a/t/t1004-kvs-namespace.t +++ b/t/t1004-kvs-namespace.t @@ -28,59 +28,7 @@ PRIMARYNAMESPACE=primary NAMESPACETEST=namespacetest NAMESPACETMP=namespacetmp NAMESPACERANK1=namespacerank1 - -test_kvs_key_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs get --json "$2" >output - echo "$3" >expected - unset FLUX_KVS_NAMESPACE - test_cmp expected output -} - -put_kvs_key_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs put --json "$2=$3" - unset FLUX_KVS_NAMESPACE -} - -dir_kvs_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs dir "$2" | sort > $3 - unset FLUX_KVS_NAMESPACE -} - -unlink_kvs_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs unlink $2 - unset FLUX_KVS_NAMESPACE -} - -unlink_kvs_dir_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs unlink -Rf $2 - unset FLUX_KVS_NAMESPACE -} - -version_kvs_namespace() { - export FLUX_KVS_NAMESPACE=$1 - version=`flux kvs version` - eval $2=$version - unset FLUX_KVS_NAMESPACE -} - -get_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs get --json "$2" - eval $3="$?" - unset FLUX_KVS_NAMESPACE -} - -dir_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs dir "$2" - eval $3="$?" - unset FLUX_KVS_NAMESPACE -} +NAMESPACEORDER=namespaceorder namespace_create_loop() { i=0 @@ -94,7 +42,7 @@ namespace_create_loop() { get_kvs_namespace_all_ranks_loop() { i=0 - while ! flux exec sh -c "export FLUX_KVS_NAMESPACE=$1; flux kvs get $2" \ + while ! flux exec sh -c "flux kvs --namespace=$1 get $2" \ && [ $i -lt ${KVS_WAIT_ITERS} ] do sleep 0.1 @@ -105,7 +53,7 @@ get_kvs_namespace_all_ranks_loop() { get_kvs_namespace_fails_all_ranks_loop() { i=0 - while ! flux exec sh -c "export FLUX_KVS_NAMESPACE=$1; ! flux kvs get $2" \ + while ! flux exec sh -c "! flux kvs --namespace=$1 get $2" \ && [ $i -lt ${KVS_WAIT_ITERS} ] do sleep 0.1 @@ -114,14 +62,6 @@ get_kvs_namespace_fails_all_ranks_loop() { return $(loophandlereturn $i) } -wait_watch_put_namespace() { - export FLUX_KVS_NAMESPACE=$1 - wait_watch_put $2 $3 - exitvalue=$? - unset FLUX_KVS_NAMESPACE - return $exitvalue -} - wait_fencecount_nonzero() { i=0 while [ "$(flux exec -r $1 sh -c "flux module stats --parse namespace.$2.#fences kvs" 2> /dev/null)" == "0" ] \ @@ -151,17 +91,17 @@ test_expect_success 'kvs: get with primary namespace works' ' ' test_expect_success 'kvs: put with primary namespace works' ' - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.test 2 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.test=2 && test_kvs_key $DIR.test 2 ' test_expect_success 'kvs: put/get with primary namespace works' ' - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.test 3 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.test=3 && test_kvs_key_namespace $PRIMARYNAMESPACE $DIR.test 3 ' test_expect_success 'kvs: unlink with primary namespace works' ' - unlink_kvs_namespace $PRIMARYNAMESPACE $DIR.test && + flux kvs --namespace=$PRIMARYNAMESPACE unlink $DIR.test && test_must_fail flux kvs get --json $DIR.test ' @@ -169,7 +109,7 @@ test_expect_success 'kvs: dir with primary namespace works' ' flux kvs put --json $DIR.a=1 && flux kvs put --json $DIR.b=2 && flux kvs put --json $DIR.c=3 && - dir_kvs_namespace $PRIMARYNAMESPACE $DIR output && + flux kvs --namespace=$PRIMARYNAMESPACE dir $DIR | sort > output && cat >expected <watch_out & + stdbuf -oL flux kvs --namespace=$PRIMARYNAMESPACE watch -o -c 1 $DIR.watch >watch_out & watchpid=$! && wait_watch_file watch_out "0" - flux kvs put --json $DIR.watch=1 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.watch=1 && wait $watchpid - unset FLUX_KVS_NAMESPACE cat >expected <<-EOF && 0 1 @@ -227,21 +162,20 @@ test_expect_success 'kvs: namespace create on rank 1 works' ' ' test_expect_success 'kvs: put/get value in new namespace works' ' - put_kvs_key_namespace $NAMESPACETEST $DIR.test 1 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.test=1 && test_kvs_key_namespace $NAMESPACETEST $DIR.test 1 ' test_expect_success 'kvs: unlink in new namespace works' ' - unlink_kvs_namespace $NAMESPACETEST $DIR.test && - get_kvs_namespace_exitvalue $NAMESPACETEST $DIR.test exitvalue && - test $exitvalue -ne 0 + flux kvs --namespace=$NAMESPACETEST unlink $DIR.test && + ! flux kvs --namespace=$NAMESPACETEST get --json $DIR.test ' test_expect_success 'kvs: dir in new namespace works' ' - put_kvs_key_namespace $NAMESPACETEST $DIR.a 4 && - put_kvs_key_namespace $NAMESPACETEST $DIR.b 5 && - put_kvs_key_namespace $NAMESPACETEST $DIR.c 6 && - dir_kvs_namespace $NAMESPACETEST $DIR output && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.a=4 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.b=5 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.c=6 && + flux kvs --namespace=$NAMESPACETEST dir $DIR | sort > output && cat >expected <watch_out & + stdbuf -oL flux kvs --namespace=$NAMESPACETEST watch -o -c 1 $DIR.watch >watch_out & watchpid=$! && wait_watch_file watch_out "0" - flux kvs put --json $DIR.watch=1 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.watch=1 && wait $watchpid - unset FLUX_KVS_NAMESPACE cat >expected <<-EOF && 0 1 @@ -292,11 +221,10 @@ test_expect_success 'kvs: namespace remove non existing namespace silently passe test_expect_success 'kvs: namespace remove works' ' flux kvs namespace-create $NAMESPACETMP-BASIC && - put_kvs_key_namespace $NAMESPACETMP-BASIC $DIR.tmp 1 && + flux kvs --namespace=$NAMESPACETMP-BASIC put --json $DIR.tmp=1 && test_kvs_key_namespace $NAMESPACETMP-BASIC $DIR.tmp 1 && flux kvs namespace-remove $NAMESPACETMP-BASIC && - get_kvs_namespace_exitvalue $NAMESPACETMP-BASIC $DIR.tmp exitvalue && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-BASIC get --json $DIR.tmp ' # A namespace-create races against the namespace-remove above, as we @@ -305,11 +233,10 @@ test_expect_success 'kvs: namespace remove works' ' # namespace-create many times until it succeeds. test_expect_success 'kvs: namespace can be re-created after remove' ' namespace_create_loop $NAMESPACETMP-BASIC && - put_kvs_key_namespace $NAMESPACETMP-BASIC $DIR.recreate 1 && + flux kvs --namespace=$NAMESPACETMP-BASIC put --json $DIR.recreate=1 && test_kvs_key_namespace $NAMESPACETMP-BASIC $DIR.recreate 1 && flux kvs namespace-remove $NAMESPACETMP-BASIC && - get_kvs_namespace_exitvalue $NAMESPACETMP-BASIC $DIR.recreate exitvalue && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-BASIC get --json $DIR.recreate ' # @@ -317,25 +244,28 @@ test_expect_success 'kvs: namespace can be re-created after remove' ' # test_expect_success 'kvs: put value in new namespace, available on other ranks' ' - unlink_kvs_dir_namespace $NAMESPACETEST $DIR && - put_kvs_key_namespace $NAMESPACETEST $DIR.all 1 && - version_kvs_namespace $NAMESPACETEST VERS && - flux exec sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACETEST; flux kvs wait ${VERS} && flux kvs get $DIR.all" + flux kvs --namespace=$NAMESPACETEST unlink -Rf $DIR && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.all=1 && + VERS=`flux kvs --namespace=$NAMESPACETEST version` && + flux exec sh -c "flux kvs --namespace=$NAMESPACETEST wait ${VERS} && \ + flux kvs --namespace=$NAMESPACETEST get $DIR.all" ' test_expect_success 'kvs: unlink value in new namespace, does not exist all ranks' ' - unlink_kvs_namespace $NAMESPACETEST $DIR.all && - version_kvs_namespace $NAMESPACETEST VERS && - flux exec sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACETEST; flux kvs wait ${VERS} && ! flux kvs get $DIR.all" + flux kvs --namespace=$NAMESPACETEST unlink $DIR.all && + VERS=`flux kvs --namespace=$NAMESPACETEST version` && + flux exec sh -c "flux kvs --namespace=$NAMESPACETEST wait ${VERS} && \ + ! flux kvs --namespace=$NAMESPACETEST get $DIR.all" ' # namespace-remove on other ranks can take time, so we loop via # get_kvs_namespace_fails_all_ranks_loop() test_expect_success 'kvs: namespace remove works, recognized on other ranks' ' flux kvs namespace-create $NAMESPACETMP-ALL && - put_kvs_key_namespace $NAMESPACETMP-ALL $DIR.all 1 && - version_kvs_namespace $NAMESPACETMP-ALL VERS && - flux exec sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACETMP-ALL; flux kvs wait ${VERS} && flux kvs get $DIR.all" && + flux kvs --namespace=$NAMESPACETMP-ALL put --json $DIR.all=1 && + VERS=`flux kvs --namespace=$NAMESPACETMP-ALL version` && + flux exec sh -c "flux kvs --namespace=$NAMESPACETMP-ALL wait ${VERS} && \ + flux kvs --namespace=$NAMESPACETMP-ALL get $DIR.all" && flux kvs namespace-remove $NAMESPACETMP-ALL && get_kvs_namespace_fails_all_ranks_loop $NAMESPACETMP-ALL $DIR.all ' @@ -351,11 +281,46 @@ test_expect_success 'kvs: namespace remove works, recognized on other ranks' ' # kvs wait, b/c the version may work against an old namespace. test_expect_success 'kvs: namespace can be re-created after remove, recognized on other ranks' ' namespace_create_loop $NAMESPACETMP-ALL && - put_kvs_key_namespace $NAMESPACETMP-ALL $DIR.recreate 1 && + flux kvs --namespace=$NAMESPACETMP-ALL put --json $DIR.recreate=1 && get_kvs_namespace_all_ranks_loop $NAMESPACETMP-ALL $DIR.recreate && flux kvs namespace-remove $NAMESPACETMP-ALL ' +# +# Namespace specification priority +# + +test_expect_success 'kvs: namespace order setup' ' + flux kvs namespace-create $NAMESPACEORDER-1 && + flux kvs namespace-create $NAMESPACEORDER-2 && + flux kvs --namespace=$PRIMARYNAMESPACE put $DIR.ordertest=1 && + flux kvs --namespace=$NAMESPACEORDER-1 put $DIR.ordertest=2 && + flux kvs --namespace=$NAMESPACEORDER-2 put $DIR.ordertest=3 && + test_kvs_key_namespace $PRIMARYNAMESPACE $DIR.ordertest 1 && + test_kvs_key_namespace $NAMESPACEORDER-1 $DIR.ordertest 2 && + test_kvs_key_namespace $NAMESPACEORDER-2 $DIR.ordertest 3 +' + +test_expect_success 'kvs: no namespace specified, defaults to primary namespace' ' + test_kvs_key $DIR.ordertest 1 +' + +test_expect_success 'kvs: namespace specified in environment variable works' ' + export FLUX_KVS_NAMESPACE=$NAMESPACEORDER-1 && + test_kvs_key $DIR.ordertest 2 && + unset FLUX_KVS_NAMESPACE && + export FLUX_KVS_NAMESPACE=$NAMESPACEORDER-2 && + test_kvs_key $DIR.ordertest 3 && + unset FLUX_KVS_NAMESPACE +' + +test_expect_success 'kvs: namespace specified in command line overrides environment variable' ' + export FLUX_KVS_NAMESPACE=$NAMESPACETMP-BAD && + test_kvs_key_namespace $NAMESPACEORDER-1 $DIR.ordertest 2 && + test_kvs_key_namespace $NAMESPACEORDER-2 $DIR.ordertest 3 && + unset FLUX_KVS_NAMESPACE +' + # # Namespace corner case tests # @@ -371,85 +336,67 @@ test_expect_success 'kvs: namespace create on existing namespace fails on rank 1 ' test_expect_success 'kvs: get fails on invalid namespace' ' - get_kvs_namespace_exitvalue $NAMESPACEBAD $DIR.test exitvalue && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACEBAD get --json $DIR.test ' test_expect_success 'kvs: get fails on invalid namespace on rank 1' ' - ! flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACEBAD ; flux kvs get $DIR.test" + ! flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACEBAD get $DIR.test" ' -test_expect_success NO_CHAIN_LINT 'kvs: put fails on invalid namespace' ' - export FLUX_KVS_NAMESPACE=$NAMESPACEBAD - flux kvs put --json $DIR.test=1 - exitvalue=$? - unset FLUX_KVS_NAMESPACE - test $exitvalue -ne 0 +test_expect_success 'kvs: put fails on invalid namespace' ' + ! flux kvs --namespace=$NAMESPACEBAD put --json $DIR.test=1 ' test_expect_success 'kvs: put fails on invalid namespace on rank 1' ' - ! flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACEBAD ; flux kvs put $DIR.test=1" + ! flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACEBAD put $DIR.test=1" ' -test_expect_success NO_CHAIN_LINT 'kvs: version fails on invalid namespace' ' - export FLUX_KVS_NAMESPACE=$NAMESPACEBAD - flux kvs version - exitvalue=$? - unset FLUX_KVS_NAMESPACE - test $exitvalue -ne 0 +test_expect_success 'kvs: version fails on invalid namespace' ' + ! flux kvs --namespace=$NAMESPACEBAD version ' test_expect_success 'kvs: version fails on invalid namespace on rank 1' ' - ! flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACEBAD ; flux kvs version" + ! flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACEBAD version" ' test_expect_success NO_CHAIN_LINT 'kvs: wait fails on invalid namespace' ' - export FLUX_KVS_NAMESPACE=$NAMESPACEBAD - flux kvs wait 1 - exitvalue=$? - unset FLUX_KVS_NAMESPACE - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACEBAD wait 1 ' test_expect_success 'kvs: wait fails on invalid namespace on rank 1' ' - ! flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACEBAD ; flux kvs wait 1" + ! flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACEBAD wait 1" ' test_expect_success NO_CHAIN_LINT 'kvs: watch fails on invalid namespace' ' - export FLUX_KVS_NAMESPACE=$NAMESPACEBAD - flux kvs watch -c 1 $DIR.test - exitvalue=$? - unset FLUX_KVS_NAMESPACE - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACEBAD watch -c 1 $DIR.test ' test_expect_success 'kvs: watch fails on invalid namespace on rank 1' ' - ! flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACEBAD ; flux kvs watch -c 1 $DIR.test" + ! flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACEBAD watch -c 1 $DIR.test" ' # watch errors are output to stdout, so grep for "Operation not supported" test_expect_success NO_CHAIN_LINT 'kvs: watch gets ENOTSUP when namespace is removed' ' flux kvs namespace-create $NAMESPACETMP-REMOVE-WATCH0 && - put_kvs_key_namespace $NAMESPACETMP-REMOVE-WATCH0 $DIR.watch 0 && + flux kvs --namespace=$NAMESPACETMP-REMOVE-WATCH0 put --json $DIR.watch=0 && wait_watch_put_namespace $NAMESPACETMP-REMOVE-WATCH0 "$DIR.watch" "0" rm -f watch_out - export FLUX_KVS_NAMESPACE=$NAMESPACETMP-REMOVE-WATCH0 - stdbuf -oL flux kvs watch -o -c 1 $DIR.watch >watch_out & + stdbuf -oL flux kvs --namespace=$NAMESPACETMP-REMOVE-WATCH0 watch -o -c 1 $DIR.watch >watch_out & watchpid=$! && wait_watch_file watch_out "0" flux kvs namespace-remove $NAMESPACETMP-REMOVE-WATCH0 && wait $watchpid && - unset FLUX_KVS_NAMESPACE grep "Operation not supported" watch_out ' # watch errors are output to stdout, so grep for "Operation not supported" test_expect_success NO_CHAIN_LINT 'kvs: watch on rank 1 gets ENOTSUP when namespace is removed' ' flux kvs namespace-create $NAMESPACETMP-REMOVE-WATCH1 && - put_kvs_key_namespace $NAMESPACETMP-REMOVE-WATCH1 $DIR.watch 0 && - version_kvs_namespace $NAMESPACETMP-REMOVE-WATCH1 VERS && + flux kvs --namespace=$NAMESPACETMP-REMOVE-WATCH1 put --json $DIR.watch=0 && + VERS=`flux kvs --namespace=$NAMESPACETMP-REMOVE-WATCH1 version` && rm -f watch_out - stdbuf -oL flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACETMP-REMOVE-WATCH1 ; flux kvs wait ${VERS}; flux kvs watch -o -c 1 $DIR.watch" > watch_out & + stdbuf -oL flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACETMP-REMOVE-WATCH1 wait ${VERS}; \ + flux kvs --namespace=$NAMESPACETMP-REMOVE-WATCH1 watch -o -c 1 $DIR.watch" > watch_out & watchpid=$! && wait_watch_file watch_out "0" && flux kvs namespace-remove $NAMESPACETMP-REMOVE-WATCH1 && @@ -463,14 +410,12 @@ test_expect_success NO_CHAIN_LINT 'kvs: watch on rank 1 gets ENOTSUP when namesp # non-zero to know it's ready for this test. test_expect_success NO_CHAIN_LINT 'kvs: incomplete fence gets ENOTSUP when namespace is removed' ' flux kvs namespace-create $NAMESPACETMP-REMOVE-FENCE0 && - export FLUX_KVS_NAMESPACE=$NAMESPACETMP-REMOVE-FENCE0 && rm -f fence_out - stdbuf -oL ${FLUX_BUILD_DIR}/t/kvs/fence_namespace_remove fence0 > fence_out & + stdbuf -oL ${FLUX_BUILD_DIR}/t/kvs/fence_namespace_remove $NAMESPACETMP-REMOVE-FENCE0 fence0 > fence_out & watchpid=$! && wait_fencecount_nonzero 0 $NAMESPACETMP-REMOVE-FENCE0 && flux kvs namespace-remove $NAMESPACETMP-REMOVE-FENCE0 && wait $watchpid && - unset FLUX_KVS_NAMESPACE && grep "flux_future_get: Operation not supported" fence_out ' @@ -482,7 +427,7 @@ test_expect_success NO_CHAIN_LINT 'kvs: incomplete fence gets ENOTSUP when names test_expect_success NO_CHAIN_LINT 'kvs: incomplete fence on rank 1 gets ENOTSUP when namespace is removed' ' flux kvs namespace-create $NAMESPACETMP-REMOVE-FENCE1 && rm -f fence_out - stdbuf -oL flux exec -r 1 sh -c "export FLUX_KVS_NAMESPACE=$NAMESPACETMP-REMOVE-FENCE1 ; ${FLUX_BUILD_DIR}/t/kvs/fence_namespace_remove fence1" > fence_out & + stdbuf -oL flux exec -r 1 sh -c "${FLUX_BUILD_DIR}/t/kvs/fence_namespace_remove $NAMESPACETMP-REMOVE-FENCE1 fence1" > fence_out & watchpid=$! && wait_fencecount_nonzero 1 $NAMESPACETMP-REMOVE-FENCE1 && flux kvs namespace-remove $NAMESPACETMP-REMOVE-FENCE1 && @@ -495,38 +440,36 @@ test_expect_success NO_CHAIN_LINT 'kvs: incomplete fence on rank 1 gets ENOTSUP # test_expect_success 'kvs: put/get in different namespaces works' ' - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.test 1 && - put_kvs_key_namespace $NAMESPACETEST $DIR.test 2 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.test=1 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.test=2 && test_kvs_key_namespace $PRIMARYNAMESPACE $DIR.test 1 && test_kvs_key_namespace $NAMESPACETEST $DIR.test 2 ' test_expect_success 'kvs: unlink in different namespaces works' ' - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.testA 1 && - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.testB 1 && - put_kvs_key_namespace $NAMESPACETEST $DIR.testA 2 && - put_kvs_key_namespace $NAMESPACETEST $DIR.testB 2 && - unlink_kvs_namespace $PRIMARYNAMESPACE $DIR.testA && - unlink_kvs_namespace $NAMESPACETEST $DIR.testB && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.testA=1 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.testB=1 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.testA=2 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.testB=2 && + flux kvs --namespace=$PRIMARYNAMESPACE unlink $DIR.testA && + flux kvs --namespace=$NAMESPACETEST unlink $DIR.testB && test_kvs_key_namespace $PRIMARYNAMESPACE $DIR.testB 1 && test_kvs_key_namespace $NAMESPACETEST $DIR.testA 2 && - get_kvs_namespace_exitvalue $PRIMARYNAMESPACE $DIR.testA exitvalue && - test $exitvalue -ne 0 && - get_kvs_namespace_exitvalue $NAMESPACETEST $DIR.testB exitvalue && - test $exitvalue -ne 0 + ! flux kvs --namespace=$PRIMARYNAMESPACE get --json $DIR.testA && + ! flux kvs --namespace=$NAMESPACETEST get --json $DIR.testB ' test_expect_success 'kvs: dir in different namespace works' ' - unlink_kvs_dir_namespace $PRIMARYNAMESPACE $DIR && - unlink_kvs_dir_namespace $NAMESPACETEST $DIR && - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.a 10 && - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.b 11 && - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.c 12 && - put_kvs_key_namespace $NAMESPACETEST $DIR.a 13 && - put_kvs_key_namespace $NAMESPACETEST $DIR.b 14 && - put_kvs_key_namespace $NAMESPACETEST $DIR.c 15 && - dir_kvs_namespace $PRIMARYNAMESPACE $DIR primaryoutput && - dir_kvs_namespace $NAMESPACETEST $DIR testoutput && + flux kvs --namespace=$PRIMARYNAMESPACE unlink -Rf $DIR && + flux kvs --namespace=$NAMESPACETEST unlink -Rf $DIR && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.a=10 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.b=11 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.c=12 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.a=13 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.b=14 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.c=15 && + flux kvs --namespace=$PRIMARYNAMESPACE dir $DIR | sort > primaryoutput && + flux kvs --namespace=$NAMESPACETEST dir $DIR | sort > testoutput && cat >primaryexpected <test_watch_out & + stdbuf -oL flux kvs --namespace=$NAMESPACETEST watch -o -c 1 $DIR.watch >test_watch_out & testwatchpid=$! && wait_watch_file test_watch_out "1" - unset FLUX_KVS_NAMESPACE - put_kvs_key_namespace $PRIMARYNAMESPACE $DIR.watch 1 && - put_kvs_key_namespace $NAMESPACETEST $DIR.watch 2 && + flux kvs --namespace=$PRIMARYNAMESPACE put --json $DIR.watch=1 && + flux kvs --namespace=$NAMESPACETEST put --json $DIR.watch=2 && wait $primarywatchpid && wait $testwatchpid cat >primaryexpected <<-EOF && diff --git a/t/t1005-kvs-security.t b/t/t1005-kvs-security.t index 20c39f0e9d67..8c055ae22b63 100755 --- a/t/t1005-kvs-security.t +++ b/t/t1005-kvs-security.t @@ -25,76 +25,6 @@ unset FLUX_KVS_NAMESPACE NAMESPACETMP=namespacetmp -test_kvs_key_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs get --json "$2" >output - echo "$3" >expected - unset FLUX_KVS_NAMESPACE - test_cmp expected output -} - -put_kvs_key_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs put --json "$2=$3" - unset FLUX_KVS_NAMESPACE -} - -unlink_kvs_dir_namespace() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs unlink -Rf $2 - unset FLUX_KVS_NAMESPACE -} - -version_kvs_namespace() { - export FLUX_KVS_NAMESPACE=$1 - version=`flux kvs version` - eval $2=$version - unset FLUX_KVS_NAMESPACE -} - -put_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs put --json "$2=$3" - eval $4="$?" - unset FLUX_KVS_NAMESPACE -} - -get_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs get --json "$2" - eval $3="$?" - unset FLUX_KVS_NAMESPACE -} - -watch_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs watch -o -c 1 "$2" - eval $3="$?" - unset FLUX_KVS_NAMESPACE -} - -version_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs version - eval $2="$?" - unset FLUX_KVS_NAMESPACE -} - -wait_kvs_namespace_exitvalue() { - export FLUX_KVS_NAMESPACE=$1 - flux kvs wait $2 - eval $3="$?" - unset FLUX_KVS_NAMESPACE -} - -wait_watch_put_namespace() { - export FLUX_KVS_NAMESPACE=$1 - wait_watch_put $2 $3 - exitvalue=$? - unset FLUX_KVS_NAMESPACE - return $exitvalue -} - set_userid() { export FLUX_HANDLE_USERID=$1 export FLUX_HANDLE_ROLEMASK=0x2 @@ -122,48 +52,42 @@ test_expect_success 'kvs: namespace create works (owner)' ' test_expect_success 'kvs: put fails (user)' ' set_userid 9999 && - put_kvs_namespace_exitvalue $NAMESPACETMP-OWNER $DIR.test 1 exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-OWNER put --json $DIR.test=1 && + unset_userid ' test_expect_success 'kvs: put works (owner)' ' - put_kvs_key_namespace $NAMESPACETMP-OWNER $DIR.test 1 && + flux kvs --namespace=$NAMESPACETMP-OWNER put --json $DIR.test=1 && test_kvs_key_namespace $NAMESPACETMP-OWNER $DIR.test 1 ' test_expect_success 'kvs: get fails (user)' ' set_userid 9999 && - get_kvs_namespace_exitvalue $NAMESPACETMP-OWNER $DIR.test exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-OWNER get --json $DIR.test && + unset_userid ' test_expect_success 'kvs: get fails on other ranks (user)' ' - ! flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-OWNER \ - FLUX_HANDLE_USERID=9999 \ + ! flux exec -r 1 sh -c "FLUX_HANDLE_USERID=9999 \ FLUX_HANDLE_ROLEMASK=0x2 \ - flux kvs get $DIR.test" + flux kvs --namespace=$NAMESPACETMP-OWNER get $DIR.test" ' test_expect_success 'kvs: get works on other ranks (owner)' ' - flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-OWNER \ - flux kvs get $DIR.test" + flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACETMP-OWNER get $DIR.test" ' test_expect_success NO_CHAIN_LINT 'kvs: watch works (owner)' ' - unlink_kvs_dir_namespace $NAMESPACETMP-OWNER $DIR && - put_kvs_key_namespace $NAMESPACETMP-OWNER $DIR.watch 0 && + flux kvs --namespace=$NAMESPACETMP-OWNER unlink -Rf $DIR && + flux kvs --namespace=$NAMESPACETMP-OWNER put --json $DIR.watch=0 && wait_watch_put_namespace $NAMESPACETMP-OWNER "$DIR.watch" "0" rm -f watch_out - export FLUX_KVS_NAMESPACE=$NAMESPACETMP-OWNER - stdbuf -oL flux kvs watch -o -c 1 $DIR.watch >watch_out & + stdbuf -oL flux kvs --namespace=$NAMESPACETMP-OWNER watch -o -c 1 $DIR.watch >watch_out & watchpid=$! && wait_watch_file watch_out "0" - flux kvs put --json $DIR.watch=1 && + flux kvs --namespace=$NAMESPACETMP-OWNER put --json $DIR.watch=1 && wait $watchpid - unset FLUX_KVS_NAMESPACE cat >expected <<-EOF && 0 1 @@ -173,30 +97,26 @@ EOF test_expect_success 'kvs: watch fails (user)' ' set_userid 9999 && - watch_kvs_namespace_exitvalue $NAMESPACETMP-OWNER $DIR.test exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-OWNER watch -o -c 1 $DIR.test && + unset_userid ' test_expect_success 'kvs: version fails (user)' ' set_userid 9999 && - version_kvs_namespace_exitvalue $NAMESPACETMP-OWNER exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-OWNER version && + unset_userid ' test_expect_success 'kvs: version fails on other ranks (user)' ' - ! flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-OWNER \ - FLUX_HANDLE_USERID=9999 \ + ! flux exec -r 1 sh -c "FLUX_HANDLE_USERID=9999 \ FLUX_HANDLE_ROLEMASK=0x2 \ - flux kvs version" + flux kvs --namespace=$NAMESPACETMP-OWNER version" ' test_expect_success 'kvs: wait fails (user)' ' set_userid 9999 && - wait_kvs_namespace_exitvalue $NAMESPACETMP-OWNER $DIR.test exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-OWNER wait $DIR.test && + unset_userid ' test_expect_success 'kvs: namespace remove fails (user)' ' @@ -206,11 +126,10 @@ test_expect_success 'kvs: namespace remove fails (user)' ' ' test_expect_success 'kvs: namespace remove works (owner)' ' - put_kvs_key_namespace $NAMESPACETMP-OWNER $DIR.tmp 1 && + flux kvs --namespace=$NAMESPACETMP-OWNER put --json $DIR.tmp=1 && test_kvs_key_namespace $NAMESPACETMP-OWNER $DIR.tmp 1 && flux kvs namespace-remove $NAMESPACETMP-OWNER && - get_kvs_namespace_exitvalue $NAMESPACETMP-OWNER $DIR.tmp exitvalue && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-OWNER get --json $DIR.tmp ' # @@ -223,62 +142,55 @@ test_expect_success 'kvs: namespace create works (owner, for user)' ' test_expect_success 'kvs: namespace put/get works (user)' ' set_userid 9999 && - put_kvs_key_namespace $NAMESPACETMP-USER $DIR.test 1 && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.test=1 && test_kvs_key_namespace $NAMESPACETMP-USER $DIR.test 1 && unset_userid ' test_expect_success 'kvs: put/get works (owner)' ' - put_kvs_key_namespace $NAMESPACETMP-USER $DIR.test 2 && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.test=2 && test_kvs_key_namespace $NAMESPACETMP-USER $DIR.test 2 ' test_expect_success 'kvs: put fails (wrong user)' ' set_userid 9000 && - put_kvs_namespace_exitvalue $NAMESPACETMP-USER $DIR.test 1 exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.test=1 && + unset_userid ' test_expect_success 'kvs: get works on other ranks (user)' ' - flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER \ - FLUX_HANDLE_USERID=9999 \ + flux exec -r 1 sh -c "FLUX_HANDLE_USERID=9999 \ FLUX_HANDLE_ROLEMASK=0x2 \ - flux kvs get $DIR.test" + flux kvs --namespace=$NAMESPACETMP-USER get $DIR.test" ' test_expect_success 'kvs: get works on other ranks (owner)' ' - flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER \ - flux kvs get $DIR.test" + flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACETMP-USER get $DIR.test" ' test_expect_success 'kvs: get fails (wrong user)' ' set_userid 9000 && - get_kvs_namespace_exitvalue $NAMESPACETMP-USER $DIR.test exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-USER get --json $DIR.test && + unset_userid ' test_expect_success 'kvs: get fails on other ranks (wrong user)' ' - ! flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER \ - FLUX_HANDLE_USERID=9000 \ + ! flux exec -r 1 sh -c "FLUX_HANDLE_USERID=9000 \ FLUX_HANDLE_ROLEMASK=0x2 \ - flux kvs get $DIR.test" + flux kvs --namespace=$NAMESPACETMP-USER get $DIR.test" ' test_expect_success NO_CHAIN_LINT 'kvs: watch works (user)' ' set_userid 9999 && - unlink_kvs_dir_namespace $NAMESPACETMP-USER $DIR && - put_kvs_key_namespace $NAMESPACETMP-USER $DIR.watch 0 && + flux kvs --namespace=$NAMESPACETMP-USER unlink -Rf $DIR && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.watch=0 && wait_watch_put_namespace $NAMESPACETMP-USER "$DIR.watch" "0" rm -f watch_out - export FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER - stdbuf -oL flux kvs watch -o -c 1 $DIR.watch >watch_out & + stdbuf -oL flux kvs --namespace=$NAMESPACETMP-USER watch -o -c 1 $DIR.watch >watch_out & watchpid=$! && wait_watch_file watch_out "0" - flux kvs put --json $DIR.watch=1 && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.watch=1 && wait $watchpid - unset FLUX_KVS_NAMESPACE unset_userid cat >expected <<-EOF && 0 @@ -288,17 +200,15 @@ EOF ' test_expect_success NO_CHAIN_LINT 'kvs: watch works (owner)' ' - unlink_kvs_dir_namespace $NAMESPACETMP-USER $DIR && - put_kvs_key_namespace $NAMESPACETMP-USER $DIR.watch 0 && + flux kvs --namespace=$NAMESPACETMP-USER unlink -Rf $DIR && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.watch=0 && wait_watch_put_namespace $NAMESPACETMP-USER "$DIR.watch" "0" rm -f watch_out - export FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER - stdbuf -oL flux kvs watch -o -c 1 $DIR.watch >watch_out & + stdbuf -oL flux kvs --namespace=$NAMESPACETMP-USER watch -o -c 1 $DIR.watch >watch_out & watchpid=$! && wait_watch_file watch_out "0" - flux kvs put --json $DIR.watch=1 && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.watch=1 && wait $watchpid - unset FLUX_KVS_NAMESPACE cat >expected <<-EOF && 0 1 @@ -308,55 +218,47 @@ EOF test_expect_success 'kvs: watch fails (wrong user)' ' set_userid 9000 && - watch_kvs_namespace_exitvalue $NAMESPACETMP-USER $DIR.test exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-USER watch -o -c 1 $DIR.test && + unset_userid ' test_expect_success NO_CHAIN_LINT 'kvs: version & wait works (user)' ' - set_userid 9999 - version_kvs_namespace $NAMESPACETMP-USER VERS + set_userid 9999 && + VERS=`flux kvs --namespace=$NAMESPACETMP-USER version` && VERS=$((VERS + 1)) - export FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER - flux kvs wait $VERS & + flux kvs --namespace=$NAMESPACETMP-USER wait $VERS & kvswaitpid=$! - flux kvs put --json $DIR.xxx=99 - unset FLUX_KVS_NAMESPACE + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.xxx=99 unset_userid test_expect_code 0 wait $kvswaitpid ' test_expect_success 'kvs: version works on other ranks (user)' ' - flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER \ - FLUX_HANDLE_USERID=9999 \ + flux exec -r 1 sh -c "FLUX_HANDLE_USERID=9999 \ FLUX_HANDLE_ROLEMASK=0x2 \ - flux kvs version" + flux kvs --namespace=$NAMESPACETMP-USER version" ' test_expect_success 'kvs: version works on other ranks (owner)' ' - flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER \ - flux kvs version" + flux exec -r 1 sh -c "flux kvs --namespace=$NAMESPACETMP-USER version" ' test_expect_success 'kvs: version fails (wrong user)' ' set_userid 9000 && - version_kvs_namespace_exitvalue $NAMESPACETMP-USER exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-USER version && + unset_userid ' test_expect_success 'kvs: version fails on other ranks (wrong user)' ' - ! flux exec -r 1 sh -c "FLUX_KVS_NAMESPACE=$NAMESPACETMP-USER \ - FLUX_HANDLE_USERID=9000 \ + ! flux exec -r 1 sh -c "FLUX_HANDLE_USERID=9000 \ FLUX_HANDLE_ROLEMASK=0x2 \ - flux kvs version" + flux kvs --namespace=$NAMESPACETMP-USER version" ' test_expect_success 'kvs: wait fails (wrong user)' ' set_userid 9000 && - wait_kvs_namespace_exitvalue $NAMESPACETMP-USER $DIR.test exitvalue && - unset_userid && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-USER wait $DIR.test && + unset_userid ' test_expect_success 'kvs: namespace remove still fails (user)' ' @@ -366,11 +268,10 @@ test_expect_success 'kvs: namespace remove still fails (user)' ' ' test_expect_success 'kvs: namespace remove still works (owner)' ' - put_kvs_key_namespace $NAMESPACETMP-USER $DIR.tmp 1 && + flux kvs --namespace=$NAMESPACETMP-USER put --json $DIR.tmp=1 && test_kvs_key_namespace $NAMESPACETMP-USER $DIR.tmp 1 && flux kvs namespace-remove $NAMESPACETMP-USER && - get_kvs_namespace_exitvalue $NAMESPACETMP-USER $DIR.tmp exitvalue && - test $exitvalue -ne 0 + ! flux kvs --namespace=$NAMESPACETMP-USER get --json $DIR.tmp ' #