* Fix installation from source transforms symlinks of dirs to empty dirs
* Add test to check symlinks to dirs are respected when installing from source
* Add changelog for collection install from source symlink to dirs issue
* Ensure that we do not squash keywords in validate. Fixes#79021
* become_user: nobody should only apply to the test tasks, not the setup_test_user role
* Update how become_user is specified
* Add test to ensure keyword inheritance is working for become
* Add clog frag
* Cache fattributes to prevent re-calculation
* ci_complete
* Remove unnecessary getattr
* Use python re to parse service output instead of grep. Fixes#78541
* Add clog frag
* Add an extra guard to abort if rc is 4, and /etc/init.d is missing
* ansible-vault: add newline to the output of the 'encrypt_string' command
* Add comment with issue description and improve string joining
* Add changelog fragment
* Update changelogs/fragments/79017-ansible-vault-string-encryption-ending-with-newline.yml
Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
* Fixed some typos in changelog fragment
* Improve comment regarding newline character at the end of file
Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
* Do not crash templating when filter/test name is not a valid Ansible plugin name.
* Store and re-raise KeyError if there was one.
Co-authored-by: s-hertel <19572925+s-hertel@users.noreply.github.com>
* omit keyword should reset to context
ensure we use context/inheritance when calculating value,
using default only when context is unavailable.
fixes#75692
- correct 'vars:' precedence to allow phasing out of include_params
- actually merge vars and always include role_vars
- avoided dupe deps from giving wrong vars
- use 'first' instance of dep as others are from previous instances/invocations
and can have diff values for vars
- ensured deps only provide exportable vars themselves
- added COMMENTS
- added tests
- apply export restrictions setting to defaults
- use 'public' as cutoff
Co-authored-by: Sloane Hertel <19572925+s-hertel@users.noreply.github.com>
ci_complete
* winrm - fix reducing 'Read timed out' error
This fix reduces the exceptiopn 'Read timed out. (read timeout=nnn)' occurring seemingly randomly and
unpredictable on some networks (which have long latency and/or many hops or other problems). The fix
ensures that the involved timeout is set to a value so this issue is reduced.
* Add changelog fragment
Co-authored-by: Jordan Borean <jborean93@gmail.com>
* Ensure that meta/runtime.yml redirects are FQCRs.
* Avoid crash when YAML errors without context mark happen, for example if file starts with 'foo---' instead of '---'.
- Allow disabled, unsupported, unstable and destructive integration test targets to be selected using their respective prefixes.
- Allow unstable tests to run when targeted changes are made and the ``--allow-unstable-changed`` option is specified (resolves https://github.com/ansible/ansible/issues/74213).
* Add --offline option to 'ansible-galaxy collection install' to prevent querying distribution servers
This allows installing/upgrading individual tarfiles to have dependency resolution.
Previously needed to be done manually with --no-deps or else all collections and dependencies needed to be included in the requirements.
Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
* Add OSMC to Debian OS_FAMILY_MAP
- os_family fact of the Debian-based OSMC distribution was not detected correctly
* tweak changelog
Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com>
* new _fqcn attribute to plugin objects
* unbreak plugins in subdirs
* Fix inadventent changes to _load_name and use existing vars
* add plugin aliases and name property, and replace plugin._load_name where incorrect
* Fix listing plugin names
Fix listing legacy and builtin together
test deprecated plugin documentation
fix doc extensions
remove sometimes inaccurate _load_name handling from plugin.name
* Add tests for REJECT_EXTS and doc extensions
Fix unpredictable collection redirects so non-fqcns in the redirect list are guaranteed to be legacy (instead of determined by the collections keyword)
Move aliases and name properties to _update_object so all plugin types, including doc fragments, can use them
* make legacy plugin names internally consistent
* rename attributes to ansible_name and ansible_aliases
This fixes bug which prevents identification of broken playbook when
passing multiple playbooks as arguments, something that is common
especially with `--syntax-check`.
Affects: ansible-lint
* Limit Galaxy API calls during ansible-galaxy collection dependency resolution when possible
Installing a tarfile with a dependency from a Galaxy server (e.g. dependencies: {'ns.coll': '>=1.0.0'}) does not get the available versions of the dependency from the galaxy server if a sufficient version is already installed.
Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
* Add a warning for collections that are attempting to be autoloaded to no effect
* Deprecate REQUIRES_WHITELIST and add support for REQUIRES_ENABLED so the docs are accurate
* Fix documentation
* add more vars plugin tests
* Simplify code and add a FIXME for another bug
* fix precedence
* Make setting the class attr at all a warning, even if it's True
* Add fun parsing for _load_name
* include _load_name in messages
* add required file to collection skeleton
This file is required to be able to upload a collection.
It is present in
https://github.com/ansible-collections/collection_template/blob/main/meta/runtime.yml
but that does not get used by default.
Without this, if you use the "ansible-galaxy collection init" command
and you try and publish that collection without adding this file, you
get the error:
"ERROR! Galaxy import process failed: 'requires_ansible' in
meta/runtime.yml is mandatory, but no meta/runtime.yml found (Code:
UNKNOWN)"
Also updates relevant test and adds a changelog fragment
* yum_repository: Do not set default value for async
The `async` repository option is deprecated in RHEL 8, but Ansible sets
```ini
async = 1
```
even when it's omitted from the module options, which causes `dnf` to complain
about an unknown configuration option.
This commit removes the default value from the `async` parameter, which means
it won't be added to the repository file if omitted from the module parameters.
Signed-off-by: Benoît Knecht <bknecht@protonmail.ch>
* Document the specific versions with the default True and the option deprecation for RHEL 8
Co-authored-by: s-hertel <19572925+s-hertel@users.noreply.github.com>
Replace get_persistent_connection_options with get_options
Remove special case for network sub_plugin in _set_plugin_options
Try to avoid mock connection pretending to be persistent
Rename variables->options to reflect what they actually are
Gather options for ssh_type_conn on network_cli
Drop reliance on sub_plugin["type"]
* ansible-config init fixes
now handles --disabled correctly for 'vars' format
also does not display internal config entries anymore
fixes#78438
note plugins have _prefixed settings that are public, this should change
* Don't actually update the cache in check mode
Add tests for updating the cache in check mode
* Don't mark packages as manually installed in check mode and add a test for it
* changelog
* Update test/integration/targets/apt/tasks/apt.yml
* fix test
* update attributes of files that are symlinks
* update attributes of files that are hard links
* fix default state in documentation
* remove unnecessary suppression
* add to changelog
Now that core requires UTF-8 filesystem encoding, ansible-test does as well.
Additionally, the `en_US.UTF-8` or `C.UTF-8` encoding must be available.
Previously the `en_US.UTF-8` encoding was requested, but its availability was never verified.
The fallback to `C.UTF-8` maintains UTF-8 encoding while allowing more flexibility in the running environment.
* Rethread pr/70185 through the dependency resolver
Hang optional metadata toggle on the ConcreteArtifactsManager instead of threading it through whole list codepath
Don't error while listing collections if a collection's metadata is missing keys required for building a collection.
Give an informative warning if metadata has been badly formatted.
Co-authored-by: Sam Doran <sdoran@redhat.com>
* Report OpenSuSE >= 15 as opensuse
Make distro.id() report newer versions of OpenSuSE (at least >=15) also report
as opensuse. They report themselves as opensuse-leap.
* Add a test
* Fix KeyError for ansible-galaxy when caching paginated responses from v3
* changelog
* generate responses in loop for test
Co-authored-by: Matt Martz <matt@sivel.net>
* wait_for - Read file and perform comparisons using bytes to avoid decode errors. Fixes#78214
* Write non-ascii via script instead of static file
* Use contexlib.closing to support py27 context manager
* Use executable from task, instead of shebang
* Update encoded bytes to utf16
- `processor_count` was erroneously set to the number of cores
- `processor_cores` was erroneously set to the number of threads per core
- `processor_vcpus` and `processor_threads_per_core` were not set
- `processor` was a string, while it's supposed to be a list
Before:
```
"ansible_processor": "PowerPC_POWER7",
"ansible_processor_cores": 4,
"ansible_processor_count": 12,
```
After:
```
"ansible_processor": [
"PowerPC_POWER7"
],
"ansible_processor_cores": 12,
"ansible_processor_count": 1,
"ansible_processor_threads_per_core": 4,
"ansible_processor_vcpus": 48,
```
Also add a unit test.
Co-authored-by: Baptiste Jonglez <git@bitsofnetworks.org>
* listify_lookup_plugin_terms deprecate dataloader
deprecated useless dataloader pass to function
also removed from callers in core
Co-authored-by: Sloane Hertel <19572925+s-hertel@users.noreply.github.com>
I'm not aware of a way to easily get vault secrets decoded on the
ansible-connection side without sending the vault secrets over the
connection in the same way, so just decode them for transport.
* Fix workding for :ref|term: subsitution
now matches 'seealso' and makes more sense:
```
delay:
applies_to:
- Task
description: Number of seconds to delay between retries. This setting is only used
in combination with `until`.
```
vs
```
delay:
applies_to:
- Task
description: Number of seconds to delay between retries. This setting is only used
in combination with website for `until`.
```
* updated unit tests
* match see also
* more sanity
* Move undefined check from concat to finalize
In the classic Jinja2's Environment str() is called on the return value of the
finalize method to potentially trigger the undefined error. That is not
the case in NativeEnvironment where string conversion of the return value is
not desired. We workaround that by checking for Undefined in all of our concat
functions. It seems simpler to do it earlier in the finalize method(s) instead.
As a side-effect it fixes an undefined variable detection in imported templates.
Fixes#78156
ci_complete
* Fix sanity
* ...
* sigh
* [dnf] Fix skip_broken, add test coverage
Change:
- skip_broken was set in config but not actually used in calls to
base.install()
- added a lot of test cases with specialized repo
- got rid of external (docker repo) nobest test cases since the
specialized repo works well for those too
- Slight cleanup and adding comments in dnf module
Test Plan:
- ci_complete
Tickets:
- Fixes#73072
Original-author: Rick Elrod <rick@elrod.me>
* Use a better test for checking results list
ci_complete
Signed-off-by: Rick Elrod <rick@elrod.me>
Co-authored-by: Rick Elrod <rick@elrod.me>
* ansible-galaxy configurable timeouts
- also fixed issues with precedence,
so --ignore-certs now overrides config
- made galaxy_timeout generic setting,
if set, it becomes default for server configs,
but now specific servers can override
- updated tests or added notes (some tests ignore/override precedence)
Co-authored-by: Sloane Hertel <19572925+s-hertel@users.noreply.github.com>
* Use ctypes to access shadow, instead of spwd which is deprecated
* Remove sanity ignore
* cast to str to satisfy mypy
* Add typing.cast polyfill
* Appease mypy redefine
* Add clog frag
* Remove .travis.yml files from galaxy init skeletons
These files have existed for many years but in light of the recent
circumstances around Travis, we should not include them by default in
the galaxy init skeletons.
* Add breaking_changes changelog fragment with recommendation to use a custom skeleton if the .travis.yml file is still needed.
Co-authored-by: s-hertel <19572925+s-hertel@users.noreply.github.com>
* Fix 'Permission denied' in user module while generating SSH keys
Fix#78017
Use try/except for spwd usage to prevent "Permission denied".
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
* facts: Add uptime fact for NetBSD
This is copied from the current OpenBSD facts code.
Tested on the GCC compile farm: https://cfarm.tetaneutral.net/
* Added changelog fragment
Co-authored-by: Baptiste Jonglez <git@bitsofnetworks.org>
Co-authored-by: Jordan Borean <jborean93@gmail.com>
Add a new handler class ZipZArchive to use unzip -Z as an alternative to zipinfo
Run 'unzip -Z' in can_handle_archive so we fall back to the next handler if it's not available (failing in is_unarchived is too late)
* Add a test for unzip -Z when zipinfo is not available
* Update test for missing binary altogether by removing /usr/bin from the PATH
* ansible-galaxy - support resolvelib versions >= 0.5.3, <= 0.8.1
Test incompatibilities are removed for resolvelib >= 0.6.0
Test against the latest 0.8.x version and fix requirements
* Fix tests - use a venv for testing the range of resolvelib versions
* Update temporary hardcoded fallback for ansible-test
* Update hardcoded upperbound for sanity tests
* Make error check more flexible
checksum can also accept a checksum only file (no filename beside the checksum).
fixes#54390
Co-authored-by: Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
* apt: fix virtual package install version detection
Change 4a62c4e3e4 introduced version
matching in installation.
The problem stems from
if version_installable or version:
pkg_list.append("'%s=%s'" % (name, version_installable or version))
When the package is a virtual-package, package_status() is returning
the "version_installable" of the package *satisfying* the
virtual-package; but then this is trying to install the
virtual-package with this version pin.
For example, "yaml-mode" is a virtual package satisifed by
"elpa-yaml-mode" (currently 0.0.14-1) and trying to install it fails
with
$ usr/bin/apt-get -y ... install 'yaml-mode=0.0.14-1'
... failed: E: Version '0.0.14-1' for 'yaml-mode' was not found ...
In the case of a virtual-package with nothing installed to satisfy it,
we should just return blank values to allow apt-get to do it's thing.
The tests are updated to install and remove this package.
Fixes: #76779
* Fix traceback when a supported version of resolvelib is not installed
Try to read the supported version range from the package distribution info and fall back to a hardcoded lowerbound/upperbound (>=0.5.3,<0.6.0).
* Add tests for unsupported resolvelib versions
* Resolve remaining import sanity test issues.
Co-authored-by: Matt Clay <matt@mystile.com>
Co-authored-by: Matt Martz <matt@sivel.net>
* If there is a platform specific handler, prefer the resolved module over the resolved action when loading module_defaults
Add a toggle for action plugins to prefer the resolved module when loading module_defaults
Allow moving away from modules intercepted as actions pattern
Fixes#77059
* winrm, psrps added missing var entry
this handles issue with the default being set to inventory_hostname
but defaults not being templated implicitly
fixes#77841
* ansible-test - Add a Ubuntu 22.04 container.
* ansible-test - Add a Fedora 36 container.
* ansible-test - Update distro containers.
* Fix dnf test on Fedora 36.
* Work around scp test issues.
* rename systemd module to services only
disambiguates what it handles since systemd is now much more
that a service manager, but the module is specific to services
* ansible-test - Add shell --export option.
* ansible-test - Support cmd args for shell command.
Also allow shell to be used without a valid layout if no delegation is required.
* ansible-test - Improve stderr/stdout consistency.
By default all output goes to stdout only, with the exception of a fatal error.
When using any of the following, all output defaults to stderr instead:
* sanity with the `--lint` option -- sanity messages to stdout
* coverage analyze -- output to stdout if the output file is `/dev/stdout`
* shell -- shell output to stdout
This fixes issues two main issues:
* Unpredictable output order when using both info and error/warning messages.
* Mixing of lint/command/shell output with bootstrapping messages on stdout.
* ansible-test - Add changelog fragment.
* Run code-smell sanity tests in UTF-8 Mode.
* Update subprocess use in sanity test programs.
* Use raw_command instead of run_command with always=True set.
* Add more capture=True usage.
* Don't expose stdin to subprocesses.
* Capture more output. Warn on retry.
* Add more captures.
* Capture coverage cli output.
* Capture windows and network host checks.
* Be explicit about interactive usage.
* Use a shell for non-captured, non-interactive subprocesses.
* Add integration test to assert no TTY.
* Add unit test to assert no TTY.
* Require blocking stdin/stdout/stderr.
* Use subprocess.run in ansible-core sanity tests.
* Remove unused arg.
* Be explicit with subprocess.run check=False.
* Add changelog.
* Use a Python subprocess instead of a shell.
* Use InternalError instead of Exception.
* Require capture argument.
* Check for invalid raw_command arguments.
* Removed pointless communicate=True usage.
* Relocate stdout w/o capture check.
* Use threads instead of a subprocess for IO.
* Prevent losing unsafe from lookups
This patch fixes a bug which under certain conditions results in data
returned from lookups not being marked as unsafe.
Each time Templar.do_template is invoked a new AnsibleContext is
created and stored effectively at two places:
1) as an instance variable in templar_obj.cur_context
2) as a local variable called new_context in do_template method of Templar
Due to custom functionality in Ansible's Context that allows for nested
templating it is possible that during resolving variable's value
template/do_template method is called recursively again, again creating
a new context. At that point the problem manifests itself because as
mentioned in 1) above the context is overwriten on the templar object
which means that any subsequent calls to _lookup will use the new
context to mark it as unsafe which is now different to the local
new_context which is used for testing for unsafe property.
The solution to the problem appears to be to restore the original
context inside do_template and also to eliminate the local variable
new_context to prevent problems in the future.
It appears that we don't have a better way of storing the context other
than as some form of global variable and so this appears to be the
"best" solution possible at this point. Hopefully data tagging will be
the solution here.
For more examples see unit and integration tests included in this patch.
Fixes#77535
* Run code-smell sanity tests in UTF-8 Mode.
* Update subprocess use in sanity test programs.
* Use raw_command instead of run_command with always=True set.
* Add more capture=True usage.
* Don't expose stdin to subprocesses.
* Capture more output. Warn on retry.
* Add more captures.
* Capture coverage cli output.
* Capture windows and network host checks.
* Be explicit about interactive usage.
* Use a shell for non-captured, non-interactive subprocesses.
* Add integration test to assert no TTY.
* Add unit test to assert no TTY.
* Require blocking stdin/stdout/stderr.
* Use subprocess.run in ansible-core sanity tests.
* Remove unused arg.
* Be explicit with subprocess.run check=False.
* Add changelog.
* git fix docs and wrapper script
fixes#77582
now env var is set to wrapper or full command depending on version
as was the intent of previous PR
added ref to git commit from git for why/how we used the env vars
* handle key_file
When looking up the `no_log` setting for a parameter that is an alias in
`AnsibleModule._log_invocation()`, the alias value will always be an
empty dictionary since `self.aliases` on the `AnsibleModule` instance is
never updated after initialization. Since the `no_log` setting is on the
canonical parameter not the alias, an incorrect warning is issued if the
parameter matches `PASSWORD_MATCH`.
This PR returns the aliases dictionary as an attribute of the
`ValidationResult` and updates the `aliases` attribute on the
`AnsibleModule` instance.
* Revert "Revert "Config, ensure templating happens at functions (#77483)""
This reverts commit 94c9106153.
* removed update configdata, which is unused
* removed test for action we don't perform anymore
* removed unused configdata
move away from special templating in constants.py
simplified main get, unified paths to get info
* Let native jinja deal with eval for type
* make constants available for templating defaults
* ensure we use config file
* ansible-connection verboistery
for cli, just use normal parser creation
this also adds --help, but that seems fine
also some error cleanup
Co-authored-by: Nathaniel Case <this.is@nathanielca.se>
* Proper error on missing jinja2 override separator
Properly catch the case when no (or a wrong) separator is used in a
jinja2 override, and return a useful error message to the user.
* Support colons in jinja2 override value
By limiting the split to 1, any colons in the value are preserved and
passed on.
* Fall back to implicit namespace.name from the path if the metadata is invalid
* Test listing a collection with null namespace/name/version fields in its galaxy.yml
* Add option --no-fail-on-errors to return errors for ansible-doc --metadata-dump in JSON result instead of failing.
* Adjust changelog fragment.
* Add basic tests.
* Support ignoring of certificates for ansible-galaxy during SCM cloning
* Add integration tests installing a role from an untrusted repository
Test installing the role without --ignore-certs fails
Test installing the role with --ignore-certs is successful
* Add a toggle to control the number of signatures required to verify the authenticity of a collection
* Make the default number of required valid signatures 1
* Add option to make signature verification strict and fail if there are no valid signatures (e.g. "+1")
* Use a regex to validate --required-valid-signature-count
* Add a toggle to limit the gpg status codes that are considered a failure
* Update documentation and changelog
* Add unit and integration tests for the new options
* Fixes#77146
Fix using user-provided signatures when running 'ansible-galaxy collection verify ns.coll --offline'
Add a test for a user-provided signature when running ansible-galaxy collection verify with --offline
Fix displaying overall gpg failure without extra verbosity
Add a test for displaying gpg failure without verbosity
Improve documentation to be more clear that signature verification only currently applies to collections directly sourced from Galaxy servers
For IPv6 addresses, Ansible already provides the prefix length for IP
addresses in the `prefix` fact. This patch adjusts the facts for IPv4
addresses to also contain the prefix length in the prefix fact. This
makes it easier to use the facts consistently when the CIDR notation is
needed.
Signed-off-by: Till Maas <opensource@till.name>
While getting hostname from container, podman command
fails to return JSON so wrap exception and return
hostname as 'None'
Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
* Add more sanity tests on schema level (so they also work for plugins).
* Fix various issues the sanity test reported.
* Add changelog fragment.
* Fix function name.
* Let validate-modules also validate plugins.
* Support 'option' in 'cli'.
* Use DOCUMENTABLE_PLUGINS instead of UNDOCUMENTED_PLUGIN_TYPES.
* Support 'keyword', clean up error codes.
* Call settings.process_errors only once; remove __version__.
* Add changelog fragment.
* Fix ansible console to respect ANSIBLE_STDOUT_CALLBACK
This makes the ansible-console able to customize the stdout callback.
Ansible console currently uses statically minimal callback.
* Add changelog
* Move the fragment changelog in the right directory
Also, bump the default. A number of people have reported problems with
this 20 second timeout for a couple of years on
https://github.com/ansible/galaxy/issues/2302
It is mentioned in the issue that resolving dns can sometimes take up to
30 seconds, and that this timeout includes dns resolution.
Includes a changelog message
* apply owner/group permissions to top folder
* remove unused var unarchive30
* fix permissions for top folders if the tarball include multiple top folders
* added test for top folder ownership
* fix facts delegation loop overwrite
partial revert of change to allow facts to be present in each loop iteration
was not needed in final results as result processing alreayd had the disctiontion
and ended up breaking the assumptions in the calling code.
fixes#76676
* play_context, compensate for existing plugins
some connection plugins are not fully using the correct configuration,
but this was previously hidden from them as play_context was providing
the info instead, now play_context provides the 'correct' info, but hitting
these bad configurations.
* ansible-galaxy collection install|verify:
- Support verifying the origin of the MANIFEST.json when the Galaxy server has provided signatures.
- Allow supplemental signatures to use during verification on the CLI/requirements file.
* ansible-galaxy collection install:
- Support disabling signature verification. This silences the warning provided by ansible-galaxy if the Galaxy server provided signatures it cannot use because no keyring is configured.
- Store Galaxy server metadata alongside installed collections for provenance. This is used by 'ansible-galaxy collection verify --offline'.
* Add unit tests for method that gets signatures from a Galaxy server
* Add integration tests for user-provided signature sources
- Test CLI option combinations
- Test installing collections with valid/invalid signature sources
- Test disabling GPG verification when installing collections
- Test verifying collections with valid/invalid signature sources
* Make signature verification advisory-by-default if signatures are provided by the Galaxy server
- Make the default keyring None
- Warn if the keyring is None but the Galaxy server provided signatures
- Error if the keyring is None but the user supplied signatures
- Error if the keyring is not None but is invalid
* changelog
* add ansible-galaxy user documentation for new options
Co-authored-by: Matt Martz <matt@sivel.net>
Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
Co-authored-by: Martin Krizek <martin.krizek@gmail.com>
Co-authored-by: Sandra McCann <samccann@redhat.com>
Co-authored-by: Andy Mott <amott@redhat.com>
Co-authored-by: John R Barker <john@johnrbarker.com>
* Return rc=0 on success.
Error handling in playbooks generally expects `rc` to be set to 0 when a module has not failed. Playbook authors should not have to check for the existence of `rc` first.
* Use single definition and added changelog
* Fix up tests with new return value
Co-authored-by: Jordan Borean <jborean93@gmail.com>
* add DebianStrategy tests
* ensure hostname can be changed by using become
* use Systemd strat for debian and Base for generic.
* add test to ensure all strategies are available
Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>