145 Commits

Author SHA1 Message Date
9cbc4c1dcd Release 1.3.0
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2025-01-07 21:16:01 +02:00
c63d678887 Merge pull request #1100 from p12tic/release
Preparation for release
2025-01-07 21:15:30 +02:00
6de335beb2 Release notes for 1.3.0
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2025-01-07 21:10:54 +02:00
23799245bd Add documentation for how to create a release
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2025-01-07 21:06:45 +02:00
eda4815715 scripts: Add script to make new release
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2025-01-07 21:06:44 +02:00
cbb0cab814 scripts: Add script to create release notes
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2025-01-07 21:06:43 +02:00
7c8696b2b2 Merge pull request #1099 from p12tic/python-3.13
Declare compatibility with Python 3.13
2025-01-05 13:20:47 +02:00
483103ac3a Declare compatibility with Python 3.13
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2025-01-05 13:12:43 +02:00
e9f1029406 Merge pull request #1092 from flixman/main
Provide support for cache_from and cache_to fields
2025-01-05 13:11:53 +02:00
804852b218 Provide support for cache_from and cache_to fields
Signed-off-by: Felix Rubio <felix@kngnt.org>
2025-01-05 12:35:30 +02:00
0e3b372a29 Merge pull request #1098 from whym/readline
Fixes #1096: read log output by chunks if a line is too long
2025-01-05 12:32:51 +02:00
f11e08eaac Read log output by chunks if a line is too long
Fixes #1096.

Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Yusuke Matsubara <whym@whym.org>
2025-01-05 12:28:13 +02:00
62789a2358 Merge pull request #1094 from p12tic/build-args-test
Add unit tests for image building
2024-12-30 01:04:16 +02:00
35cf4bcb72 tests: Add test for container_to_build_args()
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-30 00:55:19 +02:00
9964604b17 Extract container_to_build_args()
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-30 00:52:45 +02:00
61fa24bf21 Merge pull request #1093 from lisongmin/add-network-level-mac_address-attr
Support network level mac_address attribute
2024-12-29 18:58:33 +02:00
ac7ec5c166 Support network level mac_address attribute
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-29 22:59:58 +08:00
75d7be2b7b Merge pull request #1087 from lisongmin/feat-support-network-scoped-aliases
Support network scoped service aliases
2024-12-22 00:54:26 +02:00
346f7a57f0 Ignore creating networks on network_mode=bridge.
When using bridge mode, podman-compose will use the default `podman` network.
We do not need to create this network, so just return as other network_mode.

Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-21 22:52:37 +02:00
55642247e3 Add integration test for network scoped aliases
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-21 22:52:37 +02:00
978a1381bc Support network scoped service aliases
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-21 22:52:37 +02:00
4a232f5e32 Merge single and multi network handling in get_net_args_from_networks()
The behavior has not changed, single-network has a special case.

Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 20:00:17 +02:00
aa8c6fd598 Simplify network handling in get_net_args_from_networks()
Note that multiple_nets is now guaranteed to be not empty in processing
stage.

Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 20:00:15 +02:00
fb0bbd6fe1 Cleanup network alias processing
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 20:00:13 +02:00
b324029f25 Simplify network name processing when there is single network
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 20:00:11 +02:00
590c371db2 Move network alias processing to common location
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 20:00:06 +02:00
16196a1f6d Simplify ip address processing in get_net_args_from_networks()
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-18 19:59:28 +02:00
2dfbb59097 Extract multiple network handling in get_net_args_from_networks()
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 19:59:27 +02:00
a34d1d1a31 Remove unused ip_assignments in get_net_args_from_networks()
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 19:59:26 +02:00
d6da65e6c9 Extract get_net_args_from_networks()
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 19:59:25 +02:00
de2c33d7ae Simplify get_net_args_from_network_mode()
This commit takes into account that network_mode won't have networks
attribute set, accordingly get_net_args_from_network_mode() can
calculate complete net_args easily.

Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 19:59:24 +02:00
2891be01d7 Ensure that network_mode and networks are not present at the same time
See
https://docs.docker.com/reference/compose-file/services/#network_mode

Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-18 19:59:23 +02:00
a023dc145b Extract get_net_args_from_network_mode()
Modified-by: Povilas Kanapickas <povilas@radix.lt>
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 19:59:22 +02:00
d803c4c3e8 Merge pull request #1088 from lisongmin/feat-default-net-behavior-compat
Support docker-compose like default network behavior
2024-12-18 18:01:50 +02:00
420d19daf4 Add integration test for default network behavior
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 13:21:29 +08:00
2cfc617f9e Support docker-compose like default network behavior
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-12-18 08:48:21 +08:00
376f0817e6 Merge pull request #1085 from jeremyvisser/fix-device-cgroup-rules
Add device_cgroup_rules support
2024-12-06 11:02:16 +02:00
054c66b568 Add device_cgroup_rules support
"device_cgroup_rules: []" is defined in the Compose file specification,
and corresponds to "podman run --device-cgroup-rule="

Signed-off-by: Jeremy Visser <jeremy@visser.name>
2024-12-06 08:19:54 +11:00
d9fc8e91f2 Merge pull request #1082 from flixman/main
Provide support for conditional dependencies
2024-12-02 22:18:53 +02:00
145ae47c48 Simplified statements to retrieve keys from dictionaries
Signed-off-by: Felix Rubio <felix@kngnt.org>
2024-12-02 22:13:10 +02:00
a67fa0beb5 Adding support for conditional dependencies
Signed-off-by: Felix Rubio <felix@kngnt.org>
2024-12-02 22:13:10 +02:00
3ba0396e7a Normalize depends_on service property
Signed-off-by: Felix Rubio <felix@kngnt.org>
Modified-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-02 22:08:48 +02:00
973e15ba23 Wrap dependencies within a class
Signed-off-by: Felix Rubio <felix@kngnt.org>
Modified-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-02 22:08:48 +02:00
002c2e400b Extract run_container()
Signed-off-by: Felix Rubio <felix@kngnt.org>
Modified-by: Povilas Kanapickas <povilas@radix.lt>
2024-12-02 22:00:59 +02:00
626e278794 Merge pull request #1068 from jrnorth/patch-1
Fix Dockerfile link in readme
2024-11-18 22:05:35 +02:00
a358890d54 Merge pull request #1069 from containers/dependabot/github_actions/softprops/action-gh-release-2
build(deps): bump softprops/action-gh-release from 1 to 2
2024-11-11 21:14:11 +02:00
9f3251ff3d Merge pull request #1070 from containers/dependabot/github_actions/actions/checkout-4
build(deps): bump actions/checkout from 2 to 4
2024-11-11 21:13:14 +02:00
a9cfdb6704 build(deps): bump actions/checkout from 2 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 21:47:54 +00:00
c0dc3e47fd build(deps): bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 21:47:51 +00:00
41e69be201 Fix Dockerfile link in readme 2024-11-04 09:51:12 -07:00
4ae6ccb5c0 Merge pull request #1043 from iruzo/main
Download and build podman-compose using docker/podman locally
2024-11-03 15:42:05 +02:00
4203f799ee add release.yml workflow 2024-11-03 15:35:42 +02:00
69e95be2f6 add Dockerfile and related scripts 2024-11-03 15:35:42 +02:00
122a914b9b Merge pull request #1062 from tdgroot/down_removes_network
podman-compose down removes networks
2024-10-21 23:45:26 +03:00
db0aad97bd podman-compose down removes networks
Fixes #490

Signed-off-by: Timon de Groot <timon.degroot@hypernode.com>
2024-10-21 08:31:09 +02:00
a3fb4b373a Merge pull request #1058 from banditopazzo/705-ssh-key-support-in-build
feat: add support for ssh property in the build command
2024-10-15 03:18:41 +03:00
ab33954f6c add ssh support for build command
Fixes #705: Add support for ssh property in the build command

