lookout-cli 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lookout_cli-1.0.0/PKG-INFO +43 -0
- lookout_cli-1.0.0/README.md +18 -0
- lookout_cli-1.0.0/lookout_cli/__init__.py +0 -0
- lookout_cli-1.0.0/lookout_cli/banner.py +16 -0
- lookout_cli-1.0.0/lookout_cli/cli.py +40 -0
- lookout_cli-1.0.0/lookout_cli/docker/docker-compose.dev.yaml +76 -0
- lookout_cli-1.0.0/lookout_cli/docker/docker-compose.gpu.yaml +15 -0
- lookout_cli-1.0.0/lookout_cli/docker/docker-compose.network-host.yaml +18 -0
- lookout_cli-1.0.0/lookout_cli/docker/docker-compose.network-shared.yaml +33 -0
- lookout_cli-1.0.0/lookout_cli/docker/docker-compose.yaml +37 -0
- lookout_cli-1.0.0/lookout_cli/groups/__init__.py +0 -0
- lookout_cli-1.0.0/lookout_cli/groups/misc.py +267 -0
- lookout_cli-1.0.0/lookout_cli/groups/setup.py +32 -0
- lookout_cli-1.0.0/lookout_cli/helpers.py +117 -0
- lookout_cli-1.0.0/lookout_cli/test/lookout_cli_test.py +3 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/PKG-INFO +43 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/SOURCES.txt +23 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/dependency_links.txt +1 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/entry_points.txt +2 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/requires.txt +7 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/top_level.txt +1 -0
- lookout_cli-1.0.0/lookout_cli.egg-info/zip-safe +1 -0
- lookout_cli-1.0.0/setup.cfg +48 -0
- lookout_cli-1.0.0/setup.py +3 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: lookout_cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A CLI for interacting with Lookout+
|
|
5
|
+
Home-page: https://github.com/Greenroom-Robotics/lookout
|
|
6
|
+
Author: Greenroom Robotics
|
|
7
|
+
Author-email: team@greenroomrobotics.com
|
|
8
|
+
Maintainer: David Revay
|
|
9
|
+
Maintainer-email: david.revay@greenroomrobotics.com
|
|
10
|
+
License: Copyright (C) 2023, Greenroom Robotics
|
|
11
|
+
Keywords: colcon
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Plugins
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: toml~=0.10
|
|
19
|
+
Requires-Dist: setuptools
|
|
20
|
+
Requires-Dist: colorama
|
|
21
|
+
Requires-Dist: click
|
|
22
|
+
Requires-Dist: lookout-config
|
|
23
|
+
Requires-Dist: python-on-whales
|
|
24
|
+
Requires-Dist: PyYAML
|
|
25
|
+
|
|
26
|
+
# Lookout CLI
|
|
27
|
+
|
|
28
|
+
Publicly available on [PyPi](https://pypi.org/project/lookout-cli/) for convenience but if you don't work at Greenroom Robotics, you probably don't want to use this.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
* For development:
|
|
33
|
+
* `pip install -e ./libs/lookout_config`
|
|
34
|
+
* `pip install -e ./tools/lookout_cli`
|
|
35
|
+
* For production: `pip install lookout-cli`
|
|
36
|
+
* You may also need to `export PATH=$PATH:~/.local/bin` if you don't have `~/.local/bin` in your path
|
|
37
|
+
* Install autocomplete:
|
|
38
|
+
* bash: `echo 'eval "$(_lookout_COMPLETE=bash_source lookout)"' >> ~/.bashrc`
|
|
39
|
+
* zsh: `echo 'eval "$(_lookout_COMPLETE=zsh_source lookout)"' >> ~/.zshrc` (this is much nicer)
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
* `lookout --help` to get help with the CLI
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Lookout CLI
|
|
2
|
+
|
|
3
|
+
Publicly available on [PyPi](https://pypi.org/project/lookout-cli/) for convenience but if you don't work at Greenroom Robotics, you probably don't want to use this.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
* For development:
|
|
8
|
+
* `pip install -e ./libs/lookout_config`
|
|
9
|
+
* `pip install -e ./tools/lookout_cli`
|
|
10
|
+
* For production: `pip install lookout-cli`
|
|
11
|
+
* You may also need to `export PATH=$PATH:~/.local/bin` if you don't have `~/.local/bin` in your path
|
|
12
|
+
* Install autocomplete:
|
|
13
|
+
* bash: `echo 'eval "$(_lookout_COMPLETE=bash_source lookout)"' >> ~/.bashrc`
|
|
14
|
+
* zsh: `echo 'eval "$(_lookout_COMPLETE=zsh_source lookout)"' >> ~/.zshrc` (this is much nicer)
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
* `lookout --help` to get help with the CLI
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_banner(mode: str, version: str):
|
|
5
|
+
return "\n".join(
|
|
6
|
+
[
|
|
7
|
+
"\b",
|
|
8
|
+
click.style("Lookout+ CLI", fg="black", bg="green"),
|
|
9
|
+
"\b",
|
|
10
|
+
"Mode: "
|
|
11
|
+
+ click.style(mode, fg="green")
|
|
12
|
+
+ " - Version: "
|
|
13
|
+
+ click.style(version, fg="yellow"),
|
|
14
|
+
"Powered by: " + click.style("Greenroom Robotics", fg="green"),
|
|
15
|
+
]
|
|
16
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import lookout_cli.groups.misc as misc
|
|
2
|
+
import lookout_cli.groups.setup as setup
|
|
3
|
+
from lookout_cli.helpers import is_dev_version, get_version
|
|
4
|
+
from lookout_cli.banner import get_banner
|
|
5
|
+
import click
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def cli():
|
|
10
|
+
dev_mode = is_dev_version()
|
|
11
|
+
version = get_version()
|
|
12
|
+
mode = "Developer" if dev_mode else "User"
|
|
13
|
+
banner = get_banner(mode, version)
|
|
14
|
+
|
|
15
|
+
os.environ["LOOKOUT_CLI_DEV_MODE"] = "true" if dev_mode else "false"
|
|
16
|
+
|
|
17
|
+
@click.group(help=banner)
|
|
18
|
+
def lookout_cli():
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
lookout_cli.add_command(misc.authenticate)
|
|
22
|
+
lookout_cli.add_command(misc.upgrade)
|
|
23
|
+
lookout_cli.add_command(misc.build)
|
|
24
|
+
lookout_cli.add_command(misc.down)
|
|
25
|
+
lookout_cli.add_command(misc.up)
|
|
26
|
+
lookout_cli.add_command(misc.configure)
|
|
27
|
+
lookout_cli.add_command(misc.config)
|
|
28
|
+
|
|
29
|
+
if dev_mode:
|
|
30
|
+
lookout_cli.add_command(misc.lint)
|
|
31
|
+
lookout_cli.add_command(misc.bake)
|
|
32
|
+
lookout_cli.add_command(misc.type_generate)
|
|
33
|
+
lookout_cli.add_command(setup.setup)
|
|
34
|
+
setup.setup.add_command(setup.secrets)
|
|
35
|
+
|
|
36
|
+
lookout_cli()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
cli()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
version: "3.8"
|
|
2
|
+
name: lookout
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
lookout_core:
|
|
6
|
+
build:
|
|
7
|
+
context: ./
|
|
8
|
+
dockerfile: projects/lookout_core/Dockerfile
|
|
9
|
+
args:
|
|
10
|
+
GPU: ${GPU:-false}
|
|
11
|
+
secrets:
|
|
12
|
+
- apt_conf
|
|
13
|
+
- API_TOKEN_GITHUB
|
|
14
|
+
volumes:
|
|
15
|
+
- ./projects/lookout_core/src:/home/ros/lookout_core/src
|
|
16
|
+
- ./projects/lookout_core/data:/home/ros/lookout_core/data
|
|
17
|
+
- ./projects/lookout_core/ros-ts-generator-config.json:/home/ros/lookout_core/ros-ts-generator-config.json
|
|
18
|
+
- ./projects/lookout_ui/src/generated/ros:/home/ros/lookout_core/generated/ros
|
|
19
|
+
- ./logs/rosbags:/home/ros/rosbags
|
|
20
|
+
- ./logs/scripts:/home/ros/rosbag_scripts
|
|
21
|
+
- ./.secrets/apt.conf:/etc/apt/auth.conf.d/greenroom-robotics.conf
|
|
22
|
+
|
|
23
|
+
lookout_ui:
|
|
24
|
+
image: ghcr.io/greenroom-robotics/lookout_ui:${LOOKOUT_VERSION:-latest}
|
|
25
|
+
build:
|
|
26
|
+
context: ./projects/lookout_ui
|
|
27
|
+
secrets:
|
|
28
|
+
- API_TOKEN_GITHUB
|
|
29
|
+
args:
|
|
30
|
+
VITE_LOOKOUT_NAMESPACE_VESSEL: $LOOKOUT_NAMESPACE_VESSEL
|
|
31
|
+
environment:
|
|
32
|
+
VITE_LOOKOUT_NAMESPACE_VESSEL: $LOOKOUT_NAMESPACE_VESSEL
|
|
33
|
+
volumes:
|
|
34
|
+
- ./projects/lookout_ui/.eslintrc.js:/app/.eslintrc.js
|
|
35
|
+
- ./projects/lookout_ui/.nvmrc:/app/.nvmrc
|
|
36
|
+
- ./projects/lookout_ui/.prettierrc:/app/.prettierrc
|
|
37
|
+
- ./projects/lookout_ui/.yarnrc:/app/.yarnrc
|
|
38
|
+
- ./projects/lookout_ui/index.html:/app/index.html
|
|
39
|
+
- ./projects/lookout_ui/package.json:/app/package.json
|
|
40
|
+
- ./projects/lookout_ui/public:/app/public
|
|
41
|
+
- ./projects/lookout_ui/src:/app/src
|
|
42
|
+
- ./projects/lookout_ui/tsconfig.json:/app/tsconfig.json
|
|
43
|
+
- ./projects/lookout_ui/typings:/app/typings
|
|
44
|
+
- ./projects/lookout_ui/vite.config.ts:/app/vite.config.ts
|
|
45
|
+
command: yarn dev
|
|
46
|
+
|
|
47
|
+
lookout_greenstream:
|
|
48
|
+
build:
|
|
49
|
+
context: .
|
|
50
|
+
dockerfile: projects/lookout_greenstream/Dockerfile
|
|
51
|
+
secrets:
|
|
52
|
+
- apt_conf
|
|
53
|
+
- API_TOKEN_GITHUB
|
|
54
|
+
volumes:
|
|
55
|
+
- ./projects/lookout_greenstream:/home/greenstream
|
|
56
|
+
|
|
57
|
+
lookout_docs:
|
|
58
|
+
build:
|
|
59
|
+
context: ./
|
|
60
|
+
dockerfile: projects/lookout_docs/Dockerfile
|
|
61
|
+
volumes:
|
|
62
|
+
- ./projects/lookout_docs/src:/app/src
|
|
63
|
+
- ./projects/lookout_docs/static:/app/static
|
|
64
|
+
- ./projects/lookout_docs/package.json:/app/package.json
|
|
65
|
+
- ./projects/lookout_docs/yarn.lock:/app/yarn.lock
|
|
66
|
+
- ./projects/lookout_docs/sidebars.js:/app/sidebars.js
|
|
67
|
+
- ./projects/lookout_docs/docusaurus.config.js:/app/docusaurus.config.js
|
|
68
|
+
- ./projects/lookout_docs/tsconfig.json:/app/tsconfig.json
|
|
69
|
+
- ./docs:/app/docs
|
|
70
|
+
command: yarn start
|
|
71
|
+
|
|
72
|
+
secrets:
|
|
73
|
+
API_TOKEN_GITHUB:
|
|
74
|
+
file: ./.secrets/API_TOKEN_GITHUB
|
|
75
|
+
apt_conf:
|
|
76
|
+
file: ./.secrets/apt.conf
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
version: "3.8"
|
|
2
|
+
name: lookout
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
lookout_core:
|
|
6
|
+
ports:
|
|
7
|
+
- 4001:4001
|
|
8
|
+
networks:
|
|
9
|
+
- vessel
|
|
10
|
+
|
|
11
|
+
lookout_ui:
|
|
12
|
+
ports:
|
|
13
|
+
- "4000:4000"
|
|
14
|
+
networks:
|
|
15
|
+
- vessel
|
|
16
|
+
|
|
17
|
+
lookout_greenstream:
|
|
18
|
+
ports:
|
|
19
|
+
- 8000:8000
|
|
20
|
+
- 8443:8443
|
|
21
|
+
networks:
|
|
22
|
+
- vessel
|
|
23
|
+
|
|
24
|
+
lookout_docs:
|
|
25
|
+
ports:
|
|
26
|
+
- "4010:3000"
|
|
27
|
+
networks:
|
|
28
|
+
- vessel
|
|
29
|
+
|
|
30
|
+
networks:
|
|
31
|
+
vessel:
|
|
32
|
+
external: true
|
|
33
|
+
name: gama_vessel
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
version: "3.8"
|
|
2
|
+
name: lookout
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
lookout_core:
|
|
6
|
+
container_name: lookout_core
|
|
7
|
+
image: ghcr.io/greenroom-robotics/lookout_core:${LOOKOUT_VERSION:-latest}
|
|
8
|
+
volumes:
|
|
9
|
+
- /dev:/dev
|
|
10
|
+
- ~/.config/greenroom:/home/ros/.config/greenroom
|
|
11
|
+
command: ${LOOKOUT_CORE_COMMAND:-tail -f /dev/null}
|
|
12
|
+
privileged: true
|
|
13
|
+
ipc: host
|
|
14
|
+
pid: host
|
|
15
|
+
environment:
|
|
16
|
+
- ROS_DOMAIN_ID
|
|
17
|
+
|
|
18
|
+
lookout_ui:
|
|
19
|
+
container_name: lookout_ui
|
|
20
|
+
image: ghcr.io/greenroom-robotics/lookout_ui:${LOOKOUT_VERSION:-latest}
|
|
21
|
+
|
|
22
|
+
lookout_greenstream:
|
|
23
|
+
container_name: lookout_greenstream
|
|
24
|
+
image: ghcr.io/greenroom-robotics/lookout_greenstream
|
|
25
|
+
volumes:
|
|
26
|
+
- /dev:/dev
|
|
27
|
+
- ~/.config/greenroom:/home/ros/.config/greenroom
|
|
28
|
+
privileged: true
|
|
29
|
+
ipc: host
|
|
30
|
+
pid: host
|
|
31
|
+
environment:
|
|
32
|
+
- ROS_DOMAIN_ID
|
|
33
|
+
|
|
34
|
+
lookout_docs:
|
|
35
|
+
container_name: lookout_docs
|
|
36
|
+
image: ghcr.io/greenroom-robotics/lookout_docs:${LOOKOUT_VERSION:-latest}
|
|
37
|
+
|
|
File without changes
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from typing import List
|
|
3
|
+
from lookout_cli.helpers import (
|
|
4
|
+
docker_compose_path,
|
|
5
|
+
get_project_root,
|
|
6
|
+
docker_bake,
|
|
7
|
+
call,
|
|
8
|
+
get_version,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from python_on_whales.docker_client import DockerClient
|
|
12
|
+
from python_on_whales.utils import ValidPath
|
|
13
|
+
import lookout_config
|
|
14
|
+
from lookout_config import LookoutConfig, LogLevel, Mode, Network
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
DOCKER_GS = docker_compose_path("./docker-compose.yaml")
|
|
18
|
+
DOCKER_GS_DEV = docker_compose_path("./docker-compose.dev.yaml")
|
|
19
|
+
DOCKER_NETWORK_SHARED = docker_compose_path("./docker-compose.network-shared.yaml")
|
|
20
|
+
DOCKER_NETWORK_HOST = docker_compose_path("./docker-compose.network-host.yaml")
|
|
21
|
+
DOCKER_GPU = docker_compose_path("./docker-compose.gpu.yaml")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _get_compose_files(
|
|
25
|
+
prod: bool = False, network: Network = Network.HOST, gpu=False
|
|
26
|
+
) -> List[ValidPath]:
|
|
27
|
+
compose_files: List[ValidPath] = [DOCKER_GS]
|
|
28
|
+
|
|
29
|
+
if not prod:
|
|
30
|
+
compose_files.append(DOCKER_GS_DEV)
|
|
31
|
+
|
|
32
|
+
if network == Network.SHARED:
|
|
33
|
+
compose_files.append(DOCKER_NETWORK_SHARED)
|
|
34
|
+
|
|
35
|
+
if network == Network.HOST:
|
|
36
|
+
compose_files.append(DOCKER_NETWORK_HOST)
|
|
37
|
+
|
|
38
|
+
if gpu:
|
|
39
|
+
compose_files.append(DOCKER_GPU)
|
|
40
|
+
|
|
41
|
+
return compose_files
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def log_config(config: LookoutConfig):
|
|
45
|
+
click.echo(click.style("[+] Lookout Config:", fg="green"))
|
|
46
|
+
for attr, value in config.__dict__.items():
|
|
47
|
+
click.echo(
|
|
48
|
+
click.style(f" ⠿ {attr}: ".ljust(27), fg="white") + click.style(str(value), fg="green")
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@click.command(name="up")
|
|
53
|
+
@click.option(
|
|
54
|
+
"--build",
|
|
55
|
+
type=bool,
|
|
56
|
+
default=False,
|
|
57
|
+
is_flag=True,
|
|
58
|
+
help="Should we rebuild the docker containers? Default: False",
|
|
59
|
+
)
|
|
60
|
+
@click.argument("args", nargs=-1)
|
|
61
|
+
def up(
|
|
62
|
+
build: bool,
|
|
63
|
+
args: List[str],
|
|
64
|
+
):
|
|
65
|
+
"""Starts lookout"""
|
|
66
|
+
config = lookout_config.read()
|
|
67
|
+
log_config(config)
|
|
68
|
+
|
|
69
|
+
os.environ["ROS_DOMAIN_ID"] = str(config.ros_domain_id)
|
|
70
|
+
os.environ["LOOKOUT_NAMESPACE_VESSEL"] = config.namespace_vessel
|
|
71
|
+
os.environ[
|
|
72
|
+
"LOOKOUT_CORE_COMMAND"
|
|
73
|
+
] = "platform ros launch lookout_bringup lookout.launch.py --build --watch"
|
|
74
|
+
if not args:
|
|
75
|
+
services = ["lookout_docs", "lookout_core", "lookout_ui", "lookout_greenstream"]
|
|
76
|
+
else:
|
|
77
|
+
services = [arg for arg in args]
|
|
78
|
+
|
|
79
|
+
docker = DockerClient(
|
|
80
|
+
compose_files=_get_compose_files(False, config.network, config.gpu),
|
|
81
|
+
compose_project_directory=get_project_root(),
|
|
82
|
+
)
|
|
83
|
+
docker.compose.up(services, detach=True, build=build)
|
|
84
|
+
|
|
85
|
+
click.echo(click.style("UI started: http://localhost:4000", fg="green"))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@click.command(name="down")
|
|
89
|
+
@click.argument("args", nargs=-1)
|
|
90
|
+
def down(args: List[str]):
|
|
91
|
+
"""Stops lookout"""
|
|
92
|
+
|
|
93
|
+
docker = DockerClient(
|
|
94
|
+
compose_files=_get_compose_files(),
|
|
95
|
+
compose_project_directory=get_project_root(),
|
|
96
|
+
)
|
|
97
|
+
docker.compose.down()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@click.command(name="build")
|
|
101
|
+
@click.option(
|
|
102
|
+
"--no-cache",
|
|
103
|
+
type=bool,
|
|
104
|
+
default=False,
|
|
105
|
+
is_flag=True,
|
|
106
|
+
help="Should we rebuild without the docker cache?",
|
|
107
|
+
)
|
|
108
|
+
@click.argument("services", nargs=-1)
|
|
109
|
+
def build(no_cache: bool, services: List[str]):
|
|
110
|
+
"""Builds the Lookout docker containers"""
|
|
111
|
+
config = lookout_config.read()
|
|
112
|
+
os.environ["LOOKOUT_NAMESPACE_VESSEL"] = config.namespace_vessel
|
|
113
|
+
|
|
114
|
+
docker = DockerClient(
|
|
115
|
+
compose_files=_get_compose_files(gpu=config.gpu),
|
|
116
|
+
compose_project_directory=get_project_root(),
|
|
117
|
+
)
|
|
118
|
+
docker.compose.build(services=services, cache=not no_cache)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@click.command(name="bake")
|
|
122
|
+
@click.option(
|
|
123
|
+
"--version",
|
|
124
|
+
type=str,
|
|
125
|
+
required=True,
|
|
126
|
+
help="The version to bake. Default: latest",
|
|
127
|
+
)
|
|
128
|
+
@click.option(
|
|
129
|
+
"--push",
|
|
130
|
+
type=bool,
|
|
131
|
+
default=False,
|
|
132
|
+
is_flag=True,
|
|
133
|
+
help="Should we push the images to the registry? Default: False",
|
|
134
|
+
)
|
|
135
|
+
@click.argument("services", nargs=-1)
|
|
136
|
+
def bake(version: str, push: bool, services: List[str]): # type: ignore
|
|
137
|
+
"""Bakes the docker containers"""
|
|
138
|
+
compose_files = _get_compose_files()
|
|
139
|
+
docker_bake(
|
|
140
|
+
version=version,
|
|
141
|
+
services=services,
|
|
142
|
+
push=push,
|
|
143
|
+
compose_files=compose_files,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@click.command(name="lint")
|
|
148
|
+
def lint():
|
|
149
|
+
"""Lints all the things"""
|
|
150
|
+
call("pre-commit run --all")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@click.command(name="type-generate")
|
|
154
|
+
def type_generate(): # type: ignore
|
|
155
|
+
"""Generates typescript types for all ros messages"""
|
|
156
|
+
docker = DockerClient(
|
|
157
|
+
compose_files=_get_compose_files(),
|
|
158
|
+
compose_project_directory=get_project_root(),
|
|
159
|
+
)
|
|
160
|
+
docker.compose.run("lookout_core", ["npx", "ros-typescript-generator"])
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@click.command(name="upgrade")
|
|
164
|
+
@click.option("--version", help="The version to upgrade to.")
|
|
165
|
+
def upgrade(version: str):
|
|
166
|
+
"""Upgrade Lookout CLI"""
|
|
167
|
+
click.echo(f"Current version: {get_version()}")
|
|
168
|
+
result = click.prompt(
|
|
169
|
+
"Are you sure you want to upgrade?", default="y", type=click.Choice(["y", "n"])
|
|
170
|
+
)
|
|
171
|
+
if result == "n":
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
if version:
|
|
175
|
+
call(f"pip install --upgrade lookout-cli=={version}")
|
|
176
|
+
else:
|
|
177
|
+
call("pip install --upgrade lookout-cli")
|
|
178
|
+
|
|
179
|
+
click.echo(click.style("Upgrade of Lookout CLI complete.", fg="green"))
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@click.command(name="authenticate")
|
|
183
|
+
@click.option(
|
|
184
|
+
"--username",
|
|
185
|
+
help="The username to use for authentication.",
|
|
186
|
+
required=True,
|
|
187
|
+
prompt=True,
|
|
188
|
+
)
|
|
189
|
+
@click.option("--token", help="The token to use for authentication.", required=True, prompt=True)
|
|
190
|
+
def authenticate(username: str, token: str):
|
|
191
|
+
"""
|
|
192
|
+
Authenticate with the package repository so that you can pull images.
|
|
193
|
+
|
|
194
|
+
To get a username and token you'll need to contact a Greenroom Robotics employee.
|
|
195
|
+
"""
|
|
196
|
+
call(f"echo {token} | docker login ghcr.io -u {username} --password-stdin")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@click.command(name="config")
|
|
200
|
+
def config(): # type: ignore
|
|
201
|
+
"""Read Config"""
|
|
202
|
+
config = lookout_config.read()
|
|
203
|
+
log_config(config)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@click.command(name="configure")
|
|
207
|
+
@click.option("--default", is_flag=True, help="Use default values")
|
|
208
|
+
def configure(default: bool): # type: ignore
|
|
209
|
+
"""Configure Lookout"""
|
|
210
|
+
|
|
211
|
+
if default:
|
|
212
|
+
config = LookoutConfig()
|
|
213
|
+
lookout_config.write(config)
|
|
214
|
+
else:
|
|
215
|
+
# Check if the file exists
|
|
216
|
+
if os.path.exists(lookout_config.get_path()):
|
|
217
|
+
click.echo(
|
|
218
|
+
click.style(
|
|
219
|
+
f"Lookout config already exists: {lookout_config.get_path()}",
|
|
220
|
+
fg="yellow",
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
result = click.prompt(
|
|
224
|
+
"Do you want to overwrite it?", default="y", type=click.Choice(["y", "n"])
|
|
225
|
+
)
|
|
226
|
+
if result == "n":
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
try:
|
|
230
|
+
config_current = lookout_config.read()
|
|
231
|
+
except Exception:
|
|
232
|
+
config_current = LookoutConfig()
|
|
233
|
+
|
|
234
|
+
config = LookoutConfig(
|
|
235
|
+
ros_domain_id=click.prompt(
|
|
236
|
+
"ROS Domain ID", default=config_current.ros_domain_id, type=int
|
|
237
|
+
),
|
|
238
|
+
namespace_vessel=click.prompt(
|
|
239
|
+
"Namespace Vessel", default=config_current.namespace_vessel
|
|
240
|
+
),
|
|
241
|
+
mode=click.prompt(
|
|
242
|
+
"Mode",
|
|
243
|
+
default=config_current.mode,
|
|
244
|
+
type=click.Choice([item.value for item in Mode]),
|
|
245
|
+
),
|
|
246
|
+
gama_vessel=click.prompt(
|
|
247
|
+
"Is this running on a Gama Vessel?",
|
|
248
|
+
default=config_current.gama_vessel,
|
|
249
|
+
type=bool,
|
|
250
|
+
),
|
|
251
|
+
log_level=click.prompt(
|
|
252
|
+
"Log level",
|
|
253
|
+
default=config_current.log_level,
|
|
254
|
+
type=click.Choice([item.value for item in LogLevel]),
|
|
255
|
+
),
|
|
256
|
+
network=click.prompt(
|
|
257
|
+
"Network",
|
|
258
|
+
default=config_current.network,
|
|
259
|
+
type=click.Choice([item.value for item in Network]),
|
|
260
|
+
),
|
|
261
|
+
gpu=click.prompt(
|
|
262
|
+
"Should we use the GPU?",
|
|
263
|
+
default=config_current.gpu,
|
|
264
|
+
type=bool,
|
|
265
|
+
),
|
|
266
|
+
)
|
|
267
|
+
lookout_config.write(config)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from lookout_cli.helpers import get_project_root
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def write_file(path: str, content: str):
|
|
8
|
+
project_root = get_project_root() or Path()
|
|
9
|
+
click.echo(f"Writing file {project_root / path}")
|
|
10
|
+
with open(project_root / path, "w") as f:
|
|
11
|
+
f.write(content)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.group(help="Setup commands")
|
|
15
|
+
def setup():
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@click.command(name="secrets")
|
|
20
|
+
@click.argument("pat")
|
|
21
|
+
def secrets(pat: str): # type: ignore
|
|
22
|
+
"""Setup the .secrets files as docker secrets needs these to build containers"""
|
|
23
|
+
write_file(".secrets/API_TOKEN_GITHUB", pat)
|
|
24
|
+
|
|
25
|
+
greenroom_apt_conf = "\n".join(
|
|
26
|
+
[
|
|
27
|
+
"machine raw.githubusercontent.com/Greenroom-Robotics",
|
|
28
|
+
f"login {pat}",
|
|
29
|
+
"password",
|
|
30
|
+
]
|
|
31
|
+
)
|
|
32
|
+
write_file(".secrets/apt.conf", greenroom_apt_conf)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from typing import List, Dict, Any, Optional
|
|
2
|
+
import click
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import subprocess
|
|
6
|
+
import yaml
|
|
7
|
+
import platform
|
|
8
|
+
from python_on_whales.utils import ValidPath
|
|
9
|
+
import pkg_resources
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_project_root() -> Path:
|
|
13
|
+
current_file_dir = Path(__file__).parent
|
|
14
|
+
return current_file_dir.parent.parent.parent
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_version():
|
|
18
|
+
"""version is latest if it is a dev version otherwise it is the CLI version"""
|
|
19
|
+
version = pkg_resources.require("lookout-cli")[0].version
|
|
20
|
+
if version == "0.0.0":
|
|
21
|
+
version = "latest"
|
|
22
|
+
return version
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def is_dev_version():
|
|
26
|
+
if os.environ.get("LOOKOUT_CLI_DEV_MODE") == "false":
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
if os.environ.get("LOOKOUT_CLI_DEV_MODE") == "true":
|
|
30
|
+
return True
|
|
31
|
+
return pkg_resources.require("lookout_cli")[0].version == "0.0.0"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def docker_compose_path(path: str) -> Path:
|
|
35
|
+
current_file_dir = Path(__file__).parent
|
|
36
|
+
return current_file_dir / "docker" / path
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def call(command: str, abort: bool = True, env: Optional[Dict[str, Any]] = None):
|
|
40
|
+
click.echo(click.style(f"Running: {command}", fg="blue"))
|
|
41
|
+
if env:
|
|
42
|
+
env = {**os.environ, **env}
|
|
43
|
+
|
|
44
|
+
prj_root = get_project_root()
|
|
45
|
+
error = subprocess.call(command, shell=True, executable="/bin/bash", cwd=prj_root, env=env)
|
|
46
|
+
if error and abort:
|
|
47
|
+
raise click.ClickException("Failed")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_arch():
|
|
51
|
+
arch = platform.machine()
|
|
52
|
+
if arch == "x86_64":
|
|
53
|
+
return "amd64"
|
|
54
|
+
elif arch == "aarch64":
|
|
55
|
+
return "arm64"
|
|
56
|
+
else:
|
|
57
|
+
print(f"Unsupported arch: {arch}")
|
|
58
|
+
exit(1)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def docker_bake(version: str, compose_files: List[ValidPath], push: bool, services: List[str]):
|
|
62
|
+
compose_args: list[str] = []
|
|
63
|
+
for f in compose_files:
|
|
64
|
+
compose_args.append(f"--file {f}")
|
|
65
|
+
|
|
66
|
+
# Load the compose config
|
|
67
|
+
file_args = " ".join(compose_args)
|
|
68
|
+
command_get_config = f"docker compose {file_args} config"
|
|
69
|
+
print("Running command: ", command_get_config)
|
|
70
|
+
config = subprocess.run(
|
|
71
|
+
command_get_config, shell=True, check=True, cwd=get_project_root(), capture_output=True
|
|
72
|
+
)
|
|
73
|
+
config = config.stdout.decode("utf-8")
|
|
74
|
+
config = yaml.safe_load(config)
|
|
75
|
+
|
|
76
|
+
# Create the bake command args
|
|
77
|
+
bake_args = compose_args
|
|
78
|
+
bake_args.append(
|
|
79
|
+
"--provenance=false"
|
|
80
|
+
) # this allows us to create a multi-arch manifest at a later stage
|
|
81
|
+
|
|
82
|
+
# Get the arch
|
|
83
|
+
arch = get_arch()
|
|
84
|
+
|
|
85
|
+
# Get all services we should build and set their tags and arch
|
|
86
|
+
services_actual: list[str] = []
|
|
87
|
+
for service, service_config in config["services"].items():
|
|
88
|
+
if "image" in service_config and "build" in service_config:
|
|
89
|
+
# If we have a list of services to build, only build those
|
|
90
|
+
if len(services) == 0 or service in services:
|
|
91
|
+
image = service_config["image"]
|
|
92
|
+
image = image.split(":")[0]
|
|
93
|
+
bake_args.append(f"--set {service}.platform=linux/{arch}")
|
|
94
|
+
bake_args.append(f"--set {service}.tags={image}:{version}-{arch}")
|
|
95
|
+
bake_args.append(f"--set {service}.tags={image}:latest-{arch}")
|
|
96
|
+
services_actual.append(service)
|
|
97
|
+
|
|
98
|
+
# Add other args
|
|
99
|
+
if push:
|
|
100
|
+
bake_args.append("--push")
|
|
101
|
+
|
|
102
|
+
print(f"Baking services: {', '.join(services_actual)}...")
|
|
103
|
+
bake_command = " ".join(
|
|
104
|
+
[
|
|
105
|
+
"docker buildx bake",
|
|
106
|
+
" ".join(bake_args),
|
|
107
|
+
" ".join(services_actual),
|
|
108
|
+
]
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
print("Running bake command: ", bake_command)
|
|
112
|
+
subprocess.run(
|
|
113
|
+
bake_command,
|
|
114
|
+
shell=True,
|
|
115
|
+
check=True,
|
|
116
|
+
cwd=get_project_root(),
|
|
117
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: lookout_cli
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A CLI for interacting with Lookout+
|
|
5
|
+
Home-page: https://github.com/Greenroom-Robotics/lookout
|
|
6
|
+
Author: Greenroom Robotics
|
|
7
|
+
Author-email: team@greenroomrobotics.com
|
|
8
|
+
Maintainer: David Revay
|
|
9
|
+
Maintainer-email: david.revay@greenroomrobotics.com
|
|
10
|
+
License: Copyright (C) 2023, Greenroom Robotics
|
|
11
|
+
Keywords: colcon
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Plugins
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: toml~=0.10
|
|
19
|
+
Requires-Dist: setuptools
|
|
20
|
+
Requires-Dist: colorama
|
|
21
|
+
Requires-Dist: click
|
|
22
|
+
Requires-Dist: lookout-config
|
|
23
|
+
Requires-Dist: python-on-whales
|
|
24
|
+
Requires-Dist: PyYAML
|
|
25
|
+
|
|
26
|
+
# Lookout CLI
|
|
27
|
+
|
|
28
|
+
Publicly available on [PyPi](https://pypi.org/project/lookout-cli/) for convenience but if you don't work at Greenroom Robotics, you probably don't want to use this.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
* For development:
|
|
33
|
+
* `pip install -e ./libs/lookout_config`
|
|
34
|
+
* `pip install -e ./tools/lookout_cli`
|
|
35
|
+
* For production: `pip install lookout-cli`
|
|
36
|
+
* You may also need to `export PATH=$PATH:~/.local/bin` if you don't have `~/.local/bin` in your path
|
|
37
|
+
* Install autocomplete:
|
|
38
|
+
* bash: `echo 'eval "$(_lookout_COMPLETE=bash_source lookout)"' >> ~/.bashrc`
|
|
39
|
+
* zsh: `echo 'eval "$(_lookout_COMPLETE=zsh_source lookout)"' >> ~/.zshrc` (this is much nicer)
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
* `lookout --help` to get help with the CLI
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.cfg
|
|
3
|
+
setup.py
|
|
4
|
+
lookout_cli/__init__.py
|
|
5
|
+
lookout_cli/banner.py
|
|
6
|
+
lookout_cli/cli.py
|
|
7
|
+
lookout_cli/helpers.py
|
|
8
|
+
lookout_cli.egg-info/PKG-INFO
|
|
9
|
+
lookout_cli.egg-info/SOURCES.txt
|
|
10
|
+
lookout_cli.egg-info/dependency_links.txt
|
|
11
|
+
lookout_cli.egg-info/entry_points.txt
|
|
12
|
+
lookout_cli.egg-info/requires.txt
|
|
13
|
+
lookout_cli.egg-info/top_level.txt
|
|
14
|
+
lookout_cli.egg-info/zip-safe
|
|
15
|
+
lookout_cli/docker/docker-compose.dev.yaml
|
|
16
|
+
lookout_cli/docker/docker-compose.gpu.yaml
|
|
17
|
+
lookout_cli/docker/docker-compose.network-host.yaml
|
|
18
|
+
lookout_cli/docker/docker-compose.network-shared.yaml
|
|
19
|
+
lookout_cli/docker/docker-compose.yaml
|
|
20
|
+
lookout_cli/groups/__init__.py
|
|
21
|
+
lookout_cli/groups/misc.py
|
|
22
|
+
lookout_cli/groups/setup.py
|
|
23
|
+
lookout_cli/test/lookout_cli_test.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lookout_cli
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = lookout_cli
|
|
3
|
+
version = 1.0.0
|
|
4
|
+
url = https://github.com/Greenroom-Robotics/lookout
|
|
5
|
+
author = Greenroom Robotics
|
|
6
|
+
author_email = team@greenroomrobotics.com
|
|
7
|
+
maintainer = David Revay
|
|
8
|
+
maintainer_email = david.revay@greenroomrobotics.com
|
|
9
|
+
classifiers =
|
|
10
|
+
Development Status :: 3 - Alpha
|
|
11
|
+
Environment :: Plugins
|
|
12
|
+
Intended Audience :: Developers
|
|
13
|
+
Programming Language :: Python
|
|
14
|
+
Topic :: Software Development :: Build Tools
|
|
15
|
+
license = Copyright (C) 2023, Greenroom Robotics
|
|
16
|
+
license_files = LICENSE
|
|
17
|
+
description = A CLI for interacting with Lookout+
|
|
18
|
+
long_description = file: README.md
|
|
19
|
+
long_description_content_type = text/markdown
|
|
20
|
+
keywords = colcon
|
|
21
|
+
|
|
22
|
+
[options]
|
|
23
|
+
packages = find:
|
|
24
|
+
install_requires =
|
|
25
|
+
toml~=0.10
|
|
26
|
+
setuptools
|
|
27
|
+
colorama
|
|
28
|
+
click
|
|
29
|
+
lookout-config
|
|
30
|
+
python-on-whales
|
|
31
|
+
PyYAML
|
|
32
|
+
zip_safe = true
|
|
33
|
+
|
|
34
|
+
[options.package_data]
|
|
35
|
+
lookout_cli =
|
|
36
|
+
**/*.json
|
|
37
|
+
**/*.py
|
|
38
|
+
**/**/*.yaml
|
|
39
|
+
**/**/*.yml
|
|
40
|
+
|
|
41
|
+
[options.entry_points]
|
|
42
|
+
console_scripts =
|
|
43
|
+
lookout = lookout_cli.cli:cli
|
|
44
|
+
|
|
45
|
+
[egg_info]
|
|
46
|
+
tag_build =
|
|
47
|
+
tag_date = 0
|
|
48
|
+
|