From b1cb2553af9e3811ce6f66e54c0f050977332eba Mon Sep 17 00:00:00 2001
From: Jordan Borean <jborean93@gmail.com>
Date: Thu, 30 Jul 2020 07:28:43 +1000
Subject: [PATCH] ansible-galaxy - fix fallback for AH searches (#70957)

---
 .../fragments/galaxy-collection-fallback.yml   |  2 ++
 lib/ansible/galaxy/collection.py               | 16 +++++++++++-----
 .../ansible-galaxy-collection/tasks/main.yml   | 18 ++++++++++++++++++
 3 files changed, 31 insertions(+), 5 deletions(-)
 create mode 100644 changelogs/fragments/galaxy-collection-fallback.yml

diff --git a/changelogs/fragments/galaxy-collection-fallback.yml b/changelogs/fragments/galaxy-collection-fallback.yml
new file mode 100644
index 00000000000..dad92bd8221
--- /dev/null
+++ b/changelogs/fragments/galaxy-collection-fallback.yml
@@ -0,0 +1,2 @@
+bugfixes:
+- ansible-galaxy collection install - fix fallback mechanism if the AH server did not have the collection requested - https://github.com/ansible/ansible/issues/70940
diff --git a/lib/ansible/galaxy/collection.py b/lib/ansible/galaxy/collection.py
index bdc287e5927..21d76c1244f 100644
--- a/lib/ansible/galaxy/collection.py
+++ b/lib/ansible/galaxy/collection.py
@@ -525,11 +525,17 @@ class CollectionRequirement:
                 else:
                     versions = api.get_collection_versions(namespace, name)
             except GalaxyError as err:
-                if err.http_code == 404:
-                    display.vvv("Collection '%s' is not available from server %s %s"
-                                % (collection, api.name, api.api_server))
-                    continue
-                raise
+                if err.http_code != 404:
+                    raise
+
+                versions = []
+
+            # Automation Hub doesn't return a 404 but an empty version list so we check that to align both AH and
+            # Galaxy when the collection is not available on that server.
+            if not versions:
+                display.vvv("Collection '%s' is not available from server %s %s" % (collection, api.name,
+                                                                                    api.api_server))
+                continue
 
             display.vvv("Collection '%s' obtained from server %s %s" % (collection, api.name, api.api_server))
             break
diff --git a/test/integration/targets/ansible-galaxy-collection/tasks/main.yml b/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
index 76b4783b932..d24112d0c3a 100644
--- a/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
+++ b/test/integration/targets/ansible-galaxy-collection/tasks/main.yml
@@ -104,6 +104,24 @@
     server: '{{ pulp_v3_server }}'
     v3: true
 
+# fake.fake does not exist but we check the output to ensure it checked all 3
+# servers defined in the config. We hardcode to -vvv as that's what level the
+# message is shown
+- name: test install fallback on server list
+  command: ansible-galaxy collection install fake.fake -vvv
+  ignore_errors: yes
+  environment:
+    ANSIBLE_CONFIG: '{{ galaxy_dir }}/ansible.cfg'
+  register: missing_fallback
+
+- name: assert test install fallback on server list
+  assert:
+    that:
+    - missing_fallback.rc == 1
+    - '"Collection ''fake.fake'' is not available from server pulp_v2" in missing_fallback.stdout'
+    - '"Collection ''fake.fake'' is not available from server pulp_v3" in missing_fallback.stdout'
+    - '"Collection ''fake.fake'' is not available from server galaxy_ng" in missing_fallback.stdout'
+
 - name: run ansible-galaxy collection download tests
   include_tasks: download.yml
   args: