From 4309dfda520c67601ea76c4ad86b4b9023b7145b Mon Sep 17 00:00:00 2001
From: jack1142 <6032823+jack1142@users.noreply.github.com>
Date: Fri, 28 Jan 2022 07:13:08 +0100
Subject: [PATCH] Properly parse JSON Lines output from yarn (#4050)

* Properly parse JSON Lines output from yarn

* Properly support output of yarn global list

* Add changelog fragment

* Check that the string starts with 'bins-'

* Fix changelog fragment

* Update changelogs/fragments/4050-properly-parse-json-lines-output-from-yarn.yaml

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
---
 ...rly-parse-json-lines-output-from-yarn.yaml |  3 +++
 plugins/modules/packaging/language/yarn.py    | 21 +++++++++++--------
 2 files changed, 15 insertions(+), 9 deletions(-)
 create mode 100644 changelogs/fragments/4050-properly-parse-json-lines-output-from-yarn.yaml

diff --git a/changelogs/fragments/4050-properly-parse-json-lines-output-from-yarn.yaml b/changelogs/fragments/4050-properly-parse-json-lines-output-from-yarn.yaml
new file mode 100644
index 0000000000..67094f4701
--- /dev/null
+++ b/changelogs/fragments/4050-properly-parse-json-lines-output-from-yarn.yaml
@@ -0,0 +1,3 @@
+bugfixes:
+  - yarn - fix incorrect handling of ``yarn list`` and ``yarn global list`` output that could result in fatal error (https://github.com/ansible-collections/community.general/pull/4050).
+  - yarn - fix incorrectly reported status when installing a package globally (https://github.com/ansible-collections/community.general/issues/4045, https://github.com/ansible-collections/community.general/pull/4050).
diff --git a/plugins/modules/packaging/language/yarn.py b/plugins/modules/packaging/language/yarn.py
index 77489e240f..442b3b8b6f 100644
--- a/plugins/modules/packaging/language/yarn.py
+++ b/plugins/modules/packaging/language/yarn.py
@@ -241,16 +241,19 @@ class Yarn(object):
         if error:
             self.module.fail_json(msg=error)
 
-        data = json.loads(result)
-        try:
-            dependencies = data['data']['trees']
-        except KeyError:
-            missing.append(self.name)
-            return installed, missing
+        for json_line in result.strip().split('\n'):
+            data = json.loads(json_line)
+            if self.globally:
+                if data['type'] == 'list' and data['data']['type'].startswith('bins-'):
+                    # This is a string in format: 'bins-<PACKAGE_NAME>'
+                    installed.append(data['data']['type'][5:])
+            else:
+                if data['type'] == 'tree':
+                    dependencies = data['data']['trees']
 
-        for dep in dependencies:
-            name, version = dep['name'].rsplit('@', 1)
-            installed.append(name)
+                    for dep in dependencies:
+                        name, version = dep['name'].rsplit('@', 1)
+                        installed.append(name)
 
         if self.name not in installed:
             missing.append(self.name)