Signed-off-by: Domenico Salvatore <banditopazzo@gmail.com>
2024-10-15 00:35:10 +02:00
4660feb04a Merge pull request #1060 from tdgroot/podman_no_hosts_extension
Add x-podman.no_hosts extension
2024-10-14 18:05:25 +03:00
90f54b9ca5 Add x-podman.no_hosts extension
Signed-off-by: Timon de Groot <timon.degroot@hypernode.com>
2024-10-14 17:02:36 +02:00
7090de3bce Merge pull request #1049 from mokibit/automate-nets_test2
tests/integration: Automate manual `nets_test2` test
2024-10-04 04:10:31 +03:00
df8fa588a5 tests/integration: Automate manual 'nets_test2' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-10-01 12:26:42 +03:00
e2ae8bee04 Merge pull request #1048 from mokibit/automate-nets_test1
tests/integration: Automate manual `nets_test1` test
2024-09-29 15:04:40 +03:00
5c81bbfcb7 tests/integration: Automate manual 'nets_test1' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-29 14:44:17 +03:00
22b0c4b348 Merge pull request #1040 from mokibit/automate-ipam-default-test
tests/integration: Automate manual `ipam_default` test
2024-09-26 21:41:49 +03:00
380cf42dcd Merge pull request #1047 from mokibit/delete-netprio-test
tests/integration: Delete `netprio` test
2024-09-26 21:37:50 +03:00
deed4d51b0 tests/integration: Automate manual 'ipam_default' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-26 20:23:26 +03:00
08b3ac2633 tests/integration: Delete 'netprio' test
This functionality is not implemented in podman-compose so the test is
unneeded.

Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-26 20:10:37 +03:00
f8ea85e3af Merge pull request #1045 from mokibit/automate-multicompose-test
tests/integration: Automate manual `multicompose` test
2024-09-24 19:56:24 +03:00
0de7e13f1a tests/integration: Automate manual 'multicompose' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-24 19:38:33 +03:00
da7fd4fe86 Merge pull request #1044 from mokibit/automate-nethost-test
tests/integration: Automate manual `nethost` test
2024-09-24 19:37:58 +03:00
cb294d7519 tests/integration: Automate manual 'nethost' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-24 19:35:06 +03:00
351858dbec Merge pull request #1034 from mokibit/automate-interpolation-tests
tests/integration: Automate manual `interpolation` test
2024-09-24 19:32:16 +03:00
8d0dd214ae tests/integration: Automate manual 'interpolation' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-10 14:47:56 +03:00
229650cba8 Merge pull request #1032 from shuckc/main
Revert "Use defined environment variables in the image build process"
2024-09-07 00:13:36 +03:00
ab832d23c7 Merge pull request #1031 from mokibit/relocate-filesystem-test
tests/integration: Relocate `filesystem` test
2024-09-06 23:12:37 +03:00
4a7329b9e3 Revert "Use defined environment variables in the image build process"
This reverts commit 901adf47d0.
fixes #985 and #931

Signed-off-by: Chris Shucksmith <chris@shucksmith.co.uk>
2024-09-06 23:12:09 +03:00
de3f93c491 tests/integration: Relocate 'filesystem' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-06 20:08:13 +03:00
54cc055a5c Merge pull request #1029 from mokibit/automate-extends-with-file-subdir
tests/integration: Automate manual `extends_w_file_subdir` test
2024-09-06 20:07:51 +03:00
f4bf69b68e tests/integration: Automate manual 'extends_w_file_subdir' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-06 19:47:14 +03:00
5297b004af Merge pull request #1028 from mokibit/automate-extends-with-file
tests/integration: Automate manual `extends_w_file` test
2024-09-06 19:46:59 +03:00
fd1fc833b0 Merge pull request #1026 from mokibit/automate-extends-empty-service-test
tests/integration: Automate manual `extends_w_empty_service` test
2024-09-06 19:45:30 +03:00
124879a7b9 tests/integration: Automate manual 'extends_w_file' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-05 15:25:33 +03:00
368efe2ee3 tests/integration: Automate manual 'extends_w_empty_service' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-09-05 13:16:38 +03:00
eeefd37996 Merge pull request #1016 from legobeat/refactor-resolvable-type-checks
fix: improve type resolutions
2024-08-03 17:01:13 +03:00
b7514a0647 Merge pull request #1018 from legobeat/drop-python-3.8
Minimum Python version 3.9
2024-08-03 17:00:02 +03:00
561094954d test: Use stable apt-get cli for package installation
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 01:24:36 +00:00
ea239c4b77 Simplify secrets assignment
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 01:01:16 +00:00
9fdee76858 Initialize default values in PodmanCompose constructor
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 01:01:08 +00:00
0a6e0a35e1 Fix services replicas type
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 01:00:40 +00:00
26e6651d6c Type hints via annotations
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 01:00:36 +00:00
462603383c Remove is_dict,is_str for better pyright inference
When support for python3.8 and python3.9 has been dropped, it will be possible to eat the cak and
have it due to PEP-647.

Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 01:00:30 +00:00
8411db49d1 Minimum Python version 3.9
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-03 00:50:26 +00:00
fc90f60bf1 Merge pull request #1014 from legobeat/refactor-redundant-vars
refactor: clean up redundant proj_name, net vars
2024-08-02 10:22:28 +03:00
ed58ac0879 clean up redundant default_net variable
Signed-off-by: legobt <6wbvkn0j@anonaddy.me>
2024-08-01 23:16:13 +00:00
305f25b4d6 clean up redundant proj_name
- remove unutilized proj_name parameter from volume_ls

Signed-off-by: legobt <6wbvkn0j@anonaddy.me>

proj_name
2024-08-01 23:16:13 +00:00
edadf73d82 Merge pull request #1017 from mokibit/automate-extends-tests
tests/integration: Automate manual 'extends' test
2024-08-01 21:41:30 +03:00
dc04108b3e tests/integration: Automate manual 'extends' test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-08-01 21:29:43 +03:00
348461ca77 Merge pull request #1007 from mokibit/automate-env-tests
tests/integration: Automate manual `env` tests
2024-07-30 14:09:55 +03:00
92dbd3690e tests/integration: Automate 'env-file-tests' manual tests
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-30 12:46:13 +02:00
a1e9a82693 Merge pull request #1012 from mokibit/automate-exit-from-tests
tests/integration: Automate manual `exit-from` tests
2024-07-30 11:16:17 +03:00
9e11c6bfbc tests/integration: Automate manual 'exit-from' tests
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-30 09:40:20 +02:00
0d24c41afb tests/integration: Automate 'env-tests' manual test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-29 10:39:49 +02:00
585d344d0a Merge pull request #1004 from lisongmin/substitution-with-service-environment
Substitution with service environment
2024-07-27 00:06:46 +03:00
3aa6d4d158 Merge pull request #1009 from bkueng/platform_build_cmd
podman_compose.py: support "platform" property in the build command
2024-07-27 00:04:54 +03:00
34f5268e37 Add unittest for rec_subs
Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-07-27 00:04:06 +03:00
b5eaf314ad Support variable substitution with service's environment
This commit introduces the ability to substitute environment variables
within the 'environment' section of the service definition.

This allows for more dynamic configuration of services.

Signed-off-by: Songmin Li <lisongmin@protonmail.com>
2024-07-27 00:04:06 +03:00
b3c49df6eb podman_compose.py: support "platform" property in the build command
This was already added to container_to_args() in https://github.com/containers/podman-compose/pull/470
which is used for the 'up' and 'run' commands.

Definition in the schema: https://github.com/compose-spec/compose-spec/blob/main/schema/compose-spec.json#L329

Signed-off-by: Beat Küng <beat-kueng@gmx.net>
2024-07-26 23:58:11 +03:00
dbbd695463 Merge pull request #1008 from mokibit/automate-deps-test
tests/integration: Automate manual `deps` test
2024-07-23 23:12:17 +03:00
1b1d3d8c25 Merge pull request #1010 from jasonchuanet/docs_uidmaps_gidmaps
Update docs+messages to reflect uidmaps/gidmaps code
2024-07-23 23:11:00 +03:00
7d7e64fe5a Update docs+messages to reflect uidmaps/gidmaps code
Signed-off-by: Jason Chua <jasonc1804@gmail.com>
2024-07-22 20:54:41 -07:00
3c9c18c6e0 tests/integration: Automate deps manual test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-22 15:19:34 +02:00
d0a2a44442 Merge pull request #1003 from njhanley/remove-branch-names-from-contrib-docs
Remove references to nonexistent devel and stable branches
2024-07-19 19:11:48 +03:00
1e66c28bbb Remove references to nonexistent devel and stable branches
Closes #894

Signed-off-by: Nick Hanley <nicholasjhanley@gmail.com>
2024-07-18 21:41:59 -04:00
b6eadd56b1 Merge pull request #1002 from nerilex/main
Add `--network=none` if `network_mode: none` is set
2024-07-17 05:19:19 +03:00
d95b4d026b Add newsfragment
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-17 01:43:45 +03:00
bg
e2eb883709 Add --network=none if network_mode: none is set; fixes #1001.
Signed-off-by: bg <bg@nerilex.org>
2024-07-17 01:41:04 +03:00
0866492a7e Merge pull request #1000 from zoumingzhe/main
Support python direct call _parse_args or run
2024-07-15 18:48:39 +03:00
85050097e5 Support python direct call _parse_args or run
For example:
```
>>> from podman_compose import podman_compose
>>> podman_compose._parse_args(['version'])
>>> podman_compose.run(['help'])
```

Signed-off-by: Mingzhe Zou <zoumingzhe@qq.com>
2024-07-15 12:04:39 +08:00
daab93b762 Merge pull request #997 from mokibit/automate-build-tests
Automate manual `build` tests
2024-07-08 22:42:00 +03:00
9fe30387ee tests/integration: Automate 'build_fail' manual test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-08 21:37:29 +02:00
0f8348bea7 tests/integration: Automate 'build' manual test
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-08 21:36:29 +02:00
55ab3fa7f7 Merge pull request #994 from swick/wip/build-labels
Pass build description labels to podman build
2024-07-08 19:20:22 +03:00
2091ade7b1 Add newsfragment
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-08 19:15:16 +03:00
ca58d7cd58 Pass build description labels to podman build
The Compose Specification supports adding labels to the build image
which is also used in practice. Support this and pass the labels to
`podman build`.

Signed-off-by: Sebastian Wick <sebastian.wick@redhat.com>
2024-07-08 19:15:16 +03:00
3296c8d34f Merge pull request #993 from p12tic/compose-file-links
Don't resolve links to compose file
2024-07-06 19:35:18 +03:00
dab6b1b98d Merge pull request #992 from p12tic/docker-compose-name-compat
Add a way to remove dashes in default network names
2024-07-06 18:56:25 +03:00
5bf4c0fdbe Add a way to remove dashes in default network names
This is the behavior exhibited by docker compose. The network names are
user-visible through external networks, so previously anyone who
migrated from docker-compose needed to change their configuration. Now
it is possible to select compatibility via a flag in x-podman global
dictionary.

Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-06 18:50:25 +03:00
67c5352c3a Extract default_network_name_for_project()
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-06 18:32:09 +03:00
5e0f7e5e19 Merge pull request #990 from p12tic/tests-single-container-up
tests: Add integration tests for up -d with single container at a time
2024-07-06 01:06:23 +03:00
5040a37d47 tests: Add integration tests for up -d with single container at a time
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-06 00:59:50 +03:00
c82859b89f Merge pull request #989 from p12tic/github-install-requirements-unconditionally
github: Install requirements unconditionally
2024-07-04 09:19:30 +03:00
29195be77c github: Install requirements unconditionally
This makes tests less brittle as any renames to requirements files will
be noticed.

Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-04 09:17:27 +03:00
1c74d6cd11 Merge pull request #988 from p12tic/tests-discovery
Discover tests instead of passing a list of files to unittest
2024-07-03 19:52:56 +03:00
9a4af0ce62 Discover tests instead of passing a list of files to unittest
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-03 19:50:13 +03:00
0517b9e34c Merge pull request #987 from p12tic/check-if-pod-exists-before-creating
Check whether pod exists before trying to create one
2024-07-03 19:35:28 +03:00
24038dace3 Check whether pod exists before trying to create one
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-07-03 19:31:13 +03:00
0ea4cbe091 Merge pull request #984 from mokibit/reduce-path-calculation-duplication
tests/integration: Reduce base path calculation duplication
2024-07-03 09:13:49 +03:00
2056e703d5 tests/integration: Reduce base path calculation duplication
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-03 09:09:25 +03:00
137c6207b2 Merge pull request #981 from mokibit/add-unittests-for-secrets
unittests: Added unit tests for podman-compose secrets
2024-07-02 20:52:34 +03:00
4ec57c1013 unittests: Added unit tests for podman-compose secrets
Signed-off-by: Monika Kairaityte <monika@kibit.lt>
2024-07-02 20:26:58 +03:00
d9a3572461 Merge pull request #978 from PlugNPush/main
Restore support for alt dockerfiles (removing hardcoded "Dockerfile")
2024-06-26 21:39:42 +03:00
fa3e0a7772 Alt Dockerfile names fix
Signed-off-by: Michaël Nass - PlugN <michael.nass@free.fr>
2024-06-26 19:09:20 +02:00
0bcf0799b6 Merge pull request #976 from p12tic/tests-move-around
Move all tests to single directory "tests"
2024-06-26 11:30:21 +03:00
18472b53ac Move all tests to single directory "tests"
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-06-26 11:28:16 +03:00
f0bae1e2d9 Don't resolve links to compose file
docker-compose uses the path to the compose file even if it's symlink to
get the context directory.

Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2024-03-25 08:18:52 +02:00
205 changed files with 4233 additions and 940 deletions

View File

@ -13,8 +13,6 @@ A clear and concise description of what the bug is.
Please make sure it's not a bug in podman (in that case report it to podman) Please make sure it's not a bug in podman (in that case report it to podman)
or your understanding of docker-compose or how rootless containers work (for example, it's normal for rootless container not to be able to listen for port less than 1024 like 80) or your understanding of docker-compose or how rootless containers work (for example, it's normal for rootless container not to be able to listen for port less than 1024 like 80)
please try to reproduce the bug in latest devel branch
**To Reproduce** **To Reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. what is the content of the current working directory (ex. `docker-compose.yml`, `.env`, `Dockerfile`, ...etc.) 1. what is the content of the current working directory (ex. `docker-compose.yml`, `.env`, `Dockerfile`, ...etc.)

