cli config contexts
This commit is contained in:
parent
4268b2df48
commit
eb0571c679
122
photoapp/cli.py
122
photoapp/cli.py
@ -14,15 +14,16 @@ import appdirs
|
||||
|
||||
|
||||
APPNAME = "photocli"
|
||||
DEFAULT_CONFIG = {"uri": None,
|
||||
"lastbatch": None}
|
||||
DEFAULT_CONFIG = {"context": "default",
|
||||
"contexts": {"default": {"uri": None,
|
||||
"upload_workers": 2}}}
|
||||
|
||||
|
||||
class CliConfig(dict):
|
||||
def __init__(self, appname, default):
|
||||
def __init__(self, appname):
|
||||
self.confdir = appdirs.user_config_dir(appname)
|
||||
self.confpath = os.path.join(self.confdir, "cli.json") # ~/Library/Application Support/name/cli.json
|
||||
super().__init__(**default)
|
||||
self.confpath = os.path.join(self.confdir, "cli.json") # ~/Library/Application Support/photocli/cli.json
|
||||
super().__init__(**DEFAULT_CONFIG)
|
||||
self.init_config()
|
||||
|
||||
def init_config(self):
|
||||
@ -41,11 +42,41 @@ class CliConfig(dict):
|
||||
json.dump(self, f, indent=4)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""
|
||||
prevents setting of invalid config keys as they are not defined
|
||||
"""
|
||||
if key not in self:
|
||||
raise KeyError(key)
|
||||
super().__setitem__(key, value)
|
||||
self.write()
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
return self["context"]
|
||||
|
||||
def set_server(self, context_name, server_uri):
|
||||
self["contexts"][context_name]["uri"] = server_uri
|
||||
self.write()
|
||||
|
||||
def select_context(self, context_name):
|
||||
if context_name not in self["contexts"]:
|
||||
raise KeyError("Context '{}' is not defined".format(context_name))
|
||||
return self["contexts"][context_name]
|
||||
|
||||
def set_context(self, context_name):
|
||||
if context_name not in self["contexts"]:
|
||||
raise KeyError("Context '{}' is not defined".format(context_name))
|
||||
self["context"] = context_name
|
||||
self.write()
|
||||
|
||||
def edit_context(self, context_name, context):
|
||||
self["contexts"][context_name] = context
|
||||
self.write()
|
||||
|
||||
def delete_context(self, context_name):
|
||||
del self["context_name"]
|
||||
self.write()
|
||||
|
||||
|
||||
class PhotoApiClient(object):
|
||||
def __init__(self, base_url, passwd=None):
|
||||
@ -135,6 +166,8 @@ def get_args():
|
||||
parser = argparse.ArgumentParser(description="photo library cli")
|
||||
# TODO nicer uri parser
|
||||
parser.add_argument("--host", default=os.environ.get("PHOTOLIB_URI", None), help="photo api server address")
|
||||
parser.add_argument("--context", help="api server context defined in config file",
|
||||
default=os.environ.get("PHOTOLIB_CONTEXT", None))
|
||||
parser.add_argument("-y", "--yes", action="store_true", help="assume yes for all prompts")
|
||||
|
||||
sp_action = parser.add_subparsers(dest="action", help="action to take")
|
||||
@ -189,20 +222,91 @@ def get_args():
|
||||
p_delete = p_useraction.add_parser('delete', help='delete users')
|
||||
p_delete.add_argument("-u", "--username", help="username", required=True)
|
||||
|
||||
p_ctx = sp_action.add_parser("ctx", help="change server contexts")
|
||||
p_ctx.add_argument("new_context", help="context name")
|
||||
|
||||
p_editctx = sp_action.add_parser("update-context", help="create/edit server contexts")
|
||||
p_editctx.add_argument("context_name", help="context name to modify")
|
||||
p_editctx.add_argument("--set-host", help="photo api server address")
|
||||
p_editctx.add_argument("--delete", action="store_true", help="delete the context")
|
||||
|
||||
sp_action.add_parser("list-contexts", help="list available contexts")
|
||||
|
||||
return parser.parse_args(), parser
|
||||
|
||||
|
||||
def main():
|
||||
config = CliConfig(APPNAME, DEFAULT_CONFIG)
|
||||
args, parser = get_args()
|
||||
config = CliConfig(APPNAME)
|
||||
|
||||
uri = urlparse(args.host or config["uri"])
|
||||
# figure out the selected context - first the --context flag, then conf file, then "default"
|
||||
context = args.context or config.context
|
||||
|
||||
# default context is "sticky" and remembers the last --host used
|
||||
if args.host and context == "default": # TODO move this after parsing
|
||||
new_default = urlparse(args.host)
|
||||
if not new_default.netloc:
|
||||
parser.error("--host uri is invalid")
|
||||
config.set_server("default", new_default.geturl())
|
||||
|
||||
if args.host and context != "default":
|
||||
parser.error("--host not allowed for non-default contexts. Use `ctx` to switch to the default context or use "
|
||||
"`update-context --host HOST` to create a new context.")
|
||||
|
||||
# these commands manipulate the config file so we don't check it yet
|
||||
# change or edit contexts
|
||||
if args.action == "ctx":
|
||||
try:
|
||||
config.set_context(args.new_context)
|
||||
except KeyError as ke:
|
||||
parser.error("{}. Use `update-context` to define it.".format(ke.args[0]))
|
||||
return
|
||||
|
||||
elif args.action == "update-context":
|
||||
try:
|
||||
ctx = config.select_context(args.context_name)
|
||||
except KeyError:
|
||||
ctx = DEFAULT_CONFIG["contexts"]["default"]
|
||||
|
||||
if args.set_host:
|
||||
new_uri = urlparse(args.set_host)
|
||||
if not new_uri.netloc:
|
||||
parser.error("--set-host uri is invalid")
|
||||
ctx["uri"] = new_uri.geturl()
|
||||
|
||||
if args.delete:
|
||||
try:
|
||||
config.delete_context(args.context_name)
|
||||
print("Context deleted")
|
||||
except KeyError:
|
||||
pass
|
||||
return
|
||||
|
||||
if not ctx["uri"]:
|
||||
parser.error("New context must include a host, use `--set-host`.")
|
||||
|
||||
config.edit_context(args.context_name, ctx)
|
||||
print("Context updated")
|
||||
return
|
||||
|
||||
elif args.action == "list-contexts":
|
||||
for entry in sorted(config["contexts"].keys()):
|
||||
print("{}{}".format(entry, " (active)" if entry == context else ""))
|
||||
return
|
||||
|
||||
# commands below here need a valid config file and api client
|
||||
# validate the config
|
||||
try:
|
||||
server_conf = config.select_context(context)
|
||||
except KeyError as ke:
|
||||
parser.error("{}. Use `update-context` to define it.".format(ke.args[0]))
|
||||
|
||||
uri = urlparse(server_conf["uri"])
|
||||
|
||||
if not uri.netloc:
|
||||
parser.error("need --host, $PHOTOLIB_URI, or config file")
|
||||
|
||||
config["uri"] = uri.geturl()
|
||||
|
||||
# create the client
|
||||
port = f":{uri.port}" if uri.port else ""
|
||||
client = PhotoApiClient(f"{uri.scheme}://{uri.hostname}{port}", (uri.username, uri.password, ))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user