#
# Copyright 2019 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import os
import sys
import subprocess
import pathlib
import dev_contain.common as common

def start(in_args):
    parser = argparse.ArgumentParser(prog=sys.argv[0]+' start', description='Start a provided container.')
    parser.add_argument('--image', '-i', help='Name of image to launch.')
    parser.add_argument('--container', '-c', help='Name of the new container.')
    parser.add_argument('--volume', '-v', action='append', help='Volume on local machine to mount at same location in container.')
    parser.add_argument('--workdir', '-d', help='Directory to start in.')
    parser.add_argument('--user', '-u', help='Username to login into container as.')
    parser.add_argument('--graphics', '-X', action='store_true', help='Forward graphics.')
    parser.add_argument('--no-ssh', '-S', action='store_true', help='Do not forward ssh keys.')
    parser.add_argument('--args', '-a', help='Extra args to provide to the runtime. i.e. --args="--gpu"')
    args = parser.parse_args(in_args)

    manager = common.get_manager()

    username = args.user
    if not args.user:
        username = os.environ['USER']

    image = args.image
    if not args.image:
        image = 'jwp-build-latest'

    volumes = args.volume
    if not args.volume:
        volumes = ['/home/{}/Develop'.format(username)]

    container = args.container
    if not args.container:
        container = 'dev'

    workdir = args.workdir
    if not workdir:
        workdir = '/home/{}'.format(username)

    graphics_text = ''
    if args.graphics:
        graphics_text = set_up_graphics_forwards()

    args_text = ''
    if args.args:
        args_text = args.args

    # podman needs userns set to keep-id for volumes to work.
    userns_text = ''
    if manager == 'podman':
        userns_text = '--userns=keep-id'

    # Include volume for ssh keys.
    ssh_text = ''
    if not args.no_ssh:
        if 'SSH_AUTH_SOCK' in os.environ.keys():
            ssh_text = ('-v {ssh_auth_sock}:/.ssh_auth_sock '
                        '-e SSH_AUTH_SOCK=/.ssh_auth_sock').format(
                            ssh_auth_sock=os.environ['SSH_AUTH_SOCK'])
        else:
            print('SSH_AUTH_SOCK does not exist not adding ssh keys.')

    volume_text = ''
    for volume in volumes:
        new_text = parse_volume(volume)
        volume_text = volume_text + new_text

    command = ('{manager} run -d'
               ' --user {username}'
               ' --name {container}'
               ' {userns_text}'
               ' --workdir {workdir}'
               ' --ipc=host'
               ' --net=host'
               ' -e DEV_CONTAIN_CONTAINER_NAME={container}'
               ' {volume_text}'
               ' {ssh_text} {graphics_text} {args_text}'
               ' {image}').format(
                       manager=manager,
                       username=username,
                       image=image,
                       volume_text=volume_text,
                       ssh_text=ssh_text,
                       graphics_text=graphics_text,
                       args_text=args_text,
                       container=container,
                       workdir=workdir,
                       userns_text=userns_text)
    print('Running: {}'.format(command))
    subprocess.run(command, shell=True)

def parse_volume(volume):
    if not ':' in volume:
        volume = str(pathlib.Path(volume).expanduser().resolve())
        if os.path.exists(volume):
            return ' --volume {volume}:{volume}:Z'.format(volume=volume)
        else:
            print('Requested volume ({}) not present on host. Exiting.'.format(volume),
                  file=sys.stderr)
            sys.exit(1)
    else:
        volume = volume.split(':')
        volume[0] = str(pathlib.Path(volume[0]).expanduser().resolve())
         # Note the second path may not resolve on the host.
        volume[1] = str(pathlib.Path(volume[1]).expanduser())
        if os.path.exists(volume[0]):
            return ' --volume {volume0}:{volume1}:Z'.format(volume0=volume[0], volume1=volume[1])
        else:
            print('Requested volume ({}) not present on host. Exiting.'.format(volume[0]),
                  file=sys.stderr)
            sys.exit(1)

def set_up_graphics_forwards():
    # XOrg
    xorg = ''
    if os.path.exists('/tmp/.X11-unix'):
        xorg = (' -e DISPLAY=$DISPLAY'
                ' -v /tmp/.X11-unix:/tmp/.X11-unix:rw')
    # Wayland
    wayland = ''
    if os.environ.get('WAYLAND_DISPLAY'):
        wayland = (' -e XDG_RUNTIME_DIR=/tmp'
                   ' -e WAYLAND_DISPLAY=$WAYLAND_DISPLAY'
                   ' -v $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/tmp/$WAYLAND_DISPLAY')
    # (User) dbus socket.
    dbus = ''
    # What kind of socket is it?
    dbus_address = os.environ.get('DBUS_SESSION_BUS_ADDRESS')
    # If a real path, need to mount it. Otherwise --net=host takes care of it.
    if 'unix:path' in dbus_address:
        dbus_path = dbus_address.split('=')[1]
        dbus = dbus + '--volume {path}:{path}'.format(path=dbus_path)
    # Regardless need to know where to look.
    dbus = dbus + ' --env DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS"'

    return xorg + ' ' + wayland + ' ' + dbus


if __name__ == '__main__':
    start(sys.argv[1:])

#
# Copyright 2019 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import os
import sys
import subprocess
import pathlib
import dev_contain.common as common

