-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add android sdk module #9236
Add android sdk module #9236
Conversation
…fy version for a package while using sdkmanager
…ng 'latest' state
@felixfontein @russoz I also have a question regarding BOTMETA.yml. I see that some modules have |
It might be documented somewhere in the bot's repo / code (https://github.com/ansible-community/collection_bot/), but I'm not sure. Generally I would simply ignore that field. The bot might add corresponding labels to PRs/issues for the module, but that's not something we really use. |
plugins/module_utils/sdkmanager.py
Outdated
_RE_INSTALLED_PACKAGE = ( | ||
re.compile(r'^\s*(?P<name>\S+)\s*\|\s*\S+\s*\|\s*.+\s*\|\s*(\S+)\s*$') | ||
) |
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.
Breaking into multiple lines not really needed here. Moreover, if you search the second column for version numbers instead of just "not spaces", then you could possibly simplify the loop in lines 144-162 because you would not need to skip the header, it would be skipped by the fact that it does not match the regexp (with digits):
_RE_INSTALLED_PACKAGE = ( | |
re.compile(r'^\s*(?P<name>\S+)\s*\|\s*\S+\s*\|\s*.+\s*\|\s*(\S+)\s*$') | |
) | |
_RE_INSTALLED_PACKAGE = re.compile(r'^\s*(?P<name>\S+)\s*\|\s*[\d\.]+\s*\|\s*.+\s*\|\s*(\S+)\s*$') |
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.
Might not work because sometimes the version
column is not just numbers, for instance:
build-tools;32.1.0-rc1 | 32.1.0 rc1 | Android SDK Build-Tools 32.1-rc1 | build-tools/32.1.0-rc1
Here the version is 32.1.0 rc1
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.
Again, this is not something that is documented anywhere, but looking at the output of sdkmanager --list
, I see the next possible options for version
:
24.0.3
32.1.0 rc1
3.6.4111459
2
27.0.11902837 rc2
Does it make sense to make a regexp covering all theseversion
forms, considering the fact that the module does not useversion
at all?
plugins/module_utils/sdkmanager.py
Outdated
) | ||
|
||
# Example: ' platform-tools | 27.0.0 | 35.0.2' | ||
_RE_UPDATABLE_PACKAGE = re.compile(r'^\s*(?P<name>\S+)\s*\|\s*\S+\s*\|\s*\S+\s*$') |
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.
You would need to change this regexp to search for numbers as well.
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.
See comment above
plugins/module_utils/sdkmanager.py
Outdated
_RE_UPDATABLE_PACKAGES_HEADER = re.compile(r'^Available Updates:$') | ||
|
||
# Example: ' platform-tools | 27.0.0 | Android SDK Platform-Tools 27 | platform-tools ' | ||
_RE_INSTALLED_PACKAGE = re.compile(r'^\s*(?P<name>\S+)\s*\|\s*\S+\s*\|\s*.+\s*\|\s*(\S+)\s*$') |
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.
Well, from these examples, the only two possibilities that are not covered by the suggested regexp (the ones with rc1
and rc2
) are also not covered by the existing regexp: |\s*\S+\s*\|
will not match | 32.1.0 rc1 |
(because the \S+
will not match the whitespace before rc1
).
The one thing that is the delimiter here is the |
character, so maybe it would be better of as:
_RE_INSTALLED_PACKAGE = re.compile(r'^\s*(?P<name>\S+)\s*\|\s*[0-9][^|]*\b\s*\|\s*.+\s*\|\s*(\S+)\s*$')
That forces the version to begin with a digit, then anything-but-the-vertical-bar until the space and vertical bar. The \b
is used to make sure the "anything-but-the-vertical-bar" part does not include the whitespaces before the bar.
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.
As to your question of whether it makes sense to cover all the cases with the regexp, I would answer that IMHO it makes more sense to cover all the search cases with a search tool (regexp) then to cover only part of the search with it and create another search mechanism later on. Just my $0.02 ;-)
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.
Good catch, thanks
…0 rc1". Also, this allows to simplify the parsing logic as there is no need to skip table headers anymore.
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.
LGTM
Co-authored-by: Felix Fontein <[email protected]>
Looks good to me as well! If nobody objects, I'll merge by the end of the week. |
Backport to stable-10: 💚 backport PR created✅ Backport PR branch: Backported as #9293 🤖 @patchback |
* adds simple implementation of adding and removing android sdk packages * adds package update * adds simple installed packages parsing * moves parsing logic to a separate class * adds absent state for sdkmanager packages and setup for tests * adds output for installing and removing packages * removes version from Package object since it is not possible to specify version for a package while using sdkmanager * adds 'latest' state * adds tests * fixes crash when sdkmanager is invoked from python with LC_ALL=C * fixes latest state * adds sdk_root parameter * adds channel parameter * simplifies regexps, removes unused named groups * minor refactoring of sdkmanager parsing * adds java dependency variable for different distributions * adds RETURN documentation * adds check for nonexisting package * adds check for non-accepted licenses * removes excessive methods from sdkmanager * removes unused 'update' module parameter, packages may be updated using 'latest' state * minor refactoring * adds EXAMPLES doc section * adds DOCUMENTATION section and license headers * fixes formatting issues * removes diff_params * adds maintainer * fixes sanity check issues in sdkmanager * adds java dependency for macos and moves some tests to a separate FreeBSD configuration * fixes dependencies setup for OSX * fixes dependencies setup for OSX (2) * fixes dependencies setup for OSX (3) * Apply minor suggestions from code review Co-authored-by: Alexei Znamensky <[email protected]> * applies code review suggestions * changes force_lang from C.UTF-8 to auto in sdkmanager (as per discussion #9236 (comment)) * Revert "changes force_lang from C.UTF-8 to auto in sdkmanager (as per discussion #9236 (comment))" This reverts commit 619f28d. * fixes some more comments from review * minor sanity issue fix * uses the 'changed' test instead of checking the 'changed' attribute * adds 'accept_licenses' parameter. Installation is now performed independently for each package specified. * removes "Accept licenses" task from examples * fixes docs sanity issues * applies minor suggestions from code review * fixes regexps. The previous version didn't match versions like "32.1.0 rc1". Also, this allows to simplify the parsing logic as there is no need to skip table headers anymore. * renamed sdkmanager.py to android_sdkmanager.py * applies minor suggestions from code review Co-authored-by: Felix Fontein <[email protected]> * updates BOTMETA * reordered BOTMETA --------- Co-authored-by: Alexei Znamensky <[email protected]> Co-authored-by: Felix Fontein <[email protected]> (cherry picked from commit 2b2872f)
@shamilovstas thanks for your contribution! |
Add android sdk module (#9236) * adds simple implementation of adding and removing android sdk packages * adds package update * adds simple installed packages parsing * moves parsing logic to a separate class * adds absent state for sdkmanager packages and setup for tests * adds output for installing and removing packages * removes version from Package object since it is not possible to specify version for a package while using sdkmanager * adds 'latest' state * adds tests * fixes crash when sdkmanager is invoked from python with LC_ALL=C * fixes latest state * adds sdk_root parameter * adds channel parameter * simplifies regexps, removes unused named groups * minor refactoring of sdkmanager parsing * adds java dependency variable for different distributions * adds RETURN documentation * adds check for nonexisting package * adds check for non-accepted licenses * removes excessive methods from sdkmanager * removes unused 'update' module parameter, packages may be updated using 'latest' state * minor refactoring * adds EXAMPLES doc section * adds DOCUMENTATION section and license headers * fixes formatting issues * removes diff_params * adds maintainer * fixes sanity check issues in sdkmanager * adds java dependency for macos and moves some tests to a separate FreeBSD configuration * fixes dependencies setup for OSX * fixes dependencies setup for OSX (2) * fixes dependencies setup for OSX (3) * Apply minor suggestions from code review Co-authored-by: Alexei Znamensky <[email protected]> * applies code review suggestions * changes force_lang from C.UTF-8 to auto in sdkmanager (as per discussion #9236 (comment)) * Revert "changes force_lang from C.UTF-8 to auto in sdkmanager (as per discussion #9236 (comment))" This reverts commit 619f28d. * fixes some more comments from review * minor sanity issue fix * uses the 'changed' test instead of checking the 'changed' attribute * adds 'accept_licenses' parameter. Installation is now performed independently for each package specified. * removes "Accept licenses" task from examples * fixes docs sanity issues * applies minor suggestions from code review * fixes regexps. The previous version didn't match versions like "32.1.0 rc1". Also, this allows to simplify the parsing logic as there is no need to skip table headers anymore. * renamed sdkmanager.py to android_sdkmanager.py * applies minor suggestions from code review Co-authored-by: Felix Fontein <[email protected]> * updates BOTMETA * reordered BOTMETA --------- Co-authored-by: Alexei Znamensky <[email protected]> Co-authored-by: Felix Fontein <[email protected]> (cherry picked from commit 2b2872f) Co-authored-by: Stanislav Shamilov <[email protected]>
* adds simple implementation of adding and removing android sdk packages * adds package update * adds simple installed packages parsing * moves parsing logic to a separate class * adds absent state for sdkmanager packages and setup for tests * adds output for installing and removing packages * removes version from Package object since it is not possible to specify version for a package while using sdkmanager * adds 'latest' state * adds tests * fixes crash when sdkmanager is invoked from python with LC_ALL=C * fixes latest state * adds sdk_root parameter * adds channel parameter * simplifies regexps, removes unused named groups * minor refactoring of sdkmanager parsing * adds java dependency variable for different distributions * adds RETURN documentation * adds check for nonexisting package * adds check for non-accepted licenses * removes excessive methods from sdkmanager * removes unused 'update' module parameter, packages may be updated using 'latest' state * minor refactoring * adds EXAMPLES doc section * adds DOCUMENTATION section and license headers * fixes formatting issues * removes diff_params * adds maintainer * fixes sanity check issues in sdkmanager * adds java dependency for macos and moves some tests to a separate FreeBSD configuration * fixes dependencies setup for OSX * fixes dependencies setup for OSX (2) * fixes dependencies setup for OSX (3) * Apply minor suggestions from code review Co-authored-by: Alexei Znamensky <[email protected]> * applies code review suggestions * changes force_lang from C.UTF-8 to auto in sdkmanager (as per discussion ansible-collections#9236 (comment)) * Revert "changes force_lang from C.UTF-8 to auto in sdkmanager (as per discussion ansible-collections#9236 (comment))" This reverts commit 619f28d. * fixes some more comments from review * minor sanity issue fix * uses the 'changed' test instead of checking the 'changed' attribute * adds 'accept_licenses' parameter. Installation is now performed independently for each package specified. * removes "Accept licenses" task from examples * fixes docs sanity issues * applies minor suggestions from code review * fixes regexps. The previous version didn't match versions like "32.1.0 rc1". Also, this allows to simplify the parsing logic as there is no need to skip table headers anymore. * renamed sdkmanager.py to android_sdkmanager.py * applies minor suggestions from code review Co-authored-by: Felix Fontein <[email protected]> * updates BOTMETA * reordered BOTMETA --------- Co-authored-by: Alexei Znamensky <[email protected]> Co-authored-by: Felix Fontein <[email protected]>
SUMMARY
This module allows to manage Android SDK packages
ISSUE TYPE
COMPONENT NAME
android_sdk
ADDITIONAL INFORMATION
This module uses
sdkmanager
binary, which is used to install Android SDK packages. Usually, Android SDK packages are installed by Android developers using Android Studio IDE, but in case when a server needs to be set up to be used as a CI/CD runner to build Android applications,sdkmanager
command line tool is used instead.In order to use this module,
sdkmanager
binary must be present on the target machine. The official way of installingsdkmanager
is described here: https://developer.android.com/tools/sdkmanagerThere is one caveat I'm not entirely sure how/whether to fix. For some of the packages installed with
sdkmanager
a license must be accepted beforehand. The accepted licenses are placed inside the directory containing Android SDK, in a subdirectorylicenses
as a file containing a single string:[vagrant@alma licenses]$ pwd /usr/local/android/sdk/licenses [vagrant@alma licenses]$ ls android-googletv-license android-sdk-preview-license android-sdk-arm-dbt-license google-gdk-license android-sdk-license mips-android-sysimage-license [vagrant@alma licenses]$ cat android-sdk-license 24333f8a63b6825ea9c5514f83c2829b004d1fee
There are three ways how a license may be accepted
sdkmanager
sees that the license for the package has not been accepted, a command line prompt will be displayed that the user is supposed to answer interactively.sdkmanager --licenses
command may be used. In this casesdkmanager
prints every license that has not been accepted sequentially and prompts the user after each one.licenses
subdirectory for any license that must be accepted (but IMO this is error-prone as there might be new licenses, which can't be known in advance).The easiest way to accept licenses from an Ansible playbook is to use the following task:
I haven't figured a straightforward way of how to accept licenses from inside the module. What I tried was to use
data
parameter ofmodule.run_command
function to sendy
to stdin, but the problem is that in case if we try to use the 2nd approach from the list above (sdkmanager --license
), thesdkmanager
tool prints multiple prompts for each license that is not accepted. Thedata
parameter sendsy
only to the first license prompt, but the remaining prompts hang the module as they are waiting for the user input. Another idea was to usedata='y'
every time a package is installed (1st approach), but this may also lead to the module hanging as there might be several packages requested for installation, and if they belong to different licenses, this ends up the same way.So, I decided that the module assumes that all licenses are accepted in advance (this is reflected in the "Notes" section of the documentation).