I noticed I did not have enough testing on my code for getting directories under base project directory.
This is part of the code snippet of my SSHClient subclass:
def get_project_dirs(self, dirname: str = "/var/lib/awx/projects") -> Union[Dict[str, str], Dict[str, List]]: """ To get a list of directories under the Ansible AWX base project directory. :param dirname: Project base directory. Ansible searches the yaml file from base directory. :return: dictionary of response. """ try: # exec_command throws up a tuple(stdin, stdout, stderr) stdin, stdout, _ = self.exec_command(f"sudo ls -lah {dirname}", get_pty=True) stdin.write(self.password + "\n") stdin.flush() stdout_results = stdout.read().decode("utf-8") pbdirs = list() for d in stdout_results.splitlines()[3:]: # Not interested in password, sudo prompt and total 0 pbdirs.append(d.split()[-1]) # Only directory name. return { "status": "success", "playbook_dirs": pbdirs[2:] if len(pbdirs) > 2 else [] # not interested in . and .. } except CONN_EXCEPTION as CE: return { "status": "failed", "message": str(CE) }
The problem
The method gets all things under the base directory that is files and directories, that is because I have sliced and diced too much and inadvertently ignored the directory marking in linux hence whatever is inside the directory will be collected in my list.
Here is an example to illustrate on what I am talking about.
This is the content of the home directory of my CentOS server hosting Ansible AWX:
This is the code to extract the contents of the defined base directory, my intention is to get the list of directories but apparently it collects files as well as directories.
from helper.linux import LinuxSSH from getpass import getpass username = input("Username: ") password = getpass() with LinuxSSH(username=username, password=password, hostname="192.168.100.174") as linux: response = linux.get_project_dirs(dirname="/home/cyruslab") print(response)
Minor modification
So instead of getting anything excluding .
and ..
I put in check if “d” exist in the row[0] which is the first index of row after split()
.
This is the modified code to check the directory marking in order to collect just the directories.
def get_project_dirs(self, dirname: str = "/var/lib/awx/projects") -> Union[Dict[str, str], Dict[str, List]]: """ To get a list of directories under the Ansible AWX base project directory. :param dirname: Project base directory. Ansible searches the yaml file from base directory. :return: dictionary of response. """ try: # exec_command throws up a tuple(stdin, stdout, stderr) stdin, stdout, _ = self.exec_command(f"sudo ls -lah {dirname}", get_pty=True) stdin.write(self.password + "\n") stdin.flush() stdout_results = stdout.read().decode("utf-8") pbdirs = list() for row in stdout_results.splitlines()[3:]: # Not interested in password, sudo prompt and total 0 # if "d" is found in the row if "d" in row.split()[0]: pbdirs.append(row.split()[-1]) # the directory name is in the last index of the row. return { "status": "success", "playbook_dirs": pbdirs[2:] if len(pbdirs) > 2 else [] # not interested in . and .. } except CONN_EXCEPTION as CE: return { "status": "failed", "message": str(CE) }
So to test it, I purposefully touch a file that has “d” in the filename.
And running the same test code above I got these: