Skip to content

Commit

Permalink
S3: implement 'ls [--username <regx>]' function to list users and the…
Browse files Browse the repository at this point in the history
…ir buckets
  • Loading branch information
apeters1971 committed May 22, 2024
1 parent 138ad78 commit 5ae385b
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/XrdS3/app/xs3
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import string
import random
import uuid
import shutil
import re

def main():
# Create the main parser
Expand Down Expand Up @@ -63,6 +64,10 @@ def main():
deletebucket_parser.add_argument('username', help='Username')
deletebucket_parser.add_argument('bucketname', help='Bucket name')

# Add the 'ls' subcommand
ls_parser = subparsers.add_parser('ls', help='List users/buckets')
ls_parser.add_argument('--username', help='Username', default=None)

# Parse the arguments
args = parser.parse_args()

Expand All @@ -77,9 +82,39 @@ def main():
handle_addbucket(args)
elif args.subcommand == 'deletebucket':
handle_deletebucket(args)
elif args.subcommand == 'ls':
handle_ls(args)
else:
parser.print_help()

def print_directory_structure(directory, buckets_dir, indent=''):
items = os.listdir(directory)
for i, item in enumerate(items):
item_path = os.path.join(directory, item)
is_last = i == len(items) - 1

if os.path.isdir(item_path):
print(indent + ('└── ' if is_last else '├── ') + f"{item}/")
print_directory_structure(item_path, indent + (' ' if is_last else '│ '))
else:
bucket_file = os.path.join(buckets_dir, item)
bucket_owner_attr = get_bucket_extended_attribute(bucket_file, 'user.s3.owner')
bucket_path_attr = get_bucket_extended_attribute(bucket_file, 'user.s3.path')
new_bucket_path_attr = get_extended_attribute(directory, 'user.s3.new_bucket_path')
print(indent + ('└── ' if is_last else '├── ') + f"{item:20} {bucket_owner_attr:20} {bucket_path_attr:40} new:[{new_bucket_path_attr}]")

def get_extended_attribute(filepath, attribute_name):
try:
attr = os.getxattr(filepath, attribute_name)
return attr.decode()
except OSError:
return ""

def get_bucket_extended_attribute(filename, attribute_name):
base_path = os.path.join(os.path.expanduser('~'), '.xs3', 'buckets')
file_path = os.path.join(base_path, filename)
return get_extended_attribute(file_path, attribute_name)

def handle_config(args):
# Ensure exactly one argument is provided
if not args.path:
Expand Down Expand Up @@ -478,6 +513,44 @@ def handle_deletebucket(args):
except OSError as e:
print(f"Error: Failed to delete empty file '{user_bucket_file}' from users directory. {e}")

def handle_ls(args):
username = args.username

# Determine the users directory from the config file
config_dir = os.path.join(os.path.expanduser('~'), '.xs3')
config_file = os.path.join(config_dir, 'config')

if not os.path.exists(config_file):
print("Error: Configuration file does not exist. Please run 'config' subcommand first.")
return

try:
with open(config_file, 'r') as f:
config_data = json.load(f)
base_path = config_data.get('base_path')
users_dir = os.path.join(base_path, 'users')
buckets_dir = os.path.join(base_path, 'buckets')
if not base_path:
print("Error: Base path is not configured properly.")
return
except (IOError, json.JSONDecodeError) as e:
print(f"Error: Failed to read the config file '{config_file}'. {e}")
return

if username:
regex = re.compile(username)
print("Info: Listing matching user directories:")
for dir_name in os.listdir(users_dir):
if regex.match(dir_name):
user_dir = os.path.join(users_dir, dir_name)
print(f"- {dir_name}/")
print_directory_structure(user_dir, buckets_dir, ' ')
else:
print("Info: Listing all user directories:")
for dir_name in os.listdir(users_dir):
user_dir = os.path.join(users_dir, dir_name)
print(f"{dir_name}/")
print_directory_structure(user_dir, buckets_dir, ' ')

if __name__ == '__main__':
main()
Expand Down

0 comments on commit 5ae385b

Please sign in to comment.