Repository: ansible/ansible-modules-extras

Issue:
Composer - Removed No Progress
Removed no progress as default resolves #323

composer: command=dump-autoload fails because it doesn't recognize the --no-progress option
## repro

If the following two tasks are executed after each other

```
 - composer: command=update working_dir={{ your_php_app_dir }} 
# assuming {{ your_php_app_dir }} has a valid composer.json
 - composer: command=dump-autoloads working_dir={{ your_php_app_dir }}
```

The second one fails with the following error:

```
failed: [localhost] => {"failed": true}
msg: [RuntimeException] The "--no-progress" option does not exist. dump-autoload [-o|--optimize] [--no-dev]
```
## guess at the root cause

always appended default options. As per http://docs.ansible.com/composer_module.html

> Default options that are always appended in each execution are –no-ansi, –no-progress, and –no-interaction
## Versions, environment
- Composer version 1.0-dev (829199c0530ea131262c804924f921447c71d4e8) 2015-03-16 13:11:02
- ansible 1.8.4
- ubuntu/trusty64



Discussion:
i'm ok with removing it from defaults, but won't this create an issue with commands that DO support it? it will probably tie up stdout and mess with the feedback

That is a good point could be changed to default only for install/update?

that would be great

don't forget to correct the `notes:` in the doc.

@TomKita May I help you with the revision? 

@resmo Of course go for it I'm a bit tied up with other projects at the moment. Unfortunately this is on the lower end of my list.

@TomKita ok, I'll take it over.

@resmo want to just open a new pr? If so, feel free to close this one and create a new one.

got this issue too, some composer commands don't support --no-progress, ie: 'clear-cache' or 'info'


Resolving patch:
diff --git a/packaging/language/composer.py b/packaging/language/composer.py
--- a/packaging/language/composer.py
+++ b/packaging/language/composer.py
@@ -22,7 +22,9 @@
 DOCUMENTATION = '''
 ---
 module: composer
-author: "Dimitrios Tydeas Mengidis (@dmtrs)"
+author:
+    - "Dimitrios Tydeas Mengidis (@dmtrs)"
+    - "René Moser (@resmo)"
 short_description: Dependency Manager for PHP
 version_added: "1.6"
 description:
@@ -94,7 +96,7 @@
     - php
     - composer installed in bin path (recommended /usr/local/bin)
 notes:
-    - Default options that are always appended in each execution are --no-ansi, --no-progress, and --no-interaction
+    - Default options that are always appended in each execution are --no-ansi, --no-interaction and --no-progress if available.
 '''
 
 EXAMPLES = '''
@@ -105,20 +107,31 @@
 import os
 import re
 
+try:
+    import json
+except ImportError:
+    import simplejson as json
+
 def parse_out(string):
     return re.sub("\s+", " ", string).strip()
 
 def has_changed(string):
-    if "Nothing to install or update" in string:
-        return False
-    else:
-        return True
+    return "Nothing to install or update" not in string
+
+def get_available_options(module, command='install'):
+    # get all availabe options from a composer command using composer help to json
+    rc, out, err = composer_command(module, "help %s --format=json" % command)
+    if rc != 0:
+        output = parse_out(err)
+        module.fail_json(msg=output)
 
-def composer_install(module, command, options):
+    command_help_json = json.loads(out)
+    return command_help_json['definition']['options']
+
+def composer_command(module, command, options=[]):
     php_path      = module.get_bin_path("php", True, ["/usr/local/bin"])
     composer_path = module.get_bin_path("composer", True, ["/usr/local/bin"])
     cmd           = "%s %s %s %s" % (php_path, composer_path, command, " ".join(options))
-
     return module.run_command(cmd)
 
 def main():
@@ -137,38 +150,45 @@ def main():
         supports_check_mode=True
     )
 
+    # Get composer command with fallback to default
+    command = module.params['command']
+    available_options = get_available_options(module=module, command=command)
+
     options = []
 
     # Default options
-    options.append('--no-ansi')
-    options.append('--no-progress')
-    options.append('--no-interaction')
+    default_options = [
+        'no-ansi',
+        'no-interaction',
+        'no-progress',
+    ]
 
-    options.extend(['--working-dir', os.path.abspath(module.params['working_dir'])])
+    for option in default_options:
+        if option in available_options:
+            option = "--%s" % option
+            options.append(option)
 
-    # Get composer command with fallback to default
-    command = module.params['command']
+    options.extend(['--working-dir', os.path.abspath(module.params['working_dir'])])
 
-    # Prepare options
-    if module.params['prefer_source']:
-        options.append('--prefer-source')
-    if module.params['prefer_dist']:
-        options.append('--prefer-dist')
-    if module.params['no_dev']:
-        options.append('--no-dev')
-    if module.params['no_scripts']:
-        options.append('--no-scripts')
-    if module.params['no_plugins']:
-        options.append('--no-plugins')
-    if module.params['optimize_autoloader']:
-        options.append('--optimize-autoloader')
-    if module.params['ignore_platform_reqs']:
-        options.append('--ignore-platform-reqs')
+    option_params = {
+        'prefer_source':        'prefer-source',
+        'prefer_dist':          'prefer-dist',
+        'no_dev':               'no-dev',
+        'no_scripts':           'no-scripts',
+        'no_plugins':           'no_plugins',
+        'optimize_autoloader':  'optimize-autoloader',
+        'ignore_platform_reqs': 'ignore-platform-reqs',
+        }
+
+    for param, option in option_params.iteritems():
+        if module.params.get(param) and option in available_options:
+            option = "--%s" % option
+            options.append(option)
 
     if module.check_mode:
         options.append('--dry-run')
 
-    rc, out, err = composer_install(module, command, options)
+    rc, out, err = composer_command(module, command, options)
 
     if rc != 0:
         output = parse_out(err)
@@ -180,5 +200,5 @@ def main():
 
 # import module snippets
 from ansible.module_utils.basic import *
-
-main()
+if __name__ == '__main__':
+    main()


Test patch: