-
Notifications
You must be signed in to change notification settings - Fork 46
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
fix: "device update --locked" should also unlock #485
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Marques Johansson <[email protected]>
…dition args Signed-off-by: Marques Johansson <[email protected]>
updateDeviceCmd.Flags().StringSliceVarP(&tags, "tags", "t", []string{}, `Adds or updates the tags for the device --tags="tag1,tag2".`) | ||
updateDeviceCmd.Flags().BoolVarP(&alwaysPXE, "always-pxe", "a", false, "Updates the always_pxe toggle for the device (<true|false>).") | ||
updateDeviceCmd.Flags().StringVarP(&ipxescripturl, "ipxe-script-url", "s", "", "Add or update the URL of the iPXE script.") | ||
updateDeviceCmd.Flags().StringVarP(&customdata, "customdata", "c", "", "Adds or updates custom data to be included with your device's metadata.") | ||
_ = updateDeviceCmd.MarkFlagRequired("id") | ||
|
||
updateDeviceCmd.MarkFlagsMutuallyExclusive("userdata", "userdata-file") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ PACKNGO_DEBUG=1 go run ./cmd/metal device update --locked false --id 1234 --userdata foo --userdata-file=/tmp/foo
Error: if any flags in the group [userdata userdata-file] are set none of the others can be; [userdata userdata-file] were all set
Usage:
...
Surprisingly, this does not affect make generate-docs
.
updateDeviceCmd.Flags().StringSliceVarP(&tags, "tags", "t", []string{}, `Adds or updates the tags for the device --tags="tag1,tag2".`) | ||
updateDeviceCmd.Flags().BoolVarP(&alwaysPXE, "always-pxe", "a", false, "Updates the always_pxe toggle for the device (<true|false>).") | ||
updateDeviceCmd.Flags().StringVarP(&ipxescripturl, "ipxe-script-url", "s", "", "Add or update the URL of the iPXE script.") | ||
updateDeviceCmd.Flags().StringVarP(&customdata, "customdata", "c", "", "Adds or updates custom data to be included with your device's metadata.") | ||
_ = updateDeviceCmd.MarkFlagRequired("id") | ||
|
||
updateDeviceCmd.MarkFlagsMutuallyExclusive("userdata", "userdata-file") | ||
updateDeviceCmd.Args = cobra.NoArgs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ PACKNGO_DEBUG=1 go run ./cmd/metal device update --locked false --id 1234 fkk fll
Error: unknown command "fkk" for "metal device update"
Re: the |
Signed-off-by: Marques Johansson <[email protected]>
Signed-off-by: Marques Johansson <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the behavior to expect --locked
or --locked=<true|false>
and revised the docs to match.
Using --locked true|false
will result in an error:
Error: unknown command "false" for "metal device update"
@@ -80,7 +75,11 @@ func (c *Client) Update() *cobra.Command { | |||
deviceUpdate.Userdata = &userdata | |||
} | |||
|
|||
if locked { | |||
if cmd.Flag("locked").Changed { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A test for lock/unlock would build confidence that we've fixed the issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started down a path of introducing a mock because I don't like the idea of spinning up and settling electrified and cooled rust to verify that a few bytes of command line argument trigger a few bytes of json in an HTTP call.
The test in the sha is not clean or complete, but it does trigger the lock in the CLI args and look for the request to contain the expected JSON.
Alternatively, I could add steps to the existing "update" E2E to see if the resource locked
state can be toggled on and off again (which would be needed for a successful cleanup).
Interested in your thoughts on a preferred path, @ctreatma.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong preference either way for whether the test hits a live API or a mock. If we're going to mock I think it's better to set up a mock API than to inject a mock HTTP transport, since that more closely matches real usage, reduces the risk of accidentally mocking out some custom behavior, and provides a more straightforward path to maybe eventually adopting a mock that is generated from the API spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, using true/false as allowed values for a flag is generally not typical convention for CLIs. There should be an opposite flag, like --unlock
to flip it. (See https://stackoverflow.com/questions/52403065/argparse-optional-boolean)
@stevemar The precedent in the
We may find other places where Metal CLI can certainly introduce more obvious patterns in future versions, such as named pairs ( Related issues:
Another alternative that fits this particular parameter would be to introduce
The complications owe to RPC-like port endpoints in the otherwise REST-y API. In REST API's the verb is the HTTP Action ( Metal CLI could be more predictable about how it approaches API to CLI translation, if not dogmatic. Documentation in I created #487 from this feedback and to continue this conversation. |
Signed-off-by: Marques Johansson <[email protected]>
out := helper.ExecuteAndCaptureOutput(t, root) | ||
|
||
if !strings.Contains(string(out[:]), "not delete") { | ||
t.Error("expected output should include 'not delete' in the out string due to device locking") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is failing here; haven't checked this PR out yet to get a better idea of which part of this is failing (Device is not locked? Device is locked but the error message doesn't match the check on line 58? Something else?).
https://github.com/equinix/metal-cli/actions/runs/10741510710/job/29792085636?pr=485#step:5:77
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The delete subcommand waits for confirmation before deleting: https://github.com/equinix/metal-cli/blob/main/internal/devices/delete.go#L40-L41
This test will need to delete with the -f
flag to bypass the confirmation prompt.
Fixes #484
Previous behavior was to set
{"locked":true}
inPUT
requests whenever--locked
was specified. This is because the presence of the flag itself is treated as a toggle. The value argument was ignored unless given as--locked=true
or--locked=false
. When--locked=false
was given, thePUT
request was{}
, since the code required true values to add the field to the update request.This change technically breaks the current ability to do
metal device update --locked --some-other-arg
.