Skip to content

Instantly share code, notes, and snippets.

@jbarotin
Last active May 7, 2021 12:16
Show Gist options
  • Save jbarotin/0066e1332c1dc1975f7f0495e705a40c to your computer and use it in GitHub Desktop.
Save jbarotin/0066e1332c1dc1975f7f0495e705a40c to your computer and use it in GitHub Desktop.
Seaweedfs filer REST API cli
import requests
import sys
import configparser
import json
import pathlib
#
# cli that aim to query the filer REST API
# setup a ~/.seaweedfs.cfg
#
# [seaweedfs]
# filer_url = http://localhost:8888
#
# then you can query filer
# seaweedfs ls /my/directory
# seaweedfs get /path/to/my/file
# ...
# seadweefs help : to see all command
def __filer_get_request(url, headers={}):
r = requests.get(url, headers=headers)
if r.status_code != 200:
if r.status_code == 404:
print("path not found")
return "{}"
else:
raise Exception(
"Can't query {}, HTTP code {}, message '{}'".format(url,
r.status_code,
r.content.decode("utf-8")))
else:
return r.content
def __filer_get_request_json(url):
return json.loads(__filer_get_request(url, headers={"Accept": "application/json"}))
def __path_to_parent_url(filer_url, path):
path = pathlib.PurePath(path)
if path != "/":
return filer_url + str(path.parent)
else:
return filer_url
def ls(filer_url, path):
content = __filer_get_request_json(__path_to_parent_url(filer_url, path))
# print(json.dumps(content, indent=2))
for entry in content["Entries"]:
if entry["FullPath"] == path:
notFound = False
# check bit directory cf. https://golang.org/pkg/io/fs/#FileMode
if entry["Mode"] & (1 << 31):
content = __filer_get_request_json(filer_url + path)
if content["Entries"] != None:
for entry in content["Entries"]:
print(entry["FullPath"])
else: # "chunks" in entry:
# it's a plain file
print(entry["FullPath"])
return 0
print("path not found")
return 1
def get(filer_url, path):
content = __filer_get_request_json(__path_to_parent_url(filer_url, path))
if content is not None and "Entries" in content:
for entry in content["Entries"]:
if entry["FullPath"] == str(path):
sys.stdout.buffer.write(__filer_get_request(filer_url + path))
return 0
return 1
def size(filer_url, path):
content = __filer_get_request_json(__path_to_parent_url(filer_url, path))
if content is not None and "Entries" in content:
for entry in content["Entries"]:
if entry["FullPath"] == str(path):
size = 0
for chunk in entry["chunks"]:
size += int(chunk["size"])
print(size)
return 0
return 1
def put(filer_url, distant_path, local_file):
headers = {"Content-Type": "application/json",
"Accept": "application/json"}
with open(local_file, 'rb') as f:
r = requests.put(filer_url + distant_path,
data=f, headers=headers)
print("{} {}".format(r.status_code, r.content))
def read_absolute_path(path):
if path[0] == "/":
return path
else:
raise Exception("Path must start by /")
def read_config():
config = configparser.ConfigParser()
config.sections()
config.read('~/.seaweedfs.cfg')
return config["seaweedfs"]
def usage():
print("""USAGE seaweadfs ACTION [OPTION1]... :
with ACTION can be
ls DISTANT_PATH
size DISTANT_PATH
put LOCAL_PATH DISTANT_PATH
get DISTANT_PATH
""")
def main():
config = read_config()
filer_url = config["filer_url"]
if len(sys.argv) > 2:
action = sys.argv[1]
if action == "ls":
if len(sys.argv) == 3:
return ls(filer_url, read_absolute_path(sys.argv[2]))
elif action == "put":
return put(filer_url, read_absolute_path(sys.argv[3]), sys.argv[2])
elif action == "get":
return get(filer_url, read_absolute_path(sys.argv[2]))
elif action == "size":
return size(filer_url, read_absolute_path(sys.argv[2]))
elif action == "help":
usage()
else:
print(f"action not known '{action}'")
return 2
if __name__ == "__main__":
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment