def exists_image(img_name): status, rows = run("docker image ls \"" + img_name + "\"", read=True) if status != 0: error("Command error") return len(rows) >= 2
def conf_parse_cmds(args, scope="local"): value = None addr = None while args.has_next(): if args.has_cmd(): cmd = args.pop_cmd() if cmd == "--global": scope = "global" elif cmd == "--local": scope = "local" elif cmd == "--any": scope = "any" else: error("Invalid parameter:", cmd) else: tmp = args.pop_parameter() if value: error("Too many parameters") elif addr: value = tmp else: addr = tmp return scope, addr, value
def conf_pop(args): scope, addr, value = conf_parse_cmds(args, scope="local") if value: error("Too many parameters") return conf.get(addr, scope=scope)
def use(args): env = None cluster = None while args.has_next(): if args.has_cmd(): cmd = args.pop_cmd() if cmd == "--env": env = args.pop_parameter() elif cmd == "--cluster": cluster = args.pop_parameter() else: error("Invalid parameter:", cmd) else: if env is None: env = args.pop_parameter() elif cluster is None: cluster = args.pop_parameter() else: error("Too many parameters") Context().use(env, cluster)
def is_container_running(cont_name): cmd = "docker inspect -f '{{.State.Running}}' " + cont_name status, rows = run(cmd, read=True) if status != 0 or not rows: error("Command error") return rows[0] == "true\n"
def conf_get(args): scope, addr, value = conf_parse_cmds(args, scope="any") if value: error("Too many parameters") value = conf.get(addr, scope=scope, pop=False) if value: print(value)
def get_container_ip(cont_name): if type(cont_name) is list: return [(x, get_container_ip(x)) for x in cont_name] cmd = "docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' " + cont_name status, rows = run(cmd, read=True) if status != 0 or not rows: error("Command error") return rows[0].strip()
def ls_commits(): status, rows = run("docker image ls \"wcommit*\"", read=True) if status != 0: error("Command error") result = [] for row in rows[1:]: cells1 = row.split() cells2 = cells1[1].split("__") result.append([cells1[0] + ":" + cells1[1]] + cells2) return result
def parse_volumes(volumes): volumes = [j.strip() for j in volumes] volumes = [expand_path(j) for j in volumes if j] for v in volumes: src = v.split(":")[0] if not os.path.exists(src): error("Missing source directory in host:", src) if not os.path.isdir(src): error("Source volume in host is not a directory:", src) return volumes
def get_containers_in_cluster(self, clustername, abortOnFail=False): _, rows = run("docker ps -a", read=True) r = re.compile("wclus__" + clustername + "__[a-zA-Z0-9]+__[0-9]+$") result = [] for row in rows: m = r.search(row) if m: name = m.group(0) result.append(name) if abortOnFail and not result: error("Cluster not found") return result
def read_envfile(self, filepath): r = re.compile(r'(#+)\s*([a-zA-Z0-9_]+)\s*(#+)\s*') order = [] rows = [] with open(filepath, "r") as fin: for i, line in enumerate(fin): m = r.match(line) if m: l = len(m.group(1)) name = m.group(2) order.append((name, i, l)) rows.append(line) order.append(("__eof__", i + 1, 0)) root = EnvNode() node_queue = [root] for i in range(1, len(order)): name, first, lvl = order[i - 1] _, last, _ = order[i] selection = rows[first + 1:last] node = EnvNode(name, lvl, selection) head = node_queue[-1] if node.lvl == head.lvl: node_queue.pop() node_queue[-1].add(node) node_queue.append(node) elif node.lvl == head.lvl + 1: head.add(node) node_queue.append(node) elif node.lvl > head.lvl: error("Invalid node depth, should be", str(head.lvl + 1)) else: while node_queue[-1].lvl >= node.lvl: node_queue.pop() return root
def renv_set(args): try: if not args.has_parameter(): conf.set("wup.cluster_filepath", "", scope="global") conf.set("wup.cluster_name", "", scope="global") else: filepath = os.path.abspath(args.pop_parameter()) name = os.path.splitext(os.path.basename(filepath))[0] with open(filepath, "r") as fin: yaml.load(fin) conf.set("wup.cluster_filepath", filepath, scope="global") conf.set("wup.cluster_name", name, scope="global") except (FileNotFoundError, yaml.scanner.ScannerError): error("Missing or invalid file:", filepath) update_state()
def set(addr, value, scope="local"): if type(addr) is str: addr = addr.split(".") if scope == "local": filepath = get_local_filepath(os.getcwd()) elif scope == "global": filepath = get_global_filepath() elif scope == "any": error("--any is not a valid scope for this operation") if value is None: error("Missing new value") if not addr: error("Missing keys") try: root = read(filepath) except: root = {} data = root for a in addr[:-1]: if not a in data or not type(data[a]) is dict: data[a] = {} data = data[a] data[addr[-1]] = value write(root, filepath)
def new(self, clustername, qtt, outfolder): self.require(env=True) if not docker.exists_image(self.img_name): error("You must COMMIT the image first") if self.cluster_nodes: error("A cluster with this name already exist, remove it first") nodes = [ get_container_name(self.name, clustername, i) for i in range(qtt) ] for cont_name in nodes: docker.new(self.img_name, cont_name, self.e) data = { "local_arch": { cont_name: { "tags": ["fakecluster"], "host": "unknown", "user": "******", "procs": 1 } for cont_name in nodes } } outfile = os.path.join(outfolder, clustername + ".cluster") with open(outfile, "w") as fout: yaml.dump(data, fout) self.set_cluster(clustername, outfile) print("Cluster file written to " + colors.YELLOW + outfile + colors.RESET) update_state()
def new(img_name, cont_name, e): if not exists_image(img_name): error("Image not found") createCmd = "docker run -i --name tmp" if e.volumes: createCmd += " -v " + " -v ".join(e.volumes) if e.expose: createCmd += " --expose=" + " --expose=".join(e.expose) if e.map_ports: createCmd += " -p " + " -p".join(e.map_ports) createCmd += " " + img_name rm_container("tmp") cmds = e.bashrc + e.new run(createCmd, write=cmds) rm_container(cont_name) rename_container("tmp", cont_name)
def require(self, env=False, cluster=False): if env and not (self.name and self.name != "-"): error("You must set an environment first") if cluster and not (self.cluster and self.cluster != "-"): error("You must set a cluster first") if env and cluster and self.name != self.cluster_env: error( "This cluster was created from a different environment, please set the proper one" )
def lookup_cluster(name): if name == "-": return "-", "" if not os.path.exists(name): filepath = "./" + name + ".cluster" if not os.path.exists(filepath): error("Could not find a cluster definition for:", name) else: filepath = name name = os.path.splitext(os.path.basename(name))[0] if "__" in name: error( "Cluster names must not contain two consecutive underscores (__)") if name == "temp": error("You cannot use a cluster named temp") return name, filepath
def lookup_env(name): if name == "-": return "-", "" if not os.path.exists(name): filepath = "./" + name + ".env" if not os.path.exists(filepath): filepath = "~/.wup/projects/" + name + "/" + name + ".env" if not os.path.exists(filepath): error("Could not find an env declaration for:", name) else: filepath = name name = os.path.splitext(os.path.basename(name))[0] if "__" in name: error("Names must not contain two consecutive underscores (__)") if name == "temp": error("You cannot use a container named temp") return name, filepath
def init_from_envfile(self, env, env_filepath): root = self.read_envfile(env_filepath) # VARIABLES variables = {} if "VARS" in root: for row in root["VARS"].lines: row = row.strip() if not row: continue cells = row.split("=", maxsplit=1) key, value = cells variables[key.strip()] = value.strip() if "BASE" in variables: self.base = variables["BASE"] if "WORKDIR" in variables: self.workdir = variables["WORKDIR"] if "EXPOSE" in variables: self.expose = variables["EXPOSE"].split(",") if "MAP_PORTS" in variables: self.map_ports = variables["MAP_PORTS"].split(",") if "RUN" in variables: self.run = variables["RUN"] # BASHRC self.bashrc = [k + "=\"" + variables[k] + "\"\n" for k in variables] self.bashrc += [ "mkdir -p %s\n" % self.workdir, "cd %s\n" % self.workdir ] # TEMPLATES if "BUILD_VOLUMES" in root: self.build_volumes = root["BUILD_VOLUMES"] self.volumes += root["BUILD_VOLUMES"] if "DEPLOY_VOLUMES" in root: self.deploy_volumes = root["DEPLOY_VOLUMES"] self.volumes += root["DEPLOY_VOLUMES"] if "LAUNCH" in root: self.launch = root["LAUNCH"].lines if "START" in root: self.start = root["START"].lines if "NEW" in root: self.new = root["NEW"].lines if "OPEN" in root: self.open = root["OPEN"].lines if "BUILD" in root: build = root["BUILD"] self.full_build = build.lines_recursive() self.commit_prefix = "wcommit:" + env hashstr = "".join(self.bashrc) lines = crop_edge_lines(build.lines) if lines: hashstr += "ROOT" + "".join(lines) commit = Commit(0, self.commit_prefix, "ROOT", lines, hashstr) self.commits.append(commit) for node in build.children: if node.name == "ROOT": error("A commit named ROOT is not allowed") lines = crop_edge_lines(node.lines) if lines: hashstr += node.name + "".join(lines) commit = Commit(len(self.commits), self.commit_prefix, node.name, lines, hashstr) self.commits.append(commit)
def add(self, node): if node.name in self.children_map: error("Tag defined more than once:", node.name) self.children.append(node) self.children_map[node.name] = node