27
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: Build and Release
on:
push:
tags:
- 'v*.*.*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build binary
run: |
mkdir -p release/
docker build -t podman-compose-bin -v "$PWD/release:/result" .
mv "$PWD/release/podman-compose" "$PWD/release/podman-compose-linux-x86"
- name: Upload release asset
uses: softprops/action-gh-release@v2
with:
files: ./release/podman-compose-linux-x86
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -9,7 +9,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ] python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ]
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
@ -22,18 +22,18 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
set -e set -e
apt update && apt install -y podman apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y podman
python -m pip install --upgrade pip python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi pip install -r requirements.txt
if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi pip install -r test-requirements.txt
- name: Run tests in tests/ - name: Run integration tests
run: | run: |
python -m unittest -v tests/*.py python -m unittest discover -v tests/integration
env: env:
TESTS_DEBUG: 1 TESTS_DEBUG: 1
- name: Run tests in pytests/ - name: Run unit tests
run: | run: |
coverage run --source podman_compose -m unittest pytests/*.py coverage run --source podman_compose -m unittest discover tests/unit
- name: Report coverage - name: Report coverage
run: | run: |
coverage combine coverage combine

View File

@ -8,11 +8,6 @@
- Developers that want to fix bugs, - Developers that want to fix bugs,
- Developers that want to implement new functionalities or enhancements. - Developers that want to implement new functionalities or enhancements.
## Branches
Please request your pull request to be merged into the `devel` branch.
Changes to the `stable` branch are managed by the repository maintainers.
## Development environment setup ## Development environment setup
Note: Some steps are OPTIONAL but all are RECOMMENDED. Note: Some steps are OPTIONAL but all are RECOMMENDED.
@ -54,8 +49,8 @@ Note: Some steps are OPTIONAL but all are RECOMMENDED.
7. Run code coverage: 7. Run code coverage:
```shell ```shell
$ coverage run --source podman_compose -m unittest pytests/*.py $ coverage run --source podman_compose -m unittest discover tests/unit
$ python -m unittest tests/*.py $ python3 -m unittest discover tests/integration
$ coverage combine $ coverage combine
$ coverage report $ coverage report
$ coverage html $ coverage html
@ -68,8 +63,7 @@ Note: Some steps are OPTIONAL but all are RECOMMENDED.
- In the commit message, reference the Issue ID that your code fixes and a brief description of - In the commit message, reference the Issue ID that your code fixes and a brief description of
the changes. the changes.
Example: `Fixes #516: Allow empty network` Example: `Fixes #516: Allow empty network`
9. Open a pull request to `containers/podman-compose:devel` and wait for a maintainer to review your 9. Open a pull request to `containers/podman-compose` and wait for a maintainer to review your work.
work.
## Adding new commands ## Adding new commands

30
Dockerfile Normal file
View File

@ -0,0 +1,30 @@
# Use a base image with necessary build tools
FROM python:3.11-slim AS builder
# Install required packages for building
RUN apt-get update && apt-get install -y \
gcc \
musl-dev \
build-essential \
python3-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set the working directory
WORKDIR /app
# Copy the application code
COPY . .
# Install PyInstaller
RUN pip install pyinstaller
RUN pip install -r requirements.txt
# Create a binary with PyInstaller
RUN pyinstaller --onefile --clean podman_compose.py
# Create /result dir in case it is not mounted
RUN mkdir -p /result
# Export binary
RUN cp /app/dist/podman_compose /result/podman-compose

View File

@ -74,6 +74,12 @@ pip3 install https://github.com/containers/podman-compose/archive/main.tar.gz
brew install podman-compose brew install podman-compose
``` ```
### Generate binary using docker/podman locally
This script will download the repo, generate the binary using [this Dockerfile](https://github.com/containers/podman-compose/blob/main/Dockerfile), and place the binary in the directory where you called this script.
```bash
sh -c "$(curl -sSL https://raw.githubusercontent.com/containers/podman-compose/main/scripts/download_and_build_podman-compose.sh)"
```
### Manual ### Manual
```bash ```bash
@ -130,7 +136,7 @@ that are meant to test as many cases as we can to make sure we are compatible
run a unittest with following command run a unittest with following command
```shell ```shell
python -m unittest pytests/*.py python3 -m unittest discover tests/unit
``` ```
# Contributing guide # Contributing guide

47
RELEASING.md Normal file
View File

@ -0,0 +1,47 @@
Creating a release
==================
This file contains instructions for maintainers on how to release new versions of podman-compose.
Step 1: Initialize variables for subsequent steps
-------------------------------------------------
```
export VERSION=1.2.3
```
Step 2: Release notes PR
------------------------
Open a new branch (e.g. `release`) and run the following:
```
./scripts/make_release_notes.sh $VERSION
```
This collects the release notes using the `towncrier` tool and then commits the result.
This step is done as a PR so that CI can check for spelling errors and similar issues.
Certain file names are not properly supported by the `towncrier` tool and it ignores them.
Check `newsfragments` directory for any forgotten release notes
Step 3: Merge the release notes PR
----------------------------------
Step 4: Perform actual release
------------------------------
Pull the merge commit created on the `main` branch during the step 2.
Then run:
```
./scripts/make_release.sh
```
This will create release commit, tag and push everything.
Step 5: Create a release on Github
----------------------------------
The release notes must be added manually by drafting a release on the GitHub UI at
https://github.com/containers/podman-compose/releases.

38
docs/Changelog-1.3.0.md Normal file
View File

@ -0,0 +1,38 @@
Version 1.3.0 (2025-01-07)
==========================
Bug fixes
---------
- Fixed support for de-facto alternative `Dockerfile` names (e.g. `Containerfile`)
- Fixed a bug that caused attempts to create already existing pods multiple times.
- Fixed compatibility with docker-compose in how symlinks to docker-compose.yml are handled.
- Fixed freeze caused by too long log lines without a newline.
- Fixed support for `network_mode: none`.
- Improved error detection by rejecting service definitions that contain both `network_mode` and
`networks` keys, which is not allowed.
Features
--------
- Added support for build labels.
- Added support for "platform" property in the build command.
- Added support for "ssh" property in the build command.
- Added support for cache_from and cache_to fields in build section.
- Added support for honoring the condition in the depends_on section of the service, if stated.
- Added `x-podman.no_hosts` setting to pass `--no-hosts` to podman run
- Added support for compatibility with docker compose for default network behavior when no network
defined in service. This is controlled via `default_net_behavior_compat` feature flag.
- Added a way to get compatibility of default network names with docker compose.
This is selected by setting `default_net_name_compat: true` on `x-podman` global dictionary.
- Added support for the `device_cgroup_rules` property in services.
- Added support for removing networks in `podman-compose down`.
- Added support for network scoped service aliases.
- Added support for network level `mac_address` attribute.
- Added ability to substitute variables with the environment of the service.
Misc
----
- Declared compatibility with Python 3.13.

View File

@ -7,13 +7,15 @@ are generally specified under fields with "x-podman" prefix in the compose file.
The following extension keys are available under container configuration: The following extension keys are available under container configuration:
* `x-podman.uidmap` - Run the container in a new user namespace using the supplied UID mapping. * `x-podman.uidmaps` - Run the container in a new user namespace using the supplied UID mapping.
* `x-podman.gidmap` - Run the container in a new user namespace using the supplied GID mapping. * `x-podman.gidmaps` - Run the container in a new user namespace using the supplied GID mapping.
* `x-podman.rootfs` - Run the container without requiring any image management; the rootfs of the * `x-podman.rootfs` - Run the container without requiring any image management; the rootfs of the
container is assumed to be managed externally. container is assumed to be managed externally.
* `x-podman.no_hosts` - Run the container without creating /etc/hosts file
For example, the following docker-compose.yml allows running a podman container with externally managed rootfs. For example, the following docker-compose.yml allows running a podman container with externally managed rootfs.
```yml ```yml
version: "3" version: "3"
@ -36,6 +38,12 @@ Podman-compose in addition supports the specification of MAC addresses on a per-
is done by adding a `x-podman.mac_address` key to the network configuration in the container. The is done by adding a `x-podman.mac_address` key to the network configuration in the container. The
value of the `x-podman.mac_address` key is the MAC address to be used for the network interface. value of the `x-podman.mac_address` key is the MAC address to be used for the network interface.
Note that the [compose spec](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#mac_address)
now supports `mac_address` on the network level, so we recommend using
the standard `mac_address` key for setting the MAC address. The
`x-podman.mac_address` is still supported for backwards compatibility.
Specifying a MAC address for the container and for individual networks at the same time is not Specifying a MAC address for the container and for individual networks at the same time is not
supported. supported.
@ -67,7 +75,7 @@ services:
x-podman.mac_address: "02:aa:aa:aa:aa:aa" x-podman.mac_address: "02:aa:aa:aa:aa:aa"
net1: net1:
ipv4_address: "192.168.1.10" ipv4_address: "192.168.1.10"
x-podman.mac_address: "02:bb:bb:bb:bb:bb" mac_address: "02:bb:bb:bb:bb:bb" # mac_address is supported
``` ```
## Podman-specific network modes ## Podman-specific network modes
@ -91,6 +99,43 @@ The options to the network modes are passed to the `--network` option of the `po
as-is. as-is.
## Compatibility of default network names between docker-compose and podman-compose
Current versions of podman-compose may produce different default external network names than
docker-compose under certain conditions. Specifically, docker-compose removes dashes (`-` character)
from project name.
To enable compatibility between docker-compose and podman-compose, specify
`default_net_name_compat: true` under global `x-podman` key:
```
x-podman:
default_net_name_compat: true
```
By default `default_net_name_compat` is `false`. This will change to `true` at some point and the
setting will be removed.
## Compatibility of default network behavior between docker-compose and podman-compose
When there is no network defined (neither network-mode nor networks) in service,
The behavior of default network in docker-compose and podman-compose are different.
| Top-level networks | podman-compose | docker-compose |
| ------------------------------ | -------------------------- | -------------- |
| No networks | default | default |
| One network named net0 | net0 | default |
| Two networks named net0, net1 | podman(`--network=bridge`) | default |
| Contains network named default | default | default |
To enable compatibility between docker-compose and podman-compose, specify
`default_net_behavior_compat: true` under global `x-podman` key:
```yaml
x-podman:
default_net_behavior_compat: true
```
## Custom pods management ## Custom pods management
Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod. Podman-compose can have containers in pods. This can be controlled by extension key x-podman in_pod.

File diff suppressed because it is too large Load Diff

View File

@ -13,3 +13,43 @@ force-single-line = true
[tool.ruff.format] [tool.ruff.format]
preview = true # needed for quote-style preview = true # needed for quote-style
quote-style = "preserve" quote-style = "preserve"
[tool.towncrier]
package = "podman_compose"
package_dir = "master"
directory = "newsfragments"
filename = "docs/Changelog-new.md"
template = "scripts/Changelog-template.jinja"
title_format = "Version {version} ({project_date})"
[[tool.towncrier.section]]
path = ""
[[tool.towncrier.type]]
directory = "feature"
name = "Features"
showcontent = true
[[tool.towncrier.type]]
directory = "change"
name = "Changes"
showcontent = true
[[tool.towncrier.type]]
directory = "bugfix"
name = "Bug fixes"
showcontent = true
[[tool.towncrier.type]]
directory = "doc"
name = "Improved Documentation"
showcontent = true
[[tool.towncrier.type]]
directory = "removal"
name = "Deprecations and Removals"
showcontent = true
[[tool.towncrier.type]]
directory = "misc"
name = "Misc"
showcontent = true

View File

@ -1,91 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
import unittest
from podman_compose import container_to_args
from .test_container_to_args import create_compose_mock
from .test_container_to_args import get_minimal_container
class TestContainerToArgsSecrets(unittest.IsolatedAsyncioTestCase):
async def test_pass_secret_as_env_variable(self):
c = create_compose_mock()
c.declared_secrets = {
"my_secret": {"external": "true"} # must have external or name value
}
cnt = get_minimal_container()
cnt["secrets"] = [
{
"source": "my_secret",
"target": "ENV_SECRET",
"type": "env",
},
]
args = await container_to_args(c, cnt)
self.assertEqual(
args,
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--secret",
"my_secret,type=env,target=ENV_SECRET",
"busybox",
],
)
async def test_secret_as_env_external_true_has_no_name(self):
c = create_compose_mock()
c.declared_secrets = {
"my_secret": {
"name": "my_secret", # must have external or name value
}
}
cnt = get_minimal_container()
cnt["_service"] = "test-service"
cnt["secrets"] = [
{
"source": "my_secret",
"target": "ENV_SECRET",
"type": "env",
}
]
args = await container_to_args(c, cnt)
self.assertEqual(
args,
[
"--name=project_name_service_name1",
"-d",
"--network=bridge",
"--network-alias=service_name",
"--secret",
"my_secret,type=env,target=ENV_SECRET",
"busybox",
],
)
async def test_pass_secret_as_env_variable_no_external(self):
c = create_compose_mock()
c.declared_secrets = {
"my_secret": {} # must have external or name value
}
cnt = get_minimal_container()
cnt["_service"] = "test-service"
cnt["secrets"] = [
{
"source": "my_secret",
"target": "ENV_SECRET",
"type": "env",
}
]
with self.assertRaises(ValueError) as context:
await container_to_args(c, cnt)
self.assertIn('ERROR: unparsable secret: ', str(context.exception))

View File

@ -0,0 +1,33 @@
{% for section, _ in sections|dictsort(by='key') %}
{% set underline = "-" %}
{% if section %}
{{section}}
{{ underline * section|length }}{% set underline = "~" %}
{% endif %}
{% if sections[section] %}
{% for category, val in definitions|dictsort if category in sections[section]%}
{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}
{% endfor %}
{% if sections[section][category]|length == 0 %}
No significant changes.
{% else %}
{% endif %}
{% endfor %}
{% else %}
No significant changes.
{% endif %}
{% endfor %}
(venv) p12@exec-desktop:~/cod

View File

@ -0,0 +1,16 @@
#!/bin/sh
# Delete repository dir
rm -rf podman-compose-src
# Clone repository
git clone https://github.com/containers/podman-compose podman-compose-src
# Generate binary
sh podman-compose-src/scripts/generate_binary_using_dockerfile.sh
# Move binary outside repo's dir
mv podman-compose-src/podman-compose .
# Delete repository dir
rm -rf podman-compose-src

View File

@ -0,0 +1,57 @@
#!/bin/sh
# Find an available container tool (docker or podman)
find_container_tool() {
if command -v docker > /dev/null 2>&1; then
echo "sudo docker"
elif command -v podman > /dev/null 2>&1; then
echo "podman"
else
echo "Error: Neither docker nor podman is available." >&2
exit 1
fi
}
# Determine which container tool to use
CONTAINER_TOOL=$(find_container_tool)
# Locate the directory containing dockerfile (root)
PROJECT_ROOT_DIR="$(cd "$(dirname "$0")" && pwd)/.."
# Check SELinux status and set appropriate mount option
check_selinux() {
if command -v getenforce > /dev/null 2>&1; then
SELINUX_STATUS=$(getenforce)
if [ "$SELINUX_STATUS" = "Enforcing" ] || [ "$SELINUX_STATUS" = "Permissive" ]; then
echo ":z"
else
echo ""
fi
elif [ -f /sys/fs/selinux/enforce ]; then
if [ "$(cat /sys/fs/selinux/enforce)" = "1" ]; then
echo ":z"
else
echo ""
fi
else
echo ""
fi
}
# Get the SELinux option for volume mounts if SELinux is enforcing or permissive
SELINUX=$(check_selinux)
# Build binary
$CONTAINER_TOOL image rm build-podman-compose
if expr "$CONTAINER_TOOL" : '.*docker.*' >/dev/null; then
$CONTAINER_TOOL build -t build-podman-compose "$PROJECT_ROOT_DIR"
$CONTAINER_TOOL run --name build-podman-compose build-podman-compose
$CONTAINER_TOOL cp build-podman-compose:/result/podman-compose "$PROJECT_ROOT_DIR/podman-compose"
$CONTAINER_TOOL container stop build-podman-compose
$CONTAINER_TOOL container rm -f build-podman-compose
else
$CONTAINER_TOOL build -v "$PROJECT_ROOT_DIR:/result$SELINUX" -t build-podman-compose "$PROJECT_ROOT_DIR"
fi
$CONTAINER_TOOL image rm python:3.11-slim
$CONTAINER_TOOL image rm build-podman-compose

View File

@ -1,6 +1,18 @@
#!/usr/bin/env bash #!/bin/bash
./scripts/uninstall.sh
./scripts/clean_up.sh set -e
python3 setup.py register
python3 setup.py sdist bdist_wheel if [ $# -ne 1 ]; then
twine upload dist/* echo "Usage: make_release.sh VERSION"
exit 1
fi
VERSION=$1
sed "s/__version__ = .*/__version__ = \"$VERSION\"/g" -i podman_compose.py
git add podman_compose.py
git commit -m "Release $VERSION"
git tag "v$VERSION" -m "v$VERSION" -s
git push ssh://github.com/containers/podman-compose main "v$VERSION"

