Skip to content

Commit 63a5c78

Browse files
authored
Merge pull request #2 from IOES-Lab/osrf-main
Osrf main
2 parents 776dcf5 + 712142e commit 63a5c78

23 files changed

Lines changed: 1183 additions & 202 deletions

.github/workflows/basic-ci.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ jobs:
99
matrix:
1010
python-version: ['3.8', 3.x]
1111
steps:
12-
- uses: actions/checkout@v3
12+
- uses: actions/checkout@v4
1313
- name: Set up Python ${{ matrix.python-version }}
14-
uses: actions/setup-python@v4
14+
uses: actions/setup-python@v5
1515
with:
1616
python-version: ${{ matrix.python-version }}
1717
- name: Install Test Dependencies And Self
@@ -31,9 +31,9 @@ jobs:
3131
matrix:
3232
python-version: [3.8, '3.x']
3333
steps:
34-
- uses: actions/checkout@v3
34+
- uses: actions/checkout@v4
3535
- name: Set up Python ${{ matrix.python-version }}
36-
uses: actions/setup-python@v4
36+
uses: actions/setup-python@v5
3737
with:
3838
python-version: ${{ matrix.python-version }}
3939
- name: Install Dependencies And Self

CHANGELOG.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,40 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

88
<!-- insertion marker -->
9+
## [v0.2.19](https://github.com/osrf/rocker/releases/tag/v0.2.19) - 2025-02-06
10+
11+
<small>[Compare with v0.2.18](https://github.com/osrf/rocker/compare/v0.2.18...v0.2.19)</small>
12+
13+
### Added
14+
15+
- add rmw zenoh support to rmw plugin (#315) ([5c6e8e7](https://github.com/osrf/rocker/commit/5c6e8e7fe45b34868bb74a40610c69b293341505) by Tully Foote).
16+
17+
- Improve robustness of image cleanup (#313) ([149d4ef
18+
](https://github.com/osrf/rocker/commit/149d4ef86ab5b42e7373066ba84ca1e985555011))
19+
20+
- Enable redirecting non-interactive run console output to file (#317) ([66fe159](https://github.com/osrf/rocker/commit/66fe159e3be5a80d3ba189320bf064da84371e73))
21+
22+
## [v0.2.18](https://github.com/osrf/rocker/releases/tag/v0.2.18) - 2025-01-10
23+
24+
<small>[Compare with v0.2.17](https://github.com/osrf/rocker/compare/v0.2.17...v0.2.18)</small>
25+
26+
### Added
27+
28+
- Add UI feedback that image is being cleaned up, and how to avoid. ([3b21f78](https://github.com/osrf/rocker/commit/3b21f78fd4372a5451611a2a3e607f6941bcc398) by Tully Foote).
29+
- Add clear_image to ImageGenerator to enable non-persistence and not taking up all disk space. Especially for the tests. ([24dd5e1](https://github.com/osrf/rocker/commit/24dd5e1e7a6387e6c9b6c1df3644bf493f04b5c5) by Tully Foote).
30+
- Add support for ulimit flag (#291) ([cff5cb2](https://github.com/osrf/rocker/commit/cff5cb27c04f4db8d115493c2e2704c6a10726df) by Felipe Padula Sanches).
31+
- Add support for --shm-size flag (#306)
32+
33+
### Fixed
34+
35+
- fix test for new cuda installation package ([3449afa](https://github.com/osrf/rocker/commit/3449afabd700c4723d21c22163e73f9cbf9b358d) by Tully Foote).
36+
- Removed deprecation warning from volume extensino (#292)
37+
- Updated and simplified CUDA installation (#299 by jonazpiazu)
38+
39+
### Removed
40+
41+
- Remove default value for defaults (#289) ([3f02bdc](https://github.com/osrf/rocker/commit/3f02bdcc542c786eb08bdb3b324887bfa21698a2) by Tully Foote).
42+
943
## [v0.2.17](https://github.com/osrf/rocker/releases/tag/v0.2.17) - 2024-08-28
1044

1145
<small>[Compare with v0.2.16](https://github.com/osrf/rocker/compare/v0.2.16...v0.2.17)</small>

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ You can get full details on the extensions from the main `rocker --help` command
3838
- pulse -- Mount pulse audio into the container
3939
- ssh -- Pass through ssh access to the container.
4040

41-
As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, `ipc`, and `privileged`.
41+
As well as access to many of the docker arguments as well such as `device`, `env`, `volume`, `name`, `network`, `ipc`, `privileged`, and resource limits (`cpus`, `memory`, `shm-size`).
4242

4343
### Externally maintained extensions
4444

@@ -48,8 +48,20 @@ Here's a list of public repositories with extensions.
4848
- mp_rocker: https://github.com/miguelprada/mp_rocker
4949
- ghrocker: https://github.com/tfoote/ghrocker
5050
- novnc_rocker: https://github.com/tfoote/novnc-rocker
51+
- template_rocker: https://github.com/blooop/template_rocker
52+
- deps_rocker: https://github.com/blooop/deps_rocker
53+
- pixi_rocker: https://github.com/blooop/pixi_rocker
54+
- conda_rocker: https://github.com/blooop/conda_rocker
55+
- palanteer_rocker: https://github.com/blooop/palanteer_rocker
56+
- lazygit_rocker: https://github.com/blooop/lazygit_rocker
5157

5258

59+
### Externally maintained rocker wrappers
60+
61+
Here is a list of public repositories that wrap rocker and extend its functionality. These tools are meant to be a drop in replacement of rocker so that all the existing behavior stays the same.
62+
63+
- rockerc: https://github.com/blooop/rockerc wraps rocker to enable putting rocker commands into a yaml config file.
64+
- rockervsc: https://github.com/blooop/rockervsc wraps rocker so that a vscode instance attaches to the launched container.
5365

5466
# Prerequisites
5567

setup.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22

33
import os
4+
45
from setuptools import setup
56

67
# importlib-metadata dependency can be removed when RHEL8 and other 3.6 based systems are not in support cycles
@@ -35,17 +36,19 @@
3536

3637
kwargs = {
3738
'name': 'rocker',
38-
'version': '0.2.18',
39+
'version': '0.2.19',
3940
'packages': ['rocker'],
4041
'package_dir': {'': 'src'},
4142
'package_data': {'rocker': ['templates/*.em']},
4243
'entry_points': {
4344
'console_scripts': [
4445
'rocker = rocker.cli:main',
4546
'detect_docker_image_os = rocker.cli:detect_image_os',
46-
],
47+
],
4748
'rocker.extensions': [
49+
'cpu_limits = rocker.constraint_extensions:CpuLimits',
4850
'cuda = rocker.nvidia_extension:Cuda',
51+
'detach = rocker.extensions:Detach',
4952
'devices = rocker.extensions:Devices',
5053
'dev_helpers = rocker.extensions:DevHelpers',
5154
'env = rocker.extensions:Environment',
@@ -55,19 +58,22 @@
5558
'home = rocker.extensions:HomeDir',
5659
'hostname = rocker.extensions:Hostname',
5760
'ipc = rocker.extensions:Ipc',
61+
'memory_limits = rocker.constraint_extensions:MemoryLimits',
5862
'name = rocker.extensions:Name',
5963
'network = rocker.extensions:Network',
6064
'nvidia = rocker.nvidia_extension:Nvidia',
6165
'port = rocker.extensions:Port',
6266
'privileged = rocker.extensions:Privileged',
6367
'pulse = rocker.extensions:PulseAudio',
6468
'rmw = rocker.rmw_extension:RMW',
69+
'shm_size = rocker.constraint_extensions:ShmSize',
6570
'ssh = rocker.ssh_extension:Ssh',
71+
'ulimit = rocker.ulimit_extension:Ulimit',
6672
'user = rocker.extensions:User',
6773
'volume = rocker.volume_extension:Volume',
6874
'x11 = rocker.nvidia_extension:X11',
6975
]
70-
},
76+
},
7177
'author': 'Tully Foote',
7278
'author_email': 'tfoote@osrfoundation.org',
7379
'keywords': ['Docker'],
@@ -91,4 +97,3 @@
9197
}
9298

9399
setup(**kwargs)
94-

src/rocker/cli.py

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
import os
1717
import sys
1818

19-
from .core import DockerImageGenerator
20-
from .core import get_rocker_version
21-
from .core import RockerExtensionManager
22-
from .core import DependencyMissing
23-
from .core import ExtensionError
24-
19+
from .core import (OPERATION_MODES, OPERATIONS_DRY_RUN, OPERATIONS_INTERACTIVE,
20+
OPERATIONS_NON_INTERACTIVE, DependencyMissing,
21+
DockerImageGenerator, ExtensionError,
22+
RockerExtensionManager, base_image_exists,
23+
get_rocker_version)
2524
from .os_detector import detect_os
2625

2726

@@ -32,9 +31,10 @@ def main():
3231
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
3332
parser.add_argument('image')
3433
parser.add_argument('command', nargs='*', default='')
35-
parser.add_argument('--noexecute', action='store_true', help='Deprecated')
34+
parser.add_argument('--noexecute', action='store_true', help='Deprecated') # TODO(tfoote) add when 3.13 is minimum supported, deprecated=True
3635
parser.add_argument('--nocache', action='store_true')
3736
parser.add_argument('--nocleanup', action='store_true', help='do not remove the docker container when stopped')
37+
parser.add_argument('--persist-image', action='store_true', help='do not remove the docker image when stopped', default=False) #TODO(tfoote) Add a name to it if persisting
3838
parser.add_argument('--pull', action='store_true')
3939
parser.add_argument('--version', action='version',
4040
version='%(prog)s ' + get_rocker_version())
@@ -45,7 +45,7 @@ def main():
4545
extension_manager.extend_cli_parser(parser, default_args)
4646
except DependencyMissing as ex:
4747
# Catch errors if docker is missing or inaccessible.
48-
parser.error("DependencyMissing encountered: %s" % ex)
48+
parser.error(str(ex))
4949

5050
args = parser.parse_args()
5151
args_dict = vars(args)
@@ -55,23 +55,76 @@ def main():
5555
args_dict['mode'] = OPERATIONS_DRY_RUN
5656
print('DEPRECATION Warning: --noexecute is deprecated for --mode dry-run please switch your usage by December 2020')
5757

58+
# validate_operating_mode
59+
operating_mode = args_dict.get('mode')
60+
# Don't try to be interactive if there's no tty
61+
if not os.isatty(sys.__stdin__.fileno()):
62+
if operating_mode == OPERATIONS_INTERACTIVE:
63+
parser.error("No tty detected cannot operate in interactive mode")
64+
elif not operating_mode:
65+
print("No tty detected for stdin defaulting mode to non-interactive")
66+
args_dict['mode'] = OPERATIONS_NON_INTERACTIVE
67+
68+
# Check if detach extension is active and deconflict with interactive
69+
detach_active = args_dict.get('detach')
70+
operating_mode = args_dict.get('mode')
71+
if detach_active:
72+
if operating_mode == OPERATIONS_INTERACTIVE:
73+
parser.error("Command line option --mode=interactive and --detach are mutually exclusive")
74+
elif not operating_mode:
75+
print(f"Detach extension active, defaulting mode to {OPERATIONS_NON_INTERACTIVE}")
76+
args_dict['mode'] = OPERATIONS_NON_INTERACTIVE
77+
# TODO(tfoote) Deal with the case of dry-run + detach
78+
# Right now the printed results will include '-it'
79+
# But based on testing the --detach overrides -it in docker so it's ok.
80+
81+
# Default to interactive if unset
82+
if args_dict.get('mode') not in OPERATION_MODES:
83+
print("Mode unset, defaulting to interactive")
84+
args_dict['mode'] = OPERATIONS_INTERACTIVE
85+
5886
try:
5987
active_extensions = extension_manager.get_active_extensions(args_dict)
6088
except ExtensionError as e:
6189
print(f"ERROR! {str(e)}")
6290
return 1
6391
print("Active extensions %s" % [e.get_name() for e in active_extensions])
6492

93+
# Give active extensions a chance to validate the arguments
94+
for e in active_extensions:
95+
try:
96+
e.validate_environment(args_dict, parser)
97+
except TypeError as ex:
98+
import traceback
99+
print("DEPRECATION WARNING: validate_environment takes 3 arguments and is now invoked. This error is indicative of using the old prototype with two arguments.")
100+
traceback.print_exc()
101+
print("DEPRECATION WARNING: validation of the environment not successfully acomplished, but continuing. Please fix your implmentation similar to https://github.com/osrf/rocker/pull/350"
102+
" This warning will be maintained until at least Jan 2027. On removal it will cause a traceback.")
103+
104+
65105
base_image = args.image
66106

107+
# Check if base image exists before proceeding (will attempt to pull if missing)
108+
try:
109+
if not base_image_exists(base_image, output_callback=print):
110+
parser.error(f"ERROR: Base Docker image '{base_image}' not found locally and could not be pulled. Please verify the image name and try 'docker pull {base_image}' manually.")
111+
except DependencyMissing as ex:
112+
parser.error(f"DependencyMissing encountered: {ex}")
113+
67114
dig = DockerImageGenerator(active_extensions, args_dict, base_image)
68115
exit_code = dig.build(**vars(args))
69116
if exit_code != 0:
70117
print("Build failed exiting")
118+
if not (args_dict['persist_image'] or args_dict.get('image_name')):
119+
dig.clear_image()
71120
return exit_code
72121
# Convert command into string
73122
args.command = ' '.join(args.command)
74-
return dig.run(**args_dict)
123+
result = dig.run(**args_dict)
124+
if not (args_dict['persist_image'] or args_dict.get('image_name')):
125+
print(f'Clearing Image: {dig.image_id}s\nTo not clean up use --persist-image')
126+
dig.clear_image()
127+
return result
75128

76129

77130
def detect_image_os():

0 commit comments

Comments
 (0)