Name the sizes a node can ask for
Raw cpus and gpus are a property of the machines an installation has, so a node written against a cluster quietly stops meaning anything when the cluster is replaced. A node says "gpu-small" instead, and what that is stored here — editable, and read again every time the node is built, so changing the flavor changes what the next run gets. Memory joins the schema properly (`ram`, in MB, accepting "2G"), along with `duration_s` for how long a node is expected to take. That one is recorded and shown and nothing else yet: a statement for whoever is planning around the node, not a limit — the limit is still `timeout`. A flavor and a number for the same thing is refused, compared by value so an editor writing the whole object back with its defaults still round-trips. A name nothing stores is refused at the save, which covers the canvas and `fluksio sync` at once, and deleting one a node still asks for says which node. Four sizes are seeded on an installation that has none, and never re-seeded: re-adding one somebody deliberately removed is an argument nobody wins. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A6HeySA27EkGANZN95QySW
This commit is contained in:
@@ -150,3 +150,36 @@ def test_declaring_nothing_stays_exactly_as_it_was():
|
||||
def test_a_misspelled_resource_is_refused():
|
||||
with pytest.raises(ValueError):
|
||||
Resources(cpu=4)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Sizes with names, and sizes written out
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_a_size_can_be_written_the_way_people_write_sizes():
|
||||
assert Resources(ram="2G").ram == 2048
|
||||
assert Resources(ram="512M").ram == 512
|
||||
assert Resources(ram="512").ram == 512
|
||||
assert Resources(ram=512).ram == 512
|
||||
with pytest.raises(ValueError, match="not a size"):
|
||||
Resources(ram="a lot")
|
||||
|
||||
|
||||
def test_a_duration_is_one_unit_and_says_so_when_it_is_not():
|
||||
assert Resources(duration_s="2h").duration_s == 7200
|
||||
assert Resources(duration_s="30m").duration_s == 1800
|
||||
assert Resources(duration_s="90").duration_s == 90
|
||||
with pytest.raises(ValueError, match="not a duration"):
|
||||
Resources(duration_s="1h30m")
|
||||
|
||||
|
||||
def test_a_flavor_and_a_number_for_the_same_thing_is_two_answers():
|
||||
with pytest.raises(ValueError, match="already says how much"):
|
||||
Resources(flavor="gpu-small", cpus=4)
|
||||
|
||||
# The defaults are not an answer: an editor writing the whole object back
|
||||
# sends them, and that must survive the round trip.
|
||||
assert Resources(flavor="gpu-small", cpus=1, gpus=0).flavor == "gpu-small"
|
||||
# Neither is a duration, which a flavor says nothing about.
|
||||
assert Resources(flavor="gpu-small", duration_s="2h").duration_s == 7200
|
||||
|
||||
Reference in New Issue
Block a user