Skip to content

Instantly share code, notes, and snippets.

@maxfischer2781
Last active June 23, 2020 11:56
Show Gist options
  • Save maxfischer2781/d806f17f66add5725d62602e773e6dda to your computer and use it in GitHub Desktop.
Save maxfischer2781/d806f17f66add5725d62602e773e6dda to your computer and use it in GitHub Desktop.
Create a gridmapdir from a groupmap file and accounts
#!/usr/bin/env python3
from typing import NamedTuple, Iterable, Dict, List
import argparse
import pathlib
import re
CLI = argparse.ArgumentParser()
CLI.add_argument(
"--gridmapfile",
help="path to gridmapfile",
default="/etc/grid-security/grid-mapfile",
type=pathlib.Path,
)
CLI.add_argument(
"--gridmapdir",
help="path to gridmapdir",
default="/etc/grid-security/gridmapdir/",
type=pathlib.Path,
)
CLI.add_argument(
"-n",
"--no-op",
help="only report actions, do not perform them",
action="store_true",
)
class Group(NamedTuple):
pattern: str
pool_name: str
def get_groups(gridmapfile: pathlib.Path) -> Iterable[Group]:
with gridmapfile.open() as groupmap:
for line in map(str.strip, groupmap):
if not line:
continue
pattern, basename = line.rsplit(None, 1)
if basename[0] == '.':
yield Group(pattern=pattern, pool_name=basename[1:])
def get_accounts() -> Dict[str, List[str]]:
pool_pattern = re.compile(r"^(\w+?)(\d+)$")
pools: Dict[str, List[str]] = {}
with open("/etc/passwd") as passwd:
for line in map(str.strip, passwd):
if not line:
continue
name, *_ = line.split(":", 1)
try:
pool_name, number = pool_pattern.match(name).groups()
except AttributeError:
continue
else:
pools.setdefault(pool_name, []).append(name)
return {pool_name: sorted(names) for pool_name, names in pools.items()}
def create_accountmap(path: pathlib.Path):
try:
path.touch(exist_ok=False)
except FileExistsError:
return False
else:
return True
def create_accountmap_noop(path: pathlib.Path):
return not path.exists()
def ensure_gridmap(gridmapfile: pathlib.Path, gridmapdir: pathlib.Path, no_op=True):
groups = {group.pool_name for group in get_groups(gridmapfile)}
accounts = get_accounts()
ensure_account = create_accountmap_noop if no_op else create_accountmap
for group in groups:
created = existed = 0
total = len(accounts.get(group, []))
print("Ensuring", group, f"[{total}]")
for account in accounts.get(group, []):
path = gridmapdir / account
if ensure_account(path):
print("++ create:", path)
created += 1
else:
print("== exists:", path, end="\r")
existed += 1
print(f"=============================== [{created} / {total}] ====")
def main():
options = CLI.parse_args()
ensure_gridmap(
gridmapfile=options.gridmapfile,
gridmapdir=options.gridmapdir,
no_op=options.no_op,
)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment