Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python: KVSDir object should write to path it is initialized with #5308

Closed
garlick opened this issue Jul 5, 2023 · 9 comments
Closed

python: KVSDir object should write to path it is initialized with #5308

garlick opened this issue Jul 5, 2023 · 9 comments
Assignees

Comments

@garlick
Copy link
Member

garlick commented Jul 5, 2023

Problem: a KVSDir object acts like a dictionary for a KVS directory when reading from the KVS, but it discards its relative path and operates directly on the root when writing to the KVS.

For example, this program uses a KVSDir to print a key from a job directory and then update the same key:

#!/usr/bin/env python3

import sys
import flux.job
import flux.job.JobID as JobID

jobid = JobID(sys.argv[1])
key = sys.argv[2]
val = sys.argv[3]

handle = flux.Flux()
jobdir = flux.job.job_kvs(handle, jobid)
# This  refers to a key name in the job's KVS directory
print(jobdir[key])

# But this refers to a key name in the root directory
jobdir[key] = val
jobdir.commit()
$ flux ./foo.py  ƒ6acjkLQf jobspec xyz
{'resources': [{'type': 'slot', 'count': 1, 'with': [{'type': 'core', 'count': 1}], 'label': 'task'}], 'tasks': [{'command': ['hostname'], 'slot': 'task', 'count': {'per_slot': 1}}], 'attributes': {'system': {'duration': 0, 'cwd': '/nfshome/garlick', 'shell': {'options': {'rlimit': {'cpu': -1, 'fsize': -1, 'data': -1, 'stack': -1, 'core': 16384, 'nofile': 128000, 'as': -1, 'rss': -1, 'nproc': 8192}}}}}, 'version': 1}

# hmm no update
$ flux job info ƒ6acjkLQf jobspec
{"resources":[{"type":"slot","count":1,"with":[{"type":"core","count":1}],"label":"task"}],"tasks":[{"command":["hostname"],"slot":"task","count":{"per_slot":1}}],"attributes":{"system":{"duration":0,"cwd":"/nfshome/garlick","shell":{"options":{"rlimit":{"cpu":-1,"fsize":-1,"data":-1,"stack":-1,"core":16384,"nofile":128000,"as":-1,"rss":-1,"nproc":8192}}}}},"version":1}

# oops unexpected jobspec key in the root!
$ flux kvs get jobspec
"xyz"
@vsoch
Copy link
Member

vsoch commented Jul 5, 2023

Thanks for opening this @garlick !

Update: for future reference, my test cases are here: https://github.com/researchapps/test-kvs-commit

@garlick
Copy link
Member Author

garlick commented Jul 5, 2023

Thanks for finding it!

@chu11
Copy link
Member

chu11 commented Jul 8, 2023

Looking through code history, this appears to be an oversight from the initial implementation in 2015. Surprised it took so long to find :-) Also no path = .... tests in t/python/, so should do that too.

@vsoch
Copy link
Member

vsoch commented Jul 8, 2023

That's me, the bug finder!! 😆 🐛 🐞 Actually more like I'm really good at breaking things. 🔨

@vsoch
Copy link
Member

vsoch commented Jul 8, 2023

Workaround - works! researchapps/test-kvs-commit@9a8d1be

Thanks for the help! This should work for our current needs- it works for both the case that the key exists and the case that it does not.

@chu11
Copy link
Member

chu11 commented Jul 8, 2023

note: looking through code, I think fill() and mkdir() on KVSDir probably also don't work.

@chu11
Copy link
Member

chu11 commented Jul 8, 2023

thinking about this a bit ... this change has the potential to break a ton of code, if people are using it. Which I don't know if people are.

i.e.

dir = KVSDir(handle, path="foo.bar")
dir["foo.bar.a"] = 1
dir.commit()

before this created "foo.bar.a" and if we change it'll create "foo.bar.foo.bar.a".

