From 1847ad3f17a039f29e22f465508991fcb6e1cca7 Mon Sep 17 00:00:00 2001
From: Pierre Riteau <pierre@stackhpc.com>
Date: Thu, 21 Sep 2023 18:29:23 +0200
Subject: [PATCH] Fix data file path detection with new pip

Using an editable installation of Kayobe fails on Rocky Linux 9 or
Ubuntu with an error such as:

    ERROR! The requirements file '/home/rocky/kayobe/kayobe/requirements.yml' does not exist.
    Failed to install Ansible roles from /home/rocky/kayobe/kayobe/utils.py/../requirements.yml via Ansible Galaxy: returncode 1
    Control host bootstrap failed - likely Ansible Galaxy flakiness. Sleeping 5 seconds before retrying

This is caused by recent changes to how pip manages editable
installations. The egg-link file that Kayobe was using to find the
source path does not exist anymore. Instead, there is a direct_url.json
file under the kayobe dist-info directory that can be parsed.

Change-Id: I9dd5b97dec93c0e5393a1e7d9640f85003651b56
Closes-Bug: #2020135
---
 kayobe/utils.py                               | 22 +++++++++++++++++++
 ...stall-data-file-path-743b7a85a5f5db6d.yaml |  5 +++++
 2 files changed, 27 insertions(+)
 create mode 100644 releasenotes/notes/editable-install-data-file-path-743b7a85a5f5db6d.yaml

diff --git a/kayobe/utils.py b/kayobe/utils.py
index 023e64988..77cf3b18a 100644
--- a/kayobe/utils.py
+++ b/kayobe/utils.py
@@ -16,6 +16,8 @@ import base64
 from collections import defaultdict
 import glob
 import graphlib
+import importlib_metadata
+import json
 import logging
 import os
 import shutil
@@ -50,10 +52,30 @@ def _detect_install_prefix(path):
     return prefix_path
 
 
+def _get_direct_url(dist):
+    direct_url = os.path.join(dist._path, 'direct_url.json')
+    if os.path.exists(direct_url):
+        with open(direct_url, 'r') as f:
+            direct_url_content = json.loads(f.readline().strip())
+            url = direct_url_content['url']
+            prefix = 'file://'
+            if url.startswith(prefix):
+                return url[len(prefix):]
+
+    return None
+
+
 def _get_base_path():
     override = os.environ.get("KAYOBE_DATA_FILES_PATH")
     if override:
         return os.path.join(override)
+
+    kayobe_dist = list(importlib_metadata.Distribution.discover(name="kayobe"))
+    if kayobe_dist:
+        direct_url = _get_direct_url(kayobe_dist[0])
+        if direct_url:
+            return direct_url
+
     egg_glob = os.path.join(
         sys.prefix, 'lib*', 'python*', '*-packages', 'kayobe.egg-link'
     )
diff --git a/releasenotes/notes/editable-install-data-file-path-743b7a85a5f5db6d.yaml b/releasenotes/notes/editable-install-data-file-path-743b7a85a5f5db6d.yaml
new file mode 100644
index 000000000..dac75efa8
--- /dev/null
+++ b/releasenotes/notes/editable-install-data-file-path-743b7a85a5f5db6d.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+  - |
+    Fixes detection of data file path when using editable installations with a
+    recent pip.