# # This script updates a local EcFlow suite definition by # adding and overwriting EcFlow variable (i.e. Edit) values # recursively at each node in the suite, using definitions # loaded from an ecflow_server. In this way the definitions # can be modified, e.g. changing Triggering or adding/removing # families, tasks, etc) and re-uploaded without resetting # most variables to their default values. # # Note Nodes will only be updated if they exist on the remote # server and have the same node path. Variables will be modified # or added, but not deleted if they don't exist on the server. # ################################################################ from ecflow import Client, Defs import os,sys def get_defs(defspath): """ Get local definitions from the local definitions file and remote definitions from the server at $ECF_HOST and $ECF_PORT :param defspath: The path to the local suite definitions file :return: (remote_definitions, local_definitions) """ cli = Client() cli.sync_local() remote_defs = cli.get_defs() local_defs = Defs(defspath) return (remote_defs, local_defs) def update_vars(nodename, local, remote): """ Recursively add/update variables at each node from the remote definitions to the local ones. Leaves changes in triggers and node additions/removals alone. Only updates nodes that exist in both local and remote definitions :param nodename: The absolute path to the node in the local definitions :param local: A set of local definitions at a particular node. This gets further in the node tree with each level of recursion. :param remote: The set of all remote nodes. This stays constant through the recursion """ n = remote.find_abs_node(nodename) if n is None: return local for v in n.variables: # this overwrites existing variable values local.add_variable(v.name(),v.value()) nodes = local.get_all_nodes() for i in range(1,len(nodes)): path = nodes[i].get_abs_node_path() update_vars(path, nodes[i], remote) def run(): """ Entry point of the program """ if len(sys.argv) < 2: print("Usage: %s " % os.path.basename(sys.argv[0])) exit(-1) suitename = sys.argv[1] defs_path = "%s/defs/%s.def" % (os.environ['ECFLOW_DIR'], suitename) (remote, local) = get_defs(defs_path) update_vars("/%s" % suitename, local.find_suite(suitename), remote) # move original defs aside and write out updated defs os.rename(defs_path, "%s.orig" % defs_path) local.save_as_defs(defs_path) return True if __name__ == "__main__": run() exit(0)