Perhaps we could ping a few code teams and see if they use KVSDir with a path argument and do writes? If we can confirm a few teams don't use the path argument, then I'd feel better that this isn't going to break the world.

If a few teams are using it, then we perhaps should have a migration path to warn them of the change.

Edit: ugh and likewise if people use the results from job_kvs() like example above

@vsoch
Copy link
Member

vsoch commented Jul 8, 2023

If the bug hasn't been caught for 8 years, do you think people are using it?

@chu11
Copy link
Member

chu11 commented Jul 9, 2023

If the bug hasn't been caught for 8 years, do you think people are using it?

I agree low probability. Two things made me pause.

  1. With using KVSDir directly, I think this issue is a little less obvious. You going through job_kvs() makes it a bit more obvious. So it may have not been an obvious issue to any users using KVSDir directly.

  2. (this is the bigger one I paused on) there's a KVSDir function called fill() which allows the user to pass in a Mapping and put each "key=val" mapping into the KVS. It's not a dumb setter/getter that one would "just add" to a newly created class. I think there's a decent chance it was added by a user request OR added b/c of a specific need.

Edit: also should mention mkdir() also allows you to pass in a Mapping to write stuff to directory post-mkdir. Again IMO not an obvious thing to just add, so added by user request or specific need?

Edit2: scratch the mkdir() part, it didn't work at all given the initial "relative path" problem ...

@chu11 chu11 changed the title python: KVSDir object does not quite work as expected python: KVSDir object should write to relative path it is initialized with Jul 9, 2023
@chu11 chu11 changed the title python: KVSDir object should write to relative path it is initialized with python: KVSDir object should write to path it is initialized with Jul 10, 2023
chu11 added a commit to chu11/flux-core that referenced this issue Jul 10, 2023
Problem: KVSDir can be passed an initial path when initialized.  This
path gives context to all reads.  For example, if initialized with the
path "foo", a later read of the key "bar" will actually read "foo.bar".
While this works for reads, this does not work for writes.  For example,
if initialized with the path "foo", a later write of the key "bar" will
write to the path "bar", not "foo.bar".

Solution: When doing writes, ensure writes are written relative to the
initial path.

Fixes flux-framework#5308
chu11 added a commit to chu11/flux-core that referenced this issue Jul 10, 2023
Problem: The KVSDir initial path write issue (flux-framework#5308) was discovered
via the job_kvs() function in the job/kvs.py module.  There is no regression
test for this issue.

Add a new regression test t5308-kvsdir-initial-path.py.
chu11 added a commit to chu11/flux-core that referenced this issue Jul 10, 2023
Problem: The KVSDir initial path write issue (flux-framework#5308) was discovered
via the job_kvs() function in the job/kvs.py module.  There is no regression
test for this issue.

Add a new regression test t5308-kvsdir-initial-path.py.
chu11 added a commit to chu11/flux-core that referenced this issue Jul 10, 2023
Problem: KVSDir can be passed an initial path when initialized.  This
path gives context to all reads.  For example, if initialized with the
path "foo", a later read of the key "bar" will actually read "foo.bar".
While this works for reads, this does not work for writes.  For example,
if initialized with the path "foo", a later write of the key "bar" will
write to the path "bar", not "foo.bar".

Solution: When doing writes, ensure writes are written relative to the
initial path.

Fixes flux-framework#5308
chu11 added a commit to chu11/flux-core that referenced this issue Jul 10, 2023
Problem: The KVSDir initial path write issue (flux-framework#5308) was discovered
via the job_kvs() function in the job/kvs.py module.  There is no regression
test for this issue.

Add a new regression test t5308-kvsdir-initial-path.py.
chu11 added a commit to chu11/flux-core that referenced this issue Jul 12, 2023
Problem: The KVSDir initial path write issue (flux-framework#5308) was discovered
via the job_kvs() function in the job/kvs.py module.  There is no regression
test for this issue.

Add a new regression test t5308-kvsdir-initial-path.py.
@mergify mergify bot closed this as completed in fd84e30 Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants