diff --git a/plugins/module_utils/sdkmanager.py b/plugins/module_utils/sdkmanager.py index 16131881ce..293504fabb 100644 --- a/plugins/module_utils/sdkmanager.py +++ b/plugins/module_utils/sdkmanager.py @@ -17,7 +17,9 @@ def sdkmanager_runner(module, **kwargs): state=cmd_runner_fmt.as_map(_state_map), name=cmd_runner_fmt.as_list(), update=cmd_runner_fmt.as_fixed("--update"), - installed=cmd_runner_fmt.as_fixed("--list_installed") + installed=cmd_runner_fmt.as_fixed("--list_installed"), + list=cmd_runner_fmt.as_fixed('--list'), + newer=cmd_runner_fmt.as_fixed("--newer") ), **kwargs ) @@ -47,6 +49,12 @@ class AndroidSdkManager(object): _RE_INSTALLED_PACKAGES = ( re.compile(r'^\s+(?P\S+)\s+\|\s+(?P\S+)\s+\|\s(?P.+)\s\|\s+(\S+)$') ) + _RE_UPDATABLE_PACKAGES_HEADER = re.compile(r'^Available Updates:$') + + # Example: ' platform-tools | 27.0.0 | 35.0.2' + _RE_UPDATABLE_PACKAGE = ( + re.compile(r'^\s+(?P\S+)\s+\|\s+(?P\S+)\s+\|\s+(?P\S+)\s*$') + ) def __init__(self, runner): self.runner = runner @@ -74,6 +82,39 @@ class AndroidSdkManager(object): i += 1 return packages + def get_updatable_packages(self): + with self.runner('list newer') as ctx: + rc, stdout, stderr = ctx.run() + data = stdout.split('\n') + + updatable_section_found = False + i = 0 + lines_count = len(data) + packages = set() + + dbg = [] + while i < lines_count: + if not updatable_section_found: + updatable_section_found = self._RE_UPDATABLE_PACKAGES_HEADER.match(data[i]) + if updatable_section_found: + # Table has the following structure. Once it is found, 2 lines need to be skipped + # + # Available Updates: <--- we are here + # ID | Installed | Available + # ------- | ------- | ------- + # platform-tools | 27.0.0 | 35.0.2 <--- skip to here + i += 3 # skip table header + else: + i += 1 # just iterate next until we find the section's header + continue + else: + p = self._RE_UPDATABLE_PACKAGE.match(data[i]) + dbg.append((data[i], p is not None)) + if p: + packages.add(Package(p.group('name'))) + i += 1 + return packages + def install_packages(self, packages): self.apply_packages_changes(packages, 'present') @@ -88,4 +129,3 @@ class AndroidSdkManager(object): # raise ValueError(command_arg) with self.runner('state name') as ctx: ctx.run(name=command_arg, state=state) - diff --git a/plugins/modules/android_sdk.py b/plugins/modules/android_sdk.py index ddf6e537c9..f99dd0b6d7 100644 --- a/plugins/modules/android_sdk.py +++ b/plugins/modules/android_sdk.py @@ -9,13 +9,18 @@ class AndroidSdk(StateModuleHelper): state=dict(type='str', default='present', choices=['present', 'absent', 'latest']), package=dict(type='list', elements='str', aliases=['pkg', 'name']), update=dict(type='bool', default=False) - ) + ), + supports_check_mode=True ) use_old_vardict = False output_params = ('installed', 'removed') + change_params = ('installed', 'removed') + diff_params = ('installed', 'removed') def __init_module__(self): self.sdkmanager = AndroidSdkManager(sdkmanager_runner(self.module)) + self.vars.set('installed', [], change=True) + self.vars.set('removed', [], change=True) def _parse_packages(self): arg_pkgs = self.vars.package @@ -32,15 +37,29 @@ class AndroidSdk(StateModuleHelper): packages = self._parse_packages() installed = self.sdkmanager.get_installed_packages() pending_installation = packages.difference(installed) - self.sdkmanager.install_packages(pending_installation) - self.vars.installed = AndroidSdk._packages_to_str(pending_installation) + + self.vars.installed = AndroidSdk._map_packages_to_names(pending_installation) + if not self.check_mode: + self.sdkmanager.install_packages(pending_installation) def state_absent(self): packages = self._parse_packages() installed = self.sdkmanager.get_installed_packages() to_be_deleted = packages.intersection(installed) - self.sdkmanager.uninstall_packages(to_be_deleted) - self.vars.removed = AndroidSdk._packages_to_str(to_be_deleted) + self.vars.removed = AndroidSdk._map_packages_to_names(to_be_deleted) + if not self.check_mode: + self.sdkmanager.uninstall_packages(to_be_deleted) + + def state_latest(self): + packages = self._parse_packages() + installed = self.sdkmanager.get_installed_packages() + updatable = self.sdkmanager.get_updatable_packages() + not_installed = packages.difference(installed) + to_be_installed = not_installed.intersection(updatable) + self.vars.installed = AndroidSdk._map_packages_to_names(to_be_installed) + + if not self.check_mode: + self.sdkmanager.install_packages(packages) def update_packages(self): pass @@ -48,7 +67,7 @@ class AndroidSdk(StateModuleHelper): # ctx.run() @staticmethod - def _packages_to_str(packages): + def _map_packages_to_names(packages): return [x.name for x in packages] def __run__(self):