def start(in_args):
    parser = argparse.ArgumentParser(prog=sys.argv[0]+' start', description='Start a provided container.')
    parser.add_argument('--image', '-i', help='Name of image to launch.')
    parser.add_argument('--container', '-c', help='Name of the new container.')
    parser.add_argument('--volume', '-v', action='append', help='Volume on local machine to mount at same location in container.')
    parser.add_argument('--workdir', '-d', help='Directory to start in.')
    parser.add_argument('--user', '-u', help='Username to login into container as.')
    parser.add_argument('--graphics', '-X', action='store_true', help='Forward graphics.')
    parser.add_argument('--no-ssh', '-S', action='store_true', help='Do not forward ssh keys.')
    parser.add_argument('--args', '-a', help='Extra args to provide to the runtime. i.e. --args="--gpu"')
    args = parser.parse_args(in_args)

    manager = common.get_manager()

    username = args.user
    if not args.user:
        username = os.environ['USER']

    image = args.image
    if not args.image:
        image = 'jwp-build-latest'

    volumes = args.volume
    if not args.volume:
        volumes = ['/home/{}/Develop'.format(username)]

    container = args.container
    if not args.container:
        container = 'dev'

    workdir = args.workdir
    if not workdir:
        workdir = '/home/{}'.format(username)

    graphics_text = ''
    if args.graphics:
        graphics_text = set_up_graphics_forwards()

    args_text = ''
    if args.args:
        args_text = args.args

    # podman needs userns set to keep-id for volumes to work.
    userns_text = ''
    if manager == 'podman':
        userns_text = '--userns=keep-id'

    # Include volume for ssh keys.
    ssh_text = ''
    if not args.no_ssh:
        if 'SSH_AUTH_SOCK' in os.environ.keys():
            ssh_text = ('-v {ssh_auth_sock}:/.ssh_auth_sock '
                        '-e SSH_AUTH_SOCK=/.ssh_auth_sock').format(
                            ssh_auth_sock=os.environ['SSH_AUTH_SOCK'])
        else:
            print('SSH_AUTH_SOCK does not exist not adding ssh keys.')

    volume_text = ''
    for volume in volumes:
        new_text = parse_volume(volume)
        volume_text = volume_text + new_text

    command = ('{manager} run -d'
               ' --user {username}'
               ' --name {container}'
               ' {userns_text}'
               ' --workdir {workdir}'
               ' --ipc=host'
               ' --net=host'
               ' -e DEV_CONTAIN_CONTAINER_NAME={container}'
               ' {volume_text}'
               ' {ssh_text} {graphics_text} {args_text}'
               ' {image}').format(
                       manager=manager,
                       username=username,
                       image=image,
                       volume_text=volume_text,
                       ssh_text=ssh_text,
                       graphics_text=graphics_text,
                       args_text=args_text,
                       container=container,
                       workdir=workdir,
                       userns_text=userns_text)
    print('Running: {}'.format(command))
    subprocess.run(command, shell=True)

def parse_volume(volume):
    if not ':' in volume:
        volume = str(pathlib.Path(volume).expanduser().resolve())
        if os.path.exists(volume):
            return ' --volume {volume}:{volume}:Z'.format(volume=volume)
        else:
            print('Requested volume ({}) not present on host. Exiting.'.format(volume),
                  file=sys.stderr)
            sys.exit(1)
    else:
        volume = volume.split(':')
        volume[0] = str(pathlib.Path(volume[0]).expanduser().resolve())
         # Note the second path may not resolve on the host.
        volume[1] = str(pathlib.Path(volume[1]).expanduser())
        if os.path.exists(volume[0]):
            return ' --volume {volume0}:{volume1}:Z'.format(volume0=volume[0], volume1=volume[1])
        else:
            print('Requested volume ({}) not present on host. Exiting.'.format(volume[0]),
                  file=sys.stderr)
            sys.exit(1)

def set_up_graphics_forwards():
    # XOrg
    xorg = ''
    if os.path.exists('/tmp/.X11-unix'):
        xorg = (' -e DISPLAY=$DISPLAY'
                ' -v /tmp/.X11-unix:/tmp/.X11-unix:rw')
    # Wayland
    wayland = ''
    if os.environ.get('WAYLAND_DISPLAY'):
        wayland = (' -e XDG_RUNTIME_DIR=/tmp'
                   ' -e WAYLAND_DISPLAY=$WAYLAND_DISPLAY'
                   ' -v $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY:/tmp/$WAYLAND_DISPLAY')
    # (User) dbus socket.
    dbus = ''
    # What kind of socket is it?
    dbus_address = os.environ.get('DBUS_SESSION_BUS_ADDRESS')
    # If a real path, need to mount it. Otherwise --net=host takes care of it.
    if 'unix:path' in dbus_address:
        dbus_path = dbus_address.split('=')[1]
        dbus = dbus + '--volume {path}:{path}'.format(path=dbus_path)
    # Regardless need to know where to look.
    dbus = dbus + ' --env DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS"'

    return xorg + ' ' + wayland + ' ' + dbus


if __name__ == '__main__':
    start(sys.argv[1:])

# # Copyright 2019 <NAME> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # #    http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # podman needs userns set to keep-id for volumes to work. # Include volume for ssh keys. # Note the second path may not resolve on the host. # XOrg # Wayland # (User) dbus socket. # What kind of socket is it? # If a real path, need to mount it. Otherwise --net=host takes care of it. # Regardless need to know where to look.