#!/usr/bin/python
# -*- coding: utf8 -*-

description = """
Раксладыватель файлов; "массовый install(1)"
Создает каталоги, копирует файлы, устанавливает владельцев и права; 
все в соответствии с конфигом-манифестом.

direct-place-secrets -d /path/to/exported/secrets -m /path/to/manifest.json

Образец манифеста: direct-place-secrets -e
"""

TODO = """
 - (?) уметь делать симлинки вместо cp
 - режим "удалить все файлы, перечисленные в манифесте"
 - образец манифеста
"""

manifest_example = """{
    "dirs": [
        {
            "dst": "/etc/my_tokens_1"
        },
        {
            "owner": "games",
            "group": "www-data",
            "dst": "/etc/my_tokens_1"
        }
    ],
    "files": [
        {
            "mode": "0400",
            "owner": "daemon",
            "group": "www-data",
            "src": "dir-1/token-2",
            "dst": "/etc/my_tokens_1/token-2"
        },
        {
            "group": "www-data",
            "src": "<относительный путь в исходном каталоге; если он получен direct-vault export-ом -- путь из meta.json>",
            "dst": "/tmp/my_tokens/token-1"
        }
    ]
}
"""

import os
import re
import sys
import json

import argparse
import subprocess

#######
# Вспомогательные ф-ции
def die(message=''):
    sys.stderr.write("%s\n" % message)
    exit(1)

def my_system(cmd, verbose=False):
    if verbose:
        print("going to exec: %s\n" % cmd)
    exit_code = subprocess.call(cmd)
    if exit_code != 0:
        die("cmd failed, stop (%s)" % cmd)
    return
#######

def parse_options():
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("-h", "--help", dest="help", help="справка", action="store_true")
    parser.add_argument("-e", "--example", dest="example", help="пример/образец манифеста", action="store_true")
    parser.add_argument("-d", dest="dir", help="каталог с секретными файлами", type=str)
    parser.add_argument("-m", "--manifest", dest="manifest", help="конфиг 'что-куда'", type=str)
    opts, extra = parser.parse_known_args()

    if opts.help:
        print description
        print parser.format_help()
        exit(0)

    if opts.example:
        print manifest_example,
        exit(0)

    if not opts.dir:
        die("-d <source directory> required")
    if not opts.manifest:
        die("-m <manifest file> required")

    return opts


def run():
    opts = parse_options()

    manifest_json = open(opts.manifest).read()
    manifest = json.loads(manifest_json)

    to_install = []
    for d in manifest['dirs']:
        d['type'] = "dir"
        to_install += [ d ]

    for f in manifest['files']:
        f['type'] = "file"
        to_install += [ f ]

    for f in to_install:
        if f['type'] == 'dir':
            to_run = ['install', '-d', f['dst']]
        elif f['type'] == 'file':
            src_path = "%s/%s" % (opts.dir, f['src'])
            to_run = ['install', '-T', src_path, f['dst']]
        else:
            die()
        if 'mode' in f:
            to_run += ['-m', f['mode']]
        if 'owner' in f:
            to_run += ['-o', f['owner']]
        if 'group' in f:
            to_run += ['-g', f['group']]
        my_system(to_run)

    exit(0)


if __name__ == '__main__':
    run();
