#!/usr/bin/env python

import sys
from optparse import OptionParser

import microsecrets

def main():

    usage = """%prog [options] COMMAND...

Provide environment variables and files from S3 to COMMAND.

The JSON environment file should contain a dictionary with this key:
    'environment': a dictionary of environment variable & value pairs

Example JSON:
    {
      'environment': {
        'EDITOR': 'vim',
        'dbpassword': 'hunter2'
      }
    }

Example usage:

    Download environment for `testservice' from `mybucket', run /bin/myserver
    $ %prog -b mybucket -s testservice -c e3b0c44298fc1c1... -- /bin/myserver

    Display computed environment by running env(1)
    $ %prog -b mybucket -s testservice --whitelist-all -- /usr/bin/env

""".rstrip()

    parser = OptionParser(usage=usage,
                          version='microsecrets ' + microsecrets.VERSION)

    parser.add_option('-v', '--verbose', action='store_true',
                      help='Enable verbose log messages')

    parser.add_option('-r', '--region', dest='region', default='us-east-1',
                      help='Connect to REGION in S3')

    parser.add_option('-b', '--bucket', dest='bucket',
                      help='Connect to BUCKET in S3')

    parser.add_option('-s', '--service', dest='service',
                      help='Name of the service (determines S3 path)')

    parser.add_option('-c', '--checksum', dest='checksum', metavar='HASH',
                      help=('Checksum (SHA1/SHA256) of JSON environment file '
                            'to verify. Implies --whitelist-all.'))

    parser.add_option('-w', '--whitelist', dest='env_whitelist',
                      metavar='VARS', action='append',
                      help=('Whitespace separated list of allowed env '
                            'variables (may be passed multiple times)'))

    parser.add_option('-a', '--whitelist-all', dest='env_whitelist_all',
                      action='store_true',
                      help='Allow all environment variables to be set')

    parser.add_option('-i', '--ignore-extra', action='store_true',
                      help=("Quietly skip non-whitelisted env variables "
                            "(default is to abort and exit)"))

    parser.add_option('-f', '--file', dest='files', action='append',
                      metavar='NAME:PATH[:HASH]',
                      help=('Download S3 file with NAME to destination PATH, '
                            'verify with HASH (may be passed multiple times)'))

    opts, args = parser.parse_args()

    if opts.verbose:
        microsecrets.set_log_verbose_mode()

    command = args

    if not command:
        parser.print_help()
        sys.stderr.write('error: must provide COMMAND\n')
        return 1

    if not opts.bucket:
        parser.print_help()
        sys.stderr.write('error: must provide -b / --bucket for S3 bucket\n')
        return 1

    if opts.env_whitelist and opts.env_whitelist_all:
        parser.error('--whitelist and --whitelist-all are mutually exclusive')

    if opts.checksum and not opts.env_whitelist:
        opts.env_whitelist_all = True

    if not opts.env_whitelist and not opts.env_whitelist_all:
        parser.print_help()
        sys.stderr.write('\nerror: must pass one of --checksum, --whitelist, '
                         '--whitelist-all\n')
        return 1

    if opts.env_whitelist:
        env_whitelist = set()
        for string in opts.env_whitelist:
            for key in string.split():
                env_whitelist.add(key)
    else:
        env_whitelist = None

    if opts.files:
        raise NotImplementedError('No --file support yet, sorry')

    m = microsecrets.Microsecrets(region_name=opts.region,
                                  bucket_name=opts.bucket,
                                  service_name=opts.service)

    m.exec_with_s3_env(command=command, checksum=opts.checksum,
                       env_whitelist=env_whitelist,
                       env_whitelist_all=opts.env_whitelist_all,
                       ignore_extra=opts.ignore_extra)

    # not reached
    return 5

if __name__ == '__main__':
    sys.exit(main())
