Skip to content

Conversation

@tonyandrewmeyer
Copy link
Collaborator

Ops currently silently ignores the label if both are provided by the caller, so we need to preserve that behaviour. This is done in the model, because hookcmds is a low-level API that exposes the raw Juju errors when callers make mistakes (but the existing type overloads will alert callers that both should not be provided).

Copy link
Contributor

@james-garner-canonical james-garner-canonical left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix looks correct to me, but WDYT about tests asserting on the errors raised in these two cases:

  1. Call with both ID and label.
  2. Call with neither.

@tonyandrewmeyer
Copy link
Collaborator Author

  1. Call with both ID and label.
  2. Call with neither.

In test_hookcmds, that would be:

def test_secret_info_get_no_id_or_label(run: Run):
    run.handle(
        ['secret-info-get', '--format=json'],
        returncode=1, stderr='require either a secret URI or label',
    )
    with pytest.raises(hookcmds.Error):
        hookcmds.secret_info_get()  # type: ignore


def test_secret_info_get_id_and_label(run: Run):
    run.handle(
        ['secret-info-get', '--format=json', 'secret:123', '--label', 'lbl'],
        returncode=1, stderr='specifify either a secret URI or label but not both',
    )
    with pytest.raises(hookcmds.Error):
        hookcmds.secret_info_get(id='secret:123', label='lbl')  # type: ignore

I don't feel like this is really testing anything. The Juju behaviour is encoded in the test itself (the Run setup), so the test is really just asserting that if there's an error in the CLI call there will be an error raised, and there's already a test for that. The hookcmds code doesn't have code that deals with neither or both provided, it (by design) lets that fall through to Juju.

If there were tests at the model level, I don't think it's possible to do the neither case, because you can't get a Secret object that doesn't have either an ID or a label (or both). We already have a test for the both case (it's the one that's adjusted in this PR).

Copy link
Contributor

@james-garner-canonical james-garner-canonical left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining.

I agree that the hookcmds level tests don't add much, and it's better to just pass through the Juju behaviour.

I had kind of imagined tests at the model level, but I see how the 'both' case is already handled, and the 'neither' case doesn't make sense.

So LGTM without reservations now.

Copy link
Collaborator

@benhoyt benhoyt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of comments, but approving optimistically.

ops/model.py Outdated
Comment on lines 3953 to 3959
kwargs: dict[str, str] = {}
if id is not None:
kwargs['id'] = id
elif label is not None: # elif because Juju secret-info-get doesn't allow id and label
kwargs['label'] = label
with self._wrap_hookcmd('secret-info-get', id=id, label=label):
raw = hookcmds.secret_info_get( # type: ignore
id=id,
label=label,
)
raw = hookcmds.secret_info_get(**kwargs)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably it's an error if neither id or label are specified? Should we have an else: raise TypeError(...) case to handle that?

Also, it might be a bit simpler / more type safe to do this (but I don't have strong feelings):

if id is not None:
    with self._wrap_hookcmd('secret-info-get', id=id):
        raw = hookcmds.secret_info_get(id=id)
elif label is not None:
    with self._wrap_hookcmd('secret-info-get', label=label):
        raw = hookcmds.secret_info_get(label=label)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably it's an error if neither id or label are specified? Should we have an else: raise TypeError(...) case to handle that?

We can't do that in _ModelBackend because it would break backwards compatibility. We could do it in hookcmds (because _ModelBackend would have already filtered out the label argument), but overall the design for hookcmds is that errors are left to be provided by Juju, not duplicated in Python code. A type check will show that it's incorrect (because of the existing overloads). I'd prefer to keep it that way.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep it that way.

Thanks for clarifying. Yep, that's fine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably it's an error if neither id or label are specified? Should we have an else: raise TypeError(...) case to handle that?

Ah, I misread this, sorry. I thought you said both but you said neither. I don't think it's possible to get to that state in _ModelBackend (see earlier comment to James) but I can add an else to be certain, sure.

@tonyandrewmeyer tonyandrewmeyer merged commit 3ce1c7f into canonical:main Nov 16, 2025
56 checks passed
@tonyandrewmeyer tonyandrewmeyer deleted the fix-secret-info-get-not-id-and-label branch November 16, 2025 20:08
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

Successfully merging this pull request may close these issues.

3 participants