14
scripts/make_release_notes.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
set -e
if [ $# -ne 1 ]; then
echo "Usage: make_release_notes.sh VERSION"
exit 1
fi
VERSION=$1
towncrier build --version "$VERSION" --yes
git mv "docs/Changelog-new.md" "docs/Changelog-$VERSION.md"
git add "newsfragments/"
git commit -m "Release notes for $VERSION"

6
scripts/make_release_upload.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
./scripts/uninstall.sh
./scripts/clean_up.sh
python3 setup.py register
python3 setup.py sdist bdist_wheel
twine upload dist/*

View File

@ -17,11 +17,11 @@ setup(
classifiers=[ classifiers=[
"Programming Language :: Python", "Programming Language :: Python",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Operating System :: OS Independent", "Operating System :: OS Independent",
"Development Status :: 3 - Alpha", "Development Status :: 3 - Alpha",

View File

@ -29,5 +29,6 @@ pluggy==1.4.0
pyproject-api==1.6.1 pyproject-api==1.6.1
python-dotenv==1.0.1 python-dotenv==1.0.1
PyYAML==6.0.1 PyYAML==6.0.1
requests
tomlkit==0.12.4 tomlkit==0.12.4
virtualenv==20.25.1 virtualenv==20.25.1

View File

@ -1,25 +0,0 @@
# Test podman-compose with build
```
podman-compose build
podman-compose up -d
curl http://localhost:8080/index.txt
curl http://localhost:8000/index.txt
podman inspect my-busybox-httpd2
podman-compose down
```
expected output would be something like
```
2019-09-03T15:16:38+0000
ALT buildno=2 port 8000 2019-09-03T15:16:38+0000
{
...
}
```
as you can see we were able to override buildno to be 2 instead of 1,
and httpd_port to 8000.
NOTE: build labels are not passed to `podman build`

View File

@ -1,22 +0,0 @@
# Test podman-compose with build (fail scenario)
```shell
podman-compose build || echo $?
```
expected output would be something like
```
STEP 1/3: FROM busybox
STEP 2/3: RUN this_command_does_not_exist
/bin/sh: this_command_does_not_exist: not found
Error: building at STEP "RUN this_command_does_not_exist": while running runtime: exit status 127
exit code: 127
```
Expected `podman-compose` exit code:
```shell
echo $?
127
```

View File

@ -1,4 +0,0 @@
```
podman-compose run --rm sleep /bin/sh -c 'wget -O - http://web:8000/hosts'
```

View File

@ -1,37 +0,0 @@
running the following commands should always give podman-rocks-123
```
podman-compose -f project/container-compose.yaml --env-file env-files/project-1.env up
```
```
podman-compose -f $(pwd)/project/container-compose.yaml --env-file $(pwd)/env-files/project-1.env up
```
```
podman-compose -f $(pwd)/project/container-compose.env-file-flat.yaml up
```
```
podman-compose -f $(pwd)/project/container-compose.env-file-obj.yaml up
```
```
podman-compose -f $(pwd)/project/container-compose.env-file-obj-optional.yaml up
```
based on environment variable precedent this command should give podman-rocks-321
```
ZZVAR1=podman-rocks-321 podman-compose -f $(pwd)/project/container-compose.yaml --env-file $(pwd)/env-files/project-1.env up
```
_The below test should print three environment variables_
```
podman-compose -f $(pwd)/project/container-compose.load-.env-in-project.yaml run --rm app
ZZVAR1=This value is overwritten by env-file-tests/.env
ZZVAR2=This value is loaded from .env in project/ directory
ZZVAR3=This value is loaded from env-file-tests/.env
```

View File

@ -1,5 +0,0 @@
running the following command should give myval2
```
podman_compose run -l monkey -e ZZVAR1=myval2 env-test
```

View File

@ -1,15 +0,0 @@
We have service named sh1 that exits with code 1 and sh2 that exists with code 2
```
podman-compose up --exit-code-from=sh1
echo $?
```
the above should give 1.
```
podman-compose up --exit-code-from=sh2
echo $?
```
the above should give 2.

View File

@ -0,0 +1 @@
FROM busybox

View File

@ -0,0 +1,22 @@
version: "3"
services:
test_build_labels_map:
build:
context: ./context
dockerfile: Dockerfile
labels:
com.example.description: "Accounting webapp"
com.example.department: "Finance"
com.example.label-with-empty-value: ""
image: my-busybox-build-labels-map
command: env
test_build_labels_array:
build:
context: ./context
dockerfile: Dockerfile
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
image: my-busybox-build-labels-array
command: env

View File

@ -0,0 +1,60 @@
# SPDX-License-Identifier: GPL-2.0
import json
import os
import unittest
from tests.integration.test_podman_compose import podman_compose_path
from tests.integration.test_podman_compose import test_path
from tests.integration.test_utils import RunSubprocessMixin
class TestBuildLabels(unittest.TestCase, RunSubprocessMixin):
def test_build_labels(self):
"""The build context can contain labels which should be added to the resulting image. They
can be either an array or a map.
"""
compose_path = os.path.join(test_path(), "build_labels/docker-compose.yml")
try:
self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"build",
"test_build_labels_map",
"test_build_labels_array",
])
expected_labels = {
"com.example.department": "Finance",
"com.example.description": "Accounting webapp",
"com.example.label-with-empty-value": "",
}
out, _ = self.run_subprocess_assert_returncode([
"podman",
"inspect",
"my-busybox-build-labels-map",
"my-busybox-build-labels-array",
])
images = json.loads(out)
self.assertEqual(len(images), 2)
labels_map = images[0].get("Config", {}).get("Labels", {})
labels_array = images[1].get("Config", {}).get("Labels", {})
for k, v in expected_labels.items():
self.assertIn(k, labels_map)
self.assertEqual(labels_map[k], v)
self.assertIn(k, labels_array)
self.assertEqual(labels_array[k], v)
finally:
self.run_subprocess_assert_returncode([
"podman",
"rmi",
"my-busybox-build-labels-map",
"my-busybox-build-labels-array",
])

View File

@ -0,0 +1,16 @@
# Base image
FROM alpine:latest
# Install OpenSSH client
RUN apk add openssh
# Test the SSH agents during the build
RUN echo -n "default: " >> /result.log
RUN --mount=type=ssh ssh-add -L >> /result.log
RUN echo -n "id1: " >> /result.log
RUN --mount=type=ssh,id=id1 ssh-add -L >> /result.log
RUN echo -n "id2: " >> /result.log
RUN --mount=type=ssh,id=id2 ssh-add -L >> /result.log

View File

@ -0,0 +1,26 @@
version: "3"
services:
test_build_ssh_map:
build:
context: ./context
dockerfile: Dockerfile
ssh:
default:
id1: "./id_ed25519_dummy"
id2: "./agent_dummy.sock"
image: my-alpine-build-ssh-map
command:
- cat
- /result.log
test_build_ssh_array:
build:
context: ./context
dockerfile: Dockerfile
ssh:
- default
- "id1=./id_ed25519_dummy"
- "id2=./agent_dummy.sock"
image: my-alpine-build-ssh-array
command:
- cat
- /result.log

View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBWELzfWvraCAeo0rOM2OxTGqWZx7fNBCglK/1oS8FLpgAAAJhzHuERcx7h
EQAAAAtzc2gtZWQyNTUxOQAAACBWELzfWvraCAeo0rOM2OxTGqWZx7fNBCglK/1oS8FLpg
AAAEAEIrYvY3jJ2IvAnUa5jIrVe8UG+7G7PzWzZqqBQykZllYQvN9a+toIB6jSs4zY7FMa
pZnHt80EKCUr/WhLwUumAAAADnJpbmdvQGJuZHRib3gyAQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1,246 @@
# SPDX-License-Identifier: GPL-2.0
import os
import socket
import struct
import threading
import unittest
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from tests.integration.test_podman_compose import podman_compose_path
from tests.integration.test_podman_compose import test_path
from tests.integration.test_utils import RunSubprocessMixin
expected_lines = [
"default: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFYQvN9a+toIB6jSs4zY7FMapZnHt80EKCUr/WhLwUum",
"id1: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFYQvN9a+toIB6jSs4zY7FMapZnHt80EKCUr/WhLwUum",
"id2: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFYQvN9a+toIB6jSs4zY7FMapZnHt80EKCUr/WhLwUum",
]
class TestBuildSsh(unittest.TestCase, RunSubprocessMixin):
def test_build_ssh(self):
"""The build context can contain the ssh authentications that the image builder should
use during image build. They can be either an array or a map.
"""
compose_path = os.path.join(test_path(), "build_ssh/docker-compose.yml")
sock_path = os.path.join(test_path(), "build_ssh/agent_dummy.sock")
private_key_file = os.path.join(test_path(), "build_ssh/id_ed25519_dummy")
agent = MockSSHAgent(private_key_file)
try:
# Set SSH_AUTH_SOCK because `default` expects it
os.environ['SSH_AUTH_SOCK'] = sock_path
# Start a mock SSH agent server
agent.start_agent(sock_path)
self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"build",
"test_build_ssh_map",
"test_build_ssh_array",
])
for test_image in [
"test_build_ssh_map",
"test_build_ssh_array",
]:
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"run",
"--rm",
test_image,
])
out = out.decode('utf-8')
# Check if all lines are contained in the output
self.assertTrue(
all(line in out for line in expected_lines),
f"Incorrect output for image {test_image}",
)
finally:
# Now we send the stop command to gracefully shut down the server
agent.stop_agent()
if os.path.exists(sock_path):
os.remove(sock_path)
self.run_subprocess_assert_returncode([
"podman",
"rmi",
"my-alpine-build-ssh-map",
"my-alpine-build-ssh-array",
])
# SSH agent message types
SSH_AGENTC_REQUEST_IDENTITIES = 11
SSH_AGENT_IDENTITIES_ANSWER = 12
SSH_AGENT_FAILURE = 5
STOP_REQUEST = 0xFF
class MockSSHAgent:
def __init__(self, private_key_path):
self.sock_path = None
self.server_sock = None
self.running = threading.Event()
self.keys = [self._load_ed25519_private_key(private_key_path)]
self.agent_thread = None # Thread to run the agent
def _load_ed25519_private_key(self, private_key_path):
"""Load ED25519 private key from an OpenSSH private key file."""
with open(private_key_path, 'rb') as key_file:
private_key = serialization.load_ssh_private_key(key_file.read(), password=None)
# Ensure it's an Ed25519 key
if not isinstance(private_key, Ed25519PrivateKey):
raise ValueError("Invalid key type, expected ED25519 private key.")
# Get the public key corresponding to the private key
public_key = private_key.public_key()
# Serialize the public key to the OpenSSH format
public_key_blob = public_key.public_bytes(
encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
)
# SSH key type "ssh-ed25519"
key_type = b"ssh-ed25519"
# Build the key blob (public key part for the agent)
key_blob_full = (
struct.pack(">I", len(key_type))
+ key_type # Key type length + type
+ struct.pack(">I", len(public_key_blob))
+ public_key_blob # Public key length + key blob
)
# Comment (empty)
comment = ""
return ("ssh-ed25519", key_blob_full, comment)
def start_agent(self, sock_path):
"""Start the mock SSH agent and create a Unix domain socket."""
self.sock_path = sock_path
if os.path.exists(self.sock_path):
os.remove(self.sock_path)
self.server_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.server_sock.bind(self.sock_path)
self.server_sock.listen(5)
os.environ['SSH_AUTH_SOCK'] = self.sock_path
self.running.set() # Set the running event
# Start a thread to accept client connections
self.agent_thread = threading.Thread(target=self._accept_connections, daemon=True)
self.agent_thread.start()
def _accept_connections(self):
"""Accept and handle incoming connections."""
while self.running.is_set():
try:
client_sock, _ = self.server_sock.accept()
self._handle_client(client_sock)
except Exception as e:
print(f"Error accepting connection: {e}")
def _handle_client(self, client_sock):
"""Handle a single client request (like ssh-add)."""
try:
# Read the message length (first 4 bytes)
length_message = client_sock.recv(4)
if not length_message:
raise "no length message received"
msg_len = struct.unpack(">I", length_message)[0]
request_message = client_sock.recv(msg_len)
# Check for STOP_REQUEST
if request_message[0] == STOP_REQUEST:
client_sock.close()
self.running.clear() # Stop accepting connections
return
# Check for SSH_AGENTC_REQUEST_IDENTITIES
if request_message[0] == SSH_AGENTC_REQUEST_IDENTITIES:
response = self._mock_list_keys_response()
client_sock.sendall(response)
else:
print("Message not recognized")
# Send failure if the message type is not recognized
response = struct.pack(">I", 1) + struct.pack(">B", SSH_AGENT_FAILURE)
client_sock.sendall(response)
except socket.error:
print("Client socket error.")
pass # You can handle specific errors here if needed
finally:
client_sock.close() # Ensure the client socket is closed
def _mock_list_keys_response(self):
"""Create a mock response for ssh-add -l, listing keys."""
# Start building the response
response = struct.pack(">B", SSH_AGENT_IDENTITIES_ANSWER) # Message type
# Number of keys
response += struct.pack(">I", len(self.keys))
# For each key, append key blob and comment
for key_type, key_blob, comment in self.keys:
# Key blob length and content
response += struct.pack(">I", len(key_blob)) + key_blob
# Comment length and content
comment_encoded = comment.encode()
response += struct.pack(">I", len(comment_encoded)) + comment_encoded
# Prefix the entire response with the total message length
response = struct.pack(">I", len(response)) + response
return response
def stop_agent(self):
"""Stop the mock SSH agent."""
if self.running.is_set(): # First check if the agent is running
# Create a temporary connection to send the stop command
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client_sock:
client_sock.connect(self.sock_path) # Connect to the server
stop_command = struct.pack(
">B", STOP_REQUEST
) # Pack the stop command as a single byte
# Send the message length first
message_length = struct.pack(">I", len(stop_command))
client_sock.sendall(message_length) # Send the length first
client_sock.sendall(stop_command) # Send the stop command
self.running.clear() # Stop accepting new connections
# Wait for the agent thread to finish
if self.agent_thread:
self.agent_thread.join() # Wait for the thread to finish
self.agent_thread = None # Reset thread reference
# Remove the socket file only after the server socket is closed
if self.server_sock: # Check if the server socket exists
self.server_sock.close() # Close the server socket
os.remove(self.sock_path)

View File

@ -0,0 +1,4 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/

View File

@ -0,0 +1,7 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
x-podman:
default_net_behavior_compat: true

View File

@ -0,0 +1,7 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
networks:
net0: {}

View File

@ -0,0 +1,10 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
networks:
net0: {}
x-podman:
default_net_behavior_compat: true

View File

@ -0,0 +1,8 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
networks:
net0: {}
net1: {}

View File

@ -0,0 +1,11 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
networks:
net0: {}
net1: {}
x-podman:
default_net_behavior_compat: true

View File

@ -0,0 +1,9 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
networks:
net0: {}
net1: {}
default: {}

View File

@ -0,0 +1,12 @@
services:
web:
image: busybox
command: httpd -f -p 8123 -h /tmp/
networks:
net0: {}
net1: {}
default: {}
x-podman:
default_net_behavior_compat: true

View File

@ -0,0 +1,22 @@
version: "3.7"
services:
web:
image: nopush/podman-compose-test
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-h", "/etc/", "-p", "8000"]
tmpfs:
- /run
- /tmp
healthcheck:
test: ["CMD", "/bin/false"]
interval: 10s # Time between health checks
timeout: 1s # Time to wait for a response
retries: 1 # Number of consecutive failures before marking as unhealthy
sleep:
image: nopush/podman-compose-test
command: ["dumb-init", "/bin/busybox", "sh", "-c", "sleep 3600"]
depends_on:
web:
condition: service_healthy
tmpfs:
- /run
- /tmp

View File

@ -0,0 +1,22 @@
version: "3.7"
services:
web:
image: nopush/podman-compose-test
command: ["dumb-init", "/bin/busybox", "httpd", "-f", "-h", "/etc/", "-p", "8000"]
tmpfs:
- /run
- /tmp
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8000/hosts"]
interval: 30s # Time between health checks
timeout: 5s # Time to wait for a response
retries: 3 # Number of consecutive failures before marking as unhealthy
sleep:
image: nopush/podman-compose-test
command: ["dumb-init", "/bin/busybox", "sh", "-c", "sleep 3600"]
depends_on:
web:
condition: service_healthy
tmpfs:
- /run
- /tmp

View File

@ -7,5 +7,5 @@ services:
- /tmp - /tmp
env_file: env_file:
- path: ../env-files/project-1.env - path: ../env-files/project-1.env
- path: ../env-files/project-2.env - path: ../env-files/project-2.env # this file exists
required: false required: false

View File

@ -0,0 +1,11 @@
services:
app:
image: busybox
command: ["/bin/busybox", "sh", "-c", "env | grep ZZ"]
tmpfs:
- /run
- /tmp
env_file:
- path: ../env-files/project-1.env
- path: ../env-files/project-3.env # this file is missing
required: false

View File

@ -1,9 +1,10 @@
version: '3' version: "3"
services: services:
env-test: env-test:
image: busybox image: busybox
command: sh -c "export | grep ZZ" command: sh -c "export | grep ZZ"
environment: environment:
- ZZVAR1=myval1 ZZVAR1: myval1
ZZVAR2: 2-$ZZVAR1
ZZVAR3: 3-$ZZVAR2

View File

@ -1,11 +1,5 @@
version: "3" version: "3"
services: services:
too_long:
image: nopush/podman-compose-test
command: ["dumb-init", "/bin/busybox", "sh", "-c", "sleep 3600; exit 0"]
tmpfs:
- /run
- /tmp
sh1: sh1:
image: nopush/podman-compose-test image: nopush/podman-compose-test
command: ["dumb-init", "/bin/busybox", "sh", "-c", "sleep 1; exit 1"] command: ["dumb-init", "/bin/busybox", "sh", "-c", "sleep 1; exit 1"]

View File

@ -0,0 +1 @@
FROM nopush/podman-compose-test as base

View File

@ -0,0 +1 @@
../compose_symlink_dest/docker-compose.yml

View File

@ -0,0 +1 @@
data_compose_symlink

View File

@ -0,0 +1,7 @@
version: "3"
services:
container1:
image: nopush/podman-compose-test
command: ["/bin/busybox", "cat", "/file"]
volumes:
- "./file:/file"

View File

@ -0,0 +1 @@
data_compose_symlink_dest

View File

@ -4,8 +4,8 @@ services:
image: busybox image: busybox
command: ["/bin/busybox", "sh", "-c", "export | grep EXAMPLE"] command: ["/bin/busybox", "sh", "-c", "export | grep EXAMPLE"]
environment: environment:
EXAMPLE_VARIABLE: "Host user: $USER" EXAMPLE_VARIABLE: "Host user: $EXAMPLE_VARIABLE_USER"
EXAMPLE_BRACES: "Host user: ${USER}" EXAMPLE_BRACES: "Host user: ${EXAMPLE_VARIABLE_USER}"
EXAMPLE_COLON_DASH_DEFAULT: ${NOT_A_VARIABLE:-My default} EXAMPLE_COLON_DASH_DEFAULT: ${NOT_A_VARIABLE:-My default}
EXAMPLE_DASH_DEFAULT: ${NOT_A_VARIABLE-My other default} EXAMPLE_DASH_DEFAULT: ${NOT_A_VARIABLE-My other default}
EXAMPLE_DOT_ENV: $DOT_ENV_VARIABLE EXAMPLE_DOT_ENV: $DOT_ENV_VARIABLE

View File

@ -1,6 +1,6 @@
version: '3' version: '3'
# --ipam-driver must not be pass when driver is "default" # --ipam-driver must not be passed when driver is "default"
networks: networks:
ipam_test_default: ipam_test_default:
ipam: ipam:

View File

@ -0,0 +1,125 @@
# SPDX-License-Identifier: GPL-2.0
import os
import unittest
from parameterized import parameterized
from tests.integration.test_podman_compose import podman_compose_path
from tests.integration.test_podman_compose import test_path
from tests.integration.test_utils import RunSubprocessMixin
class TestLifetime(unittest.TestCase, RunSubprocessMixin):
def test_up_single_container(self):
"""Podman compose up should be able to start containers one after another"""
compose_path = os.path.join(test_path(), "lifetime/up_single_container/docker-compose.yml")
try:
self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"up",
"-d",
"container1",
])
self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"up",
"-d",
"container2",
])
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"logs",
"container1",
])
self.assertEqual(out, b"test1\n")
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"logs",
"container2",
])
self.assertEqual(out, b"test2\n")
finally:
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"down",
])
@parameterized.expand([
("no_ports", "up_single_container_many_times"),
("with_ports", "up_single_container_many_times_with_ports"),
])
def test_up_single_container_many_times(self, name, subdir):
"""Podman compose up should be able to start a container many times after it finishes
running.
"""
compose_path = os.path.join(test_path(), f"lifetime/{subdir}/docker-compose.yml")
try:
self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"up",
"-d",
"container1",
])
for _ in range(0, 3):
self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"up",
"-d",
"container2",
])
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"logs",
"container1",
])
self.assertEqual(out, b"test1\n")
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"logs",
"container2",
])
# BUG: container should be started 3 times, not 4.
self.assertEqual(out, b"test2\n" * 4)
finally:
out, _ = self.run_subprocess_assert_returncode([
podman_compose_path(),
"-f",
compose_path,
"down",
])

View File

@ -0,0 +1,8 @@
version: "3"
services:
container1:
image: nopush/podman-compose-test
command: ["/bin/bash", "-c", "echo test1; sleep infinity"]
container2:
image: nopush/podman-compose-test
command: ["/bin/bash", "-c", "echo test2; sleep infinity"]

View File

@ -0,0 +1,9 @@
version: "3"
services:
container1:
image: nopush/podman-compose-test
command: ["/bin/bash", "-c", "echo test1; sleep infinity"]
container2:
image: nopush/podman-compose-test
restart: never
command: ["/bin/bash", "-c", "echo test2"]

Some files were not shown because too many files have changed in this diff Show More