ThePorgs / Exegol

Fully featured and community-driven hacking environment
https://exegol.readthedocs.io/
GNU General Public License v3.0
1.95k stars 191 forks source link

[BUG] Case Sensitivity Issue Preventing Container Creation/Removal #167

Closed wem-r closed 1 year ago

wem-r commented 1 year ago

Describe the bug

Hello There!

While debugging another Exegol issue (unrelated to this one) that I have, I discovered a bug that prevents me from starting or removing an existing container.


What I think is the reason :

Container creation is case insensitive (you can create Test and test) but the host file system might not be.
Egexol do not warn you that an image already exists with that name, regardless of casing.

Even tho exegol info will list the two containers, only 1 workplace will be created

╭ [~]
╰ ➜ exegol info

[...]

👽 Available containers
┌───────────────┬─────────┬───────────┬──────────────────────┐
│ Container tag │ State   │ Image tag │ Configurations       │
├───────────────┼─────────┼───────────┼──────────────────────┤
│ Test          │ Stopped │ full      │ Network mode: bridge │
│ test          │ Stopped │ full      │ Network mode: bridge │
└───────────────┴─────────┴───────────┴──────────────────────┘
╭ [~]
╰ ➜ ls ~/.exegol/workspaces
Test

(See steps to reproduce first)

Since removing Test deleted ~/.exegol/workspaces/Test, the remaining container test cannot be started anymore, nor can it be deleted, because the workplace directory do not exist anymore. I don't think it's really needed, but as asked, I pasted the execution logs bellow.


This is only an issue on file systems that are case sensitve. By that I mean FS that prevents you to have two directory with the same name with different casing.


A few exemples

on widows:
NTFS is case sensitive = issue

C:\tmp> mkdir Test

C:\tmp> mkdir test
A subdirectory or file Test already exists.

# The issue will be reproductible here

or MacOS
By default MacOS uses APFS, which is case sensitive = issue

╭ [~]
╰ ➜ mkdir Test
╭ [~]
╰ ➜ mkdir test
mkdir: test: File exists

# The issue will be reproductible here


This is not a problem on FS that are case-insensitive
I tested on Kali (EXT4) , Kaisen (BTRFS) and Manjaro (EXT4)

user@kaisen ~/tmp $ mkdir test
user@kaisen ~/tmp $ mkdir Test
user@kaisen ~/tmp $ ls
test  Test

# The issue will not be reproductible

System configuration

MacOS Ventura 13.4 (M2 Pro MBP)
Python 3.11.3

Steps To Reproduce

  1. Create a new container : exegol start test (doesn't matter which image)
    • exit (no need to do anything specific in it)
  2. Create another container with the same name, but with a different casing : exegol start Test
    • exit

I now have the two containers

  1. Removing (either) one of them : exegol remove Test
  2. And, that's it

Exegol Wrapper Version

╭ [~]
╰ ➜ exegol version -vvv
[*] Exegol is currently in version v4.2.3
[*] Exegol Discord serv.: https://discord.gg/cXThyp7D6P
[*] Exegol documentation: https://exegol.rtfd.io/
[+] We thank Capgemini for supporting the project (helping with dev) 🙏
[+] We thank HackTheBox for sponsoring the multi-arch support 💚
[D] Pip installation: On ✔
[D] Git source installation: Off 🪓
[D] Host OS: HostOs.MAC (DockerEngine.MAC)
[D] Arch: arm64
[D] Docker desktop: On ✔
[D] Shell type: HostOs.MAC
[D] Last wrapper update check: 2023-06-13 00:00:00

Host OS

MacOS


Execution logs in debug mode

╭ [~]
╰ ➜ exegol remove test -vvv
[D] Running remove module
[*] Exegol is currently in version v4.2.3
[*] Exegol Discord serv.: https://discord.gg/cXThyp7D6P
[*] Exegol documentation: https://exegol.rtfd.io/
[+] We thank Capgemini for supporting the project (helping with dev) 🙏
[+] We thank HackTheBox for sponsoring the multi-arch support 💚
[D] Pip installation: On ✔
[D] Git source installation: Off 🪓
[D] Host OS: HostOs.MAC (DockerEngine.MAC)
[D] Arch: arm64
[D] Docker desktop: On ✔
[D] Shell type: HostOs.MAC
[D] Last wrapper update check: 2023-06-13 00:00:00

[*] Removing an exegol container
[D] Attribute not found in parameters: containertag
[D] == Loading container : exegol-test
[D] Parsing envs : DISPLAY=host.docker.internal:0
[D] Parsing envs : _JAVA_AWT_WM_NONREPARENTING=1
[D] Parsing envs : QT_X11_NO_MITSHM=1
[D] Parsing envs : PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[D] Parsing label : org.exegol.app
[D] Parsing label : org.exegol.build_date
[D] Parsing label : org.exegol.metadata.creation_date
[D] Parsing label : org.exegol.src_repository
[D] Parsing label : org.exegol.tag
[D] Parsing label : org.exegol.version
[D] Capabilities : []
[D] Load devices : []
[D] Parsing mount : {'Type': 'bind', 'Source': '/etc/localtime', 'Destination': '/etc/localtime', 'Mode': '', 'RW': False, 'Propagation': 'rprivate'}
[D] Parsing mount : {'Type': 'bind', 'Source': '/Users/wem/.exegol/my-resources', 'Destination': '/opt/my-resources', 'Mode': '', 'RW': True, 'Propagation': 'rprivate'}
[D] Parsing mount : {'Type': 'bind', 'Source': '/Users/wem/.exegol/exegol-resources', 'Destination': '/opt/resources', 'Mode': '', 'RW': True, 'Propagation': 'rprivate'}
[D] Parsing mount : {'Type': 'bind', 'Source': '/Users/wem/.exegol/workspaces/test', 'Destination': '/workspace', 'Mode': '', 'RW': True, 'Propagation': 'rprivate'}
[D] Loading workspace volume source : /Users/wem/.exegol/workspaces/test
[D] Private workspace detected
[D] Try to retrieve image version from labels
[D] └── full    → (remote) sha256:2c2257cb94a8047cd03c59c512c295b89101e5982105e982c406ed850deef7d9
[?] Are you sure you want to permanently remove the following containers? [ test ] [y/N]: y
[V] Removing workspace volume
[D] Removing volume /Users/wem/.exegol/workspaces/test
[-] It seems that something unexpected happened ...
[-] To draw our attention to the problem and allow us to fix it, you can share your error with us (by copying and pasting it with this syntax: ``` <error> ```) by creating a GitHub issue at this address: https://github.com/ThePorgs/Exegol/issues
[+] Thank you for your collaboration!
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/exegol/manager/E │
│ xegolController.py:59 in main                                                                    │
│                                                                                                  │
│   56 │   │   # Set logger verbosity depending on user input                                      │
│   57 │   │   ExeLog.setVerbosity(ParametersManager().verbosity, ParametersManager().quiet)       │
│   58 │   │   # Start Main controller & Executing action selected by user CLI                     │
│ ❱ 59 │   │   ExegolController.call_action()                                                      │
│   60 │   except KeyboardInterrupt:                                                               │
│   61 │   │   logger.empty_line()                                                                 │
│   62 │   │   logger.info("Exiting")                                                              │
│                                                                                                  │
│ /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/exegol/manager/E │
│ xegolController.py:39 in call_action                                                             │
│                                                                                                  │
│   36 │   │   │   # Fetch main operation function                                                 │
│   37 │   │   │   main_action = cls.__action()                                                    │
│   38 │   │   │   # Execute main function                                                         │
│ ❱ 39 │   │   │   main_action()                                                                   │
│   40 │   │   else:                                                                               │
│   41 │   │   │   # TODO review required parameters                                               │
│   42 │   │   │   logger.error(f"These parameters are mandatory but missing: {','.join(missing    │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │            cls = <class 'exegol.manager.ExegolController.ExegolController'>                  │ │
│ │    main_action = <bound method ExegolManager.remove of <class                                │ │
│ │                  'exegol.manager.ExegolManager.ExegolManager'>>                              │ │
│ │ missing_params = []                                                                          │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/exegol/manager/E │
│ xegolManager.py:187 in remove                                                                    │
│                                                                                                  │
│   184 │   │   │   logger.error("Aborting operation.")                                            │
│   185 │   │   │   return                                                                         │
│   186 │   │   for c in containers:                                                               │
│ ❱ 187 │   │   │   c.remove()                                                                     │
│   188 │   │   │   # If the image used is deprecated, it must be deleted after the removal of i   │
│   189 │   │   │   if c.image.isLocked() and UserConfig().auto_remove_images:                     │
│   190 │   │   │   │   DockerUtils.removeImage(c.image, upgrade_mode=True)                        │
│                                                                                                  │
│ ╭────────────────────────────────────── locals ───────────────────────────────────────╮          │
│ │   all_name = 'test'                                                                 │          │
│ │          c = <exegol.model.ExegolContainer.ExegolContainer object at 0x107140890>   │          │
│ │        cls = <class 'exegol.manager.ExegolManager.ExegolManager'>                   │          │
│ │ containers = [<exegol.model.ExegolContainer.ExegolContainer object at 0x107140890>] │          │
│ ╰─────────────────────────────────────────────────────────────────────────────────────╯          │
│                                                                                                  │
│ /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/exegol/model/Exe │
│ golContainer.py:184 in remove                                                                    │
│                                                                                                  │
│   181 │                                                                                          │
│   182 │   def remove(self):                                                                      │
│   183 │   │   """Stop and remove the docker container"""                                         │
│ ❱ 184 │   │   self.__removeVolume()                                                              │
│   185 │   │   self.stop(timeout=2)                                                               │
│   186 │   │   logger.info(f"Removing container {self.name}")                                     │
│   187 │   │   try:                                                                               │
│                                                                                                  │
│ ╭────────────────────────────────── locals ───────────────────────────────────╮                  │
│ │ self = <exegol.model.ExegolContainer.ExegolContainer object at 0x107140890> │                  │
│ ╰─────────────────────────────────────────────────────────────────────────────╯                  │
│                                                                                                  │
│ /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/exegol/model/Exe │
│ golContainer.py:207 in __removeVolume                                                            │
│                                                                                                  │
│   204 │   │   │   logger.verbose("Removing workspace volume")                                    │
│   205 │   │   │   logger.debug(f"Removing volume {volume_path}")                                 │
│   206 │   │   │   try:                                                                           │
│ ❱ 207 │   │   │   │   list_files = os.listdir(volume_path)                                       │
│   208 │   │   │   except PermissionError:                                                        │
│   209 │   │   │   │   if Confirm(f"Insufficient permission to view workspace files {volume_pat   │
│   210 │   │   │   │   │   │      f"do you still want to delete them?", default=False):           │
│                                                                                                  │
│ ╭────────────────────────────────────── locals ──────────────────────────────────────╮           │
│ │        self = <exegol.model.ExegolContainer.ExegolContainer object at 0x107140890> │           │
│ │ volume_path = '/Users/wem/.exegol/workspaces/test'                                 │           │
│ ╰────────────────────────────────────────────────────────────────────────────────────╯           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
FileNotFoundError: [Errno 2] No such file or directory: '/Users/wem/.exegol/workspaces/test'

Anything else?

Manual fix

This is what I've done to manually fix this for me:

I need to mention that I've not been using Exegol for an extensive period of time, so there may be a "native" way to address this issue that I'm not yet familiar with.
I don't know if opening a GH issue was really needed, or if it's just because I'm not using it correctly. So please, let me know if there are any specific documentation that cover this issue, any recommended steps within Exegol to mitigate the problem, or if you need any more informations.

In any case (pun itended), thx in advence.

Dramelac commented 1 year ago

Hello,

Thank you for pointing out this error, I hadn't thought of it! I'll fix it in a future version (probably by not allowing the creation of containers with the same name on OSes that don't support the distinction correctly).

Dramelac commented 1 year ago

Fixed in 2b449bbe