community.general
community.general copied to clipboard
onepassword - Support v2
SUMMARY
Fixes #4396. Closes #4415.
The interface and data schema for op
version two changed significantly. Create a base class defining the common interface then define version specific classes.
The appropriate class will be used based on the discovered op
version.
The lookups/module will fail gracefully for unsupported versions.
ISSUE TYPE
- Bugfix Pull Request
COMPONENT NAME
plugins/lookup/onepassword.py
ADDITIONAL INFORMATION
Still a work in progress. Open to feedback.
cc @azenk @scottsb click here for bot help
Still working on this, just as time allows.
Making some good progress. It's mostly working (only the full login is not). I need to do some more polishing and update the tests.
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
tests/unit/plugins/lookup/test_onepassword.py:104:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
tests/unit/plugins/lookup/test_onepassword.py:104:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
tests/unit/plugins/lookup/test_onepassword.py:104:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
tests/unit/plugins/lookup/test_onepassword.py:104:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 11 errors:
tests/unit/plugins/lookup/test_onepassword.py:113:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:117:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:134:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:138:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:147:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:164:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:173:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:40: E231: missing whitespace after ','
tests/unit/plugins/lookup/test_onepassword.py:197:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:205:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 11 errors:
tests/unit/plugins/lookup/test_onepassword.py:113:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:117:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:134:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:138:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:147:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:164:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:173:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:40: E231: missing whitespace after ','
tests/unit/plugins/lookup/test_onepassword.py:197:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:205:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 11 errors:
tests/unit/plugins/lookup/test_onepassword.py:113:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:117:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:134:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:138:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:147:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:164:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:173:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:40: E231: missing whitespace after ','
tests/unit/plugins/lookup/test_onepassword.py:197:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:205:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test pep8
[explain] failed with 11 errors:
tests/unit/plugins/lookup/test_onepassword.py:113:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:117:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:134:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:138:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:147:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:164:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:173:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:184:40: E231: missing whitespace after ','
tests/unit/plugins/lookup/test_onepassword.py:197:1: E302: expected 2 blank lines, found 1
tests/unit/plugins/lookup/test_onepassword.py:205:1: E302: expected 2 blank lines, found 1
The test ansible-test sanity --test metaclass-boilerplate
[explain] failed with 1 error:
tests/unit/plugins/lookup/onepassword/conftest.py:0:0: missing: __metaclass__ = type
The test ansible-test sanity --test future-import-boilerplate
[explain] failed with 1 error:
tests/unit/plugins/lookup/onepassword/conftest.py:0:0: missing: from __future__ import (absolute_import, division, print_function)
Hi @samdoran, thanks for working on this! I am eagerly waiting for this PR to be merged. As per your message in #4415 I just tested the current implementation and have some feedback. I only tested the v2 implementation. I'd be happy to help with the implementation if needed.
Items in Sections
Currently specifying a section
breaks lookups with a 'NoneType' object is not iterable.
error. This is because data.get(section)
does not work for the v2 JSON schema.
https://github.com/samdoran/community.general/blob/c979d31dd156588743fd16841685885ce7480e5f/plugins/lookup/onepassword.py#L446-L447
This isn't such a huge problem because fields are looked up by their unique ID anyways. I think there are two possible ways to deal with this (I'd prefer the second option):
- Remove the
section
field for the v2 lookup completely and require thefield
to be the unique ID of an item's field. - Lookup fields by their ID or their label. If a section is specified (by ID or by label) only consider items whose section is set to this value (ID or label). If multiple or no matches are found, raise an error. As far as I can tell this mirrors the behavior of the
op item get
command. This could be enhanced by matching an empty section value""
against items in the default section (and treating theNone
section as any section).
Handling of missing fields
Currently if a field is not found in an item an empty string is returned. I feel like this is prone to errors (e.g. accidentally setting an empty password because of a typo). I would expect an error message in a case like this.
https://github.com/samdoran/community.general/blob/c979d31dd156588743fd16841685885ce7480e5f/plugins/lookup/onepassword.py#L456
Field Selection
Currently the requested field is matched against the field's ID as well as the keys of the item's JSON representation. I don't see an application for this. Moreover this makes it impossibly to query the value of a field whose ID matches one of those keys. Maybe it also makes sense to also match against the field label in v2 (the op item get --field
command does this and errors out if there are multiple results)…
https://github.com/samdoran/community.general/blob/c979d31dd156588743fd16841685885ce7480e5f/plugins/lookup/onepassword.py#L448-L450
For example: I created an API_CREDENTIAL
item and set its type
to "bearer"
. However lookup('community.general.onepassword', 'Test', field='type')
returns "STRING"
. If the application here is to be able to query other properties of fields (such as their labels), I think this this would better be done via a dedicated argument such as lookup('community.general.onepassword', 'Test', field='type', subfield='label')
. The subfield
could be set to "value"
by default.
Documentation
The v1 version of the plugin did lookups based on a field's label
(or rather I think there wasn't really a difference between labels and IDs). The v2 version looks up fields by their id
s. I think this behavior should be documented, especially since it doesn't seem possible to view IDs via the 1Password Apps (only via the CLI).
https://github.com/samdoran/community.general/blob/c979d31dd156588743fd16841685885ce7480e5f/plugins/lookup/onepassword.py#L27-L28
Also as a side node the docs still say Tested with op version 0.5.3
.
Additional suggestions
- Maybe a useful addition might be to allow the selection of a value via the 1Password secret reference format:
op://<vault>/<item>/<section>/<field>
, orop://<vault>/<item>/<field>
. This might improve convenience a little but apart from that provides little value. - It might also be useful to allow filtering fields by field type using an additional
type
argument. However this is probably most useful if the user wants to retrieve all fields of a specific type, not just a single field.
@codello This is excellent feedback. Give me a bit to read through and respond.
Currently specifying a section breaks lookups with a 'NoneType' object is not iterable. error. This is because data.get(section) does not work for the v2 JSON schema.
Great catch. The simple fix would be to default to en empty list instead of None
. Also, we need a test case for that.
Currently if a field is not found in an item an empty string is returned.
I'm in favor of matching on ID or label. Looking through some items, ID and label are the same sometimes, but not always. ID seems to be a GUID most of the time whereas label is the human-visible field. It might make sense to prefer label as the primary match and fall back to ID.
If multiple or no matches are found, raise an error. Currently if a field is not found in an item an empty string is returned.
I would have to think more about what to do in this case. This would be a breaking change and should be addressed in a separate PR.
Currently the requested field is matched against the field's ID as well as the keys of the item's JSON representation. I don't see an application for this.
Yeah, that seems a bit greedy. The matching should be on label first and fall back to ID.
Also as a side node the docs still say Tested with op version 0.5.3
I'll fix that.
Looking the v2 schema for sections
, there is no value
field, so I'm not sure it makes sense to allow sections
in the v2 CLI. Maybe we could warn for that?
Docs Build 📝
Thank you for contribution!✨
This PR has been merged and your docs changes will be incorporated when they are next published.
Looking the v2 schema for sections, there is no value field, so I'm not sure it makes sense to allow sections in the v2 CLI. Maybe we could warn for that?
I am not sure if I completely understand. Completely removing support for sections would not be my preferred solution, mostly because I tend to re-use the same field labels (like Username or Password) in different sections. When accessing fields via ID this is not a problem but when accessing fields by their label this would probably cause problems. In general I'd expect the lookup to work like this:
- If a field is specified by ID, the field should be returned. I think for this to work IDs should be prioritized over labels during the lookup. Below is an example where this might be necessary.
- If a field is specified by label and that label is unique the field should be returned.
- If a field is specified by name and is not unique, I expect an error. As you said this might be considered a breaking change and might need to be addressed separately.
- If a section is identified by label or ID I'd expect any resulting field to be in that section.
There is one edge case that is not quite clear to me: If a field is specified by ID and that field exists but in a different section than the user specified I am not sure which case takes priority. I think in this case the result should be empty (or preferably an error) because even though the item is uniquely identified it does not match the expected section so clearly something is wrong. This also matches the behavior of op item get
.
I tried to put this behavior into some pseudo-code. I did not test this but hopefully it makes my though process clear:
def _parse_field(self, data_json, field_name, section_title=None):
data = json.loads(data_json)
matches = []
for field in data.get("fields", []):
if section_title == "" and "section" in field:
# Treat the empty string as the default section. If a field belongs
# to a section but we requested the default section, this is not a match.
continue
if section_title is not None:
if "section" not in field:
# We requested a section but the field does not belong to one.
# This is not a match.
continue
if (
field["section"].get("id") != section_title
and field["section"].get("label") != section_title
):
# We requested a section but neither the id nor the label of this
# item's section match. This is not a match.
continue
if field.get("id") == field_name:
# We might want to prioritize IDs and bail out here to be able to
# guarantee that each field can be addressed.
return field
if field.get("label") == field_name:
matches.append(field)
if len(matches) == 0:
raise NotFoundError
if len(matches) > 1:
raise TooManyMatchesError
return matches[0]
Here is a (slightly redacted) JSON of an item in my 1Password vault for reference:
{
"id": "4fym...",
"title": "Test",
"version": 3,
"vault": {
"id": "dkov...",
"name": "Personal"
},
"category": "API_CREDENTIAL",
"last_edited_by": "N43H...",
"created_at": "2022-09-03T20:32:29Z",
"updated_at": "2022-09-03T21:04:36Z",
"additional_information": "bearer",
"sections": [
{
"id": "ver6dax344cakdckoq4clvbgg4",
"label": "Database"
},
{
"id": "js566w4t4wagh7yjivlujneiem",
"label": "SMTP"
}
],
"fields": [
{
"id": "notesPlain",
"type": "STRING",
"purpose": "NOTES",
"label": "notesPlain",
"reference": "op://Personal/Test/notesPlain"
},
{
"id": "username",
"type": "STRING",
"label": "Benutzername",
"value": "some name",
"reference": "op://Personal/Test/Benutzername"
},
{
"id": "credential",
"type": "CONCEALED",
"label": "Anmeldedaten",
"value": "some password",
"reference": "op://Personal/Test/Anmeldedaten"
},
{
"id": "type",
"type": "MENU",
"label": "Typ",
"value": "bearer",
"reference": "op://Personal/Test/Typ"
},
{
"id": "q3wjz2pdkjb3axohgbrmtvql2e",
"type": "STRING",
"label": "type",
"value": "MyType",
"reference": "op://Personal/Test/type"
},
{
"id": "qeoer3o33xufkrgiywiqaymgha",
"section": {
"id": "ver6dax344cakdckoq4clvbgg4",
"label": "Database"
},
"type": "STRING",
"label": "user",
"value": "my-db-user",
"reference": "op://Personal/Test/Database/user"
},
{
"id": "6ryw2k4sdkeg7phmdzuacbmoiq",
"section": {
"id": "js566w4t4wagh7yjivlujneiem",
"label": "SMTP"
},
"type": "STRING",
"label": "user",
"value": "my-smpt-user",
"reference": "op://Personal/Test/SMTP/user"
}
]
}
Here the preference of IDs over labels is important. A lookup of the field type
should imo return a unique result "bearer"
, even though the field with the label type
might also be a match. This is analogous to the op item get --field
command.
I am not sure if I completely understand.
I meant that the value of sections
doesn't contain any values:
"sections": [
{
"id": "ver6dax344cakdckoq4clvbgg4",
"label": "Database"
},
{
"id": "js566w4t4wagh7yjivlujneiem",
"label": "SMTP"
}
],
I think my understanding of the "section" parameter was a bit off. "section" doesn't iterate through "sections" in the output but should match on fields[item]["section"]["label"]
. Does that sound correct?
The test licenses
failed with 10 errors:
tests/unit/plugins/lookup/onepassword/files/v2_out_01.json:0:0: found no copyright notice
tests/unit/plugins/lookup/onepassword/files/v2_out_01.json:0:0: must have at least one license
tests/unit/plugins/lookup/onepassword/files/v1_out_02.json:0:0: found no copyright notice
tests/unit/plugins/lookup/onepassword/files/v1_out_02.json:0:0: must have at least one license
tests/unit/plugins/lookup/onepassword/files/v1_out_01.json:0:0: found no copyright notice
tests/unit/plugins/lookup/onepassword/files/v1_out_01.json:0:0: must have at least one license
tests/unit/plugins/lookup/onepassword/files/v1_out_03.json:0:0: found no copyright notice
tests/unit/plugins/lookup/onepassword/files/v1_out_03.json:0:0: must have at least one license
tests/unit/plugins/lookup/onepassword/files/v2_out_02.json:0:0: found no copyright notice
tests/unit/plugins/lookup/onepassword/files/v2_out_02.json:0:0: must have at least one license
I meant that the value of sections doesn't contain any values
Ah ok, now I got it. Thanks!
"section" doesn't iterate through "sections" in the output but should match on fields[item]["section"]["label"]. Does that sound correct?
Yes, pretty much. I think the sections
array in the JSON is only there to be able to order the sections the same way 1Password does. For the purpose of finding a field the fields
array contains all the information needed and fields[i]["section"]["label"]
and fields[i]["section"]["id"]
contain the label and ID of the section respectively.
If a field belongs to the default section fields[I]["section"]
does not exist.
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
plugins/lookup/onepassword_raw.py:90:9: E303: too many blank lines (2)
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
plugins/lookup/onepassword_raw.py:90:9: E303: too many blank lines (2)
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
plugins/lookup/onepassword_raw.py:90:9: E303: too many blank lines (2)
The test ansible-test sanity --test pep8
[explain] failed with 1 error:
plugins/lookup/onepassword_raw.py:90:9: E303: too many blank lines (2)
I've tested it here locally with both op versions (2.7.1 and 1.12.4). Both works for me.
This is a very valuable PR. @samdoran can you add a changelog fragment please?
Will do. I have few minor things left to finalize and want to add more test scenarios, but I'm feeling good about where it is currently.
Please note that the community.general 6.0.0 release is in two weeks (November 7th), I think it would be great if this PR could make it into that one.
Eek. Thanks for the push. I started a new job and have been focused that. I will do my best to get this over the line.
The test ansible-test sanity --test import --python 3.9
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.8
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.5
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.11
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.10
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test pylint
[explain] failed with 1 error:
plugins/module_utils/onepassword.py:14:0: ansible-bad-module-import: Import external package or ansible.module_utils not ansible.errors
The test ansible-test sanity --test import --python 3.9
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.8
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.5
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.10
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.9
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.8
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.5
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.10
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.9
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.8
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.5
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.11
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.10
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test pylint
[explain] failed with 1 error:
plugins/module_utils/onepassword.py:14:0: ansible-bad-module-import: Import external package or ansible.module_utils not ansible.errors
The test ansible-test sanity --test pylint
[explain] failed with 1 error:
plugins/module_utils/onepassword.py:14:0: ansible-bad-module-import: Import external package or ansible.module_utils not ansible.errors
The test ansible-test sanity --test import --python 3.9
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.8
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 3.5
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.7
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test import --python 2.6
[explain] failed with 2 errors:
plugins/module_utils/onepassword.py:14:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context
plugins/modules/onepassword_info.py:169:0: traceback: ImportError: import of "ansible.errors" is not allowed in this context (at plugins/module_utils/onepassword.py:14:0)
The test ansible-test sanity --test pylint
[explain] failed with 1 error:
plugins/module_utils/onepassword.py:14:0: ansible-bad-module-import: Import external package or ansible.module_utils not ansible.errors
The test ansible-test sanity --test pylint
[explain] failed with 1 error:
plugins/module_utils/onepassword.py:14:0: ansible-bad-module-import: Import external package or ansible.module_utils not ansible.errors
The test ansible-test sanity --test compile --python 3.5
[explain] failed with 1 error:
tests/unit/plugins/lookup/onepassword/test_onepassword.py:165:44: SyntaxError: f"v{cls.supports_version}_{idx + 1}" for cls in MOCK_ENTRIES
The test ansible-test sanity --test compile --python 2.7
[explain] failed with 1 error:
tests/unit/plugins/lookup/onepassword/test_onepassword.py:165:44: SyntaxError: f"v{cls.supports_version}_{idx + 1}" for cls in MOCK_ENTRIES
The test ansible-test sanity --test compile --python 2.6
[explain] failed with 1 error:
tests/unit/plugins/lookup/onepassword/test_onepassword.py:165:44: SyntaxError: f"v{cls.supports_version}_{idx + 1}" for cls in MOCK_ENTRIES
This is good to merge now.
Thanks for all the feedback and patience, everyone.
@samdoran thanks a lot for your contribution! @ahussey-redhat @codello @markuman thanks for reviewing and giving feedback!