def systemctl_start(service): if not el.scb("systemctl is-active {service} || true") == "active\n": el.bash(lf("systemctl start {service}")) return True else: print(lf("{service}: OK")) return False
def systemctl_enable(service): if service in systemctl_enabled_services(): print(lf("{service}: OK")) return False else: el.bash(lf("systemctl enable {service}")) return True
def patch(fname, patches): """Patch FNAME applying PATCHES. Each PATCH in PATCHES is in diff -u format. Each line in PATCH starts with [+- ]. [ ] lines are the optional start and end context. [-] lines are expected to exist in the file and will be removed. [+] lines will be added to the file after [-] lines are removed. PATCH lines should be in contiguous order: optional start context, [-] lines, [+] lines, optional end context. If PATCH was already applied for FNAME, it will be ignored. PATCHES can also be a file name of a "diff -u" output. """ (host, name) = parse_fname(fname) patches = parse_patches(patches) if el.file_exists_p(fname): txt = el.slurp(fname) else: assert not any([ re.search("^\\-", patch, flags=re.MULTILINE) for patch in patches ]) el.sc("touch {name}") txt = "" no_change = True for ptch in patches: patch_lines = el.delete("", ptch.splitlines()) chunk_before = render_patch(patch_lines, True) chunk_after = render_patch(patch_lines, False) if chunk_before == "": if not re.search("^" + re.escape(chunk_after), txt, re.MULTILINE): no_change = False if not (txt == "" or txt[-1] == "\n"): txt += "\n" txt += chunk_after + "\n" elif (re.search("^" + re.escape(chunk_before), txt, re.MULTILINE) and not re.search("^" + re.escape(chunk_after), txt, re.MULTILINE)): no_change = False txt = re.sub("^" + re.escape(chunk_before), chunk_after, txt, flags=re.MULTILINE) else: # either already patched or fail assert chunk_after in txt if no_change: print(fname + ": OK") return False else: print(fname + ": Patch") with el.hostname(None): el.barf("/tmp/insta.txt", txt) if host is not None: cmd = lf("scp /tmp/insta.txt {host}:{name}") else: cmd = sudo(lf("cp /tmp/insta.txt {name}"), name) with el.hostname(None): bash(cmd, desc=(host, "edit " + name)) return True
def main(): argv = sys.argv[1:] if len(argv) == 0: argv = ["-h"] get_args(argv) args = get_args(argv) cmd = docker_run(get_image(args.docker_image), args.cmds, args.m, args.E, args.flags) el.bash(cmd)
def wget(url, download_dir="/tmp/"): if download_dir[:-1] == "/": fname = url.split("/")[-1] full_name = el.expand_file_name(fname, download_dir) else: full_name = download_dir if el.file_exists_p(full_name): print(lf("{full_name}: OK")) else: bash(lf("wget '{url}' -O {full_name}")) return full_name
def chown(fname, owner): current = sc("stat -c %U:%G {fname}") if current == owner: print(lf("{fname}: OK")) return False else: if el.HOST is not None: bash(lf("chown -R {owner} {fname}")) else: bash(lf("sudo chown -R {owner} {fname}")) return True
def chmod(fname, permissions): current = sc("stat -c %a {fname}") if current == permissions: print(lf("{fname}: OK")) return False else: if el.HOST is not None: scb("chmod {permissions} {fname}") else: cmd = sudo(lf("chmod {permissions} {fname}"), fname) bash(cmd) return True
def install_package(package, url=None): if isinstance(package, list): res = False for p in package: res |= install_package(p, url) return res user = sc("whoami") su = "" if user == "root" else "sudo " if el.file_exists_p("/usr/bin/dpkg"): if package_installed_p_dpkg(package): print(lf("{package}: OK")) return False else: if url is None: bash( lf("{su}apt-get update && DEBIAN_FRONTEND=noninteractive {su}apt-get install -y {package}" )) else: fname = wget(url) bash(lf("{su}dpkg -i {fname}")) return True else: if package_installed_p_yum(package): print(lf("{package}: OK")) return False else: if url is None: bash( lf("{su}yum update -y && {su}yum upgrade -y && {su}yum install -y '{package}'" )) else: fname = wget(url) bash(lf("{su}yum localinstall -y {fname}")) return True
def _main(book, module, flags, args): if len(args) == 0: print(describe(book, module)) elif args[0] == "--list": print(recipe_names(book)) elif args[0] == "--help": print(describe(book)) else: recipe = args[0] fun = recipe_dict(book)[recipe] cfg = book_config(book) if "tee" in cfg and recipe != "bash": basedir = os.path.expanduser(cfg["tee"]["location"]) fname = log_file_name(basedir, book, recipe) el.barf(fname, lf("Book: {book}\nRecipe: {recipe}\n")) tee = subprocess.Popen(["setsid", "-w", "tee", "-a", fname], stdin=subprocess.PIPE) os.dup2(tee.stdin.fileno(), sys.stdout.fileno()) os.dup2(tee.stdin.fileno(), sys.stderr.fileno()) old_sc_hookfn = el.sc_hookfn log = CommandLog() el.sc_hookfn = log.record try: if "-p" in flags: sys.stdout = open(os.devnull, "w") ret_cmds = fun(42, *recipe_args(fun, args[1:])) or [] except: if cfg.get("pdb", False): import pdb pdb.set_trace() return else: raise el.sc_hookfn = old_sc_hookfn if "-l" in flags: sys.stdout = sys.__stdout__ print("\n".join([cmd[2:] for cmd in log.cmds] + ret_cmds)) else: if len(log.cmds) < 10: spec = inspect.getfullargspec(fun) if ("log" in spec.args) and spec.defaults and spec.defaults[ spec.args.index("log") - 1] is None: pass else: print("\n".join(log.cmds)) if ret_cmds: el.bash(ret_cmds, echo=True)
def apt_add_repository(url, categories, gpg_key=None): if gpg_key is None: distro = scb("lsb_release -cs") line = f"deb {url} {distro} {categories}" cmd = f"sudo apt-add-repository '{line}'" else: gpg_key_url = repo_url + gpg_key gpg_key_file = "/usr/share/keyrings/" + gpg_key make(gpg_key_file, f"wget -O $1 {gpg_key_url}") line = f"deb [signed-by={gpg_key_file}] {repo_url} {categories}" cmd = f"echo 'line' | sudo tee {fname}" fname = "/etc/apt/sources.list" if line in el.slurp_lines(fname): print(fname + ": OK") else: bash(cmd)
def install_go(version="1.17.1"): existing_exe = shutil.which("go") if existing_exe: existing_version = el.re_find("go([0-9]+\\.[0-9]+\\.[0-9]+)", scb(f"{existing_exe} version")) print("Found go: ", existing_version) if existing_version == version: print("Versions match. Exit") return bash("sudo rm -rf /usr/local/go /usr/local/bin/go") tar_file = f"go{version}.linux-amd64.tar.gz" tar_file_full = el.expand_file_name(tar_file, "/tmp/") url = f"https://golang.org/dl/go{version}.linux-amd64.tar.gz" fname = wget(url, "~/Software/") make("/usr/local/go", [ "sudo rm -rf '/usr/local/go'", f"cat {fname} | sudo tar -xz -C /usr/local"]) make("/usr/local/bin/go", [ "sudo ln -sf /usr/local/go/bin/go $@"])
def ln(fr, to): fr_full = el.expand_file_name(fr) if not el.file_exists_p(fr_full): raise RuntimeError("File doesn't exist", fr_full) to_full = el.expand_file_name(to) if el.file_exists_p(to_full): if symlink_p(to_full): print(lf("{to_full}: OK")) else: if file_equal(fr_full, to_full): print(lf("{to_full} exists, contents equal")) else: print(lf("{to_full} exists, contents NOT equal")) else: if el.HOST: cmd = lf("ln -s {fr} {to}") else: fr_abbr = os.path.relpath(fr_full, os.path.dirname(to)) cmd = sudo(lf("ln -s {fr_abbr} {to_full}"), to_full) bash(cmd)
def make(target, cmds, deps=()): if (el.file_exists_p(target) and \ all([get_change_time(target) > get_change_time(dep) for dep in deps])): print(lf("{target}: OK")) return False else: if isinstance(cmds, str): cmds = [cmds] elif callable(cmds): cmds(target) return True fcmds = [] for cmd in cmds: cmd1 = re.sub("\\$@", target, cmd) cmd2 = re.sub("\\$\\^", " ".join([shlex.quote(dep) for dep in deps]), cmd1) cmd3 = re.sub("\\$<", shlex.quote(deps[0]), cmd2) if deps else cmd2 if el.sc_hookfn: el.sc_hookfn(cmd3) fcmds.append(cmd3) bash(fcmds) return True
def barf(fname, text): if el.file_exists_p(fname) and text == el.slurp(fname): print(lf("{fname}: OK")) else: quoted_text = shlex.quote(text) bash(lf("echo {quoted_text} | sudo tee {fname} > /dev/null"))
def apt_key_add(email, url): if grep("apt-key list", email): print(email + " key: OK") else: install_package("gnupg2") bash(lf("wget -qO - {url} | sudo apt-key add -"))
def update(recipe): cook_el = el.emacs_cook_script("cook.el") user_p = " --user " if "/.local/" in cook_el else " " el.bash(el.lf("pip3 install{user_p}--upgrade pycook")) if "INSIDE_EMACS" in os.environ: el.sc(el.emacsclient_eval(el.lf('(load-file "{cook_el}")')))
def debconf_select(package, var, v_type, v_val): bash( lf("echo '{package} {var} {v_type} {v_val}' | debconf-set-selections"))
def apt_key_add(email, url): if grep("apt-key list", email): print(email + " key: OK") else: bash(lf("wget -qO - {url} | apt-key add -"))