diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 3dbcdc8..0000000 --- a/.dockerignore +++ /dev/null @@ -1,10 +0,0 @@ -AMP_CLI.egg-info/ -amp_cli.py -docker/ -.dockerignore -.git/ -.github/ -.gitignore -__pycache__/ -README.md -setup.py diff --git a/.gitignore b/.gitignore index ccb8184..f5fd977 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,10 @@ +# ROS build directories build/ devel/ + +# AMP-CLI files __pycache__/ AMP_CLI.egg-info/ + +# Catkin ignore files CATKIN_IGNORE diff --git a/README.md b/README.md index 8167d59..3b2ce48 100644 --- a/README.md +++ b/README.md @@ -19,17 +19,8 @@ slam\_mode\_goal is intended to put out high-level, ideal cart commands that are Takes MoveBaseGoal and converts them to cmd_vel to the simulated kart # Running -* Show available options help +* To build the amp-cli tool, run: ``` -. amd64-docker.sh 0 -``` - -To build the docker image, have a second argument behind the number. -* Run intel graphics docker -``` -. amd64-docker.sh 1 -``` -* Run nvidia graphics docker -``` -. amd64-docker.sh 2 +pip install . ``` +* Run `amp-cli` to view the available options. diff --git a/amp_cli.py b/amp_cli.py index d25c589..15eaf7f 100644 --- a/amp_cli.py +++ b/amp_cli.py @@ -10,67 +10,60 @@ def cli(): """This is the official AMP Software Sub-Team CLI Tool that helps you develop on AMP_ASSv2 using docker containers in your current environment. - In order to run it, you must be in the root directory of the AMP_ASSv2 repo - in order for docker files to build properly. + In order to run some of the functions, you must be in the root directory + of the AMP_ASSv2 repo. If there are any features you would like to see, + or bugs that need to be fixed, feel free to open an issue or PR! """ pass @cli.command() -@click.option('-b', '--build', is_flag=True) +@click.option('-b', '--build', is_flag=True, + help='Build the frame container, if not up-to-date.') @click.option('--display', default='mesa', - type=click.Choice(['mesa', 'nvidia'], case_sensitive=False)) + type=click.Choice(['mesa', 'nvidia'], case_sensitive=False), + help='Choose display driver option.') def devel(build: bool, display: str): """Develop with current directory mounted on the container. """ - print(display) - click.echo('Successfully exited the container') - - -@cli.command() -@click.option('-b', '--build', is_flag=True, - help='Build a new container.') -@click.option('--display', default='mesa', show_default=True, - type=click.Choice(['mesa', 'nvidia'], case_sensitive=False), - help='Choose display option.') -def scratch(build: bool, display: str): - """Develop on a fully isolated container. - """ # Initialize docker client environment client = docker.from_env() cwd = os.getcwd() + tag = 'amp-devel:frame-desktop' # Make sure current directory is AMP_ASSv2 if cwd.split('/')[-1] != 'AMP_ASSv2': raise click.ClickException(click.style( - 'AMP CLI only works inside root directory of the AMP_ASSv2 local repository', fg='red')) - - tag = f'amp-ass:{display}' - dockerfile = cwd + f'/docker/{display}.Dockerfile' + 'Devel only works when executed from the root directory of the AMP_ASSv2 local repo.', fg='red')) - # Build container if build: click.echo('Building containers...') - click.echo('Step 1/2: Building amp-base:default') + + click.echo('Step 1/2: Building amp-devel:noetic-desktop.') try: _ = client.images.build( - path=cwd, tag='amp-base:default', - dockerfile=(cwd+'/docker/base.Dockerfile')) + path=cwd, tag='amp-devel:noetic-desktop', + dockerfile=(cwd+'/docker/desktop.Dockerfile')) click.secho( - f' ---> Finished building amp-base:default', fg='yellow') + ' ---> Finished building amp-devel:noetic-desktop.', fg='yellow') except Exception as exception: - raise click.ClickException(exception) + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError: {exception}') - click.echo(f'Step 2/2: Building {tag}') + click.echo(f'Step 2/2: Building {tag}.') try: _ = client.images.build( - path=cwd, tag=tag, dockerfile=dockerfile) - click.secho(f' ---> Finished building {tag}', fg='yellow') + path=cwd, tag=tag, + dockerfile=(cwd+'/docker/frame.Dockerfile')) + click.secho( + f' ---> Finished building {tag}.', fg='yellow') except Exception as exception: - raise click.ClickException(exception) + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError: {exception}') try: # Run the contianer + click.echo(f'Running {tag}...') if display == 'mesa': container = client.containers.run( tag, stdin_open=True, tty=True, auto_remove=True, @@ -84,15 +77,96 @@ def scratch(build: bool, display: str): volumes={ '/tmp/.X11-unix': { 'bind': '/tmp/.X11-unix', - 'mode': 'rw' - } + 'mode': 'rw', + }, + cwd: { + 'bind': '/amp_ws', + 'mode': 'rw', + }, }, privileged=True, detach=True) + # TODO: NVidia settings else: + raise click.ClickException('NVidia config WIP') + # Attach to the container + click.echo('Use [ + D] to stop and exit the container.') + click.secho( + f'Entering container {container.name}:{container.short_id}.', fg='blue') + subprocess.run(['bash', '-c', f'docker attach {container.id}']) + click.secho('Successfully exited and stopped container.', fg='green') + except docker.errors.ImageNotFound: + raise click.ClickException( + f'Unable to find {tag}, maybe try running with "--build" flag?') + except Exception as exception: + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError {exception}') + + +@cli.command() +@click.option('-b', '--build', is_flag=True, + help='Build the corresponding containers.') +@click.option('--display', default='mesa', show_default=True, + type=click.Choice(['mesa', 'nvidia'], case_sensitive=False), + help='Choose display driver option.') +def scratch(build: bool, display: str): + """Develop on a fully isolated container. + """ + # Initialize docker client environment + client = docker.from_env() + cwd = os.getcwd() + + tag = f'amp-devel:{display}-build' + dockerfile = cwd + f'/docker/{display}.Dockerfile' + + # Build container + if build: + # Make sure current directory is AMP_ASSv2 + if cwd.split('/')[-1] != 'AMP_ASSv2': + raise click.ClickException(click.style( + 'Build only works inside root directory of the AMP_ASSv2 local repository.', fg='red')) + + click.echo('Building containers...') + + click.echo('Step 1/3: Building amp-devel:noetic-desktop.') + try: + _ = client.images.build( + path=cwd, tag='amp-devel:noetic-desktop', + dockerfile=(cwd+'/docker/desktop.Dockerfile')) + click.secho( + ' ---> Finished building amp-devel:noetic-desktop.', fg='yellow') + except Exception as exception: + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError {exception}') + + click.echo('Step 2/3: Building amp-devel:frame-desktop.') + try: + _ = client.images.build( + path=cwd, tag='amp-devel:frame-desktop', + dockerfile=(cwd+'/docker/frame.Dockerfile')) + click.secho( + ' ---> Finished building amp-devel:frame-desktop.', fg='yellow') + except Exception as exception: + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError {exception}') + + click.echo(f'Step 3/3: Building {tag}.') + try: + _ = client.images.build( + path=cwd, tag=tag, dockerfile=dockerfile) + click.secho(f' ---> Finished building {tag}.', fg='yellow') + except Exception as exception: + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError {exception}') + + try: + # Run the contianer + click.echo(f'Running {tag}...') + if display == 'mesa': container = client.containers.run( tag, stdin_open=True, tty=True, auto_remove=True, network_mode='host', + name='amp-assv2-scratch', environment={ 'DISPLAY': os.getenv('DISPLAY'), 'QT_X11_NO_MITSHM': 1, @@ -101,16 +175,24 @@ def scratch(build: bool, display: str): volumes={ '/tmp/.X11-unix': { 'bind': '/tmp/.X11-unix', - 'mode': 'rw' - } + 'mode': 'rw', + }, }, privileged=True, detach=True) + # TODO: NVidia settings + else: + raise click.ClickException('NVidia config WIP') + # Attach to the container + click.echo('Use [ + D] to stop and exit the container.') click.secho( - f'Entering container {container.name}:{container.short_id}', fg='blue') + f'Entering container {container.name}:{container.short_id}.', fg='blue') + subprocess.run(['bash', '-c', f'docker attach {container.id}']) + click.secho('Successfully exited and stopped container.', fg='green') - # Attach to the container - subprocess.run(['docker', 'attach', container.id]) - click.secho('Successfully exited and stopped container', fg='green') + except docker.errors.ImageNotFound: + raise click.ClickException( + f'Unable to find {tag}, maybe try running with "--build" flag?') except Exception as exception: - raise click.ClickException(exception) + raise click.ClickException( + f'Ran into an error, look at the help menu.\nError {exception}') diff --git a/docker/base.Dockerfile b/docker/base.Dockerfile deleted file mode 100644 index 450ecb8..0000000 --- a/docker/base.Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM ros:noetic-ros-base -SHELL ["/bin/bash", "-c"] -WORKDIR /amp_ws - -RUN \ - apt update && \ - apt install -y \ - tmux \ - curl \ - wget \ - vim \ - libgl1-mesa-glx \ - libgl1-mesa-dri \ - mesa-utils \ - unzip \ - && apt upgrade -y && \ - rm -rf /var/lib/apt/list/* diff --git a/docker/desktop.Dockerfile b/docker/desktop.Dockerfile new file mode 100644 index 0000000..312f2b6 --- /dev/null +++ b/docker/desktop.Dockerfile @@ -0,0 +1,5 @@ +FROM ros:noetic-ros-base + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ros-noetic-desktop \ + && rm -rf /var/lib/apt/lists/* diff --git a/docker/frame.Dockerfile b/docker/frame.Dockerfile new file mode 100644 index 0000000..6296a32 --- /dev/null +++ b/docker/frame.Dockerfile @@ -0,0 +1,18 @@ +FROM amp-devel:noetic-desktop +SHELL ["/bin/bash", "-c"] +WORKDIR /amp_ws + +RUN apt-get update && apt-get install -q -y --no-install-recommends \ + tmux \ + curl \ + wget \ + vim \ + libgl1-mesa-glx \ + libgl1-mesa-dri \ + mesa-utils \ + unzip \ + && rm -rf /var/lib/apt/list/* \ + && rosdep update + +ENTRYPOINT ["/ros_entrypoint.sh"] +CMD ["bash"] diff --git a/docker/mesa.Dockerfile b/docker/mesa.Dockerfile index 06a8238..451ff51 100644 --- a/docker/mesa.Dockerfile +++ b/docker/mesa.Dockerfile @@ -1,9 +1,14 @@ -FROM amp-base:default +FROM amp-devel:frame-desktop SHELL ["/bin/bash", "-c"] WORKDIR /amp_ws -COPY . . +COPY src ./src +COPY .catkin_workspace . + RUN . /opt/ros/noetic/setup.bash && \ rosdep install --from-paths src -r -y && \ - catkin_make && echo "source /amp_ws/devel/setup.bash" >> ~/.bashrc + catkin_make +RUN echo "source /amp_ws/devel/setup.bash" >> ~/.bashrc +ENTRYPOINT ["/ros_entrypoint.sh"] +CMD ["bash"] diff --git a/setup.py b/setup.py index 8a89651..b9a4cb5 100644 --- a/setup.py +++ b/setup.py @@ -7,8 +7,6 @@ install_requires=[ 'click', 'docker', - 'os', - 'subprocess', ], entry_points={ 'console_scripts': [