Compare commits

...

1919 Commits

Author SHA1 Message Date
Paweł Gronowski 6e6a273573
Merge pull request #3270 from Khushiyant/volume-subpath
Implement Subpath Support for Volumes in Docker-Py (#3243)
2025-06-11 09:21:35 +00:00
Sebastiaan van Stijn 526a9db743
Merge pull request #3336 from thaJeztah/fix_onbuild_assert
integration: adjust tests for omitted "OnBuild"
2025-05-22 10:44:55 +02:00
Sebastiaan van Stijn e5c3eb18b6
integration: adjust tests for omitted "OnBuild"
The Docker API may either return an empty "OnBuild" or omit the
field altogether if it's not set.

Adjust the tests to make either satisfy the test.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-05-22 01:46:53 +02:00
Khushiyant 820769e23c feat(docker/api/container): add support for subpath in volume_opts
TESTED: Yes, added unit tests to verify subpath functionality
Signed-off-by: Khushiyant <khushiyant2002@gmail.com>
2025-03-18 23:16:03 +05:30
Shaun Thompson db7f8b8bb6
Merge pull request #3296 from thaJeztah/fix_test_create_volume_invalid_driver
integration: test_create_volume_invalid_driver allow either 400 or 404
2025-01-17 12:32:14 -05:00
Shaun Thompson 747d23b9d7
Merge pull request #3307 from thaJeztah/deprecated_json_error
image load: don't depend on deprecated JSONMessage.error field
2025-01-17 12:30:54 -05:00
Sebastiaan van Stijn fad84c371a
integration: test_create_volume_invalid_driver allow either 400 or 404
The API currently returns a 404 error when trying to create a volume with
an invalid (non-existing) driver. We are considering changing this status
code to be a 400 (invalid parameter), as even though the _reason_ of the
error may be that the plugin / driver is not found, the _cause_ of the
error is that the user provided a plugin / driver that's invalid for the
engine they're connected to.

This patch updates the test to pass for either case.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-14 14:23:24 +01:00
Sebastiaan van Stijn 5a8a42466e
image load: don't depend on deprecated JSONMessage.error field
The error field  was deprecated in favor of the errorDetail struct in
[moby@3043c26], but the API continued to return both. This patch updates
docker-py to not depend on the deprecated field.

[moby@3043c26]: 3043c26419

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-14 13:23:38 +01:00
Sebastiaan van Stijn 03e43be6af
Merge pull request #3297 from thaJeztah/fix_makefile_circref
Makefile: fix circular reference for integration-dind
2024-11-18 18:03:11 +01:00
Sebastiaan van Stijn 80a584651b
Merge pull request #2442 from thaJeztah/test_service_logs_un_experimental
test_service_logs: stop testing experimental versions
2024-11-18 18:02:30 +01:00
Sebastiaan van Stijn 8ee28517c7
test_service_logs: stop testing experimental versions
Service logs are no longer experimental, so updating the tests
to only test against "stable"  implementations, and no longer
test the experimental ones.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-18 16:09:21 +01:00
Sebastiaan van Stijn d9f9b965b2
Makefile: fix circular reference for integration-dind
Noticed this warning;

    make: Circular integration-dind <- integration-dind dependency dropped.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-18 16:07:01 +01:00
Bjorn Neergaard fba6ffe297
Merge pull request #3267 from thaJeztah/add_default_version
Set a dummy-version if none set, and remove unused APT_MIRROR build-arg
2024-11-18 07:48:00 -07:00
Sebastiaan van Stijn 99ce2e6d56
Makefile: remove unused APT_MIRROR build-arg
The APT_MIRROR build-arg was removed from the Dockerfile in commit
ee2310595d, but wasn't removed from the
Makefile.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-18 15:41:24 +01:00
Sebastiaan van Stijn 504ce6193c
Set a dummy-version if none set
Make sure the Dockerfiles can be built even if no VERSION build-arg
is passed.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-18 15:41:19 +01:00
Sebastiaan van Stijn bb0edd1f66
Merge pull request #3261 from thaJeztah/bump_engine_versions
Bump default API version to 1.45 (Moby 26.0/26.1)
2024-10-27 17:09:14 +01:00
Sebastiaan van Stijn e47e966e94
Bump default API version to 1.45 (Moby 26.0/26.1)
- Update API version to the latest maintained release.
0 Adjust tests for API 1.45

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-27 17:03:02 +01:00
Sebastiaan van Stijn a8bac88221
Merge pull request #3292 from yasonk/fix-exec_run-doc
fixing doc for stream param in exec_run
2024-09-30 23:22:45 +02:00
Sebastiaan van Stijn e031cf0c23
Merge pull request #3290 from laurazard/exec-no-executable-exit-code
tests/exec: expect 127 exit code for missing executable
2024-09-30 15:18:31 +02:00
Laura Brehm b1265470e6
tests/exec: add test for exit code from exec
Execs should return the exit code of the exec'd process, if it started.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-09-30 14:07:04 +01:00
yasonk 6bbf741c8c
fixing doc for stream param in exec_run
Signed-off-by: yasonk <yason@hey.com>
2024-09-29 18:58:38 -07:00
Laura Brehm 96ef4d3bee
tests/exec: expect 127 exit code for missing executable
Docker Engine has always returned `126` when starting an exec fails due
to a missing binary, but this was due to a bug in the daemon causing the
correct exit code to be overwritten in some cases – see: https://github.com/moby/moby/issues/45795

Change tests to expect correct exit code (`127`).

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-09-27 15:33:11 +01:00
Sebastiaan van Stijn a3652028b1
Merge pull request #3264 from krissetto/rename-env-var-in-release-pipeline
Change env var name in release pipeline to match hatch expectations
2024-05-23 13:09:32 +02:00
Christopher Petito 1ab40c8e92 Fix env var name in release pipeline to match hatch expectations
Signed-off-by: Christopher Petito <47751006+krissetto@users.noreply.github.com>
2024-05-23 10:49:23 +00:00
Laura Brehm b33088e0ca
Merge pull request #3263 from krissetto/fix-release-pipeline
Fix env var name in release pipeline
2024-05-23 11:32:12 +01:00
Christopher Petito 45488acfc1 Fix env var name in release pipeline
Signed-off-by: Christopher Petito <47751006+krissetto@users.noreply.github.com>
2024-05-23 10:14:18 +00:00
Laura Brehm 20879eca6a
Merge pull request #3262 from krissetto/changelog-7.1.0 2024-05-23 10:37:29 +01:00
Christopher Petito 4f2a26d21e Added 7.1.0 changelog
Signed-off-by: Christopher Petito <47751006+krissetto@users.noreply.github.com>
2024-05-23 09:30:30 +00:00
Sebastiaan van Stijn 7785ad913d
Merge pull request #3257 from felixfontein/requests-hotfix
Fix for requests 2.32
2024-05-22 15:02:59 +02:00
Felix Fontein d8e9bcb278 requests 2.32.0 and 2.32.1 have been yanked.
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-05-22 14:50:14 +02:00
Felix Fontein 2a059a9f19 Extend fix to requests 2.32.2+.
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-05-22 14:50:14 +02:00
Felix Fontein e33e0a437e Hotfix for requests 2.32.0.
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-05-22 14:50:14 +02:00
Sebastiaan van Stijn b86573a3e3
Merge pull request #3260 from krissetto/fix-ci
CI fix
2024-05-22 14:45:11 +02:00
Christopher Petito e34bcf20d9 Update setup-python gh action
Signed-off-by: Christopher Petito <47751006+krissetto@users.noreply.github.com>
2024-05-22 11:10:22 +00:00
Christopher Petito 205d2f2bd0 Fix to get our CI working again since we rely on parsing tags.
See https://github.com/docker/docker-py/pull/3259 attempts for more details

Signed-off-by: Christopher Petito <47751006+krissetto@users.noreply.github.com>
2024-05-22 10:58:13 +00:00
Bob Du b6464dbed9
chore: fix return type docs for `container.logs()` (#2240) 2024-04-09 16:13:21 -04:00
Milas Bowman 9ad4bddc9e
chore(ci): fix-ups across Make / Docker / GitHub Actions (#3241) 2024-04-03 08:44:29 -04:00
Milas Bowman 336e65fc3c
Merge pull request #3212 from valohai/ruff-i 2024-03-29 13:31:57 -04:00
Milas Bowman 4c6437d292 Merge pull request #3212 from valohai/ruff-i 2024-03-29 13:28:43 -04:00
Milas Bowman 0fd79c8c0d
Merge pull request #3207 from valohai/modernize-build 2024-03-29 13:14:36 -04:00
Paweł Gronowski 3d79ce8c60
Merge pull request #3231 from vvoland/engine-25
Bump default API version to 1.44 (Moby 25.0)
2024-03-25 17:36:55 +01:00
Paweł Gronowski dd82f9ae8e
Bump minimum API version to 1.24
25.0 raised the minimum supported API verison: https://github.com/moby/moby/pull/46887

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-03-14 11:04:39 +01:00
Paweł Gronowski e91b280074
Bump default API version to 1.44 (Moby 25.0)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-03-14 11:04:37 +01:00
Rob Murray cb21af7f69 Fix tests that look at 'Aliases'
Inspect output for 'NetworkSettings.Networks.<network>.Aliases'
includes the container's short-id (although it will be removed
in API v1.45, in moby 26.0).

Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-03-13 14:54:25 +00:00
Aarni Koskela 1818712b8c Untangle circular imports
Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 21:40:11 +02:00
Aarni Koskela d50cc429c2 Enable Ruff I (import sort), autofix
Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 21:28:56 +02:00
Aarni Koskela 047df6b0d3 Build wheel in CI, upload artifact for perusal
Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 21:20:13 +02:00
Aarni Koskela ae45d477c4 Use `hatch` for packaging
Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 21:20:11 +02:00
Aarni Koskela f128956034 Use `build` instead of calling setup.py
Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 21:20:02 +02:00
Milas Bowman bd164f928a
Merge pull request #3205 from valohai/drop-packaging-dep
Drop `packaging` dependency
2024-01-03 14:19:02 -05:00
Aarni Koskela 249654d4d9 Drop `packaging` dependency
Compare versions like Moby (api/types/versions/compare.go)

Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 21:12:37 +02:00
Milas Bowman 694d9792e6
lint: fix string formatting (#3211)
Merged a linter upgrade along with an older PR, so this was immediately in violation

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-01-03 14:01:42 -05:00
Khushiyant eeb9ea1937
docs: change image.history() return type to list (#3202)
Fixes #3076.

Signed-off-by: Khushiyant <khushiyant2002@gmail.com>
2024-01-03 18:56:10 +00:00
Aarni Koskela 08956b5fbc
ci: update Ruff & fix some minor issues (#3206)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2024-01-03 13:49:07 -05:00
Khushiyant b8a6987cd5
fix: keyerror when creating new config (#3200)
Closes #3110.

---------

Signed-off-by: Khushiyant <khushiyant2002@gmail.com>
2024-01-03 18:44:53 +00:00
Sebastiaan van Stijn f467fd9df9
Merge pull request #3208 from vvoland/fix-datetime_to_timestamp
utils: Fix datetime_to_timestamp
2024-01-03 19:13:33 +01:00
Sven 3ec5a6849a
fix(build): tag regex should allow ports (#3196)
Update the regex and add test cases.

(There are some xfails here for cases that the regex is not currently
handling. It's too strict for IPv6 domains at the moment.)

Closes: https://github.com/docker/docker-py/issues/3195
Related: https://github.com/opencontainers/distribution-spec/pull/498

Signed-off-by: Sven Kieske <kieske@osism.tech>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2024-01-03 10:48:45 -05:00
Paweł Gronowski 1784cc2962
utils: Fix datetime_to_timestamp
Replace usage of deprecated function `datetime.utcfromtimestamp` and
make sure the input date is UTC before subtracting.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-12-22 10:57:52 +01:00
Guillaume Lours 6ceb08273c
Merge pull request #3203 from vvoland/deprecated-containerconfig
integration/commit: Don't check for deprecated fields
2023-12-20 17:43:12 +01:00
Guillaume Lours 097382b973
Merge pull request #3199 from vvoland/engine-24
Bump default API version to 1.43 (Moby 24.0)
2023-12-20 08:24:37 +01:00
Paweł Gronowski 0fad869cc6
integration/commit: Don't check for deprecated fields
Container related Image fields (`Container` and `ContainerConfig`) will
be deprecated in API v1.44 and will be removed in v1.45.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-12-19 10:28:28 +01:00
Paweł Gronowski 2a5f354b50
Bump default API version to 1.43 (Moby 24.0)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-12-15 10:40:27 +01:00
Guillaume Lours 7d8a161b12
Merge pull request #3193 from milas/prep-7.0
chore: update changelog and maintainer
2023-12-08 09:52:27 +01:00
Milas Bowman 5388413dde chore: update changelog and maintainer
Preparing for the 7.0.0 final release 🎉

Added a couple more changelog items that came in as part of
`7.0.0b2` and updated the maintainer to be generically Docker,
Inc. instead of an individual.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-07 15:41:29 -05:00
Emran Batmanghelich 3d0a3f1d77
feat: accept all / filters / keep_storage in prune_builds (#3192)
Added in API v1.39.

---------

Signed-off-by: Emran Batmanghelich <emran.bm@gmail.com>
2023-12-05 10:05:44 -05:00
Daniel Lombardi a9b5494fd0
fix: validate tag before build using OCI regex (#3191)
Sources:
 * https://github.com/opencontainers/distribution-spec
 * https://docs.docker.com/engine/reference/commandline/tag/

Closes #3153.
---------

Signed-off-by: Daniel Lombardi <lombardi.daniel.o@gmail.com>
2023-12-05 00:03:13 -05:00
Milas Bowman cb8f2c6630
chore: fix missing setuptools in CI (#3189)
Install `setuptools` in addition to `wheel` before trying to run
`python setup.py` manually.

Note that `setuptools` is already correctly listed in the
`pyproject.toml` file for consumers installing via `pip` etc, but
in CI the file is run directly to generate `sdist` and `bdist_wheel`
artifacts for PyPI.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-11-27 09:17:47 -05:00
Milas Bowman 7140969239
chore: update MAINTAINERS and remove CODEOWNERS (#3188)
Update `MAINTAINERS` with the current folks, adn remove the
`CODEOWNERS` file entirely -- it's not really helpful here,
as this project isn't big enough to have multiple subsections
with different maintainers/owners.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-11-21 12:17:12 -05:00
Milas Bowman 586988ce2d
chore: remove support for Python 3.7 (#3187)
Python 3.7 reached EOL in June 2023: https://endoflife.date/python

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-11-21 12:14:23 -05:00
Milas Bowman fd2f5029f0
chore: add changelog for 7.0.0 (#3186)
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-11-21 12:08:25 -05:00
Milas Bowman db4878118b
breaking: Python 3.12 compatibility & remove custom SSL adapter (#3185)
Add support for Python 3.12.

`match_hostname` is gone in Python 3.12 and has been unused by
Python since 3.7.

The custom SSL adapter allows passing a specific SSL version; this
was first introduced a looong time ago to handle some SSL issues
at the time.

Closes #3176.

---------

Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2023-11-21 10:42:53 -05:00
dependabot[bot] 976c84c481
build(deps): Bump urllib3 from 1.26.11 to 1.26.18 (#3183)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.11 to 1.26.18.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.11...1.26.18)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-20 16:56:50 -05:00
Milas Bowman b3349c88ef Merge branch 'pr-3147' 2023-11-20 16:18:23 -05:00
Milas Bowman b2378db7f1 chore: fix lint issue
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-11-20 16:18:08 -05:00
Milas Bowman 911f866f72
Merge branch 'main' into patch-1 2023-11-20 16:15:52 -05:00
Milas Bowman 26e07251d4 chore: fix lint issues
ruff ruff ruff!

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-11-20 16:11:06 -05:00
Aarni Koskela c9e3efddb8
feat: move websocket-client to extra dependency (#3123)
Also bump minimum version to that prescribed by #3022

Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-11-20 15:55:28 -05:00
Milas Bowman 4a88112345 Merge branch 'pr-3121'
https://github.com/docker/docker-py/pull/3121
2023-11-20 15:44:37 -05:00
Milas Bowman b70cbd0129 Merge remote-tracking branch 'upstream/main' into Skazza94/main 2023-11-20 15:38:27 -05:00
Mariano Scazzariello 7752996f78
Replace `network_config` with a dict of EndpointConfig
- Renamed parameter from `network_config` to `networking_config` to be more semantically correct with the rest of the API.
2023-09-30 00:20:44 +02:00
Jay Turner 5abae2dc8e
Merge branch 'main' into patch-1 2023-09-12 13:35:03 +01:00
Albin Kerouanton c38656dc78
integration: Remove test_create_check_duplicate (#3170)
integration: check_duplicate is now the default behavior

moby/moby#46251 marks CheckDuplicate as deprecated. Any NetworkCreate
request with a conflicting network name will now return an error.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2023-08-21 09:31:57 -04:00
Albin Kerouanton 378325363e
integration: Fix bad subnet declaration (#3169)
Some network integration tests are creating networks with subnet
`2001:389::1/64`. This is an invalid subnet as the host fragment is
non-zero (ie. it should be `2001:389::/64`).

PR moby/moby#45759 is adding strict validation of network configuration.
Docker API will now return an error whenever a bad subnet is passed.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2023-08-21 09:30:21 -04:00
Milas Bowman 0f0b20a6a7 Merge branch 'jannefleischer/main'
Manually merging #3164.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-08-15 14:04:29 -04:00
Janne Jakob Fleischer bea63224e0 volume: added support for bind propagation
https://docs.docker.com/storage/bind-mounts/#configure-bind-propagation

Signed-off-by: Janne Jakob Fleischer <janne.fleischer@ils-forschung.de>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-08-15 10:35:07 -04:00
Milas Bowman 8b9ad7807f Merge branch 'ruffify'
Manually merging #3126.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-08-15 09:58:21 -04:00
Aarni Koskela c68d532f54 Fix duplicate dict key literal (ruff F601)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela a9a3775b15 Noqa pytest.raises(Exception)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 3948540c89 Fix or noqa B003 (assigning to os.environ doesn't do what you expect)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 0566f1260c Fix missing asserts or assignments
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela cc76c9c20d Fix B082 (no explicit stacklevel for warnings)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 09f12f2046 Fix B005 (probably an actual bug too)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 6aec90a41b Fix Ruff B904s (be explicit about exception causes)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 8447f7b0f0 Enable Ruff B rules and autofix
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 601476733c Enable Ruff C rules and autofix
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela ec58856ee3 Clean up unnecessary noqa comments
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela fad792bfc7 Get rid of star import
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 9313536601 Switch linting from flake8 to ruff
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Aarni Koskela 8a3402c049 Replace string formatting with f-strings
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-08-15 13:36:53 +03:00
Sebastiaan van Stijn ee2310595d
test: remove APT_MIRROR from Dockerfile (#3145)
The official Python images on Docker Hub switched to debian bookworm,
which is now the current stable version of Debian.

However, the location of the apt repository config file changed, which
causes the Dockerfile build to fail;

    Loaded image: emptyfs:latest
    Loaded image ID: sha256:0df1207206e5288f4a989a2f13d1f5b3c4e70467702c1d5d21dfc9f002b7bd43
    INFO: Building docker-sdk-python3:5.0.3...
    tests/Dockerfile:6
    --------------------
       5 |     ARG APT_MIRROR
       6 | >>> RUN sed -ri "s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g" /etc/apt/sources.list \
       7 | >>>     && sed -ri "s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g" /etc/apt/sources.list
       8 |
    --------------------
    ERROR: failed to solve: process "/bin/sh -c sed -ri \"s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g\" /etc/apt/sources.list     && sed -ri \"s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g\" /etc/apt/sources.list" did not complete successfully: exit code: 2

The APT_MIRROR build-arg was originally added when the Debian package
repositories were known to be unreliable, but that hasn't been the
case for quite a while, so let's remove this altogether.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2023-08-14 15:12:44 -04:00
dependabot[bot] dbc061f4fa
build(deps): Bump requests from 2.28.1 to 2.31.0 (#3136)
Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 15:08:38 -04:00
VincentLeeMax 4571f7f9b4
feat: add pause option to commit api (#3159)
add commit pause option

Signed-off-by: VincentLeeMax <lichlee@yeah.net>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2023-08-14 14:52:38 -04:00
Mehmet Nuri Deveci 0618951093
fix: use response.text to get string rather than bytes (#3156)
Signed-off-by: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2023-08-14 14:43:31 -04:00
Milas Bowman 806d36a8cd
Merge pull request #3167 from thaJeztah/fix_ci_badge
README: fix link for CI status badge
2023-08-14 09:59:38 -04:00
Milas Bowman 79c4c38b42
Merge pull request #3165 from thaJeztah/tests_relax
tests/integration: update some tests for updated error-messages
2023-08-14 09:52:37 -04:00
Sebastiaan van Stijn 62b4bb8489
README: fix link for CI status badge
The default branch was renamed from master to main, but the badge was still
linking to the status for the master branch.

Remove the branch-name so that the badge always refers to the "default"
branch

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-14 14:58:34 +02:00
Sebastiaan van Stijn 5064995bc4
tests/integration: update some tests for updated error-messages
I was in the process of cleaning up some error-messages, and it looks like
the docker-py tests were depending on strings that will be removed;

    =================================== FAILURES ===================================
    _____________ CreateContainerTest.test_create_with_restart_policy ______________
    tests/integration/api_container_test.py:126: in test_create_with_restart_policy
        assert 'You cannot remove ' in err
    E   AssertionError: assert 'You cannot remove ' in 'cannot remove container d11580f6078108691096ec8a23404a6bda9ad1d1b2bafe88b17d127a67728833: container is restarting: stop the container before removing or force remove'
    ____________________ ErrorsTest.test_api_error_parses_json _____________________
    tests/integration/errors_test.py:13: in test_api_error_parses_json
        assert 'You cannot remove a running container' in explanation
    E   AssertionError: assert 'You cannot remove a running container' in 'cannot remove container 4b90ce2e907dd0f99d0f561619b803e7a2a31809ced366c537874dd13f8a47ec: container is running: stop the container before removing or force remove'

This updates the tests to match on a string that will be present in both the
old and new error-messages, but added a "lower()", so that matching will be
done case-insensitive (Go errors generally should be lowercase).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-14 14:52:58 +02:00
Milas Bowman 54ec0c6bf7
Merge pull request #3166 from thaJeztah/fix_flake8_failures
tests/integration: fix flake8 failures (E721 do not compare types), and fix Dockerfile for debian "bookworm"
2023-08-14 08:37:58 -04:00
Sebastiaan van Stijn 83e93228ea
tests/Dockerfile: fix Dockerfile for debian bookworm
The Dockerfile failed to build due to the base-image having switched to "bookworm";

    Dockerfile:8
    --------------------
       7 |     ARG APT_MIRROR
       8 | >>> RUN sed -ri "s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g" /etc/apt/sources.list \
       9 | >>>     && sed -ri "s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g" /etc/apt/sources.list
      10 |
    --------------------
    ERROR: failed to solve: process "/bin/sh -c sed -ri \"s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g\" /etc/apt/sources.list     && sed -ri \"s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g\" /etc/apt/sources.list" did not complete successfully: exit code: 2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-14 10:32:04 +02:00
Sebastiaan van Stijn fb974de27a
tests/integration: fix flake8 failures (E721 do not compare types)
Run flake8 docker/ tests/
      flake8 docker/ tests/
      shell: /usr/bin/bash -e {0}
      env:
        DOCKER_BUILDKIT: 1
        pythonLocation: /opt/hostedtoolcache/Python/3.11.4/x64
        PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.11.4/x64/lib/pkgconfig
        Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.4/x64
        Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.4/x64
        Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.4/x64
        LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.11.4/x64/lib
    tests/integration/api_container_test.py:1395:16: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
    tests/integration/api_container_test.py:1408:24: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
    tests/integration/api_image_test.py:35:16: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
    tests/integration/api_image_test.py:46:16: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
    Error: Process completed with exit code 1.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-14 10:26:36 +02:00
Jay Turner f0d38fb7f4
Add health property to Containers model
Signed-off-by: Jay Turner <jay.turner@kayenta.io>
2023-06-27 12:51:40 +01:00
Hao Yu 84414e343e
fix user_guides/multiplex.rst (#3130)
Signed-off-by: Longin-Yu <longinyh@gmail.com>
2023-06-06 14:28:15 -04:00
Mathieu Virbel 78439ebbe1
fix: eventlet compatibility (#3132)
Check if poll attribute exists on select module instead of win32 platform check

The implementation done in #2865 is breaking usage of docker-py library within eventlet.
As per the Python `select.poll` documentation (https://docs.python.org/3/library/select.html#select.poll) and eventlet select removal advice (https://github.com/eventlet/eventlet/issues/608#issuecomment-612359458), it is preferable to use an implementation based on the availability of the `poll()` method that trying to check if the platform is `win32`.

Fixes #3131

Signed-off-by: Mathieu Virbel <mat@meltingrocks.com>
2023-06-01 10:19:01 -04:00
Mariano Scazzariello 0318ad8e7e
Fix blank line
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-05-15 14:51:44 +02:00
Mariano Scazzariello 8ca9c6394f
Merge branch 'docker:main' into main 2023-05-15 12:57:02 +02:00
Milas Bowman bc4c0d7cf4 ci: empty commit to trigger readthedocs
Fixing integration

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-05-11 16:05:16 -04:00
Milas Bowman 14e8d07d45
docs: update changelog (#3127)
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-05-11 15:35:42 -04:00
loicleyendecker c5e582c413
api: avoid socket timeouts when executing commands (#3125)
Only listen to read events when polling a socket in order
to avoid incorrectly trying to read from a socket that is
not actually ready.

Signed-off-by: Loïc Leyendecker <loic.leyendecker@gmail.com>
2023-05-11 13:36:37 -04:00
Imogen 9cadad009e
api: respect timeouts on Windows named pipes (#3112)
Signed-off-by: Imogen <59090860+ImogenBits@users.noreply.github.com>
2023-05-08 13:01:19 -04:00
RazCrimson 443a35360f
Fix container.stats infinite blocking on stream mode (#3120)
fix: api - container.stats infinite blocking on stream mode

Includes additional test for no streaming

Signed-off-by: Bharath Vignesh J K <52282402+RazCrimson@users.noreply.github.com>
2023-05-07 19:51:24 -04:00
Mariano Scazzariello e011ff5be8
More sanity checking of EndpointConfig params
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-05-07 12:40:08 +02:00
Mariano Scazzariello 7870503c52
Fix case when "network_config" is not passed
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-05-07 12:15:32 +02:00
Mariano Scazzariello a18f91bf08
Fix long line
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-05-07 11:49:59 +02:00
Mariano Scazzariello a662d5a305
Fix pytests
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-05-07 11:47:07 +02:00
Mariano Scazzariello 1d697680d2
Full support to networking config during container creation
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-05-07 11:46:58 +02:00
John Yang 576e47aaac
api: update return type of `diff` method (#3115)
Signed-off-by: John Yang <john.yang20@berkeley.edu>
2023-05-05 16:21:46 -04:00
Felix Fontein 3178c8d48b
deps: compatiblity with requests ≥ 2.29.0 and urllib3 2.x (#3116)
Requirements are the same, so it's still possible to use `urllib3 < 2`
or `requests == 2.28.2` for example.

Signed-off-by: Felix Fontein <felix@fontein.de>
2023-05-05 11:39:31 -04:00
I-question-this a02ba74333
socket: use poll() instead of select() except on Windows (#2865)
Fixes #2278, which was originally addressed in #2279, but was not
properly merged. Additionally it did not address the problem
of poll not existing on Windows. This patch falls back on the
more limited select method if host system is Windows.

Signed-off-by: Tyler Westland <tylerofthewest@gmail.com>
2023-04-21 17:53:58 -04:00
Aarni Koskela aaf68b7f98
api: note the data arg may also be a stream in `put_archive` (#2478)
Signed-off-by: Aarni Koskela <akx@iki.fi>
2023-02-22 14:05:19 -05:00
Milas Bowman f84623225e
socket: fix for errors on pipe close in Windows (#3099)
Need to return data, not size. By returning an empty
string, EOF will be detected properly since `len()`
will be `0`.

Fixes #3098.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-02-22 12:00:47 -05:00
Lorin Bucher 7cd7458f2f
api: add `status` parameter to services list (#3093)
Signed-off-by: Lorin Bucher <lorin@lbtec.dev>
2023-02-16 10:38:52 -05:00
Andy Roxby e9d4ddfaec
api: add `one-shot` option to container `stats` (#3089)
Signed-off-by: Andy Roxby <107427605+aroxby-wayscript@users.noreply.github.com>
2023-02-16 10:27:45 -05:00
Milas Bowman aca129dd69 Merge branch 'master'
(Old PR unintentionally went to the `master` branch.)
2023-01-27 09:27:42 -05:00
Mariano Scazzariello ee9151f336
client: add `network_driver_opt` to container run and create (#3083)
Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2023-01-27 09:26:21 -05:00
Peter Wu 34e6829dd4
exec: fix file handle leak with container.exec_* APIs (#2320)
Requests with stream=True MUST be closed or else the connection will
never be returned to the connection pool. Both ContainerApiMixin.attach
and ExecApiMixin.exec_start were leaking in the stream=False case.
exec_start was modified to follow attach for the stream=True case as
that allows the caller to close the stream when done (untested).

Tested with:

    # Test exec_run (stream=False) - observe one less leak
    make integration-test-py3 file=models_containers_test.py' -k test_exec_run_success -vs -W error::ResourceWarning'
    # Test exec_start (stream=True, fully reads from CancellableStream)
    make integration-test-py3 file=api_exec_test.py' -k test_execute_command -vs -W error::ResourceWarning'

After this change, one resource leak is removed, the remaining resource
leaks occur because none of the tests call client.close().

Fixes https://github.com/docker/docker-py/issues/1293
(Regression from https://github.com/docker/docker-py/pull/1130)

Signed-off-by: Peter Wu <pwu@cloudflare.com>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2023-01-13 15:41:01 -05:00
Yanlong Wang 22718ba59a
fix(store): warn on init instead of throw (#3080)
Signed-off-by: yanlong.wang <yanlong.wang@naiver.org>
2023-01-10 17:45:25 -05:00
dependabot[bot] d38b41a13c
build(deps): Bump setuptools from 63.2.0 to 65.5.1 (#3082)
Bumps [setuptools](https://github.com/pypa/setuptools) from 63.2.0 to 65.5.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v63.2.0...v65.5.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 17:25:12 -05:00
Maxim Mironyuk 3afb4b61c3
docs: fix wrong command syntax in code annotation (#3081)
Signed-off-by: Maxim Mironyuk <serieznyi@gmail.com>
2023-01-10 16:58:51 -05:00
loicleyendecker 82cf559b5a
volume: do not strip trailing characters from names (#3073)
Only remove `:ro` or `:rw` suffixes in their entirety; do not
strip arbitrary `r` / `o` / `w` / `:` characters individually.

Signed-off-by: Loïc Leyendecker <loic.leyendecker@gmail.com>
2022-12-02 14:48:04 -05:00
Hugo van Kemenade 8590eaad3c
ci: add support for Python 3.11 (#3064)
Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2022-11-15 08:10:56 -05:00
Nick Santos 30022984f6
socket: handle npipe close on Windows (#3056)
Fixes https://github.com/docker/docker-py/issues/3045

Signed-off-by: Nick Santos <nick.santos@docker.com>
2022-11-02 15:31:00 -04:00
Brian Goff bc0a5fbacd
test: use anonymous volume for prune (#3051)
This is related to https://github.com/moby/moby/pull/44216

Prunes will, by default, no longer prune named volumes, only anonymous ones.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2022-10-05 13:54:45 -04:00
Rhiza 923e067ddd
api: add support for floats to docker logs params since / until (#3031)
Add support for floats to docker logs params `since` / `until` since the
Docker Engine APIs support it.

This allows using fractional seconds for greater precision.

Signed-off-by: Archi Moebius <poerhiz@gmail.com>
2022-08-19 15:10:53 -04:00
Sebastiaan van Stijn 1c27ec1f0c
ci: use latest stable syntax for Dockerfiles (#3035)
I noticed one Dockerfile was pinned to 1.4; given that there's a
backward compatibility guarantee on the stable syntax, the general
recommendation is to use `dockerfile:1`, which makes sure that the
latest stable release of the Dockerfile syntax is pulled before
building.

While changing, I also made some minor changes to some Dockerfiles
to reduce some unneeded layers.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-08-19 15:09:12 -04:00
Milas Bowman 2494d63f36
docs: install package in ReadTheDocs build (#3032)
Need to install ourselves so that we can introspect on version
using `setuptools_scm` in `docs/conf.py`.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-08-18 17:03:32 -04:00
Milas Bowman e901eac7a8
test: add additional tests for cgroupns option (#3024)
See #2930.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-08-12 14:27:53 -04:00
Chris Hand fc86ab0d85
swarm: add support for DataPathPort on init (#2987)
Adds support for setting the UDP port used for VXLAN traffic between
swarm nodes

Signed-off-by: Chris Hand <dexteradeus@users.noreply.github.com>
2022-08-12 09:58:57 -04:00
Milas Bowman 45bf9f9115 Merge remote-tracking branch 'upstream/main' into patch-1 2022-08-12 09:43:20 -04:00
Milas Bowman c03aeb659e Merge remote-tracking branch 'upstream/main' into connect-with-mac 2022-08-12 09:21:51 -04:00
Quentin Mathorel 58aa62bb15
swarm: add sysctl support for services (#3029)
Signed-off-by: Quentin Mathorel <quentin.mathorel@outlook.fr>
2022-08-12 08:55:19 -04:00
Milas Bowman ff0b4ac60b
docs: add changelog for 6.0.0 (#3019)
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-08-11 17:20:13 -04:00
Leonard Kinday 66402435d1
Support `global-job` and `replicated-job` modes in Docker Swarm (#3016)
Add `global-job` and `replicated-job` modes

Fixes #2829.

Signed-off-by: Leonard Kinday <leonard@kinday.ru>
2022-08-11 16:20:31 -04:00
Ningú 42789818be
credentials: eliminate distutils deprecation warnings (#3028)
While removing any usage of the deprecated `distutils` package,
("The distutils package is deprecated and slated for removal in Python 3.12.")
this internal utility can be removed straightaway because the
`shutil.which` replacement for `distutils.spawn.find_executable`
already honors the `PATHEXT` environment variable in windows systems.

See https://docs.python.org/3/library/shutil.html#shutil.which

Signed-off-by: Daniel Möller <n1ngu@riseup.net>
2022-08-02 10:19:50 -04:00
q0w ab5e927300
lint: remove extraneous logic for `preexec_func` (#2920)
`preexec_func` is still None if it is win32

Signed-off-by: q0w <43147888+q0w@users.noreply.github.com>
2022-08-02 10:11:07 -04:00
Saurav Maheshkar b7daa52feb
docs: add `gzip` arg to `BuildApiMixin` (#2929)
Signed-off-by: Saurav Maheshkar <sauravvmaheshkar@gmail.com>
2022-08-02 10:08:24 -04:00
Thomas Gassmann 3f0095a7c1
docs: remove duplicate 'on' in comment (#2370)
Remove duplicate 'on' in comment

Signed-off-by: Thomas Gassmann <thomas.gassmann@hotmail.com>
2022-07-30 12:43:29 -04:00
Milas Bowman 631b332cd9
ci: add missing wheel package
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-30 12:23:53 -04:00
Milas Bowman 7f1bde162f
ci: fix quoting in YAML
Because apparently `!` is special

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-30 12:20:50 -04:00
Milas Bowman cd2c35a9b6
ci: add workflow for releases (#3018)
GitHub Actions workflow to create a release: will upload to PyPI
and create a GitHub release with the `sdist` and `bdist_wheel`
as well.

The version code is switched to `setuptools_scm` to work well
with this flow (e.g. avoid needing to write a script that does
a `sed` on the version file and commits as part of release).

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-30 12:14:27 -04:00
Milas Bowman 828d06f5f5
docs: fix RollbackConfig/Order values (#3027)
Closes #2626.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-30 12:09:36 -04:00
Max Fan dff849f6bb
docs: image build clarifications/grammar (#2489)
I changed was build > was built and reorganized a few sentences to be more clear.

Signed-off-by: InnovativeInventor <theinnovativeinventor@gmail.com>
2022-07-29 16:15:58 -04:00
Hristo Georgiev 52fb27690c
docs: fix image save example (#2570)
Signed-off-by: Hristo Georgiev <hristo.a.georgiev@gmail.com>
2022-07-29 16:04:23 -04:00
Milas Bowman 547cc5794d Merge branch 'docs-healthcheck'
Manually merging #2595 to include a tiny fix.
2022-07-29 16:02:47 -04:00
Milas Bowman 003a16503a docs: fix list formatting
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-29 16:01:29 -04:00
Milas Bowman c6c2bbdcda Merge remote-tracking branch 'upstream/main' into HEAD 2022-07-29 15:56:01 -04:00
Ville Skyttä 73421027be
docs: clarify TLSConfig verify parameter (#2573)
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
2022-07-29 15:55:14 -04:00
Ville Skyttä 55f47299c4
docs: fix TLS server verify example (#2574)
Leaving out the verify parameter means verification will not be done.

Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
2022-07-29 15:54:27 -04:00
Clément Loiselet 3ee3a2486f
build: trim trailing whitespace from dockerignore entries (#2733)
fix(dockerignore): trim trailing whitespace

Signed-off-by: Clément Loiselet <clement.loiselet@capgemini.com>
2022-07-29 15:33:23 -04:00
Milas Bowman 868e996269
model: add remove() to Image (#3026)
Allow an Image to be deleted by calling the remove() method on it,
just like a Volume.

Signed-off-by: Ahmon Dancy <dancy@dancysoft.com>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
Co-authored-by: Ahmon Dancy <dancy@dancysoft.com>
2022-07-29 15:28:16 -04:00
ercildoune 26753c81de
api: add rollback_config to service create (#2917)
`rollback_config` was not in the list of `CREATE_SERVICE_KWARGS`
which prevented it from being an argument when creating services.
It has now been added and the problem fixed, allowing services to
have a rollback_config during creation and updating.

Fixes #2832.

Signed-off-by: Fraser Patten <pattenf00@gmail.com>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2022-07-29 14:54:55 -04:00
Till! 0031ac2186
api: add force to plugin disable (#2843)
Signed-off-by: till <till@php.net>
2022-07-29 14:51:43 -04:00
Peter Dave Hello b2a18d7209
build: disable pip cache in Dockerfile (#2828)
Signed-off-by: Peter Dave Hello <hsu@peterdavehello.org>
2022-07-29 14:09:06 -04:00
David d69de54d7c
api: add cgroupns option to container create (#2930)
Signed-off-by: David Otto <ottodavid@gmx.net>
2022-07-29 14:04:47 -04:00
Felix Fontein 1a4cacdfb6
api: add platform to container create (#2927)
Add platform parameter for container creation/run

Signed-off-by: Felix Fontein <felix@fontein.de>
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2022-07-29 13:57:30 -04:00
Milas Bowman 26064dd6b5
deps: upgrade websocket-client to latest (#3022)
* Upgrade websocket-client to latest
* Add basic integration test for streaming logs via websocket

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-29 11:09:47 -04:00
Milas Bowman 05e143429e
api: preserve cause when re-raising error (#3023)
Use `from e` to ensure that the error context is propagated
correctly.

Fixes #2702.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-29 11:08:00 -04:00
Ben Fasoli 23cf16f03a
client: use 12 character short IDs (#2862)
Use 12 characters for Docker resource IDs for
consistency with the Docker CLI.

Signed-off-by: Ben Fasoli <benfasoli@gmail.com>
2022-07-29 09:06:22 -04:00
Milas Bowman ab43018b02
docs: fix markdown rendering (#3020)
Follow instructions at https://www.sphinx-doc.org/en/master/usage/markdown.html.

This switches from `recommonmark` (deprecated) to `myst-parser`
(recommended).

Only impacts the changelog page, which was broken after recent upgrades
to Sphinx for Python 3.10 compatibility.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-28 16:38:57 -04:00
Milas Bowman 9bdb5ba2ba
lint: fix line length violation (#3017)
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-28 11:25:17 -04:00
Milas Bowman be942f8390
deps: upgrade & remove unnecessary dependencies (#3014)
The `requirements.txt` and `setup.py` had a lot of extra transitive
dependencies to try and address various SSL shortcomings from the
Python ecosystem.

Thankfully, between modern Python versions (3.6+) and corresponding
`requests` versions (2.26+), this is all unnecessary now!

As a result, a bunch of transitive dependencies have been removed
from `requirements.txt`, the minimum version of `requests` increased,
and the `tls` extra made into a no-op.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-28 08:32:00 -04:00
Milas Bowman bf026265e0
ci: bump version to 6.0.0-dev (#3013)
It's been a long time without a release, and we've included a
number of fixes as well as raised the minimum Python version,
so a major release seems in order.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-28 08:31:45 -04:00
Tim Gates d2d097efbb
docs: fix simple typo, containe -> container (#3015)
There is a small typo in docker/types/services.py.

Should read `container` rather than `containe`.

Signed-off-by: Tim Gates <tim.gates@iress.com>
2022-07-28 08:30:40 -04:00
Milas Bowman acdafbc116
ci: run SSH integration tests (#3012)
Fix & enable SSH integration test suite.

This also adds a new test for connecting to unknown hosts when
using the Python SSH implementation (Paramiko). See #2932 for
more info.

Because of the above, some of the config/static key files have been
moved around and adjusted.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-27 16:25:27 -04:00
Vilhelm Prytz ea4cefe4fd
lint: remove unnecessary pass statements (#2541)
Signed-off-by: Vilhelm Prytz <vilhelm@prytznet.se>
2022-07-27 15:31:04 -04:00
Karthikeyan Singaravelan adf5a97b12
lint: fix deprecation warnings from threading package (#2823)
Set `daemon` attribute instead of using `setDaemon` method that
was deprecated in Python 3.10.

Signed-off-by: Karthikeyan Singaravelan <tir.karthi@gmail.com>
2022-07-27 15:25:11 -04:00
Audun V. Nes d9298647d9
ssh: reject unknown host keys when using Python SSH impl (#2932)
In the Secure Shell (SSH) protocol, host keys are used to verify the identity of remote hosts. Accepting unknown host keys may leave the connection open to man-in-the-middle attacks.

Do not accept unknown host keys. In particular, do not set the default missing host key policy for the Paramiko library to either AutoAddPolicy or WarningPolicy. Both of these policies continue even when the host key is unknown. The default setting of RejectPolicy is secure because it throws an exception when it encounters an unknown host key.

Reference: https://cwe.mitre.org/data/definitions/295.html

NOTE: This only affects SSH connections using the native Python SSH implementation (Paramiko), when `use_ssh_client=False` (default). If using the system SSH client (`use_ssh_client=True`), the host configuration
(e.g. `~/.ssh/config`) will apply.

Signed-off-by: Audun Nes <audun.nes@gmail.com>
2022-07-27 15:01:41 -04:00
errorcode bb40ba051f
ssh: do not create unnecessary subshell on exec (#2910)
Signed-off-by: liubo <liubo@uniontech.com>
2022-07-27 14:57:26 -04:00
Milas Bowman 52e29bd446
deps: remove backports.ssl_match_hostname (#3011)
This is no longer needed as it exists in every supported (non-EOL)
version of Python that we target.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-27 14:44:50 -04:00
Milas Bowman da62a28837
deps: test on Python 3.10 by default (#3010)
* Upgrade to latest Sphinx / recommonmark
* Small CSS fix for issue in new version of Alabaster theme
* Fix `Makefile` target for macOS

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-27 14:44:36 -04:00
Leonard Kinday 0ee9f260e4
ci: run integration tests & fix race condition (#2947)
* Fix integration tests race condition
* Run integration tests on CI
* Use existing DIND version

Signed-off-by: Leonard Kinday <leonard@kinday.ru>

Co-authored-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 16:33:21 -04:00
Milas Bowman b9ca58a56d
Merge pull request #3009 from milas/lint-flake8
ci: add flake8 job
2022-07-26 15:48:55 -04:00
Milas Bowman cf6210316f
Merge pull request #3008 from milas/flaky-tests
test: fix a couple flaky/broken tests
2022-07-26 15:48:35 -04:00
Francesco Casalegno 2e6dad7983
deps: use `packaging` instead of deprecated `distutils` (#2931)
Replace `distutils.Version` (deprecated) with `packaging.Version`

Signed-off-by: Francesco Casalegno <francesco.casalegno@gmail.com>
2022-07-26 15:45:51 -04:00
Guy Lichtman 4e19cc48df
transport: fix ProxyCommand for SSH conn (#2993)
Signed-off-by: Guy Lichtman <glicht@users.noreply.github.com>
2022-07-26 15:16:12 -04:00
Milas Bowman 56dd6de7df
tls: use auto-negotiated highest version (#3007)
Specific TLS versions are deprecated in latest Python, which
causes test failures due to treating deprecation errors as
warnings.

Luckily, the fix here is straightforward: we can eliminate some
custom version selection logic by using `PROTOCOL_TLS_CLIENT`,
which is the recommended method and will select the highest TLS
version supported by both client and server.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 15:12:03 -04:00
Maor Kleinberger bb11197ee3
client: fix exception semantics in _raise_for_status (#2954)
We want "The above exception was the direct cause of the following exception:" instead of "During handling of the above exception, another exception occurred:"

Signed-off-by: Maor Kleinberger <kmaork@gmail.com>
2022-07-26 15:07:23 -04:00
Milas Bowman 3ffdd8a1c5 lint: fix outstanding flake8 violations
Since flake8 wasn't actually being run in CI, we'd accumulated some
violations.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 13:48:47 -04:00
Milas Bowman ce40d4bb34 ci: add flake8 job
Project is already configured for flake8 but it never gets run in
CI.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 13:48:10 -04:00
Milas Bowman 4765f62441 test: mark invalid test as xfail
This test looks for some behavior on non-chunked HTTP requests.

It now fails because it looks like recent versions of Docker Engine
ALWAYS return chunked responses (or perhaps this specific response
changed somehow to now trigger chunking whereas it did not previously).

The actual logic it's trying to test is also unusual because it's
trying to hackily propagate errors under the assumption that it'd get
a non-chunked response on failure, which is...not reliable. Arguably,
the chunked reader should be refactored somehow but that's a refactor
we can't really commit to (and it's evidently been ok enough as is
up until now).

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 13:00:49 -04:00
Milas Bowman 74e0c5eb8c test: fix flaky container log test
Ensure the container has exited before attempting to grab the logs.

Since we are not streaming them, it's possible to attach + grab logs
before the output is processed, resulting in a test failure. If the
container has exited, it's guaranteed to have logged :)

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 13:00:49 -04:00
Sebastiaan van Stijn 7168e09b16
test: fix for cgroupv2 (#2940)
This test was verifying that the container has the right options set (through
`docker inspect`), but also checks if the cgroup-rules are set within the
container by reading `/sys/fs/cgroup/devices/devices.list`

Unlike cgroups v1, on cgroups v2, there is no file interface, and rules are
handled through ebpf, which means that the test will fail because this file
is not present.

From the Linux documentation for cgroups v2:
https://github.com/torvalds/linux/blob/v5.16/Documentation/admin-guide/cgroup-v2.rst#device-controller

> (...)
> Device controller manages access to device files. It includes both creation of
> new device files (using mknod), and access to the existing device files.
>
> Cgroup v2 device controller has no interface files and is implemented on top
> of cgroup BPF. To control access to device files, a user may create bpf programs
> of type BPF_PROG_TYPE_CGROUP_DEVICE and attach them to cgroups with
> BPF_CGROUP_DEVICE flag. (...)

Given that setting the right cgroups is not really a responsibility of this SDK,
it should be sufficient to verify that the right options were set in the container
configuration, so this patch is removing the part that checks the cgroup, to
allow this test to be run on a host with cgroups v2 enabled.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-07-26 12:06:51 -04:00
Milas Bowman f16c4e1147
utils: fix IPv6 address w/ port parsing (#3006)
This was using a deprecated function (`urllib.splitnport`),
ostensibly to work around issues with brackets on IPv6 addresses.

Ironically, its usage was broken, and would result in mangled IPv6
addresses if they had a port specified in some instances.

Usage of the deprecated function has been eliminated and extra test
cases added where missing. All existing cases pass as-is. (The only
other change to the test was to improve assertion messages.)

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 11:35:44 -04:00
Milas Bowman 2933af2ca7
ci: remove Python 3.6 and add 3.11 pre-releases (#3005)
* Python 3.6 went EOL Dec 2021
* Python 3.11 is in beta and due for GA release in October 2022

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 08:51:52 -04:00
Milas Bowman a6db044bd4
deps: upgrade pywin32 & relax version constraint (#3004)
Upgrade to latest pywin32, which has support for Python 3.10 and
resolves a CVE (related to ACL APIs, outside the scope of what
`docker-py` relies on, which is npipe support, but still gets
flagged by scanners).

The version constraint has also been relaxed in `setup.py` to allow
newer versions of pywin32. This is similar to how we handle the
other packages there, and should be safe from a compatibility
perspective.

Fixes #2902.
Closes #2972 and closes #2980.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2022-07-26 08:43:45 -04:00
Laura Brehm e131955685
Merge pull request #2974 from docker/dependabot/pip/paramiko-2.10.1
Bump paramiko from 2.8.0 to 2.10.1
2022-07-13 12:50:12 +02:00
dependabot[bot] e0a3abfc37
Bump paramiko from 2.8.0 to 2.10.1
Bumps [paramiko](https://github.com/paramiko/paramiko) from 2.8.0 to 2.10.1.
- [Release notes](https://github.com/paramiko/paramiko/releases)
- [Changelog](https://github.com/paramiko/paramiko/blob/main/NEWS)
- [Commits](https://github.com/paramiko/paramiko/compare/2.8.0...2.10.1)

---
updated-dependencies:
- dependency-name: paramiko
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-29 21:55:39 +00:00
Stefan Scherer a48a5a9647
Merge pull request #2898 from hugovk/add-3.10
Add support for Python 3.10
2021-10-14 19:25:22 +02:00
Stefan Scherer ac5f6ef93a
Merge pull request #2897 from aiordache/changelog_5.0.3
Update changelog for 5.0.3
2021-10-14 10:46:17 +02:00
Hugo van Kemenade 4bb99311e2 Don't install mock backport
Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2021-10-11 23:06:12 +03:00
Hugo van Kemenade bbbc29191a Bump minimum paramiko to support Python 3.10
Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2021-10-11 23:06:12 +03:00
Hugo van Kemenade 72bcd1616d Bump pytest (and other dependencies) for Python 3.10
Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2021-10-11 23:06:12 +03:00
Hugo van Kemenade 4150fc4d9d Universal wheels are for code expected to work on both Python 2 and 3
Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2021-10-11 23:06:12 +03:00
Hugo van Kemenade a9de343210 Add support for Python 3.10
Signed-off-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
2021-10-11 23:06:12 +03:00
Anca Iordache ecace769f5 Post-release changelog update
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2021-10-08 00:58:26 +02:00
Anca Iordache 7172269b06
Merge pull request #2806 from feliperuhland/fix-low-level-volumes-example
Fix volumes low-level documentation examples
2021-10-08 00:05:55 +02:00
Anca Iordache fcb35f4197
Merge pull request #2810 from feliperuhland/fix-low-level-swarm-example
Fix swarm low-level documentation examples
2021-10-08 00:04:02 +02:00
Anca Iordache 3c5f0d0ee1
Merge pull request #2805 from feliperuhland/fix-low-level-network-example
Fix network low-level documentation examples
2021-10-08 00:03:11 +02:00
Anca Iordache 7779b84e87
Merge pull request #2809 from feliperuhland/add-service-capability
Add service capability
2021-10-08 00:01:28 +02:00
Anca Iordache df59f538c2
Merge pull request #2852 from Phat3/feat/add_templating_parameter_docker_config
Add the possibility to set a templating driver when creating a new Docker config
2021-10-07 23:59:08 +02:00
Anca Iordache aae6be0c58
Merge branch 'master' into feat/add_templating_parameter_docker_config 2021-10-07 23:29:03 +02:00
Anca Iordache b8258679b3
Merge pull request #2888 from aiordache/changelog_5.0.2
Post-release changelog update
2021-10-07 23:17:38 +02:00
Anca Iordache b27faa62e7
Merge pull request #1959 from segevfiner/logs-read-timeout
Fix getting a read timeout for logs/attach with a tty and slow output
2021-09-17 12:58:19 +02:00
Segev Finer 63618b5e11 Fix getting a read timeout for logs/attach with a tty and slow output
Fixes #931

Signed-off-by: Segev Finer <segev208@gmail.com>
2021-09-17 13:01:14 +03:00
Anca Iordache a9265197d2 Post-release changelog update
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2021-09-01 19:23:59 +02:00
Anca Iordache 264688e37c
Merge pull request #2878 from sina-rostami/master
Improve containers documentation
2021-09-01 18:55:38 +02:00
Anca Iordache d06db4d9e1
Merge pull request #2884 from aiordache/changelog_update_5.0.1
Update changelog post-release 5.0.1
2021-09-01 18:46:28 +02:00
Ulysses Souza dbb28a5af1
Merge pull request #2886 from Aposhian/fix-disable-buffering
fix(transport): remove disable_buffering option
2021-09-01 06:44:48 -07:00
Adam Aposhian f9b85586ca fix(transport): remove disable_buffering option
Signed-off-by: Adam Aposhian <aposhian.dev@gmail.com>
2021-08-31 15:26:09 -06:00
Anca Iordache c5fc193857 Update changelog for 5.0.1 release
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2021-08-31 16:39:50 +02:00
Ulysses Souza 3c3aa69997
Merge pull request #2883 from aiordache/changelog
Update changelog for v5.0.0
2021-08-31 07:11:12 -07:00
Anca Iordache 4a3cddf4bf Update changelog for v5.0.0
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2021-08-31 15:57:32 +02:00
Anca Iordache 62af2bbb13
Merge pull request #2846 from shehzaman/feature/missing-identity-file
Put back identityfile parameter from .ssh/config
2021-08-31 14:42:26 +02:00
Shehzaman 8da03e0126 Put back identityfile parameter
Signed-off-by: Shehzaman <shehzi.1@gmail.com>
2021-08-31 09:23:44 -03:00
Ulysses Souza 5705d12813
Merge pull request #2874 from docker/dependabot/pip/pywin32-301
Bump pywin32 from 227 to 301
2021-08-31 04:53:47 -07:00
sinarostami 2fa56879a2 Improve containers documentation
Signed-off-by: sinarostami <Sinarostami4188.1@gmail.com>
2021-08-16 00:24:12 +04:30
dependabot[bot] e0d186d754
Bump pywin32 from 227 to 301
Bumps [pywin32](https://github.com/mhammond/pywin32) from 227 to 301.
- [Release notes](https://github.com/mhammond/pywin32/releases)
- [Changelog](https://github.com/mhammond/pywin32/blob/master/CHANGES.txt)
- [Commits](https://github.com/mhammond/pywin32/commits)

---
updated-dependencies:
- dependency-name: pywin32
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 20:57:04 +00:00
Ulysses Souza 1abeb46dfa
Merge pull request #2850 from docker/dependabot/pip/urllib3-1.26.5
Bump urllib3 from 1.24.3 to 1.26.5
2021-08-06 05:58:50 -07:00
dependabot[bot] 582f6277ce
Bump urllib3 from 1.24.3 to 1.26.5
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.24.3 to 1.26.5.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.24.3...1.26.5)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-06 12:46:56 +00:00
Ulysses Souza 2cf3900030
Merge pull request #2873 from ulyssessouza/bump-requests
Bump requests => 2.26.0
2021-08-06 05:46:04 -07:00
Ulysses Souza 19d6cd8a01 Bump requests => 2.26.0
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2021-08-06 09:32:42 -03:00
Ulysses Souza a9748a8b70
Merge pull request #2863 from asottile/py36_plus
use python3.6+ constructs
2021-07-08 11:29:25 -03:00
Anthony Sottile 5fcc293ba2 use python3.6+ constructs
Signed-off-by: Anthony Sottile <asottile@umich.edu>
2021-07-05 18:30:07 -04:00
Mathieu Champlon 650aad3a5f
Merge pull request #2851 from huogerac/issue836_better_docs
Update the Image.save documentation with a working example. Issue #836
2021-06-29 08:53:34 +02:00
Sebastiano Mariani f42a81dca2 Add the possibility to set a templating driver when creating a new Docker config
Signed-off-by: Sebastiano Mariani <smariani@vmware.com>
2021-06-03 15:51:52 -07:00
Roger Camargo d58ca97207 [DOCS] Update the Image.save documentation with a working example. Issue #836
Signed-off-by: Roger Camargo <huogerac@gmail.com>
2021-06-03 09:40:50 -03:00
Felipe Ruhland 13c316de69 Fix swarm low-level documentation examples
I realize that low-level documentation has outdated examples, so I
created issue #2800 to fix that

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-07 22:55:23 +02:00
Felipe Ruhland 7ac8b56730 Add `CapabilityAdd` and `CapabilityDrop` to
ContainerSpec

Docker Engine v1.41 added `CapAdd` and `CapDrop` as part of the
ContainerSpec, and `docker-py` should do the same.

```
GET /services now returns CapAdd and CapDrop as part of the ContainerSpec.
GET /services/{id} now returns CapAdd and CapDrop as part of the ContainerSpec.
POST /services/create now accepts CapAdd and CapDrop as part of the ContainerSpec.
POST /services/{id}/update now accepts CapAdd and CapDrop as part of the ContainerSpec.
GET /tasks now returns CapAdd and CapDrop as part of the ContainerSpec.
GET /tasks/{id} now returns CapAdd and CapDrop as part of the ContainerSpec.
```

I added capabilities on docstrings, `service.create` init method and
create tests for that.

That change was mention in issue #2802.

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-07 22:11:52 +02:00
Felipe Ruhland f53e615e0f Update API and Engine versions
The Makefile and `docker/constants.py` were with old versions, so I
updated them to the current one

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-07 21:44:24 +02:00
Felipe Ruhland 50a0ff596f Fix network low-level documentation examples
I realize that low-level documentation has outdated examples, so I
created issue #2800 to fix that

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-06 20:52:49 +02:00
Felipe Ruhland 4b44fa7e5d Fix volumes low-level documentation examples
I realize that low-level documentation has outdated examples, so I
created issue #2800 to fix that

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-06 20:32:05 +02:00
Anca Iordache 96c12726fd
Merge pull request #2804 from aiordache/update_maintainer
Update maintainers file and setup.py
2021-04-06 17:08:27 +01:00
Anca Iordache 8945fda6be Update maintainers
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2021-04-06 16:01:16 +02:00
Anca Iordache 18fdc23b7c
Merge pull request #2476 from feliperuhland/add-search-images-limit
Add limit parameter to image search endpoint
2021-04-06 14:43:07 +01:00
Anca Iordache 8813c3d2e0
Merge pull request #2799 from feliperuhland/fix-low-level-pull-example
Fix images low-level documentation examples
2021-04-06 14:41:44 +01:00
Anca Iordache 7a2ec95951
Merge pull request #2801 from feliperuhland/fix-low-level-containers-example
Fix containers low-level documentation examples
2021-04-06 14:40:39 +01:00
Felipe Ruhland ac9ae1f249 Fix containers low-level documentation examples
I realize that low-level documentation has outdated examples, so I
created issue #2800 to fix that

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-05 15:31:43 +02:00
Felipe Ruhland a34dd8b1a9 Fix images low-level documentation examples
I realize that the documentation of low-level `images` was outdated when
answering issue #2798

The issue can reproduce it with a simple test:

```py
In [1]: import docker
In [2]: client = docker.from_env()
In [3]: client.pull
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-d0931943ca5d> in <module>
----> 1 client.pull

~/docker-py/docker/client.py in __getattr__(self, name)
    219                      "object APIClient. See the low-level API section of the "
    220                      "documentation for more details.")
--> 221         raise AttributeError(' '.join(s))
    222
    223

AttributeError: 'DockerClient' object has no attribute 'pull' In Docker SDK for Python 2.0, this method is now on the object APIClient. See the low-level API section of the documentation for more details.

In [4]: client.push
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-f7d5b860a184> in <module>
----> 1 client.push

~/docker-py/docker/client.py in __getattr__(self, name)
    219                      "object APIClient. See the low-level API section of the "
    220                      "documentation for more details.")
--> 221         raise AttributeError(' '.join(s))
    222
    223

AttributeError: 'DockerClient' object has no attribute 'push' In Docker SDK for Python 2.0, this method is now on the object APIClient. See the low-level API section of the documentation for more details.

In [5]: client.tag
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-043bdfd088ca> in <module>
----> 1 client.tag

~/docker-py/docker/client.py in __getattr__(self, name)
    219                      "object APIClient. See the low-level API section of the "
    220                      "documentation for more details.")
--> 221         raise AttributeError(' '.join(s))
    222
    223

AttributeError: 'DockerClient' object has no attribute 'tag' In Docker SDK for Python 2.0, this method is now on the object APIClient. See the low-level API section of the documentation for more details.

In [6]: client.get_image
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-477c12713276> in <module>
----> 1 client.get_image

~/docker-py/docker/client.py in __getattr__(self, name)
    219                      "object APIClient. See the low-level API section of the "
    220                      "documentation for more details.")
--> 221         raise AttributeError(' '.join(s))
    222
    223

AttributeError: 'DockerClient' object has no attribute 'get_image' In Docker SDK for Python 2.0, this method is now on the object APIClient. See the low-level API section of the documentation for more details.

In [7]: client.api.get_image
Out[7]: <bound method ImageApiMixin.get_image of <docker.api.client.APIClient object at 0x7fad6a2037c0>>

In [8]: client.api.tag
Out[8]: <bound method ImageApiMixin.tag of <docker.api.client.APIClient object at 0x7fad6a2037c0>>

In [9]: client.api.pull
Out[9]: <bound method ImageApiMixin.pull of <docker.api.client.APIClient object at 0x7fad6a2037c0>>

In [10]: client.api.push
Out[10]: <bound method ImageApiMixin.push of <docker.api.client.APIClient object at 0x7fad6a2037c0>>
```

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-05 15:01:09 +02:00
Ulysses Souza 0892fcfc12
Merge pull request #2795 from feliperuhland/upgrade-cryptography-to-3.4.7
Upgrade cryptography library to version 3.4.7
2021-04-03 14:48:58 -03:00
Felipe Ruhland 2403774e76 Upgrade cryptography library to version 3.4.7
Dependabot opened a pull request
93bcc0497d to upgrade cryptography from
2.3 to 3.2.

However, only `requirements.txt` was updated.
The extra requirements were kept outdated.

This commit was made to update the library to the last version.

Fix #2791

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-04-02 02:51:20 +02:00
Ulysses Souza a60bd9a454
Merge pull request #2781 from feliperuhland/fix-readme-badge
Fix continuous integration status badged
2021-03-29 22:06:31 +02:00
Anca Iordache 30d482d359
Merge pull request #2788 from docker/set-minimal-python-to-3_6
Make python 3.6 the minimum version
2021-03-25 09:59:41 +01:00
Anca Iordache d2aa221638
Merge pull request #2793 from feliperuhland/create-secret-missing-name
Fix `KeyError` when creating a new secret
2021-03-25 09:58:02 +01:00
Felipe Ruhland d4310b2db0 Fix `KeyError` when creating a new secret
How to reproduce the issue:

```py
>>> import docker
>>> cli = docker.from_env()
>>> cli.secrets.create(name="any_name", data="1")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/docker-py/docker/models/secrets.py", line 10, in __repr__
    return "<%s: '%s'>" % (self.__class__.__name__, self.name)
  File "/home/docker-py/docker/models/secrets.py", line 14, in name
    return self.attrs['Spec']['Name']
KeyError: 'Spec'
```

The exception raises because create secrets API `/secrets/create` only
return the `id` attribute:
https://docs.docker.com/engine/api/v1.41/#operation/SecretCreate
The secret model is created using just the `id` attribute and fails
when looking for Spec.Name attribute.

```py
def __repr__(self):
    return "<%s: '%s'>" % (self.__class__.__name__, self.name)
```

```py
@property
def name(self):
    return self.attrs['Spec']['Name']
```

I came up with a ugly solution but will prevent the problem to happen
again:

```py
def create(self, **kwargs):
    obj = self.client.api.create_secret(**kwargs)
+   obj.setdefault("Spec", {})["Name"] = kwargs.get("name")
    return self.prepare_model(obj)
```

After the API call, I added the name attribute to the right place to be
used on the property name.

```py
>>> import docker
>>> cli = docker.from_env()
>>> cli.secrets.create(name="any_name", data="1")
<Secret: 'any_name'>
```

It isn't the most elegant solution, but it will do the trick.
I had a previous PR #2517 when I propose using the `id` attribute
instead of `name` on the `__repr__` method, but I think this one will be better.

That fixes #2025

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-03-24 18:03:54 +01:00
Ulysses Souza c8fba210a2 Remove support to pre python 3.6
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2021-03-22 10:18:23 -03:00
Anca Iordache 31775a1532
Merge pull request #2782 from hakanardo/verify_tls
Verify TLS keys loaded from docker contexts
2021-03-10 16:17:34 +01:00
Nicolas De Loof 563124163a relax PORT_SPEC regex so it accept and ignore square brackets
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2021-03-10 11:25:18 +01:00
Hakan Ardo c239d66d5d Verify TLS keys loaded from docker contexts
This maches the behaviour of the docker cli when using contexts.

Signed-off-by: Hakan Ardo <hakan@debian.org>
2021-03-03 09:30:19 +01:00
Felipe Ruhland d836bb8703 Fix continuous integration status badged
https://docs.github.com/en/actions/managing-workflow-runs/
adding-a-workflow-status-badge

Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-02-26 22:02:55 +01:00
Ulysses Souza 55f405e04a
Merge pull request #2780 from aiordache/changelog_4.4.4
Update changelog for 4.4.4
2021-02-25 10:30:18 -03:00
Felipe Ruhland 7d316641a3 Add limit parameter to image search endpoint
Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2021-02-24 23:42:20 +01:00
aiordache 148f9161e1 Update changelog for 4.4.4
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-24 18:20:24 +01:00
Anca Iordache d09fe8d225
Merge pull request #2778 from aiordache/openssl_mismatch_bug
Drop LD_LIBRARY_PATH env var for SSH shellout
2021-02-24 16:39:55 +01:00
Anca Iordache 69087ab977
Merge pull request #2772 from aiordache/update_changelog_4.4.3
Update changelog post-release 4.4.3
2021-02-24 14:32:02 +01:00
aiordache 43ca2f8ff9 Drop LD_LIBRARY_PATH env var for SSH shellout
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-23 19:04:03 +01:00
aiordache fe995ae79f Update changelog post-release 4.4.3
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-19 17:33:16 +01:00
aiordache e6689e0bb9 Post-release 4.4.2 changelog updates
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-18 11:19:11 -03:00
aiordache 2807fde6c9 Fix SSH port parsing and add regression tests
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-18 10:56:29 -03:00
Anca Iordache d065daf522
Merge pull request #2711 from vlad-ro/fix-doc-formatting
Fix doc formatting
2021-02-12 16:38:20 +01:00
Anca Iordache c15ee3925d
Merge pull request #2764 from StefanScherer/clean-home-docker
Use DOCKER_CONFIG to have creds in dind environment
2021-02-11 20:31:13 +01:00
aiordache 00da4dc0ea Run unit tests in a container with no .docker/config mount
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-11 19:58:35 +01:00
Stefan Scherer 6de6936f5d
Use DOCKER_CONFIG to have creds in dind environment
Signed-off-by: Stefan Scherer <stefan.scherer@docker.com>
2021-02-11 18:40:37 +01:00
Anca Iordache 407dcfd65b
Merge pull request #2763 from StefanScherer/revert-to-wrappedNode
Revert back to wrappedNode
2021-02-11 17:16:49 +01:00
Stefan Scherer 94d7983ef0
Revert back to wrappedNode
Signed-off-by: Stefan Scherer <stefan.scherer@docker.com>
2021-02-11 10:24:57 +01:00
Vlad Romanenko 56d4b09700 Fix doc formatting
Signed-off-by: Vlad Romanenko <vlad.romanenko@hotmail.com>
2021-02-10 21:27:15 +02:00
Anca Iordache b3aa239432
Merge pull request #2761 from StefanScherer/no-wrappedNode
Remove wrappedNode
2021-02-10 17:18:12 +01:00
Stefan Scherer 9556b890f9
Remove wrappedNode
Signed-off-by: Stefan Scherer <stefan.scherer@docker.com>
2021-02-10 16:57:30 +01:00
Anca Iordache caef663729
Merge pull request #2741 from WojciechowskiPiotr/maxreplicas
Support for docker.types.Placement.MaxReplicas
2021-02-10 14:54:55 +01:00
aiordache ccab78840e Bump cffi to 1.14.4
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-10 10:35:55 -03:00
aiordache f520b4c4eb Update GH action step
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-10 10:35:55 -03:00
WojciechowskiPiotr 6d1dffe3e5 Unit and integration tests added
Signed-off-by: WojciechowskiPiotr <devel@it-playground.pl>
2021-02-09 21:37:26 +01:00
Anca Iordache a653052276
Merge pull request #2759 from StefanScherer/ubuntu-2004
Update CI to ubuntu-2004
2021-02-09 20:54:21 +01:00
Stefan Scherer 9e007469ef
Update CI to ubuntu-2004
Signed-off-by: Stefan Scherer <stefan.scherer@docker.com>
2021-02-09 20:39:54 +01:00
Christian Clauss da32a2f1a2 GitHub Actions: Upgrade actions/checkout
https://github.com/actions/checkout/releases
Signed-off-by: Christian Clauss <cclauss@me.com>
2021-02-09 16:10:42 -03:00
WojciechowskiPiotr 514f98a0d6 Support for docker.types.Placement.MaxReplicas (new in API 1.40) in Docker Swarm Service
Signed-off-by: WojciechowskiPiotr <devel@it-playground.pl>
2021-02-09 19:45:52 +01:00
Anca Iordache d7b16ef0fb
Merge pull request #2755 from aiordache/fix_ssh_bug
Fix host trimming and remove quiet flag for the ssh connection
2021-02-09 18:26:44 +01:00
Anca Iordache 78f5249ed0
Merge pull request #2739 from cclauss/setup.py-py38-py39
setup.py: Add support for Python 3.8 and 3.9
2021-02-09 18:21:55 +01:00
Anca Iordache 8615a61bd1
Merge pull request #2743 from cclauss/patch-2
print() is a function in Python 3
2021-02-09 15:18:12 +01:00
aiordache caab390696 Fix host trimming and remove quiet flag for the ssh connection
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-09 10:17:00 +01:00
Anca Iordache f0517f842b
Merge pull request #2754 from aiordache/update_Jenkins_setup
Set the base image to `dockerpinata/docker-py` in Jenkinsfile
2021-02-08 20:35:58 +01:00
aiordache 0edea80c41 Update base image to `dockerpinata/docker-py` in Jenkinsfile
Signed-off-by: aiordache <anca.iordache@docker.com>
2021-02-08 20:04:14 +01:00
Christian Clauss 10ff403079 print() is a function in Python 3
Like #2740 but for the docs

Signed-off-by: Christian Clauss <cclauss@me.com>
2020-12-28 19:14:55 +01:00
Christian Clauss ce2669e3ed print() is a function in Python 3
Signed-off-by: Christian Clauss <cclauss@me.com>
2020-12-28 17:26:25 +00:00
Piotr Wojciechowski f0ab0ed25d Support for docker.types.Placement.MaxReplicas (new in API 1.40) in Docker Swarm Service
Signed-off-by: WojciechowskiPiotr <devel@it-playground.pl>
2020-12-25 16:39:44 +01:00
Christian Clauss 2426a5ffd5 setup.py: Add support for Python 3.8 and 3.9
Signed-off-by: Christian Clauss <cclauss@me.com>
2020-12-24 15:14:05 +01:00
Ulysses Souza b72926b382 Post 4.4.1 release
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-12-22 20:53:42 +00:00
Ulysses Souza 2f3e0f9fc4 Prepare release 4.4.1
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-12-22 20:37:46 +00:00
aiordache 3ec7fee736 Avoid setting unsuported parameter for subprocess.Popen on Windows
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-12-18 18:00:07 +00:00
Ulysses Souza 4757eea80c Trigger GHA on pull_request
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-12-18 14:53:55 +00:00
Anca Iordache f1af005eca
Merge pull request #2707 from aiordache/after_release
Post-release 4.4.0
2020-12-18 15:42:48 +01:00
Ulysses Souza ab0d65e2e0 Remove travis
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-12-18 14:39:40 +00:00
Ulysses Souza d8bbbf2351 Add Github Actions
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-12-18 14:39:40 +00:00
Sebastiaan van Stijn 1757c974fa docker/api/image: replace use of deprecated "filter" argument
The "filter" argument was deprecated in docker 1.13 (API version 1.25),
and removed from API v1.41 and up. See https://github.com/docker/cli/blob/v20.10.0-rc1/docs/deprecated.md#filter-param-for-imagesjson-endpoint

This patch applies the name as "reference" filter, instead of "filter" for API
1.25 and up.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-11-26 17:07:27 +00:00
aiordache 990ef4904c Post-release v4.4.0
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-11-23 13:16:23 +01:00
Anca Iordache 4328197660
Merge pull request #2705 from aiordache/jenkins_dockerhub_creds
Update Jenkinsfile with docker registry credentials
2020-11-20 09:54:51 +01:00
aiordache c854aba15e Mount docker config to DIND containers for authentication
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-11-19 19:33:24 +01:00
aiordache 260114229a Update Jenkinsfile with docker registry credentials
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-11-19 18:51:59 +01:00
Anca Iordache 5b471d4482
Merge pull request #2704 from aiordache/cleanup
Fix condition to avoid syntax warning
2020-11-19 18:18:09 +01:00
aiordache a0c51be228 Syntax warning fix
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-11-19 15:38:26 +01:00
Anca Iordache 27e3fa3e2e
Merge pull request #2703 from aiordache/cleanup_before_release
Fix docs typo and `port_bindings` check
2020-11-19 09:53:39 +01:00
aiordache db9af44e5b Fix docs typo
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-11-18 19:00:27 +01:00
Anca Iordache d83a2ad51b
Merge pull request #2691 from aiordache/fix_ssh_conn
Fix the connection via ssh client shellout
2020-11-18 15:55:25 +01:00
aiordache f5531a94e1 Fix ssh connection - don't override the host and port of the http pool
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-11-18 14:44:24 +01:00
Guillaume Tardif 6da140e26c
Merge pull request #2511 from daeseokyoun/handle-network-host
raise an error for binding specific ports in 'host' mode of network
2020-11-17 16:01:16 +01:00
Mariano Scazzariello bb1c528ab3
Add max_pool_size parameter (#2699)
* Add max_pool_size parameter

Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>

* Add client version to tests

Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>

* Fix parameter position

Signed-off-by: Mariano Scazzariello <marianoscazzariello@gmail.com>
2020-11-17 15:42:36 +01:00
Daeseok Youn 433264d04b Correct comments on ports_binding and host mode as network_mode
Signed-off-by: Daeseok Youn <daeseok.youn@navercorp.com>
2020-11-17 21:27:15 +09:00
Daeseok Youn 9c53024ead raise an error for binding specific ports in 'host' mode of network
The binding ports are ignored where the network mode is 'host'.
It could be a problem in case of using these options together on
Mac or Windows OS. Because the limitation that could not use
the 'host' in network_mode on Mac and Windows. When 'host' mode
is set on network_mode, the specific ports in 'ports' are ignored
 so the network is not able to be accessed through defined ports
by developer.

Signed-off-by: Daeseok Youn <daeseok.youn@navercorp.com>
2020-11-17 21:26:55 +09:00
Anca Iordache 800222268a
Merge pull request #2553 from fengbaolong/fix-unicode-in-dockerfile
fix docker build error when dockerfile contains unicode character.
2020-11-16 17:44:09 +01:00
Anca Iordache 8c893dd9c4
Merge pull request #2694 from docker/dependabot/pip/cryptography-3.2
Bump cryptography from 2.3 to 3.2
2020-11-16 16:48:19 +01:00
Anca Iordache 5b60bba104
Merge pull request #2642 from YuviGold/feature/api-server-error-message-url
Add response url to Server Error and Client Error messages
2020-11-16 15:50:04 +01:00
dependabot[bot] 93bcc0497d
Bump cryptography from 2.3 to 3.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 2.3 to 3.2.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/2.3...3.2)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-27 21:18:15 +00:00
Yuval Goldberg 3766f77c20 Add response url to Server Error and Client Error messages
Signed-off-by: Yuval Goldberg <yuvigoldi@hotmail.com>
2020-10-17 03:43:11 +03:00
Anca Iordache 2c6ef9b11d
Merge pull request #2687 from IamTheFij/fix-model-plugin-upgrade-reload
Fix plugin model upgrade
2020-10-16 11:37:36 +02:00
Anca Iordache daa9f179c3
Merge pull request #2671 from aiordache/default_tag
Set image default tag on pull
2020-10-16 11:35:16 +02:00
Anca Iordache e09b070575
Merge pull request #2680 from aiordache/replace_paramiko
Shell out to local SSH client as alternative to a paramiko connection
2020-10-16 11:34:00 +02:00
aiordache 180414dcbb Shell out to SSH client for an ssh connection
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-10-13 10:42:38 +02:00
Ian Fijolek 910cc12423 Fix plugin model upgrade
When upgrading a plugin via the model interface, it would yield the
following error:

    AttributeError: 'Plugin' object has no attribute '_reload'

It appears that the proper method is `self.reload()`. This is what is
used by all other methods in the class and base. I'm not finding any
references to `_reload` apart from this instance in the project either.

I've verified that this patch fixes the issue on my machine and all
tests pass.

Signed-off-by: Ian Fijolek <ian@iamthefij.com>
2020-10-09 18:29:26 -07:00
Anca Iordache 9d8cd023e8
Merge pull request #2673 from ulyssessouza/remove-tinyurl-link
Fix url of examples in ulimits
2020-09-28 11:14:27 +02:00
aiordache aed5700985 update `pull` method docs
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-09-21 10:23:29 +02:00
Ulysses Souza ea093a75dd Fix url of examples in ulimits
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-09-17 17:09:14 +02:00
Anca Iordache ff44e7e375
Merge pull request #2670 from ulyssessouza/add-github-maintainers
Add github supported CODEOWNERS file
2020-09-17 16:54:30 +02:00
aiordache cec152db5f Set image default tag on pull
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-09-16 17:36:50 +02:00
Ulysses Souza 84857a896c Add github supported CODEOWNERS file
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-09-15 15:33:04 +02:00
aiordache ed46fb0143 Add release 4.3.1 information to changelog
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-09-07 17:55:36 +02:00
Anca Iordache 2b1c7eb724
Merge pull request #2650 from aiordache/default_version_auto
Set default version to 'auto'
2020-08-20 20:58:25 +02:00
Anca Iordache f158888003
Merge pull request #2534 from HaaLeo/feature/openssh-identity-file
Support OpenSSH Identityfile option
2020-08-20 18:33:45 +02:00
aiordache c7c5b551fc set engine version for unit tests to avoid querying the engine
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-20 15:29:24 +02:00
aiordache 727080b3cc set version to 'auto' to avoid breaking on old engine versions
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-19 14:19:29 +02:00
Yuval Goldberg 0dfae33ce8 Add file environment variable to integration-dind
Signed-off-by: Yuval Goldberg <yuvigoldi@hotmail.com>
2020-08-18 15:18:52 +02:00
Anca Iordache 2c522fb362
Fix memory conversion to bytes (#2645)
* Fix memory conversion to bytes

Co-authored-by: Ulysses Souza <ulysses.souza@gmail.com>

Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-17 18:32:48 +02:00
Anca Iordache 30ff9f339c
Merge pull request #2638 from aiordache/release
Release 4.3.0
2020-08-10 19:35:01 +02:00
aiordache 5cdbbab3ee Update version to the next dev version
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-10 19:21:44 +02:00
aiordache 9579b7ac0e Fix changelog merge
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-10 19:16:52 +02:00
aiordache 8080fbb4ed Fix merge
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-10 19:15:50 +02:00
aiordache 746a2509ab Prepare release 4.3.0
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-10 19:15:50 +02:00
aiordache 3999707fb3 Make orchestrator field optional
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-08-10 19:15:50 +02:00
Ulysses Souza 2e274d00b3 Specify when to use `tls` on Context constructor
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-08-10 19:15:50 +02:00
Ulysses Souza 67b77f2fa3 Post release 4.2.0 update:
- Changelog
- Next Version

Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-08-10 19:15:46 +02:00
Anca Iordache 087b3f0a49 Implement context management, lifecycle and unittests.
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2020-08-10 19:14:00 +02:00
Till Riedel fcd0093050 obey Hostname Username Port and ProxyCommand settings from .ssh/config
Signed-off-by: Till Riedel <riedel@teco.edu>
2020-08-10 19:14:00 +02:00
Till Riedel 70cdb08f9a set logging level of paramiko to warn
Signed-off-by: Till Riedel <riedel@teco.edu>
2020-08-10 19:14:00 +02:00
Sebastiaan van Stijn 0be75d54ca Update credentials-helpers to v0.6.2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-08-10 19:14:00 +02:00
Sebastiaan van Stijn b4beaaac8c
Update default API version to v1.39 (#2512)
* Update default API version to v1.39

When running the docker-py integration tests in the Moby repository, some
tests were skipped because the API version used was too low:

    SKIPPED [1] tests/integration/api_service_test.py:882: API version is too low (< 1.38)
    SKIPPED [1] tests/integration/api_swarm_test.py:59: API version is too low (< 1.39)
    SKIPPED [1] tests/integration/api_swarm_test.py:38: API version is too low (< 1.39)
    SKIPPED [1] tests/integration/api_swarm_test.py:45: API version is too low (< 1.39)
    SKIPPED [1] tests/integration/api_swarm_test.py:52: API version is too low (< 1.39)

While it's possible to override the API version to use for testing
using the `DOCKER_TEST_API_VERSION` environment variable, we may want
to set the default to a version that supports all features that were
added.

This patch updates the default API version to v1.39, which is the minimum
version required for those features, and corresponds with Docker 18.09.

Note that the API version of the current (19.03) Docker release is v1.40,
but using that version as default would exclude users that did not update
their Docker version yet (and would not be needed yet for the features provided).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

* Makefile: set DOCKER_TEST_API_VERSION to v1.39

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-08-07 16:45:20 +02:00
Anca Iordache cceae0c384
Merge pull request #2572 from scop/tlsconfig-error-messages
Fix parameter names in TLSConfig error messages
2020-08-07 15:14:39 +02:00
Anca Iordache 6367bbee2e
Merge pull request #2520 from Nicceboy/master
Disable compression by default when using container:get_archive method
2020-08-07 14:42:58 +02:00
Anca Iordache 62afadc13b
Merge pull request #2584 from thaJeztah/bump_engine
Update test engine version to 19.03.12
2020-08-07 14:34:06 +02:00
Ville Skyttä 631abd156a
Spelling fixes (#2571)
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
2020-08-07 14:33:19 +02:00
Lucidiot dd0450a14c
Add device requests (#2471)
* Add DeviceRequest type

Signed-off-by: Erwan Rouchet <rouchet@teklia.com>

* Add device_requests kwarg in host config

Signed-off-by: Erwan Rouchet <rouchet@teklia.com>

* Add unit test for device requests

Signed-off-by: Erwan Rouchet <rouchet@teklia.com>

* Fix unit test

Signed-off-by: Erwan Rouchet <rouchet@teklia.com>

* Use parentheses for multiline import

Signed-off-by: Erwan Rouchet <rouchet@teklia.com>

* Create 1.40 client for device-requests test

Signed-off-by: Laurie O <laurie_opperman@hotmail.com>

Co-authored-by: Laurie O <laurie_opperman@hotmail.com>
Co-authored-by: Bastien Abadie <abadie@teklia.com>
2020-08-07 13:58:35 +02:00
Sebastiaan van Stijn 26d8045ffa Fix CreateContainerTest.test_invalid_log_driver_raises_exception
This test was updated in 7d92fbdee1, but
omitted the "error" prefix in the message, causing the test to fail;

    _________ CreateContainerTest.test_invalid_log_driver_raises_exception _________
    tests/integration/api_container_test.py:293: in test_invalid_log_driver_raises_exception
        assert excinfo.value.explanation in expected_msgs
    E   AssertionError: assert 'error looking up logging plugin asdf: plugin "asdf" not found' in ["logger: no log driver named 'asdf' is registered", 'looking up logging plugin asdf: plugin "asdf" not found']
    E    +  where 'error looking up logging plugin asdf: plugin "asdf" not found' = APIError(HTTPError('400 Client Error: Bad Request for url: http+docker://localhost/v1.39/containers/create')).explanation
    E    +    where APIError(HTTPError('400 Client Error: Bad Request for url: http+docker://localhost/v1.39/containers/create')) = <ExceptionInfo APIError tblen=6>.value

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-07-17 15:59:12 +02:00
Ofek Lev c65d437843 Upgrade Windows dependency
Signed-off-by: Ofek Lev <ofekmeister@gmail.com>
2020-07-07 08:43:02 +02:00
Ulysses Souza 74a0734d37
Merge pull request #2551 from haboustak/2550-add-driveropts-to-endpointconfig
Add support for DriverOpts in EndpointConfig
2020-07-02 10:51:35 +02:00
Ulysses Souza d3adac9027
Merge pull request #2609 from ulyssessouza/post-release
Post release 4.2.2
2020-07-01 15:09:42 +02:00
Ulysses Souza 6d9847838a Update version to 4.3.0-dev
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-30 18:30:49 +02:00
Ulysses Souza e18a64b630 Bump 4.2.2
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2020-06-30 18:25:58 +02:00
Sebastiaan van Stijn 2c68b382a8
Update test engine version to 19.03.12
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-06-30 17:57:36 +02:00
Ulysses Souza 26a7f85af7 Merge remote-tracking branch 'upstream/master' 2020-06-30 17:17:05 +02:00
Ulysses Souza 0a248c0906
Merge pull request #2602 from aiordache/fix_context_meta_load
Fix context load for non-docker endpoints
2020-06-30 17:16:10 +02:00
aiordache 309ce44052 Skip parsing non-docker endpoints
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-06-26 18:21:35 +02:00
Janosch Deurer bf1a3518f9 Add healthcheck doc for container.run
Signed-off-by: Janosch Deurer <deurer@mps-med.de>
2020-06-15 16:49:28 +02:00
Ulysses Souza 5efe28149a
Merge pull request #2585 from thaJeztah/better_worker_selection
Jenkinsfile: update node selection labels
2020-06-03 11:14:49 +02:00
Sebastiaan van Stijn fefa96cd0e
Jenkinsfile: update node selection labels
Make sure we use the LTS nodes, to prevent using machines that
we prepared with cgroups v2 (which is not yet supported by docker v19.03)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-06-03 10:43:42 +02:00
Ulysses Souza b49d22f053
Merge pull request #2583 from ulyssessouza/post-release-4.2.1
Post release 4.2.1
2020-06-02 17:25:24 +02:00
Ulysses Souza 57a8a0c561 Update version after 4.2.1 release
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-02 16:59:17 +02:00
Ulysses Souza 525ff592ee Bump 4.2.1
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-02 16:43:27 +02:00
Ulysses Souza 88163c00f2 Bump 4.2.0
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-02 16:43:24 +02:00
Ulysses Souza df08c14c87 Bump 3.7.2
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2020-06-02 16:41:51 +02:00
Ulysses Souza 1b2029e08e Post release 4.2.1 update:
- Changelog

Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-02 16:25:52 +02:00
Ulysses Souza b22095f742
Merge pull request #2580 from ulyssessouza/4.2.1-release
Bump 4.2.1
2020-06-02 16:15:59 +02:00
Ulysses Souza 9923746095 Bump 4.2.1
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-02 15:53:06 +02:00
aiordache 67cad6842c add test for context load without orchestrator
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-06-02 15:52:25 +02:00
aiordache 31276df6a3 Make orchestrator field optional
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-06-02 15:52:25 +02:00
Ulysses Souza 105efa02a9 Specify when to use `tls` on Context constructor
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-06-02 15:52:25 +02:00
Wilson Júnior 9b59e49113 Fix tests to support both log plugin feedbacks
Signed-off-by: Wilson Júnior <wilsonpjunior@gmail.com>
Docker-DCO-1.1-Signed-off-by: Wilson Júnior <wilsonpjunior@gmail.com> (github: wpjunior)
2020-06-02 15:52:25 +02:00
Sebastiaan van Stijn 913d129dc9 Update test engine version to 19.03.5
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-06-02 15:52:25 +02:00
Sebastiaan van Stijn 9713227d7b Jenkinsfile: remove obsolete engine versions
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-06-02 15:52:25 +02:00
Sebastiaan van Stijn db6a2471f5 Use official docker:dind image instead of custom image
This replaces the custom dockerswarm/dind image with the official
dind images, which should provide the same functionality.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-06-02 15:52:25 +02:00
Sebastiaan van Stijn fd4526a7d3 xfail "docker top" tests, and adjust for alpine image
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-06-02 15:52:25 +02:00
Ulysses Souza a5270865e6
Merge pull request #2578 from aiordache/fix_context_load_without_orch
Make context orchestrator field optional
2020-06-02 15:10:33 +02:00
aiordache 7133916798 add test for context load without orchestrator
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-06-02 10:50:03 +02:00
aiordache 1e11ecec34 Make orchestrator field optional
Signed-off-by: aiordache <anca.iordache@docker.com>
2020-05-30 11:01:22 +02:00
Ulysses Souza 71adba9a1d
Merge pull request #2576 from ulyssessouza/fix-tls-host-protocol
Specify when to use `tls` on Context constructor
2020-05-28 21:37:24 +02:00
Ulysses Souza 3ce2d8959d Specify when to use `tls` on Context constructor
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-05-28 20:53:45 +02:00
Ville Skyttä 81eb5d42c9 Fix parameter names in TLSConfig error messages and comments
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
2020-05-25 08:52:23 +03:00
Mike Haboustak df7bf5f5e0
Add support for DriverOpts in EndpointConfig
Docker API 1.32 added support for providing options to a network driver
via EndpointConfig when connecting a container to a network.

Signed-off-by: Mike Haboustak <haboustak@gmail.com>
2020-04-30 05:27:45 -04:00
fengbaolong a07b5ee16c fix docker build error when dockerfile contains unicode character.
if dockerfile contains unicode character,len(contents) will return character length,this length will less than len(contents_encoded) length,so contants data will be truncated.

Signed-off-by: fengbaolong <fengbaolong@hotmail.com>
2020-04-28 20:01:59 +08:00
Ulysses Souza 9a24df5cdd
Merge pull request #2549 from wpjunior/fix-plugin-feedback
Fix tests to support both log plugin feedbacks
2020-04-22 10:30:02 +02:00
Wilson Júnior 7d92fbdee1
Fix tests to support both log plugin feedbacks
Signed-off-by: Wilson Júnior <wilsonpjunior@gmail.com>
Docker-DCO-1.1-Signed-off-by: Wilson Júnior <wilsonpjunior@gmail.com> (github: wpjunior)
2020-04-21 17:00:48 -03:00
Leo Hanisch dac038aca2 Fixes docker/docker-py#2533
Signed-off-by: Leo Hanisch <23164374+HaaLeo@users.noreply.github.com>
2020-03-20 12:40:58 +01:00
Niklas Saari 51fd6dd1ce
Disable compression by default when using get_archive method
Signed-off-by: Niklas Saari <niklas.saari@tutanota.com>
2020-02-26 23:09:38 +02:00
Ulysses Souza 030af62dca
Merge pull request #2514 from thaJeztah/remove_obsolete_versions
Jenkinsfile: remove obsolete engine versions
2020-02-21 16:17:07 +01:00
Ulysses Souza 12fe645aba
Merge pull request #2515 from thaJeztah/use_official_dind_images
Use official docker:dind image instead of custom image
2020-02-21 16:16:36 +01:00
Sebastiaan van Stijn 8ced47dca9
Use official docker:dind image instead of custom image
This replaces the custom dockerswarm/dind image with the official
dind images, which should provide the same functionality.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-17 10:25:56 +01:00
Sebastiaan van Stijn da90bb3259
xfail "docker top" tests, and adjust for alpine image
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-17 10:25:53 +01:00
Sebastiaan van Stijn 7bef5e8676
Update test engine version to 19.03.5
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-15 00:00:48 +01:00
Sebastiaan van Stijn 789b6715ca
Jenkinsfile: remove obsolete engine versions
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-15 00:00:41 +01:00
Ulysses Souza a9867c9912
Merge pull request #2508 from ulyssessouza/update-release-4.2.0
Post release 4.2.0 update
2020-02-07 11:24:25 +01:00
Ulysses Souza 7c4194ce5d Post release 4.2.0 update:
- Changelog
- Next Version

Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-02-07 01:00:18 +01:00
Ulysses Souza 1d1532f0be
Merge pull request #2506 from ulyssessouza/4.2.0-release
4.2.0 release
2020-02-06 11:43:03 +01:00
Ulysses Souza ab5678469c Bump 4.2.0
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
2020-02-06 10:41:28 +01:00
Anca Iordache 6e44d8422c Implement context management, lifecycle and unittests.
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2020-02-06 10:33:31 +01:00
Sebastiaan van Stijn 6c29375fd1 Fix ImageCollectionTest.test_pull_multiple flakiness
The ImageCollectionTest.test_pull_multiple test performs a `docker pull` without
a `:tag` specified) to pull all tags of the given repository (image).

After pulling the image, the image(s) pulled are checked to verify if the list
of images contains the `:latest` tag.

However, the test assumes that all tags of the image are tags for the same
version of the image (same digest), and thus a *single* image is returned, which
is not always the case.

Currently, the `hello-world:latest` and `hello-world:linux` tags point to a
different digest, therefore the `client.images.pull()` returns multiple images:
one image for digest, making the test fail:

    =================================== FAILURES ===================================
    ____________________ ImageCollectionTest.test_pull_multiple ____________________
    tests/integration/models_images_test.py:90: in test_pull_multiple
        assert len(images) == 1
    E   AssertionError: assert 2 == 1
    E    +  where 2 = len([<Image: 'hello-world:linux'>, <Image: 'hello-world:latest'>])

This patch updates the test to not assume a single image is returned, and instead
loop through the list of images and check if any of the images contains the
`:latest` tag.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-06 10:33:31 +01:00
Christopher Crone 9b0d07f9a8 Version bump
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
2020-02-06 10:33:31 +01:00
rentu 61e2d5f69b Fix win32pipe.WaitNamedPipe throw exception in windows container.
Signed-off-by: Renlong Tu <rentu@microsoft.com>
2020-02-06 10:33:31 +01:00
Nicolas De Loof a67d180e2c Fix CI labels so we run on amd64 nodes
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2020-02-06 10:33:31 +01:00
Till Riedel ed9b208e15 obey Hostname Username Port and ProxyCommand settings from .ssh/config
Signed-off-by: Till Riedel <riedel@teco.edu>
2020-02-06 10:33:31 +01:00
Till Riedel bc6777eb01 set host key policy for ssh transport to WarningPolicy()
Signed-off-by: Till Riedel <riedel@teco.edu>
2020-02-06 10:33:31 +01:00
Till Riedel 1e567223ef set logging level of paramiko to warn
Signed-off-by: Till Riedel <riedel@teco.edu>
2020-02-06 10:33:31 +01:00
Ulysses Souza c6a33f25dc
Merge pull request #2495 from aiordache/issue#28_compose_context_target
Implement docker contexts
2020-02-05 15:30:48 +01:00
Anca Iordache 64fdb32ae8 Implement context management, lifecycle and unittests.
Signed-off-by: Anca Iordache <anca.iordache@docker.com>
2020-02-05 14:49:42 +01:00
Ulysses Souza f2e09ae632
Merge pull request #2485 from thaJeztah/fix_ImageCollectionTest_test_pull_multiple
Fix ImageCollectionTest.test_pull_multiple flakiness
2020-01-07 17:13:28 +01:00
Ulysses Souza 6010527ac6
Merge pull request #2444 from chris-crone/sync-release-4.1.0
Sync release 4.1.0
2020-01-07 17:12:50 +01:00
Sebastiaan van Stijn 940805dde6
Fix ImageCollectionTest.test_pull_multiple flakiness
The ImageCollectionTest.test_pull_multiple test performs a `docker pull` without
a `:tag` specified) to pull all tags of the given repository (image).

After pulling the image, the image(s) pulled are checked to verify if the list
of images contains the `:latest` tag.

However, the test assumes that all tags of the image are tags for the same
version of the image (same digest), and thus a *single* image is returned, which
is not always the case.

Currently, the `hello-world:latest` and `hello-world:linux` tags point to a
different digest, therefore the `client.images.pull()` returns multiple images:
one image for digest, making the test fail:

    =================================== FAILURES ===================================
    ____________________ ImageCollectionTest.test_pull_multiple ____________________
    tests/integration/models_images_test.py:90: in test_pull_multiple
        assert len(images) == 1
    E   AssertionError: assert 2 == 1
    E    +  where 2 = len([<Image: 'hello-world:linux'>, <Image: 'hello-world:latest'>])

This patch updates the test to not assume a single image is returned, and instead
loop through the list of images and check if any of the images contains the
`:latest` tag.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:46:23 +01:00
Yuval Goldberg 656db96b4a Fix mac_address connect usage in network functions && addind appropriate test
Signed-off-by: Yuval Goldberg <yuvigoldi@hotmail.com>
2019-12-19 15:43:03 +02:00
Hongbin Lu 755fd73566 Add mac_address to connect_container_to_network
Signed-off-by: Hongbin Lu <hongbin.lu@huawei.com>
2019-12-19 15:40:29 +02:00
Djordje Lukic a0b9c3d0b3
Merge pull request #2421 from SLdragon/master
Fix win32pipe.WaitNamedPipe throw exception in windows container
2019-11-06 09:29:39 +01:00
Jack Laxson 19171d0e1e remove hyphens in literals
Signed-off-by: Jack Laxson <jackjrabbit@gmail.com>
2019-10-28 05:45:28 -04:00
Nicolas De Loof 1d8aa3019e Fix CI labels so we run on amd64 nodes
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2019-10-16 14:31:50 +02:00
Till Riedel c285bee1bc obey Hostname Username Port and ProxyCommand settings from .ssh/config
Signed-off-by: Till Riedel <riedel@teco.edu>
2019-10-16 14:31:50 +02:00
Till Riedel eb8c78c3b3 set host key policy for ssh transport to WarningPolicy()
Signed-off-by: Till Riedel <riedel@teco.edu>
2019-10-16 14:31:50 +02:00
Till Riedel 2dc569a232 set logging level of paramiko to warn
Signed-off-by: Till Riedel <riedel@teco.edu>
2019-10-16 14:31:50 +02:00
Christopher Crone efc7e3c4b0 Version bump
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
2019-10-03 16:40:23 +02:00
Christopher Crone c81200a483 Bump 4.1.0
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
2019-10-03 16:39:40 +02:00
Chris Crone 66495870de
Merge pull request #2443 from docker/4.1.0-release
4.1.0 release
2019-10-03 16:16:42 +02:00
Christopher Crone 2bb08b3985 Bump 4.1.0
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
2019-10-03 15:49:27 +02:00
Kir Kolyshkin 88219c682c Bump pytest to 4.3.1
Pytest 4.3.1 includes the fix from

	https://github.com/pytest-dev/pytest/pull/4795

which should fix the following failure:

> INFO: Building docker-sdk-python3:4.0.2...
> sha256:c7a40413c985b6e75df324fae39b1c30cb78a25df71b7892f1a4a15449537fb3
> INFO: Starting docker-py tests...
> Traceback (most recent call last):
>   File "/usr/local/bin/pytest", line 10, in <module>
>     sys.exit(main())
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 61, in main
>     config = _prepareconfig(args, plugins)
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 182, in _prepareconfig
>     config = get_config()
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 156, in get_config
>     pluginmanager.import_plugin(spec)
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 530, in import_plugin
>     __import__(importspec)
>   File "/usr/local/lib/python3.6/site-packages/_pytest/tmpdir.py", line 25, in <module>
>     class TempPathFactory(object):
>   File "/usr/local/lib/python3.6/site-packages/_pytest/tmpdir.py", line 35, in TempPathFactory
>     lambda p: Path(os.path.abspath(six.text_type(p)))
> TypeError: attrib() got an unexpected keyword argument 'convert'
> Sending interrupt signal to process
> Terminated
> script returned exit code 143

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2019-10-03 15:49:27 +02:00
Sebastiaan van Stijn bc89de6047 Fix broken test due to BUSYBOX -> TEST_IMG rename
The BUSYBOX variable was renamed to TEST_IMG in
54b48a9b7a, however
0ddf428b6c got merged
after that change, but was out of date, and therefore
caused the tests to fail:

```
=================================== FAILURES ===================================
________ ServiceTest.test_create_service_with_network_attachment_config ________
tests/integration/api_service_test.py:379: in test_create_service_with_network_attachment_config
    container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
E   NameError: global name 'BUSYBOX' is not defined
```

Fix the test by using the correct variable name.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:27 +02:00
Hannes Ljungberg 7c8264ce96 Correctly reference SecretReference
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-10-03 15:49:27 +02:00
Hannes Ljungberg ec63237da0 Correctly reference ConfigReference
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-10-03 15:49:27 +02:00
Hannes Ljungberg 934072a5e7 Add NetworkAttachmentConfig type
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-10-03 15:49:27 +02:00
Sebastiaan van Stijn 0be550dcf0 Jenkinsfile: update python 3.6 -> 3.7
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:27 +02:00
Sebastiaan van Stijn 38fe3983ba Jenkinsfile: update API version matrix; set default to v1.40
- Added new entry for Docker 19.03
- Removed obsolete engine versions that reached EOL (both
  as Community Edition and Enterprise Edition)
- Set the fallback/default API version to v1.40, which
  corresponds with Docker 19.03 (current release)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:27 +02:00
Frank Sachsenheim c88205c5ce Amends the docs concerning multiple label filters
Closes #2338

Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2019-10-03 15:49:27 +02:00
Sebastiaan van Stijn 63760b1922 test/Dockerfile: allow using a mirror for the apt repository
With this change applied, the default debian package repository can be
replaced with a mirror;

```
make APT_MIRROR=cdn-fastly.deb.debian.org build-py3

...

Step 5/19 : RUN apt-get update && apt-get -y install     gnupg2     pass     curl
 ---> Running in 01c1101a0bd0
Get:1 http://cdn-fastly.deb.debian.org/debian buster InRelease [118 kB]
Get:2 http://cdn-fastly.deb.debian.org/debian-security buster/updates InRelease [39.1 kB]
Get:3 http://cdn-fastly.deb.debian.org/debian buster-updates InRelease [46.8 kB]
Get:4 http://cdn-fastly.deb.debian.org/debian buster/main amd64 Packages [7897 kB]
Get:5 http://cdn-fastly.deb.debian.org/debian-security buster/updates/main amd64 Packages [22.8 kB]
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:27 +02:00
Matt Fluet 06c606300c Correct INDEX_URL logic in build.py _set_auth_headers
Signed-off-by: Matt Fluet <matt.fluet@appian.com>
2019-10-03 15:49:27 +02:00
Sebastiaan van Stijn c238315c64 pytest: update to v4.2.1 - use xunit2 for compatibility with Jenkins
- pytest-dev/pytest#3547: `--junitxml` can emit XML compatible with Jenkins
  xUnit. `junit_family` INI option accepts `legacy|xunit1`, which produces
  old style output, and `xunit2` that conforms more strictly to
  https://github.com/jenkinsci/xunit-plugin/blob/xunit-2.3.2/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:27 +02:00
Sebastiaan van Stijn 57c2193f6d pytest: set junitxml suite name to "docker-py"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Ryan McCullagh 2d327bf743 Fix typo in comment. networks => network
Signed-off-by: Ryan McCullagh <ryan@amezmo.com>
2019-10-03 15:49:26 +02:00
Matt Fluet cce0954089 Fix for empty auth keys in config.json
Signed-off-by: Matt Fluet <matt.fluet@appian.com>
2019-10-03 15:49:26 +02:00
Sebastiaan van Stijn 73ad8b8f19 Update alpine version to 3.10, and rename BUSYBOX variable
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Sebastiaan van Stijn 23635d43ab Adjust `--platform` tests for changes in docker engine
These tests started failing on recent versions of the engine because the error string changed,
and due to a regression, the status code for one endpoint changed from a 400 to a 500.

On Docker 18.03:

The `docker build` case properly returns a 400, and "invalid platform" as error string;

```bash
docker build --platform=foobar -<<EOF
FROM busybox
EOF

Sending build context to Docker daemon  2.048kB
Error response from daemon: invalid platform: invalid platform os "foobar"
```

```
DEBU[2019-07-15T12:17:22.745511870Z] Calling GET /_ping
DEBU[2019-07-15T12:17:22.748224796Z] Calling POST /session
DEBU[2019-07-15T12:17:22.748692282Z] Calling POST /v1.37/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&platform=foobar&rm=1&session=d7b6ceba9d8d0aed67a805528554feb5285781fe888a4bf4e0c15cb09bffd614&shmsize=0&target=&ulimits=null
```

The `docker pull --platform=foobar hello-world:latest` case incorrectly returns a 500

```
DEBU[2019-07-15T12:16:08.744827612Z] Calling POST /v1.37/images/create?fromImage=hello-world&platform=foobar&tag=latest
DEBU[2019-07-15T12:16:08.745594874Z] FIXME: Got an API for which error does not match any expected type!!!: invalid platform: invalid platform os "foobar"  error_type="*errors.errorString" module=api
ERRO[2019-07-15T12:16:08.745916686Z] Handler for POST /v1.37/images/create returned error: invalid platform: invalid platform os "foobar"
DEBU[2019-07-15T12:16:08.746191172Z] FIXME: Got an API for which error does not match any expected type!!!: invalid platform: invalid platform os "foobar"  error_type="*errors.errorString" module=api
```

On Docker 18.09;

```bash
docker build --platform=foobar -<<EOF
FROM busybox
EOF

Error response from daemon: "foobar": unknown operating system or architecture: invalid argument
```

Which incorrectly returns a 500 status;

```
DEBU[2019-07-15T11:59:20.687268380Z] Calling POST /v1.39/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&platform=foobar&rm=1&session=jko7kejjvs93judyfnq7shoda&shmsize=0&target=&ulimits=null&version=1
DEBU[2019-07-15T11:59:20.687282279Z] Calling POST /session
INFO[2019-07-15T11:59:20.687761392Z] parsed scheme: ""                             module=grpc
INFO[2019-07-15T11:59:20.687833668Z] scheme "" not registered, fallback to default scheme  module=grpc
INFO[2019-07-15T11:59:20.688017578Z] ccResolverWrapper: sending new addresses to cc: [{ 0  <nil>}]  module=grpc
INFO[2019-07-15T11:59:20.688270160Z] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2019-07-15T11:59:20.688353083Z] pickfirstBalancer: HandleSubConnStateChange: 0xc4209b0630, CONNECTING  module=grpc
INFO[2019-07-15T11:59:20.688985698Z] pickfirstBalancer: HandleSubConnStateChange: 0xc4209b0630, READY  module=grpc
DEBU[2019-07-15T11:59:20.812700550Z] client is session enabled
DEBU[2019-07-15T11:59:20.813139288Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
ERRO[2019-07-15T11:59:20.813210677Z] Handler for POST /v1.39/build returned error: "foobar": unknown operating system or architecture: invalid argument
DEBU[2019-07-15T11:59:20.813276737Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
```

Same for the `docker pull --platform=foobar hello-world:latest` case:

```bash
docker pull --platform=foobar hello-world:latest
Error response from daemon: "foobar": unknown operating system or architecture: invalid argument
```

```
DEBU[2019-07-15T12:00:18.812995330Z] Calling POST /v1.39/images/create?fromImage=hello-world&platform=foobar&tag=latest
DEBU[2019-07-15T12:00:18.813229172Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
ERRO[2019-07-15T12:00:18.813365546Z] Handler for POST /v1.39/images/create returned error: "foobar": unknown operating system or architecture: invalid argument
DEBU[2019-07-15T12:00:18.813461428Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Sebastiaan van Stijn cd3a696603 xfail test_init_swarm_data_path_addr
This test can fail if `eth0` has multiple IP addresses;

   E   docker.errors.APIError: 400 Client Error: Bad Request ("interface eth0 has more than one IPv6 address (2001:db8:1::242:ac11:2 and fe80::42:acff:fe11:2)")

Which is not a failiure, but depends on the environment that
the test is run in.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Sebastiaan van Stijn 38d18a2d1f Update credentials-helpers to v0.6.3
full diff:
https://github.com/docker/docker-credential-helpers/compare/v0.6.2...v0.6.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Francis Laniel a316e6a927 Add documentation to argument 'mem_reservation'.
The documentation was added for function ContainerCollection::run and
ContainerApiMixin::create_host_config.

Signed-off-by: Francis Laniel <francis.laniel@lip6.fr>

Add documentation to argument 'mem_reservation'.

The documentation was added for function ContainerCollection::run and
ContainerApiMixin::create_host_config.

Signed-off-by: Francis Laniel <francis.laniel@lip6.fr>
2019-10-03 15:49:26 +02:00
Sebastiaan van Stijn ea4fbd7ddf Update to python 3.7 (buster) and use build-args
The build arg can be used to either test different versions, but
also makes it easier to "grep" when upgrading versions.

The output format of `gpg2 --list-secret-keys` changed in the version
installed on Buster, so `grep` was replaced with `awk` to address
the new output format;

Debian Jessie:

    gpg2 --no-auto-check-trustdb --list-secret-keys
    /root/.gnupg/secring.gpg
    ------------------------
    sec   1024D/A7B21401 2018-04-25
    uid                  Sakuya Izayoi <sakuya@gensokyo.jp>
    ssb   1024g/C235E4CE 2018-04-25

Debian Buster:

    gpg2 --no-auto-check-trustdb --list-secret-keys
    /root/.gnupg/pubring.kbx
    ------------------------
    sec   dsa1024 2018-04-25 [SCA]
          9781B87DAB042E6FD51388A5464ED987A7B21401
    uid           [ultimate] Sakuya Izayoi <sakuya@gensokyo.jp>
    ssb   elg1024 2018-04-25 [E]

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Djordje Lukic 546bc63244 Bump dev
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2019-10-03 15:49:26 +02:00
Sebastiaan van Stijn f3961244a0 Update credentials-helpers to v0.6.2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-03 15:49:26 +02:00
Michael Crosby c2ed66552b Remove exec detach test
Forking off an exec process and detaching isn't a supported method

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2019-10-03 15:49:26 +02:00
Ulysses Souza 8077d80118
Merge pull request #2441 from kolyshkin/pytest-4.3
Bump pytest to 4.3.1
2019-10-02 13:32:06 +02:00
Kir Kolyshkin 44904f696f Bump pytest to 4.3.1
Pytest 4.3.1 includes the fix from

	https://github.com/pytest-dev/pytest/pull/4795

which should fix the following failure:

> INFO: Building docker-sdk-python3:4.0.2...
> sha256:c7a40413c985b6e75df324fae39b1c30cb78a25df71b7892f1a4a15449537fb3
> INFO: Starting docker-py tests...
> Traceback (most recent call last):
>   File "/usr/local/bin/pytest", line 10, in <module>
>     sys.exit(main())
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 61, in main
>     config = _prepareconfig(args, plugins)
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 182, in _prepareconfig
>     config = get_config()
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 156, in get_config
>     pluginmanager.import_plugin(spec)
>   File "/usr/local/lib/python3.6/site-packages/_pytest/config/__init__.py", line 530, in import_plugin
>     __import__(importspec)
>   File "/usr/local/lib/python3.6/site-packages/_pytest/tmpdir.py", line 25, in <module>
>     class TempPathFactory(object):
>   File "/usr/local/lib/python3.6/site-packages/_pytest/tmpdir.py", line 35, in TempPathFactory
>     lambda p: Path(os.path.abspath(six.text_type(p)))
> TypeError: attrib() got an unexpected keyword argument 'convert'
> Sending interrupt signal to process
> Terminated
> script returned exit code 143

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2019-10-01 17:21:38 -07:00
rentu 015f44d8f8 Fix win32pipe.WaitNamedPipe throw exception in windows container.
Signed-off-by: Renlong Tu <rentu@microsoft.com>
2019-08-30 10:19:33 +01:00
Joffrey F 8acd2c3d08
Merge pull request #2420 from thaJeztah/fix_master_builds
Fix broken test due to BUSYBOX -> TEST_IMG rename
2019-08-29 15:21:57 -07:00
Sebastiaan van Stijn 53469e0dd3
Fix broken test due to BUSYBOX -> TEST_IMG rename
The BUSYBOX variable was renamed to TEST_IMG in
54b48a9b7a, however
0ddf428b6c got merged
after that change, but was out of date, and therefore
caused the tests to fail:

```
=================================== FAILURES ===================================
________ ServiceTest.test_create_service_with_network_attachment_config ________
tests/integration/api_service_test.py:379: in test_create_service_with_network_attachment_config
    container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
E   NameError: global name 'BUSYBOX' is not defined
```

Fix the test by using the correct variable name.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-30 00:14:20 +02:00
Joffrey F 8fea5738d3
Merge pull request #2333 from hannseman/network-attachment-config
Add NetworkAttachmentConfig for service create/update
2019-08-27 00:21:27 -07:00
Joffrey F 1fc62e6a32
Merge pull request #2408 from thaJeztah/jenkins_update_versions
Jenkinsfile: update API versions and update to Python 3.7
2019-08-27 00:17:59 -07:00
Joffrey F 912824e599
Merge pull request #2352 from funkyfuture/container_list_docs
Amends the docs concerning multiple label filters
2019-08-27 00:17:04 -07:00
Joffrey F 5660730d36
Merge pull request #2383 from thaJeztah/support_mirrors
test/Dockerfile: allow using a mirror for the apt repository
2019-08-27 00:16:00 -07:00
Joffrey F 33b430ab7f
Merge pull request #2399 from fluetm/build-index-url-fix
Correct INDEX_URL logic in build.py _set_auth_headers
2019-08-27 00:14:40 -07:00
Joffrey F 9443decdf6
Merge pull request #2409 from thaJeztah/update_pytest
Update pytest to v4.2.1, use xunit2 for Jenkins compatibility, and small config changes
2019-08-27 00:13:28 -07:00
Joffrey F 70907325a5
Merge pull request #2414 from rmccullagh/patch-1
Fix typo in comment. networks => network
2019-08-27 00:11:48 -07:00
Joffrey F 1c36417d8f
Merge pull request #2401 from fluetm/fix-osxkeychain-issue
Fix for empty auth keys in config.json
2019-08-26 11:11:32 -07:00
Ryan McCullagh 93dc5082de Fix typo in comment. networks => network
Signed-off-by: Ryan McCullagh <ryan@amezmo.com>
2019-08-23 10:38:59 -05:00
Matt Fluet aa13df40b1 Fix for empty auth keys in config.json
Signed-off-by: Matt Fluet <matt.fluet@appian.com>
2019-08-15 18:15:57 -04:00
Joffrey F 845d31dbd2
Merge pull request #2407 from thaJeztah/update_alpine
Update alpine version to 3.10, and rename BUSYBOX variable
2019-08-12 11:14:32 -07:00
Sebastiaan van Stijn 9ea3da37a7
pytest: update to v4.2.1 - use xunit2 for compatibility with Jenkins
- pytest-dev/pytest#3547: `--junitxml` can emit XML compatible with Jenkins
  xUnit. `junit_family` INI option accepts `legacy|xunit1`, which produces
  old style output, and `xunit2` that conforms more strictly to
  https://github.com/jenkinsci/xunit-plugin/blob/xunit-2.3.2/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-11 02:13:30 +02:00
Sebastiaan van Stijn f0fc266eb5
Jenkinsfile: update python 3.6 -> 3.7
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-10 19:22:52 +02:00
Sebastiaan van Stijn 16794d1d23
Jenkinsfile: update API version matrix; set default to v1.40
- Added new entry for Docker 19.03
- Removed obsolete engine versions that reached EOL (both
  as Community Edition and Enterprise Edition)
- Set the fallback/default API version to v1.40, which
  corresponds with Docker 19.03 (current release)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-10 19:19:32 +02:00
Sebastiaan van Stijn 54b48a9b7a
Update alpine version to 3.10, and rename BUSYBOX variable
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-10 19:11:58 +02:00
Sebastiaan van Stijn 7b22b14715
pytest: set junitxml suite name to "docker-py"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-10 18:50:36 +02:00
Matt Fluet d7caa6039d Correct INDEX_URL logic in build.py _set_auth_headers
Signed-off-by: Matt Fluet <matt.fluet@appian.com>
2019-08-06 12:40:17 -04:00
Joffrey F 17c86429e4
Merge pull request #2382 from thaJeztah/fix_platform_tests
Adjust `--platform` tests for changes in docker engine
2019-07-18 22:49:54 -07:00
Joffrey F b20b10cac4
Merge pull request #2380 from thaJeztah/xfail_test_init_swarm_data_path_addr
xfail test_init_swarm_data_path_addr
2019-07-18 22:47:21 -07:00
Joffrey F fd32dc4f15
Merge pull request #2384 from thaJeztah/bump_credential_helpers_0.6.3
Update credentials-helpers to v0.6.3
2019-07-18 22:45:56 -07:00
Sebastiaan van Stijn b2a1b03163
Update credentials-helpers to v0.6.3
full diff:
https://github.com/docker/docker-credential-helpers/compare/v0.6.2...v0.6.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-17 10:54:08 +02:00
Joffrey F 01dcde2f0c
Merge pull request #2217 from eiffel-fl/master
Add documentation to argument 'mem_reservation' in ContainerCollection::run
2019-07-16 10:55:03 -07:00
Francis Laniel a1bc6c289b Add documentation to argument 'mem_reservation'.
The documentation was added for function ContainerCollection::run and
ContainerApiMixin::create_host_config.

Signed-off-by: Francis Laniel <francis.laniel@lip6.fr>

Add documentation to argument 'mem_reservation'.

The documentation was added for function ContainerCollection::run and
ContainerApiMixin::create_host_config.

Signed-off-by: Francis Laniel <francis.laniel@lip6.fr>
2019-07-16 18:25:43 +02:00
Sebastiaan van Stijn 5a91c2e83e
test/Dockerfile: allow using a mirror for the apt repository
With this change applied, the default debian package repository can be
replaced with a mirror;

```
make APT_MIRROR=cdn-fastly.deb.debian.org build-py3

...

Step 5/19 : RUN apt-get update && apt-get -y install     gnupg2     pass     curl
 ---> Running in 01c1101a0bd0
Get:1 http://cdn-fastly.deb.debian.org/debian buster InRelease [118 kB]
Get:2 http://cdn-fastly.deb.debian.org/debian-security buster/updates InRelease [39.1 kB]
Get:3 http://cdn-fastly.deb.debian.org/debian buster-updates InRelease [46.8 kB]
Get:4 http://cdn-fastly.deb.debian.org/debian buster/main amd64 Packages [7897 kB]
Get:5 http://cdn-fastly.deb.debian.org/debian-security buster/updates/main amd64 Packages [22.8 kB]
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-16 12:51:01 +02:00
Joffrey F 068ddf835d
Merge pull request #2379 from thaJeztah/bump_python
Update to python 3.7 (buster) and use build-args
2019-07-15 10:56:36 -07:00
Joffrey F 4c71641544
Merge pull request #2366 from docker/sync-release
Sync release
2019-07-15 10:53:07 -07:00
Sebastiaan van Stijn bc46490a68
Adjust `--platform` tests for changes in docker engine
These tests started failing on recent versions of the engine because the error string changed,
and due to a regression, the status code for one endpoint changed from a 400 to a 500.

On Docker 18.03:

The `docker build` case properly returns a 400, and "invalid platform" as error string;

```bash
docker build --platform=foobar -<<EOF
FROM busybox
EOF

Sending build context to Docker daemon  2.048kB
Error response from daemon: invalid platform: invalid platform os "foobar"
```

```
DEBU[2019-07-15T12:17:22.745511870Z] Calling GET /_ping
DEBU[2019-07-15T12:17:22.748224796Z] Calling POST /session
DEBU[2019-07-15T12:17:22.748692282Z] Calling POST /v1.37/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&platform=foobar&rm=1&session=d7b6ceba9d8d0aed67a805528554feb5285781fe888a4bf4e0c15cb09bffd614&shmsize=0&target=&ulimits=null
```

The `docker pull --platform=foobar hello-world:latest` case incorrectly returns a 500

```
DEBU[2019-07-15T12:16:08.744827612Z] Calling POST /v1.37/images/create?fromImage=hello-world&platform=foobar&tag=latest
DEBU[2019-07-15T12:16:08.745594874Z] FIXME: Got an API for which error does not match any expected type!!!: invalid platform: invalid platform os "foobar"  error_type="*errors.errorString" module=api
ERRO[2019-07-15T12:16:08.745916686Z] Handler for POST /v1.37/images/create returned error: invalid platform: invalid platform os "foobar"
DEBU[2019-07-15T12:16:08.746191172Z] FIXME: Got an API for which error does not match any expected type!!!: invalid platform: invalid platform os "foobar"  error_type="*errors.errorString" module=api
```

On Docker 18.09;

```bash
docker build --platform=foobar -<<EOF
FROM busybox
EOF

Error response from daemon: "foobar": unknown operating system or architecture: invalid argument
```

Which incorrectly returns a 500 status;

```
DEBU[2019-07-15T11:59:20.687268380Z] Calling POST /v1.39/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&platform=foobar&rm=1&session=jko7kejjvs93judyfnq7shoda&shmsize=0&target=&ulimits=null&version=1
DEBU[2019-07-15T11:59:20.687282279Z] Calling POST /session
INFO[2019-07-15T11:59:20.687761392Z] parsed scheme: ""                             module=grpc
INFO[2019-07-15T11:59:20.687833668Z] scheme "" not registered, fallback to default scheme  module=grpc
INFO[2019-07-15T11:59:20.688017578Z] ccResolverWrapper: sending new addresses to cc: [{ 0  <nil>}]  module=grpc
INFO[2019-07-15T11:59:20.688270160Z] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2019-07-15T11:59:20.688353083Z] pickfirstBalancer: HandleSubConnStateChange: 0xc4209b0630, CONNECTING  module=grpc
INFO[2019-07-15T11:59:20.688985698Z] pickfirstBalancer: HandleSubConnStateChange: 0xc4209b0630, READY  module=grpc
DEBU[2019-07-15T11:59:20.812700550Z] client is session enabled
DEBU[2019-07-15T11:59:20.813139288Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
ERRO[2019-07-15T11:59:20.813210677Z] Handler for POST /v1.39/build returned error: "foobar": unknown operating system or architecture: invalid argument
DEBU[2019-07-15T11:59:20.813276737Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
```

Same for the `docker pull --platform=foobar hello-world:latest` case:

```bash
docker pull --platform=foobar hello-world:latest
Error response from daemon: "foobar": unknown operating system or architecture: invalid argument
```

```
DEBU[2019-07-15T12:00:18.812995330Z] Calling POST /v1.39/images/create?fromImage=hello-world&platform=foobar&tag=latest
DEBU[2019-07-15T12:00:18.813229172Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
ERRO[2019-07-15T12:00:18.813365546Z] Handler for POST /v1.39/images/create returned error: "foobar": unknown operating system or architecture: invalid argument
DEBU[2019-07-15T12:00:18.813461428Z] FIXME: Got an API for which error does not match any expected type!!!: invalid argument
github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs.init
	/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/errdefs/errors.go:40
github.com/docker/docker/vendor/github.com/containerd/containerd/content.init
	<autogenerated>:1
github.com/docker/docker/builder/builder-next.init
	<autogenerated>:1
github.com/docker/docker/api/server/backend/build.init
	<autogenerated>:1
main.init
	<autogenerated>:1
runtime.main
	/usr/local/go/src/runtime/proc.go:186
runtime.goexit
	/usr/local/go/src/runtime/asm_amd64.s:2361  error_type="*errors.fundamental" module=api
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-15 15:48:06 +02:00
Sebastiaan van Stijn 6f6572bb8a
Update to python 3.7 (buster) and use build-args
The build arg can be used to either test different versions, but
also makes it easier to "grep" when upgrading versions.

The output format of `gpg2 --list-secret-keys` changed in the version
installed on Buster, so `grep` was replaced with `awk` to address
the new output format;

Debian Jessie:

    gpg2 --no-auto-check-trustdb --list-secret-keys
    /root/.gnupg/secring.gpg
    ------------------------
    sec   1024D/A7B21401 2018-04-25
    uid                  Sakuya Izayoi <sakuya@gensokyo.jp>
    ssb   1024g/C235E4CE 2018-04-25

Debian Buster:

    gpg2 --no-auto-check-trustdb --list-secret-keys
    /root/.gnupg/pubring.kbx
    ------------------------
    sec   dsa1024 2018-04-25 [SCA]
          9781B87DAB042E6FD51388A5464ED987A7B21401
    uid           [ultimate] Sakuya Izayoi <sakuya@gensokyo.jp>
    ssb   elg1024 2018-04-25 [E]

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-15 13:27:07 +02:00
Sebastiaan van Stijn 1126ea9d6f
xfail test_init_swarm_data_path_addr
This test can fail if `eth0` has multiple IP addresses;

   E   docker.errors.APIError: 400 Client Error: Bad Request ("interface eth0 has more than one IPv6 address (2001:db8:1::242:ac11:2 and fe80::42:acff:fe11:2)")

Which is not a failiure, but depends on the environment that
the test is run in.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-12 22:50:35 +02:00
Joffrey F 53a182d6e2
Merge pull request #2377 from thaJeztah/bump_credential_helpers
Update credentials-helpers to v0.6.2
2019-07-12 10:32:50 -07:00
Sebastiaan van Stijn df340bea60
Update credentials-helpers to v0.6.2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-12 01:28:41 +02:00
Joffrey F 4d8e5eb2ad
Merge pull request #2369 from crosbymichael/detach-exec
Remove exec detach test
2019-06-25 11:26:57 -07:00
Michael Crosby 8303884612 Remove exec detach test
Forking off an exec process and detaching isn't a supported method

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2019-06-25 13:08:39 -04:00
Djordje Lukic 4db37a1267 Bump dev
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2019-06-20 13:34:03 +02:00
Djordje Lukic 46fdeffb10 Bump 4.0.2
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2019-06-20 13:33:44 +02:00
Djordje Lukic 1308cfb78d
Merge pull request #2365 from docker/4.0.2-release
4.0.2 release
2019-06-20 13:23:27 +02:00
Djordje Lukic 805f5f4b38 Bump 4.0.2
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2019-06-20 12:58:37 +02:00
Djordje Lukic a821502b9e Bump websocket-client -> 0.56.0
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2019-06-20 12:58:37 +02:00
Kajetan Champlewski 1f38d270e0 Clean up healtcheck.py docs
Signed-off-by: Kajetan Champlewski <contact@kajetan.ch>
2019-06-20 12:58:37 +02:00
Kajetan Champlewski 241aaaab23 Handle str in setter for test.
Signed-off-by: Kajetan Champlewski <contact@kajetan.ch>
2019-06-20 12:58:37 +02:00
Kajetan Champlewski c5ca2ef85e Fix documentation for inspect_secret referring to removal.
Signed-off-by: Kajetan Champlewski <contact@kajetan.ch>
2019-06-20 12:58:37 +02:00
Joffrey F 1ef822afee dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-06-20 12:58:37 +02:00
Chris Crone 20b5491363
Merge pull request #2362 from rumpl/bump-websockets
Bump websocket-client -> 0.56.0
2019-06-19 08:27:04 -07:00
Djordje Lukic 7dd3d563f6 Bump websocket-client -> 0.56.0
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2019-06-19 14:09:47 +02:00
Joffrey F 0f368939de
Merge pull request #2353 from mildlyincompetent/improve-healthcheck
Handle `str` in setter for test on HealthCheck
2019-05-31 10:42:29 -07:00
Kajetan Champlewski dcff8876b1
Clean up healtcheck.py docs
Signed-off-by: Kajetan Champlewski <contact@kajetan.ch>
2019-05-31 09:13:30 +00:00
Kajetan Champlewski 7302d1af04
Handle str in setter for test.
Signed-off-by: Kajetan Champlewski <contact@kajetan.ch>
2019-05-31 09:11:20 +00:00
Frank Sachsenheim 4b924dbaf4 Amends the docs concerning multiple label filters
Closes #2338

Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2019-05-27 22:07:24 +02:00
Joffrey F a208de9e5b
Merge pull request #2351 from mildlyincompetent/master
Fix documentation for inspect_secret referring to removal.
2019-05-24 10:16:27 -07:00
Kajetan Champlewski 0624ccc9cc
Fix documentation for inspect_secret referring to removal.
Signed-off-by: Kajetan Champlewski <contact@kajetan.ch>
2019-05-24 15:37:58 +00:00
Joffrey F 542251af3a
Merge pull request #2349 from docker/resync-release
Resync release notes (4.0.1)
2019-05-18 21:00:20 -07:00
Joffrey F 0200e051c0 dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 20:28:19 -07:00
Joffrey F 4828138f50 Changelog 4.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 20:27:35 -07:00
Joffrey F bc827a2ea9 Bump 4.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 20:27:35 -07:00
Joffrey F ead0bb9e08
Merge pull request #2348 from docker/4.0.1-release
4.0.1 release
2019-05-18 20:18:03 -07:00
Joffrey F 307e2b3eda Changelog 4.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 20:05:20 -07:00
Joffrey F 4d08f2c33d Bump 4.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:54:35 -07:00
Joffrey F fc0285c09b Version bump
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:54:35 -07:00
Simon Gurcke df182fd42d Change os.errno to errno for py3.7 compatibility
Signed-off-by: Simon Gurcke <simon@gurcke.de>
2019-05-18 19:54:35 -07:00
Joffrey F 4a8a86eed4 Add readthedocs config
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:54:35 -07:00
Batuhan Taşkaya 80f68c81cd reference swarm page correctly
Signed-off-by: Batuhan Taşkaya <btaskaya33@gmail.com>
2019-05-18 19:54:35 -07:00
Joffrey F c657ca316e
Merge pull request #2347 from docker/resync-release
Resync release branch with master
2019-05-18 19:45:41 -07:00
Joffrey F a33dbd8682
Merge pull request #2335 from isidentical/master
reference swarm page correctly
2019-05-18 19:38:48 -07:00
Joffrey F c2ceb89329
Merge pull request #2346 from itssimon/master
Change os.errno to errno for py3.7 compatibility
2019-05-18 19:34:36 -07:00
Joffrey F eee115c2b8 Version bump
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:33:48 -07:00
Joffrey F b406bfb463 Update changelog for 4.0.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:33:48 -07:00
Joffrey F 3267d1f0cc Bump version 4.0.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:33:48 -07:00
Ulysses Souza efdac34ef4 Bump 3.7.2
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-05-18 19:33:48 -07:00
Ulysses Souza ccd9ca4947 Xfail test_attach_stream_and_cancel on TLS
This test is quite flaky on ssl integration test

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-05-18 19:33:48 -07:00
Simon Gurcke 31fec93872 Change os.errno to errno for py3.7 compatibility
Signed-off-by: Simon Gurcke <simon@gurcke.de>
2019-05-19 12:20:12 +10:00
Joffrey F 181fade33a
Merge pull request #2343 from docker/rtd-conf
Add readthedocs config
2019-05-18 19:17:54 -07:00
Joffrey F 31236ba5a7 Add readthedocs config
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-18 19:13:45 -07:00
Joffrey F 5d42ab81c3
Merge pull request #2331 from docker/4.0.0-release
4.0.0 release
2019-05-18 18:35:54 -07:00
Ulysses Souza 5de5af1155 Bump urllib3 -> 1.24.3
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-05-18 18:15:27 -07:00
Joffrey F 37e442aaed
Merge pull request #2339 from ulyssessouza/bump-urllib3
Bump urllib3 -> 1.24.3
2019-05-15 13:06:14 -07:00
Ulysses Souza 690b0ce9c4 Bump urllib3 -> 1.24.3
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-05-15 10:21:26 +02:00
Joffrey F 36a09df21c Merge branch 'release' into 4.0.0-release
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-13 22:46:05 -07:00
Joffrey F 589e76ea3c Update changelog for 4.0.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-13 22:44:49 -07:00
Joffrey F f6781575c1 Bump version 4.0.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-13 22:44:48 -07:00
Ulysses Souza d863f72939 Bump 3.7.2
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-05-13 22:44:48 -07:00
Ulysses Souza 12d73c6d38 Xfail test_attach_stream_and_cancel on TLS
This test is quite flaky on ssl integration test

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-05-13 22:44:33 -07:00
Batuhan Taşkaya 384043229b reference swarm page correctly
Signed-off-by: Batuhan Taşkaya <btaskaya33@gmail.com>
2019-05-09 20:34:42 +03:00
Joffrey F 23c5c001c6
Merge pull request #2329 from docker/end_3.4_support
End Python 3.4 support
2019-05-05 16:37:45 -07:00
Hannes Ljungberg bcd61e40dd Correctly reference SecretReference
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-03 22:27:56 +02:00
Hannes Ljungberg ff0cbe4c79 Correctly reference ConfigReference
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-03 22:27:32 +02:00
Hannes Ljungberg 0ddf428b6c Add NetworkAttachmentConfig type
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-03 22:27:32 +02:00
Joffrey F e2c1c9caac
Merge pull request #2332 from docker/use_proxy_config_default
Change use_config_proxy default value to True to match CLI behavior
2019-05-02 13:11:07 -07:00
Joffrey F 7f56f7057c Don't add superfluous arguments
Signed-off-by: Joffrey F <f.joffrey@gmail.com>
2019-05-02 12:46:56 -07:00
Joffrey F 87ee18aa39 Change use_config_proxy default value to True to match CLI behavior
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 20:52:01 -07:00
Joffrey F 836194c64f
Merge pull request #2295 from hannseman/swarm-rotate-token
Add support for rotate_manager_unlock_key
2019-05-01 20:36:45 -07:00
Joffrey F bdc954b009 Stop supporting EOL Python 3.4
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 19:51:29 -07:00
Joffrey F 1aae20d13a Remove obsolete win32-requirements file
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 19:44:23 -07:00
Joffrey F 75e0ad017c
Merge pull request #2328 from docker/modernize_test_deps
Update some test dependencies / default values with newer versions
2019-05-01 02:48:05 -07:00
Hannes Ljungberg 532c62ee51 Add support for rotate_manager_unlock_key
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-01 11:45:20 +02:00
Joffrey F eba8345c37 Update some test dependencies / default values with newer versions
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 02:36:19 -07:00
Joffrey F 4d62dd0a64
Merge pull request #2296 from hannseman/swarm-init-response
Return node id on swarm init
2019-05-01 02:29:30 -07:00
Joffrey F 9682422718
Merge pull request #2303 from hannseman/swarm-DataPathAddr
Add support for swarm DataPathAddr
2019-05-01 02:22:06 -07:00
Joffrey F cc13b82e9f
Merge pull request #2222 from docker/vendor_dockerpycreds
Make dockerpycreds part of the SDK under docker.credentials
2019-05-01 01:39:54 -07:00
Joffrey F be9cf3e39e
Merge pull request #2327 from docker/demux_test_fixes
Streaming TTY messages sometimes get truncated
2019-05-01 01:30:29 -07:00
Hannes Ljungberg 110c6769c9 Add test for join on already joined swarm
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-01 10:24:50 +02:00
Hannes Ljungberg c7b9cae0a0 Add swarm support for data_addr_path
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-01 10:24:50 +02:00
Hannes Ljungberg acd7a8f430 Return node id on swarm init
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-05-01 10:24:02 +02:00
Joffrey F 1a4881acd9 Improve low_timeout test resilience
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 01:15:41 -07:00
Joffrey F 34ffc56865 Streaming TTY messages sometimes get truncated. Handle gracefully in demux tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 00:59:35 -07:00
Joffrey F 992e0dcdfb
Merge pull request #2317 from docker/fix_socket_detach_helper
Fix socket detach helper
2019-05-01 00:57:27 -07:00
Joffrey F 62c8bcbbb6 Increase timeout on test with long sleeps
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 00:47:16 -07:00
Joffrey F a2a2d100e8 Reorder imports
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 00:35:12 -07:00
Joffrey F 2e67cd1cc7 Improve socket_detached test helper to support future versions of the daemon
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 00:35:12 -07:00
Joffrey F 63cda2e7b5
Merge pull request #2326 from docker/fix_exec_demux_tests
Avoid demux test flakiness
2019-05-01 00:34:28 -07:00
Joffrey F 073a21c28a Separate into individual tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-05-01 00:20:40 -07:00
Joffrey F b06e437da8 Avoid demux test flakiness
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-04-30 23:47:09 -07:00
Joffrey F 4c45067df9 New Jenkinsfile build instructions
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-04-30 23:37:55 -07:00
Joffrey F a823acc2ca Make dockerpycreds part of the SDK under docker.credentials
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-04-30 23:37:55 -07:00
Joffrey F 0287cd9f2e
Merge pull request #2309 from thaJeztah/remove_init_path_create
Remove init_path from create
2019-04-30 23:37:06 -07:00
Joffrey F 41e1c05426
Merge pull request #2325 from docker/fix_versions_script
Fix versions.py to include release stage
2019-04-30 23:36:23 -07:00
Joffrey F 20a5c06724 Fix versions.py to include release stage
Signed-off-by: Joffrey F <f.joffrey@gmail.com>
2019-04-30 23:16:09 -07:00
Joffrey F 613d6aad83
Merge pull request #2322 from adamtheturtle/fix-rendered-exit-code-exec-run
Replace triple backtick in exec_run documentation which caused a rend…
2019-04-27 15:28:42 -07:00
Adam Dangoor 221d64f427 Replace triple backtick in exec_run documentation which caused a rendering error.
Signed-off-by: Adam Dangoor <adamdangoor@gmail.com>
2019-04-27 09:16:28 +01:00
Joffrey F 1aaa76dc5b
Merge pull request #2297 from hannseman/service-init
Add support for setting init on services
2019-04-14 15:07:47 -07:00
Sebastiaan van Stijn 50d475797a
Remove init_path from create
This option was never functional, and was not intended
to be added to the "container create" API, so let's
remove it, because it has been removed in Docker 17.05,
and was broken in versions before that; see

- https://github.com/moby/moby/issues/32355 --init-path does not seem to work
- https://github.com/moby/moby/pull/32470 remove --init-path from client

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-10 02:42:23 +02:00
Chris Crone 5e8b1c0e2a
Merge pull request #2304 from hannseman/swarm-join-listen_addr
Document correct listen_addr default on join swarm
2019-04-04 14:51:17 +02:00
Ulysses Souza 94d1edc33e
Merge pull request #2307 from ulyssessouza/xfail-flaky-test
Avoid race condition on test
2019-04-04 14:35:31 +02:00
Ulysses Souza ef043559c4 Add 'sleep 2' to avoid race condition on attach
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-04-04 14:09:18 +02:00
Ulysses Souza 1b572a4340
Merge pull request #1882 from larkost/1743-container-ports
add ports to containers
2019-04-03 11:20:02 +02:00
Hannes Ljungberg 8010d8ba1e Document correct listen_addr on join swarm
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-31 23:20:16 +02:00
Ulysses Souza a4c251d230
Merge pull request #2299 from ulyssessouza/3.7.2-release
Bump 3.7.2 release
2019-03-28 17:30:26 +01:00
Hannes Ljungberg 0d5aacc464 Add support for setting init on services
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-28 16:03:48 +01:00
Ulysses Souza 8f2d9a5687 Bump 3.7.2
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-28 15:56:18 +01:00
Ian Campbell cd59491b9a scripts/version.py: Use regex grouping to extract the version
The `lstrip` and `rstrip` functions take a set of characters to remove, not a
prefix/suffix. Thus `rstrip('-x86_64')` will remove any trailing characters in
the string `'-x86_64'` in any order (in effect it strips the suffix matching
the regex `[-_x468]*`). So with `18.09.4` it removes the `4` suffix resulting
in trying to `int('')` later on:

    Traceback (most recent call last):
      File "/src/scripts/versions.py", line 80, in <module>
        main()
      File "/src/scripts/versions.py", line 73, in main
        versions, reverse=True, key=operator.attrgetter('order')
      File "/src/scripts/versions.py", line 52, in order
        return (int(self.major), int(self.minor), int(self.patch)) + stage
    ValueError: invalid literal for int() with base 10: ''

Since we no longer need to check for the arch suffix (since it no longer
appears in the URLs we are traversing) we could just drop the `rstrip` and
invent a local prefix stripping helper to replace `lstrip('docker-')`. Instead
lets take advantage of the behaviour of `re.findall` which is that if the regex
contains a single `()` match that will be returned. This lets us match exactly
the sub-section of the regex we require.

While editing the regex, also ensure that the suffix is precisely `.tgz` and
not merely `tgz` by adding an explicit `\.`, previously the literal `.` would
be swallowed by the `.*` instead.

Signed-off-by: Ian Campbell <ijc@docker.com>
2019-03-28 15:56:18 +01:00
Ulysses Souza f97c577c1d
Merge pull request #2298 from ijc/fix-docker-version-detection-script
scripts/version.py: Use regex grouping to extract the version
2019-03-28 15:50:44 +01:00
Ian Campbell b0abdac90c scripts/version.py: Use regex grouping to extract the version
The `lstrip` and `rstrip` functions take a set of characters to remove, not a
prefix/suffix. Thus `rstrip('-x86_64')` will remove any trailing characters in
the string `'-x86_64'` in any order (in effect it strips the suffix matching
the regex `[-_x468]*`). So with `18.09.4` it removes the `4` suffix resulting
in trying to `int('')` later on:

    Traceback (most recent call last):
      File "/src/scripts/versions.py", line 80, in <module>
        main()
      File "/src/scripts/versions.py", line 73, in main
        versions, reverse=True, key=operator.attrgetter('order')
      File "/src/scripts/versions.py", line 52, in order
        return (int(self.major), int(self.minor), int(self.patch)) + stage
    ValueError: invalid literal for int() with base 10: ''

Since we no longer need to check for the arch suffix (since it no longer
appears in the URLs we are traversing) we could just drop the `rstrip` and
invent a local prefix stripping helper to replace `lstrip('docker-')`. Instead
lets take advantage of the behaviour of `re.findall` which is that if the regex
contains a single `()` match that will be returned. This lets us match exactly
the sub-section of the regex we require.

While editing the regex, also ensure that the suffix is precisely `.tgz` and
not merely `tgz` by adding an explicit `\.`, previously the literal `.` would
be swallowed by the `.*` instead.

Signed-off-by: Ian Campbell <ijc@docker.com>
2019-03-28 13:18:02 +00:00
Ulysses Souza b05bfd7b22 Fix base_url to keep TCP protocol
This fix lets the responsability of changing the
protocol to `parse_host` afterwards, letting
`base_url` with the original value.

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-28 14:16:52 +01:00
Ulysses Souza 33b8fd6eec Xfail test_attach_stream_and_cancel on TLS
This test is quite flaky on ssl integration test

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-28 14:16:18 +01:00
Ulysses Souza 3244094d97
Merge pull request #2292 from ulyssessouza/fix-config-proxy-mapping
Fix base_url to keep TCP protocol
2019-03-27 17:52:31 +01:00
Ulysses Souza d1f7979f24 Refactor and add tests
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-26 17:28:49 +01:00
Karl Kuehn 4890864d65 add ports to containers
Signed-off-by: Karl Kuehn <kuehn.karl@gmail.com>
2019-03-26 16:55:45 +01:00
Ulysses Souza b2175c9475 Fix base_url to keep TCP protocol
This fix lets the responsability of changing the
protocol to `parse_host` afterwards, letting
`base_url` with the original value.

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-26 16:04:06 +01:00
Ulysses Souza 15862eacbf Xfail test_attach_stream_and_cancel on TLS
This test is quite flaky on ssl integration test

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-26 16:04:06 +01:00
Ian Campbell 02e660da12
Merge pull request #2227 from docker/2225-inspect_distrib_auth
Add registry auth header to inspect_distribution requests
2019-03-26 10:17:12 +00:00
Ian Campbell c1fea8ee4a
Merge pull request #2288 from hannseman/container-run-create-volume_driver
Move volume_driver to RUN_HOST_CONFIG_KWARGS
2019-03-25 12:24:54 +00:00
Ian Campbell d38c7246a4
Merge pull request #2287 from hannseman/swarm-default-addr-pool-redux
Redux added arguments to create a swarm with a custom address pool and subnet size.
2019-03-25 12:01:15 +00:00
Ian Campbell 5abf671442
Merge pull request #2282 from ulyssessouza/avoid-race-condition-on-autoremove
Avoid race condition on short execution
2019-03-25 12:00:28 +00:00
Ulysses Souza 8f42dd1484 Avoid race condition on short execution
- Add a sleep of 2 seconds to be sure the logs
can be requested before the daemon removes the
container when run with auto_remove=True

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-25 12:42:54 +01:00
Ulysses Souza d47e5aaa9a
Merge pull request #2281 from hannseman/sctp-protocol
Support for SCTP
2019-03-25 12:04:41 +01:00
Joffrey F 565489e2d0
Merge pull request #2265 from lekster/master
set buildargs default value if None
2019-03-23 13:44:30 -07:00
Hannes Ljungberg 523371e21d Move volume_driver to RUN_HOST_CONFIG_KWARGS
Fixes #2271

Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-23 20:57:23 +01:00
Hannes Ljungberg 68a271cef4 Fix documentation and order of arguments
Following https://github.com/docker/docker-py/pull/2201#pullrequestreview-192571911

Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
Co-authored-by: Hannes Ljungberg <hannes@5monkeys.se>
Co-authored-by: bluikko <14869000+bluikko@users.noreply.github.com>
2019-03-22 20:30:17 +01:00
Barry Shapira d6cc972cd9 Split monolithic integration tests into individual tests.
The integration tests require restarting the swarm once for each
test.  I had done so manually with self.init_swarm(force_new_cluster=True)
but that wasn't resetting the swarm state correctly.  The usual
test teardown procedure cleans up correctly.

Signed-off-by: Barry Shapira <barry@whiterabbit.ai>
2019-03-22 10:40:27 +01:00
Barry Shapira 781dc30ad4 Check API version before setting swarm addr pool.
Also corrected a documentation error: the default API version from
constants is currently 1.35, not 1.30 as was sometimes listed.

Signed-off-by: Barry Shapira <barry@whiterabbit.ai>

Removed accidental whitespace.

Signed-off-by: Barry Shapira <barry@whiterabbit.ai>
2019-03-22 10:40:27 +01:00
Barry Shapira 5d69a0a62e Added arguments to creeate a swarm with a custom address pool and subnet size.
Signed-off-by: Barry Shapira <barry@whiterabbit.ai>
2019-03-22 10:38:13 +01:00
Chris Crone 142db4b3d3
Merge pull request #2284 from ulyssessouza/master
Update changelog and next milestone
2019-03-20 15:27:32 +01:00
Ulysses Souza 7df248a2dd Update changelog and next milestone
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-20 15:06:15 +01:00
Djordje Lukic cb8b462605
Merge pull request #2283 from ulyssessouza/3.7.1-release
3.7.1 release
2019-03-20 13:49:36 +01:00
Ulysses Souza 963818a4d2 Bump 3.7.1
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-20 11:56:24 +01:00
Ulysses Souza 89485bf26e Fix BaseHTTPAdapter for the SSL case
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-20 11:54:23 +01:00
Ulysses Souza 313f736488 Homogenize adapters close() behaviour.
- Adds a BaseHTTPAdapter with a close method to ensure that the
pools is clean on close()
- Makes SSHHTTPAdapter reopen a closed connection when needed
like the others

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-20 11:54:13 +01:00
Ulysses Souza e577f5d61d Sets a different default number of pools to SSH
This is because default the number of connections
in OpenSSH is 10

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-20 11:54:00 +01:00
Yincen Xia 729c2e7830 Update doc for container.exec_run & exec_api about demux
Signed-off-by: Yincen Xia <philip980507@msn.cn>
2019-03-19 15:11:49 +01:00
Ulysses Souza 0f7af860d8 Fix BaseHTTPAdapter for the SSL case
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-19 11:05:56 +01:00
Hannes Ljungberg 7143cf02ab Test port lookup with protocols
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-18 22:15:49 +01:00
Hannes Ljungberg 35714c46b1 Test all split_port with all valid protocols
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-18 22:15:45 +01:00
Hannes Ljungberg 5d76e8e13e Support sctp as protocol
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-18 22:15:40 +01:00
Joffrey F 1047376f0d
Merge pull request #2272 from hannseman/update-service-response
Return API response on service update
2019-03-16 22:34:05 -07:00
Joffrey F e0024b5b3f
Merge pull request #2203 from docker/terminate_3.3_support
[4.0] Terminate support for Python 3.3 (EOL in 2018)
2019-03-16 11:54:40 -07:00
Joffrey F 55ffb761bf Terminate support for Python 3.3 (EOL in 2018)
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-03-16 09:41:38 -07:00
Ulysses Souza 4d7d408413 Homogenize adapters close() behaviour.
- Adds a BaseHTTPAdapter with a close method to ensure that the
pools is clean on close()
- Makes SSHHTTPAdapter reopen a closed connection when needed
like the others

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-15 11:23:00 +01:00
Ulysses Souza e48a1a94e6 Sets a different default number of pools to SSH
This is because default the number of connections
in OpenSSH is 10

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-03-15 11:23:00 +01:00
Hannes Ljungberg 8d1e9670b1 Return API response on service update
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-03-13 10:12:17 +01:00
Leks 37e096f6ad set buildargs default value if None
Signed-off-by: Leks <alexsmir@list.ru>
2019-03-01 14:05:39 +03:00
Jean-Christophe Sirot 24ace2dac8
Merge pull request #2259 from p1100i/patch-1
Fix `network_mode` API documentation wording
2019-02-28 14:56:23 +01:00
p1100i 189552eb57 Fix `network_mode` API documentation wording
Signed-off-by: p1100i <p1100i@gmx.com>
2019-02-21 07:55:38 +01:00
Joffrey F 61bab63798
Merge pull request #2245 from thombashi/fix_api_ver_desc
Fix descriptions of the default API version in docs
2019-01-25 20:32:43 -08:00
Tsuyoshi Hombashi 6935ce8819
Fix descriptions of the default API version in docs
1.30 -> 1.35

Signed-off-by: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
2019-01-26 12:47:20 +09:00
Ulysses Souza d7772b73f2
Merge pull request #2234 from hannseman/placement-preference-tuples
Make PlacementPreference build correct context
2019-01-22 17:24:38 +01:00
Ulysses Souza 26f9e4b23f
Merge pull request #2233 from wvaske/2232-Adding_supported_options_to_container_run_documentation
Added missing options from RUN_HOST_CONFIG_KWARGS list in docker.models.containers to the docstring for client.containers.run()
2019-01-22 15:02:02 +01:00
Hannes Ljungberg d429a823ed Make PlacementPreference build correct context
Signed-off-by: Hannes Ljungberg <hannes@5monkeys.se>
2019-01-18 21:50:31 +01:00
wvaske 24f7c6db66 Added missing options from RUN_HOST_CONFIG_KWARGS list in docker.models.containers to the docstring for client.containers.run()
Signed-off-by: wvaske <wvaske@micron.com>
2019-01-17 10:43:20 -06:00
Joffrey F b6f6e7270e Add registry auth header to inspect_distribution requests
Update docstring for auth_config parameter in pull, push, and
inspect_distribution

Signed-off-by: Joffrey F <joffrey@docker.com>
2019-01-11 16:39:16 -08:00
Christopher Crone 28c9100a7c Bump to next dev version
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
2019-01-10 18:26:02 +01:00
Chris Crone 78b15e0f63
Merge pull request #2224 from docker/release
Resync release
2019-01-10 18:20:12 +01:00
Chris Crone ac92219295
Merge pull request #2223 from docker/3.7.0-release
3.7.0 release
2019-01-10 18:15:58 +01:00
Ulysses Souza e6783d8cf3 Bump 3.7.0
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
2019-01-10 17:58:39 +01:00
Joffrey F 55a62c26e7
Merge pull request #2221 from docker/proxy_env_fixes
Remove use_config_proxy from exec. Add use_config_proxy docs to DockerClient
2019-01-09 14:58:32 -08:00
Joffrey F a579e9e205 Remove use_config_proxy from exec. Add use_config_proxy docs to DockerClient
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-01-09 14:45:13 -08:00
Joffrey F 1073b73648
Merge pull request #2216 from thaJeztah/fix_status_code_check
Regression 443 test: relax status-code check
2019-01-09 12:40:31 -08:00
Sebastiaan van Stijn 219c52141e
Regression 443 test: relax status-code check
This test was testing for a 500 status, but this status
is actually a bug in the API (as it's due to an invalid
request), and the API should actually return a 400 status.

To make this test handle both situations, relax the test
to accept either a 4xx or 5xx status.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-09 21:23:11 +01:00
Joffrey F 5455c04f75
Merge pull request #2219 from docker/2199-proxy-support
Support using proxy values from config
2019-01-09 12:05:39 -08:00
Joffrey F 65bebc085a Style fixes and removed some unused code
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 6969e8becd handle url-based proxy configurations
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 2c4a8651a8 By default, disable proxy support
This is to avoid a breaking change

Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 73c17f85e5 fix typo in docstring
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry f97f71342f refactor ProxyConfig
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 9146dd57d7 code style improvement
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 708ef6d81e Revert "make the integration tests more verbose"
This reverts commit 7584e5d7f0.

Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 0d37390c46 add integration tests for proxy support
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 4f79ba160e make the integration tests more verbose
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 545adc2a59 add unit tests for ProxyConfig
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry 6e227895d3 tests: remove outdated code
the _cfg attribute does not exist anymore

Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Corentin Henry bfdd0a881e add support for proxies
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2019-01-09 11:30:58 -08:00
Joffrey F 4ca4e94ea7
Merge pull request #2218 from docker/fix_test_deps
Update test dependencies to latest version, fix some flake8 errors
2019-01-09 11:30:38 -08:00
Joffrey F 72f4f527ad Update test dependencies to latest version, fix some flake8 errors
Signed-off-by: Joffrey F <joffrey@docker.com>
2019-01-09 11:18:40 -08:00
Joffrey F 5fc7f62ec4
Merge pull request #2213 from docker/2210-swarm-init-return
Make swarm.init() return value match documentation
2018-12-28 16:19:33 -08:00
Joffrey F 3cda1e8bbd Make swarm.init() return value match documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-12-28 15:45:54 -08:00
Joffrey F 3151b0ef2f
Merge pull request #2207 from BoboTiG/patch-1
Fix DeprecationWarning: invalid escape sequence in services.py
2018-12-28 07:32:10 +09:00
Joffrey F 60ffeede92
Merge pull request #2208 from BoboTiG/patch-2
Fix DeprecationWarning: invalid escape sequence in ports.py
2018-12-28 07:30:46 +09:00
Mickaël Schoentgen e99ce1e359 Fix DeprecationWarning: invalid escape sequence in ports.py
Signed-off-by: Mickaël Schoentgen <contact@tiger-222.fr>
2018-12-20 14:54:52 +01:00
Mickaël Schoentgen 341e2580aa Fix DeprecationWarning: invalid escape sequence in services.py
Signed-off-by: Mickaël Schoentgen <contact@tiger-222.fr>
2018-12-20 14:54:15 +01:00
Joffrey F 7911c54635
Merge pull request #2204 from MaxBischoff/typo-fix
Fixed a typo in the configs api doc
2018-12-14 12:27:25 -08:00
Maximilian Bischoff 543d83cb09 Fixed a typo in the configs api doc
The documentation for id in ConfigApiMixin inspect_config was wrongly
mentioning removal of a config

Signed-off-by: Maximilian Bischoff <maximilianbischoff2@gmail.com>
2018-12-14 19:21:57 +01:00
Joffrey F d77d4256d7
Merge pull request #2197 from docker/2185-placement-prefs
Improve handling of placement preferences and associated docs
2018-12-11 08:41:33 -08:00
Joffrey F f39b1df407
Merge pull request #2198 from docker/update_versionmap
Update Jenkinsfile version map
2018-12-11 08:40:53 -08:00
Joffrey F a207122c0d Update Jenkinsfile version map
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-12-07 17:04:54 -08:00
Joffrey F b297b837df Dynamically retrieve version information for generated docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-12-07 16:57:40 -08:00
Joffrey F e15db4cb20 Improve handling of placement preferences; improve docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-12-07 16:56:45 -08:00
Joffrey F 92236550d2
Merge pull request #2196 from docker/2194-clean-release
Prevent untracked files in releases
2018-12-07 16:08:18 -08:00
Joffrey F 1bc5783a3d Prevent untracked files in releases
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-12-07 16:08:00 -08:00
Joffrey F 11250042eb
Merge pull request #2193 from docker/update_setup_py
Update setup.py for modern pypi / setuptools
2018-11-30 18:00:55 -08:00
Joffrey F 3381f7be15 Update setup.py for modern pypi / setuptools
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 17:26:50 -08:00
Joffrey F 5c748467d7
Merge pull request #2192 from docker/authconfig_fix
Fix empty authconfig detection
2018-11-30 16:33:35 -08:00
Joffrey F bc84ed11ec Fix empty authconfig detection
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 15:56:39 -08:00
Joffrey F c344660f20
Merge pull request #2188 from docker/c6374-credhelpers
Modernize auth management
2018-11-30 15:32:30 -08:00
Joffrey F b72fb1e571 Merge branch 'little-dude-master' 2018-11-30 15:27:49 -08:00
Joffrey F 16c28093b9 Move exec_run example to user guides section of docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 15:26:51 -08:00
Joffrey F b2ad302636 Fix test names
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 14:58:18 -08:00
Joffrey F ee6ec4c6e8 Merge branch 'master' of https://github.com/little-dude/docker-py into little-dude-master 2018-11-30 14:48:19 -08:00
Joffrey F 666388168d
Merge pull request #2181 from funkyfuture/exec_run_docs
Fixes the documented return value of models.containers.Container.exec_run
2018-11-30 14:44:08 -08:00
Joffrey F cc38efa68e Add some credHelpers tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 14:41:56 -08:00
Joffrey F bef10ecac1 Add credstore_env to all load_config calls
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 13:51:40 -08:00
Joffrey F 01ccaa6af2 Make AuthConfig a dict subclass for backward-compatibility
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-30 13:51:01 -08:00
Joffrey F bc5d7c8cb6 Modernize auth management
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 19:32:01 -08:00
Corentin Henry 7b3b83dfdb fix exec api inconsistency
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-28 15:16:23 -08:00
Corentin Henry 41c0eb7e80 fix exec_start() documentation
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-28 15:16:17 -08:00
Joffrey F 9a67e2032e Next dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 14:31:28 -08:00
Joffrey F 80e862aafa Merge branch 'release' 2018-11-28 14:30:06 -08:00
Corentin Henry 76447d0ca3 tests various exec_create/exec_start combinations
Test the interation of the tty, demux and stream parameters

Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-28 13:37:17 -08:00
Corentin Henry 6540900dae add tests for _read_from_socket
Check that the return value against the various combination of
parameters this function can take (tty, stream, and demux).

This commit also fixes a bug that the tests uncovered a bug in
consume_socket_output.

Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-28 13:37:10 -08:00
Joffrey F d74bfa69ab
Merge pull request #2187 from docker/3.6.0-release
3.6.0 release
2018-11-28 12:11:38 -08:00
Joffrey F 24ed2f356b Release 3.6.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:57:19 -08:00
Joffrey F 30d16ce89a Update DockerClient.images.pull to always stream response
Also raise a warning when users attempt to specify the "stream" parameter

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
adw1n 7117855f6e Fix pulling images with `stream=True`
Pulling an image with option `stream=True` like this:
```
client.api.pull('docker.io/user/repo_name', tag='latest', stream=True)
```
without consuming the generator oftentimes results in premature drop of the connection. Docker daemon tries to send progress of pulling the image to the client, but it encounters an error (broken pipe) and therefore cancells the pull action:
```
Thread 1 "dockerd-dev" received signal SIGPIPE, Broken pipe.
ERRO[2018-09-03T05:12:35.746497638+02:00] Not continuing with pull after error: context canceled
```
As described in issue #2116, even though client receives response with status code 200, image is not pulled.

Closes #2116

Signed-off-by: Przemysław Adamek <adw1n@users.noreply.github.com>
2018-11-28 11:56:28 -08:00
Joffrey F f9505da1d6 Correctly handle longpath prefix in process_dockerfile when joining paths
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Corentin Henry 2d5a7c3894 tests: bump pytest-timeout
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>

pytest-timeout 1.2.1 seems to be incompatible with pytest 3.6.3:

INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/main.py", line 185, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/main.py", line 225, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/hooks.py", line 284, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 67, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 61, in <lambda>
INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 81, in get_result
INTERNALERROR>     _reraise(*ex)  # noqa
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/main.py", line 246, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/hooks.py", line 284, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 67, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 61, in <lambda>
INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 81, in get_result
INTERNALERROR>     _reraise(*ex)  # noqa
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 182, in _multicall
INTERNALERROR>     next(gen)  # first yield
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 76, in pytest_runtest_protocol
INTERNALERROR>     timeout_setup(item)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 104, in timeout_setup
INTERNALERROR>     timeout, method = get_params(item)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 162, in get_params
INTERNALERROR>     timeout, method = _parse_marker(item.keywords['timeout'])
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 178, in _parse_marker
INTERNALERROR>     if not marker.args and not marker.kwargs:
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/mark/structures.py", line 25, in warned
INTERNALERROR>     warnings.warn(warning, stacklevel=2)
INTERNALERROR> RemovedInPytest4Warning: MarkInfo objects are deprecated as they contain merged marks which are hard to deal with correctly.
INTERNALERROR> Please use node.get_closest_marker(name) or node.iter_markers(name).
INTERNALERROR> Docs: https://docs.pytest.org/en/latest/mark.html#updating-code
2018-11-28 11:56:28 -08:00
Corentin Henry ad4f5f9d0c tests: fix failure due to pytest deprecation
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-28 11:56:28 -08:00
Joffrey F cafb802c51 Fix versions script to accept versions without -ce suffix
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F e6889eb9d6 Fix file mode in image.save examples
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F 584204bbdd Add doc example for get_archive
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F 66666f9824 Properly convert non-string filters to expected string format
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F d9e08aedc3 Disallow incompatible combination stats(decode=True, stream=False)
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F ebfba8d4c3 Fix incorrect return info for inspect_service
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F bc45e71c55 Document attr caching for Container objects
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F d4b1c259a2 Update links docs and fix bug in normalize_links
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F 049e7e16d4 Improved LogConfig documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F 9467fa4809 Improve ulimits documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:28 -08:00
Joffrey F f1d629fb5c Add named parameter to image.save to identify which repository name to use in the resulting tarball
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Adam Dangoor 8f3dc4740e Add a missing space in a log message
Signed-off-by: Adam Dangoor <adamdangoor@gmail.com>
2018-11-28 11:56:08 -08:00
Joffrey F 3d5313a5fd Rewrite utils.parse_host to detect more invalid addresses.
The method now uses parsing methods from urllib to better split provided URLs.
Addresses containing query strings, parameters, passwords or fragments no longer fail silently.
SSH addresses containing paths are no longer accepted.

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 6777c28dee Clear error for cancellable streams over SSH
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 8c86aa90b1 Update tests to properly dispose of client instances in tearDown
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F c9edc9c748 Update tests for ssh protocol compatibility
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 2b2d711a5b Remove misleading fileno method from NpipeSocket class
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 956474a1bf Add support for SSH protocol in base_url
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F e4368fb0f3 Add paramiko requirement for SSH transport
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 2e4a45358e Update version detection script for CI
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 26daa6194a Add xfail to ignore 18.09 beta bug
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F a422924a5e Bump requests dependency in requirements.txt (CVE-2018-18074)
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:56:08 -08:00
Joffrey F 042a0e5474
Merge pull request #2186 from docker/adw1n-i2116
Fix pulling images with `stream=True`
2018-11-28 11:45:52 -08:00
Joffrey F c53423f118 Update DockerClient.images.pull to always stream response
Also raise a warning when users attempt to specify the "stream" parameter

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-28 11:27:04 -08:00
adw1n a74d546864 Fix pulling images with `stream=True`
Pulling an image with option `stream=True` like this:
```
client.api.pull('docker.io/user/repo_name', tag='latest', stream=True)
```
without consuming the generator oftentimes results in premature drop of the connection. Docker daemon tries to send progress of pulling the image to the client, but it encounters an error (broken pipe) and therefore cancells the pull action:
```
Thread 1 "dockerd-dev" received signal SIGPIPE, Broken pipe.
ERRO[2018-09-03T05:12:35.746497638+02:00] Not continuing with pull after error: context canceled
```
As described in issue #2116, even though client receives response with status code 200, image is not pulled.

Closes #2116

Signed-off-by: Przemysław Adamek <adw1n@users.noreply.github.com>
2018-11-28 11:27:04 -08:00
Corentin Henry 5f157bbaca implement stream demultiplexing for exec commands
fixes https://github.com/docker/docker-py/issues/1952

Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-27 17:01:48 -08:00
Joffrey F e1e4048753
Merge pull request #2183 from docker/c6356-longpath-prefix
Correctly handle longpath prefix in process_dockerfile when joining paths
2018-11-26 17:45:48 -08:00
Joffrey F 114630161a Correctly handle longpath prefix in process_dockerfile when joining paths
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-26 17:34:26 -08:00
Joffrey F f3231a1ebb
Merge pull request #2178 from little-dude/fix_deprecation
tests: fix failure due to pytest deprecation
2018-11-26 16:39:12 -08:00
Frank Sachsenheim 3fca75ffef
Fixes return value models.containers.Container.exec_run.__doc__
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2018-11-27 01:06:02 +01:00
Corentin Henry 493d7f0f30 tests: bump pytest-timeout
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>

pytest-timeout 1.2.1 seems to be incompatible with pytest 3.6.3:

INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/main.py", line 185, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/main.py", line 225, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/hooks.py", line 284, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 67, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 61, in <lambda>
INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 81, in get_result
INTERNALERROR>     _reraise(*ex)  # noqa
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/main.py", line 246, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/hooks.py", line 284, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 67, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/manager.py", line 61, in <lambda>
INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 81, in get_result
INTERNALERROR>     _reraise(*ex)  # noqa
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pluggy/callers.py", line 182, in _multicall
INTERNALERROR>     next(gen)  # first yield
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 76, in pytest_runtest_protocol
INTERNALERROR>     timeout_setup(item)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 104, in timeout_setup
INTERNALERROR>     timeout, method = get_params(item)
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 162, in get_params
INTERNALERROR>     timeout, method = _parse_marker(item.keywords['timeout'])
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/pytest_timeout.py", line 178, in _parse_marker
INTERNALERROR>     if not marker.args and not marker.kwargs:
INTERNALERROR>   File "/usr/local/lib/python2.7/site-packages/_pytest/mark/structures.py", line 25, in warned
INTERNALERROR>     warnings.warn(warning, stacklevel=2)
INTERNALERROR> RemovedInPytest4Warning: MarkInfo objects are deprecated as they contain merged marks which are hard to deal with correctly.
INTERNALERROR> Please use node.get_closest_marker(name) or node.iter_markers(name).
INTERNALERROR> Docs: https://docs.pytest.org/en/latest/mark.html#updating-code
2018-11-21 18:29:02 -08:00
Corentin Henry 47c10aa383 tests: fix failure due to pytest deprecation
Signed-off-by: Corentin Henry <corentinhenry@gmail.com>
2018-11-21 17:17:50 -08:00
Joffrey F f7a1052b2b Fix versions script to accept versions without -ce suffix
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 18:58:06 -08:00
Joffrey F 302cb78f87
Merge pull request #2172 from docker/fix_docs
Documentation fixes
2018-11-08 18:10:09 -08:00
Joffrey F 35b9460748 Remove prematurely committed file
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:38:59 -08:00
Joffrey F 852d79b08d Fix file mode in image.save examples
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:32:33 -08:00
Joffrey F cebdee4aef Add doc example for get_archive
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:31:22 -08:00
Joffrey F f83fe7c959 Properly convert non-string filters to expected string format
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:22:24 -08:00
Joffrey F 89ee08f511 Disallow incompatible combination stats(decode=True, stream=False)
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:13:19 -08:00
Joffrey F b927a5f62c Fix incorrect return info for inspect_service
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:08:41 -08:00
Joffrey F 6bfe4c9090 Document attr caching for Container objects
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 17:05:42 -08:00
Joffrey F 6064947431 Update links docs and fix bug in normalize_links
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 16:55:58 -08:00
Joffrey F d5bc46ad45 Improved LogConfig documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 16:20:28 -08:00
Joffrey F 1d124a1262 Improve ulimits documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 15:32:10 -08:00
Joffrey F 9987c1bc42 Fix docs examples to work with Python 3
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-08 15:05:22 -08:00
Joffrey F 5467658bbc
Merge pull request #2169 from docker/2124-image-save-with-name
Add named parameter to image.save to identify which repository name to use in the resulting tarball
2018-11-08 12:50:03 -08:00
Joffrey F e237c0ea16 Add named parameter to image.save to identify which repository name to use in the resulting tarball
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-06 14:46:37 -08:00
Joffrey F 7252086054
Merge pull request #2165 from docker/ssh_protocol_support
SSH protocol support
2018-11-06 11:09:00 -08:00
Joffrey F c9bee7716f
Merge pull request #2168 from adamtheturtle/patch-1
Add a missing space in a log message
2018-11-04 22:57:57 -08:00
Adam Dangoor 490b2db3ae Add a missing space in a log message
Signed-off-by: Adam Dangoor <adamdangoor@gmail.com>
2018-11-05 00:11:59 +00:00
Joffrey F f302756599 Rewrite utils.parse_host to detect more invalid addresses.
The method now uses parsing methods from urllib to better split provided URLs.
Addresses containing query strings, parameters, passwords or fragments no longer fail silently.
SSH addresses containing paths are no longer accepted.

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:44:43 -07:00
Joffrey F 6bfe2005e0 Clear error for cancellable streams over SSH
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:24:22 -07:00
Joffrey F 94aa9a89f7 Update tests to properly dispose of client instances in tearDown
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:24:22 -07:00
Joffrey F 1df021ee24 Update tests for ssh protocol compatibility
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:24:22 -07:00
Joffrey F f4e9a1dc2a Remove misleading fileno method from NpipeSocket class
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:24:22 -07:00
Joffrey F 338dfb00b1 Add support for SSH protocol in base_url
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:24:22 -07:00
Joffrey F 479f13eff1 Add paramiko requirement for SSH transport
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:24:22 -07:00
Joffrey F dd7386de30 Update version detection script for CI
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-11-01 15:23:21 -07:00
Joffrey F a3111d9e00 Add xfail to ignore 18.09 beta bug
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-10-31 18:05:26 -07:00
Joffrey F b36124d91e
Merge pull request #2161 from docker/bump_requests
Bump requests dependency in requirements.txt (CVE-2018-18074)
2018-10-29 20:25:27 -05:00
Joffrey F e688c09d68 Bump requests dependency in requirements.txt (CVE-2018-18074)
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-10-29 14:46:27 -07:00
Joffrey F 7cc0a1b6eb
Merge pull request #2156 from docker/3.5.1-release
3.5.1 release
2018-10-17 15:03:27 -07:00
Joffrey F f097ea5b98 Bump 3.5.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-10-17 14:38:39 -07:00
Joffrey F 8820e737c6
Merge pull request #2155 from docker/bump_pyopenssl
Bump pyopenssl to prevent installation of vulnerable version
2018-10-17 14:25:08 -07:00
Joffrey F 609045f343 Bump pyopenssl to prevent installation of vulnerable version
CVE refs:
CVE-2018-1000807
CVE-2018-1000808

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-10-17 13:52:39 -07:00
Joffrey F 567d552699
Merge pull request #2145 from mirake/fix-typos
Fix typo: Addtional -> Additional
2018-10-17 13:47:29 -07:00
Rui Cao 46a9b10b63 Fix typo: Addtional -> Additional
Signed-off-by: Rui Cao <ruicao@alauda.io>
2018-09-27 21:10:36 +08:00
Joffrey F 416ea74e3f
Merge pull request #2135 from docker/2133-services-docs
Fix docs for Service objects
2018-09-14 17:23:44 -07:00
Joffrey F 2b10c3773c Fix docs for Service objects
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-09-14 16:58:11 -07:00
Joffrey F 87352cd057
Merge pull request #2111 from bfirsh/document-defaults-of-logs
Document defaults of logs()
2018-09-14 16:42:09 -07:00
Joffrey F 02316eaf25
Merge pull request #2129 from adw1n/i2122-docs
Fix docs for `chunk_size` parameter
2018-09-14 16:40:58 -07:00
adw1n 74a293a9c9 Fix docs for `chunk_size` parameter
Closes #2122

Signed-off-by: Przemysław Adamek <adw1n@users.noreply.github.com>
2018-09-03 03:12:33 +02:00
Ben Firshman 67308c1e55
Document defaults of logs()
This is not obvious because some are True by default.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2018-08-12 13:01:02 +04:00
Joffrey F e78e4e7491 Add RollbackConfig to API docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:33:22 -07:00
Joffrey F 87d72c0f6c Misc release script improvements
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:28:35 -07:00
Joffrey F 205a2f76bd Bump dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:28:06 -07:00
Joffrey F 4130e7b8b0 Merge branch 'release'
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:27:19 -07:00
Joffrey F e0495a91e4
Merge pull request #2110 from docker/3.5.0-release
3.5.0 release
2018-08-09 17:24:22 -07:00
Joffrey F 05fa0be8ef 3.5.0 release
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:12:46 -07:00
Joffrey F 91e9258659 Add support for RollbackConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:11:47 -07:00
Joffrey F e4b509ecac Add version checks and test
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:11:47 -07:00
Joffrey F c2c9ccdd80 Improve placement handling in DockerClient.services.create
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:11:47 -07:00
Anthony Sottile cbc7623ea0 Allow user=0 to be passed in create_container
Signed-off-by: Anthony Sottile <asottile@umich.edu>
2018-08-09 17:11:47 -07:00
Nikolay Murga 8ee446631d Add documentation for delay property
Signed-off-by: Nikolay Murga <work@murga.kiev.ua>
2018-08-09 17:11:47 -07:00
Nikolay Murga 185f72723a Add 'rollback' command as allowed for failure_action
Signed-off-by: Nikolay Murga <work@murga.kiev.ua>
2018-08-09 17:11:47 -07:00
Joffrey F d4345b5824 Add credHelpers support to set_auth_headers in build
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:11:47 -07:00
Joffrey F f71d1cf3cf Update deps for 3.3 & 3.7 support
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 17:11:47 -07:00
Aron Parsons dac943a91d honor placement preferences via services.create()
this allows creating a service with placement preferences when
calling services.create().  only constraints were being honored
before.

related to https://github.com/docker/docker-py/pull/1615

Signed-off-by: Aron Parsons <aron@knackworks.com>
2018-08-09 17:11:47 -07:00
Marco Trillo 29dee5ac2e Add support for `uts_mode` parameter in `Client.create_host_config`.
This parameter allows to set the UTS namespace of the container, as in
the `--uts=X` Docker CLI parameter:
<https://docs.docker.com/engine/reference/run/#uts-settings---uts>
The only allowed value, if set, is "host".

Signed-off-by: Marco Trillo <martri@arantia.com>
Signed-off-by: Diego Alvarez <dyako.developer@gmail.com>
2018-08-09 17:11:47 -07:00
Joffrey F c4a1134e95
Merge pull request #2109 from docker/rollback_config
Add support for RollbackConfig
2018-08-09 16:56:24 -07:00
Joffrey F 82445764e0 Add support for RollbackConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 16:41:25 -07:00
Joffrey F 7e79524083
Merge pull request #2108 from docker/NikolayMurha-master
Add 'rollback' command as allowed for failure_action
2018-08-09 16:13:29 -07:00
Joffrey F 14524f19e2 Add version checks and test
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-09 15:56:11 -07:00
Joffrey F 0c72cd6241 Merge branch 'master' of https://github.com/NikolayMurha/docker-py into NikolayMurha-master 2018-08-09 15:42:40 -07:00
Joffrey F cc766633de
Merge pull request #2103 from asottile/allow_uid_integer_0
Allow user=0 to be passed in create_container
2018-08-06 14:21:32 -07:00
Joffrey F 8d35ae69b7 Merge branch 'knackworks-service-create-placement-preferences' 2018-08-03 14:16:39 -07:00
Joffrey F c28ff85542 Improve placement handling in DockerClient.services.create
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-08-03 14:04:04 -07:00
Joffrey F e7307e5891 Merge branch 'service-create-placement-preferences' of https://github.com/knackworks/docker-py into knackworks-service-create-placement-preferences 2018-08-03 13:46:09 -07:00
Anthony Sottile 3c9738a584 Allow user=0 to be passed in create_container
Signed-off-by: Anthony Sottile <asottile@umich.edu>
2018-08-02 12:00:55 -07:00
Nikolay Murga 24fff59bd9 Add documentation for delay property
Signed-off-by: Nikolay Murga <work@murga.kiev.ua>
2018-07-20 13:20:19 +03:00
Nikolay Murga 3112d39209 Add 'rollback' command as allowed for failure_action
Signed-off-by: Nikolay Murga <work@murga.kiev.ua>
2018-07-20 12:57:50 +03:00
Joffrey F 64a1d8c69a
Merge pull request #2081 from docker/2078-credhelpers-support
Add credHelpers support to set_auth_headers in build
2018-07-19 11:57:39 -07:00
Joffrey F 87f8956a32 Add credHelpers support to set_auth_headers in build
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-07-19 11:46:02 -07:00
Joffrey F e75d79fb7f
Merge pull request #2089 from docker/deps-update
Update deps for 3.3 & 3.7 support
2018-07-19 11:26:42 -07:00
Joffrey F d7bb808ca6 Update deps for 3.3 & 3.7 support
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-07-18 19:21:54 -07:00
Aron Parsons 6152dc8dad honor placement preferences via services.create()
this allows creating a service with placement preferences when
calling services.create().  only constraints were being honored
before.

related to https://github.com/docker/docker-py/pull/1615

Signed-off-by: Aron Parsons <aron@knackworks.com>
2018-07-18 19:12:33 -04:00
Joffrey F 1e389b7cfe
Merge pull request #2074 from docker/3.4.1-release
3.4.1 release
2018-06-29 12:01:25 -07:00
Joffrey F bc28fd0ee2 Bump 3.4.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-29 11:50:42 -07:00
Joffrey F e6b58410bd Re-add walk method to utils.build
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-29 11:31:07 -07:00
Joffrey F 088094c644 On Windows, convert paths to use forward slashes before fnmatch call
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-29 11:30:52 -07:00
Joffrey F 5017de498e Improved .dockerignore pattern processing to better match Docker CLI behavior
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-29 11:30:40 -07:00
Joffrey F 180a0fd085 Fix detach assert function to account for new behavior in engine 18.06
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-29 11:30:19 -07:00
Joffrey F 310ea91383 Fix support for legacy .dockercfg auth config format
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-29 11:30:01 -07:00
Joffrey F b3d2e54a2d
Merge pull request #2063 from mtszb/master
Add support for `uts_mode` parameter in `Client.create_host_config`.
2018-06-29 11:20:51 -07:00
Joffrey F cb19bf117d
Merge pull request #2065 from docker/c6024-improved_excludes
Improved .dockerignore pattern processing to better match Docker CLI behavior
2018-06-29 11:16:17 -07:00
Marco Trillo 098318ad95 Add support for `uts_mode` parameter in `Client.create_host_config`.
This parameter allows to set the UTS namespace of the container, as in
the `--uts=X` Docker CLI parameter:
<https://docs.docker.com/engine/reference/run/#uts-settings---uts>
The only allowed value, if set, is "host".

Signed-off-by: Marco Trillo <martri@arantia.com>
Signed-off-by: Diego Alvarez <dyako.developer@gmail.com>
2018-06-29 14:54:49 +02:00
Joffrey F 37ba1c1eac Re-add walk method to utils.build
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-28 17:11:24 -07:00
Joffrey F ced86ec813 On Windows, convert paths to use forward slashes before fnmatch call
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-28 17:11:24 -07:00
Joffrey F 81b7d48ad6 Improved .dockerignore pattern processing to better match Docker CLI behavior
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-28 17:11:24 -07:00
Joffrey F 101214e5de
Merge pull request #2071 from docker/1806-detach-fix
Fix detach assert function to account for new behavior in engine 18.06
2018-06-28 17:11:00 -07:00
Joffrey F e195e022cf Fix detach assert function to account for new behavior in engine 18.06
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-28 16:33:06 -07:00
Joffrey F dd9cff4f03
Merge pull request #2068 from docker/c6047-legacy-auth
Fix support for legacy .dockercfg auth config format
2018-06-28 13:18:17 -07:00
Joffrey F 8c35eee0fb Fix support for legacy .dockercfg auth config format
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-27 17:04:32 -07:00
Joffrey F 5a85cad547 3.5.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-18 15:26:13 -07:00
Joffrey F f70545e89a
Merge pull request #2062 from docker/3.4.0-release
3.4.0 Release
2018-06-18 15:22:42 -07:00
Joffrey F e5f56247e3 Bump 3.4.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-18 15:11:12 -07:00
Güray Yıldırım 000331cfc1 Swarm Mode service scaling parameter mistake is fixed.
Signed-off-by: Güray Yıldırım <guray@gurayyildirim.com.tr>
2018-06-18 14:07:13 -07:00
Alex Lloyd 76471c6519 Fixed typo in ContainerSpec Docs
Signed-off-by: Alexander Lloyd <axl639@student.bham.ac.uk>
2018-06-12 11:15:05 -07:00
Joffrey F f1189bfb4b Allow passing of env overrides to credstore through APIClient ctor
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-08 15:43:58 -07:00
Chris Mark 2d0c5dd484 Adding missing comma in spec list.
Fixing #2046, syntax error caused by missing comma on CONTAINER_SPEC_KWARGS list.

Signed-off-by: Chris Mark <chrismarkou92@gmail.com>
2018-06-06 17:54:45 -07:00
Joffrey F dbe52dcb7d Fix socket reading function for TCP (non-HTTPS) connections on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-06-06 17:53:50 -07:00
Mike Lee 49bb7386a3 query plugin privilege with registry auth header
Signed-off-by: Mike Lee <eemike@gmail.com>
2018-06-05 12:37:33 -07:00
Anthony Sottile 22b7b76142 Use six.moves to handle a py2+py3 import
Signed-off-by: Anthony Sottile <asottile@umich.edu>
2018-05-25 10:11:36 -07:00
Joffrey F b4efdc1b28 Fix several integration tests on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-05-25 10:11:02 -07:00
Joffrey F 40711cb501 Fix cancellable streams on Windows clients + HTTPS transport
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-05-25 10:11:02 -07:00
Joffrey F 95ad903c35 Fix create_plugin on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-05-25 10:11:02 -07:00
Joffrey F 17f41b5672 Avoid unwanted modification of dockerfile path
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-05-25 10:11:02 -07:00
Srinivas Reddy Thatiparthy 8228059f1e return the pruned networks
Signed-off-by: Srinivas Reddy Thatiparthy <thatiparthysreenivas@gmail.com>
2018-05-24 11:23:48 -07:00
Joffrey F 467cacb00d 3.4.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 18:03:15 -07:00
Joffrey F 2b82f9327a Merge branch 'release'
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 18:02:59 -07:00
Joffrey F e88751cb9a Bump 3.3.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 9d86194dda Add prune_builds to DockerClient
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 94e9108441 Add ignore_removed param to containers.list() to control whether to
raise or ignore NotFound

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Ben Doan eacf9f6d08 avoid race condition in containers.list
Signed-off-by: Ben Doan <ben@bendoan.me>
2018-04-25 17:55:16 -07:00
Joffrey F cc953cf8bf prune_builds test
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F f2c1ae37dd Fix session timeout = None case
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 2454e81026 Total timeout should be HTTP timeout + operation timeout
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Matthieu Nottale 1848d2c949 stop(), restart(): Adjust request timeout.
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-04-25 17:55:16 -07:00
John Hu c0c46a3d14 Set minimum version for configs api to 1.30
See:
https://docs.docker.com/engine/reference/commandline/config/
https://docs.docker.com/engine/api/v1.30/
Signed-off-by: John Hu <hszqqq12@gmail.com>
2018-04-25 17:55:16 -07:00
Joffrey F d14dfedcad Remove obsolete docker-py check in setup.py
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 0dbb5da922 Bump docker-pycreds dependency
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 33cae41d90 Support absolute paths for in-context Dockerfiles
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 298b7e1474 Use networks instead of legacy links for test setup
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F 23e6b5c46b Add test for container list with sparse=True
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Matthieu Nottale 0b289bc79e Add sparse argument to DockerClient.containers.list().
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-04-25 17:55:16 -07:00
Joffrey F a1587e77c5 Bump test engine versions
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:55:16 -07:00
Ronald van Zantvoort 8b5f281e00 build_prune
Signed-off-by: Ronald van Zantvoort <the.loeki@gmail.com>
2018-04-25 17:55:16 -07:00
Joffrey F d5693ed903 Add prune_builds to DockerClient
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:28:51 -07:00
Joffrey F 9709dd454b Add ignore_removed param to containers.list() to control whether to
raise or ignore NotFound

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 17:18:26 -07:00
Ben Doan b3ae4d6ebd avoid race condition in containers.list
Signed-off-by: Ben Doan <ben@bendoan.me>
2018-04-25 17:18:26 -07:00
Joffrey F 827bd98d07 Merge branch 'master' of github.com:docker/docker-py 2018-04-25 16:30:24 -07:00
Joffrey F c6c45d9c45 Merge branch 'The-Loeki-build_prune' 2018-04-25 16:30:04 -07:00
Joffrey F 8360ecae97 prune_builds test
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 16:29:41 -07:00
Joffrey F d893a7644f Merge branch 'build_prune' of https://github.com/The-Loeki/docker-py into The-Loeki-build_prune
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 16:14:37 -07:00
Joffrey F ae8f77737c Fix session timeout = None case
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 15:31:26 -07:00
Joffrey F da028d88a2 Total timeout should be HTTP timeout + operation timeout
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 15:31:26 -07:00
Matthieu Nottale cef9940ed3 stop(), restart(): Adjust request timeout.
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-04-25 15:31:26 -07:00
John Hu caf0f37927 Set minimum version for configs api to 1.30
See:
https://docs.docker.com/engine/reference/commandline/config/
https://docs.docker.com/engine/api/v1.30/
Signed-off-by: John Hu <hszqqq12@gmail.com>
2018-04-25 15:28:54 -07:00
Joffrey F accb9de52f Remove obsolete docker-py check in setup.py
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 14:49:18 -07:00
Joffrey F e1ab5457ca Bump docker-pycreds dependency
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-25 14:17:24 -07:00
Joffrey F 1d6f8ecf92 Support absolute paths for in-context Dockerfiles
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-04-12 13:22:47 -07:00
Joffrey F d2d998281b Bump 3.2.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-30 11:23:54 -07:00
Joffrey F 06f5a47d91 Properly handle relative Dockerfile paths and Dockerfile on different drives
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-30 11:23:54 -07:00
Joffrey F 16751ac509 Properly handle relative Dockerfile paths and Dockerfile on different drives
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-30 11:00:41 -07:00
Joffrey F bdee6e3087 dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:37:52 -07:00
Joffrey F 2dcedec7c9 Merge branch 'release' 2018-03-29 16:36:33 -07:00
Joffrey F 2ecc3adcd4 Bump 3.2.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F bedabbfa35 Add methods for /distribution/<name>/json endpoint
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F f39c0dc18d Improve extra_files override check
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F fce99c329f Move build utils to appropriate file
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F 77c3e57dcf Support building with Dockerfile outside of context
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F 20939d0681 Update MAINTAINERS file
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F 27322fede7 Add isolation param to build
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F 73a9003758 Generate test engines list dynamically
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F e9f31e1e27 Remove redundant single-socket select call
Clean up + use pytest-timeout

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Viktor Adam dd743db4b3 Allow cancelling the streams from other threads
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2018-03-29 16:25:14 -07:00
Joffrey F d310d95fbc Add test for container list with sparse=True
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 16:25:14 -07:00
Matthieu Nottale 726d7f31ca Add sparse argument to DockerClient.containers.list().
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-03-29 16:25:14 -07:00
Matthieu Nottale 35520ab01f Add close() method to DockerClient.
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-03-29 16:25:14 -07:00
Joffrey F 9ff787cb5f Add methods for /distribution/<name>/json endpoint
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-29 15:45:06 -07:00
Joffrey F 899f3cf5a8 Improve extra_files override check
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-27 11:12:05 -07:00
Joffrey F 3fdc0127c1 Move build utils to appropriate file
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-27 11:12:05 -07:00
Joffrey F 081b78f15e Support building with Dockerfile outside of context
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-27 11:12:05 -07:00
Joffrey F 12a6833eba Update MAINTAINERS file
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-26 14:13:57 -07:00
Joffrey F c88db80f01 Add isolation param to build
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-23 14:14:49 +01:00
Joffrey F cd9fed108c Generate test engines list dynamically
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-22 14:07:41 +01:00
Joffrey F ea682a69d6 Bump 3.1.4
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-21 14:35:50 +01:00
Joffrey F a9ecb7234f Don't descend into symlinks when building context tar
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-21 14:35:50 +01:00
Joffrey F 7a28cad58e Don't descend into symlinks when building context tar
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-21 14:20:41 +01:00
Joffrey F af674155b7 Bump 3.1.3
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 12:08:24 +01:00
Joffrey F 88b0d697aa Bump test engine versions
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 10:14:09 +01:00
Joffrey F 791de789ec Bump 3.1.2
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 10:14:09 +01:00
Joffrey F 3f3ca7ed43 Use networks instead of legacy links for test setup
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 10:14:09 +01:00
Joffrey F ffdc0487f5 Fix socket tests for TLS-enabled tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 10:14:09 +01:00
James cf1d869105 Updates docs for rename of `name` to `repository`
Signed-off-by: James Meakin <jamesmeakin@gmail.com>
2018-03-20 10:14:09 +01:00
Joffrey F 9c2b4e12f8 Use same split rules for Dockerfile as other include/exclude patterns
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 10:14:09 +01:00
Joffrey F 284c3d90d6 Remove redundant single-socket select call
Clean up + use pytest-timeout

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-20 09:25:29 +01:00
Viktor Adam 719d4e9e20 Allow cancelling the streams from other threads
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2018-03-20 09:25:29 +01:00
Joffrey F a4e642b015 Use networks instead of legacy links for test setup
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-15 16:37:58 -07:00
Joffrey F 884261e241 Fix socket tests for TLS-enabled tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-15 16:37:58 -07:00
James 16ccf377a3 Updates docs for rename of `name` to `repository`
Signed-off-by: James Meakin <jamesmeakin@gmail.com>
2018-03-15 10:13:53 -07:00
Joffrey F 78600d52ab Merge branch 'mnottale-container-list-sparse' 2018-03-14 16:54:29 -07:00
Joffrey F 90c0dbe5f8 Add test for container list with sparse=True
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-14 16:53:56 -07:00
Joffrey F f873e3d1e0 Merge branch 'container-list-sparse' of https://github.com/mnottale/docker-py into mnottale-container-list-sparse 2018-03-14 16:29:06 -07:00
Joffrey F 69f248ccdd
Merge pull request #1957 from docker/1956-dockerignore-include-dockerfile
Use same split rules for Dockerfile as other include/exclude patterns
2018-03-14 14:39:06 -07:00
Joffrey F 33f1ca9a48 Use same split rules for Dockerfile as other include/exclude patterns
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-14 14:11:42 -07:00
Joffrey F 8701c9634e
Merge pull request #1954 from mnottale/dockerclient-close
Add close() method to DockerClient.
2018-03-14 10:57:02 -07:00
Matthieu Nottale 1829bd2699 Add sparse argument to DockerClient.containers.list().
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-03-14 16:11:32 +01:00
Matthieu Nottale b75799d33a Add close() method to DockerClient.
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-03-14 16:10:56 +01:00
Joffrey F d291d8c9f7
Merge pull request #1944 from docker/bump-jenkinsfile
Bump test engine versions
2018-03-05 15:39:38 -08:00
Joffrey F 4c263ee2c9
Merge pull request #1943 from docker/3.1.1-release
3.1.1 release
2018-03-05 15:28:28 -08:00
Joffrey F 110672d1a8 Bump test engine versions
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-05 15:26:59 -08:00
Joffrey F 52c3d528f6 Bump 3.1.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-05 15:15:37 -08:00
Joffrey F 9260f5af18 Merge branch 'levin-du-develop' 2018-03-05 11:50:11 -08:00
Joffrey F 13609359ac Improve dockerignore comment test
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-03-05 11:49:43 -08:00
Wanzhi Du 74586cdd4c Fix flake8 case
Signed-off-by: Wanzhi Du <wanzhi09@gmail.com>
2018-03-05 19:26:56 +08:00
Wanzhi Du 7a28ff3510 Ignore comment line from the .dockerignore file
This fixed the bug that test comment line in .dockerignore file as ignore rule
bug.

Add test for "# comment" patterns in .dockerignore.

Signed-off-by: Wanzhi Du <wanzhi09@gmail.com>
2018-03-05 18:10:09 +08:00
Joffrey F 9b8e022fa1
Merge pull request #1928 from mnottale/fix-spurious-resolution-macos-slowdown
Workaround requests resolving our unix socket URL on macosx.
2018-02-27 08:58:59 -08:00
Joffrey F fe966764ef
Merge pull request #1927 from mefyl/master
Add test for "/.." patterns in .dockerignore.
2018-02-26 10:53:41 -08:00
Ronald van Zantvoort ab21746d8f
build_prune
Signed-off-by: Ronald van Zantvoort <the.loeki@gmail.com>
2018-02-26 19:52:08 +01:00
Matthieu Nottale 15c26e7057 Workaround requests resolving our unix socket URL on macosx.
Signed-off-by: Matthieu Nottale <matthieu.nottale@docker.com>
2018-02-26 14:47:26 +01:00
mefyl 4295919103
Add test for "/.." patterns in .dockerignore.
Signed-off-by: mefyl <quentin.hocquet@docker.com>
2018-02-26 12:59:46 +01:00
Joffrey F 8b246db271
Merge pull request #1922 from yongtang/02232018-cleanup
Cleanup containers during the tests
2018-02-23 13:34:55 -08:00
Yong Tang ab1f90a379 Cleanup containers during the tests
This fix tries to clean up the containers during the tests
so that no pre-existing volumes left in docker integration tests.

This fix adds `-v` when removing containers, and makes sure
containers launched in non-daemon mode are removed.

This fix is realted to moby PR 36292

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2018-02-23 15:22:42 +00:00
Joffrey F d41e06092d 3.2.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-22 14:59:19 -08:00
Joffrey F 79f27c68ab
Merge pull request #1921 from docker/3.1.0-release
3.1.0 release
2018-02-22 14:43:15 -08:00
Joffrey F 1d85818f4c Bump 3.1.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-22 13:52:44 -08:00
Joffrey F 9a4cc53c52 Merge branch 'release' into 3.1.0-release
Signed-off-by: Joffrey F <joffrey@docker.com>

Conflicts:
	docker/version.py
	tests/unit/api_test.py
	tests/unit/utils_test.py
2018-02-22 13:36:15 -08:00
Joffrey F cc6e1b1249
Merge pull request #1914 from mefyl/master
Improve .dockerignore compliance
2018-02-22 13:35:41 -08:00
Joffrey F ad5f49b690
Merge pull request #1918 from rycus86/service-restart-method
Shorthand method for service.restart()
2018-02-21 12:05:10 -08:00
Viktor Adam e54e8f4199 Shorthand method for service.force_update()
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2018-02-21 19:55:17 +00:00
mefyl 0c948c7df6
Add note about potential dockerignore optimization.
Signed-off-by: mefyl <quentin.hocquet@docker.com>
2018-02-21 17:05:27 +01:00
mefyl 3b464f983e
Skip entirely excluded directories when handling dockerignore.
This is pure optimization to not recurse into directories when
	there are no chances any file will be included.

Signed-off-by: mefyl <quentin.hocquet@docker.com>
2018-02-21 17:05:27 +01:00
mefyl bb3ad64060
Fix .dockerignore: accept wildcard in inclusion pattern, honor last line precedence.
Signed-off-by: mefyl <quentin.hocquet@docker.com>
2018-02-21 17:05:26 +01:00
mefyl c8f5a5ad40
Fix dockerignore handling of absolute path exceptions.
Signed-off-by: mefyl <quentin.hocquet@docker.com>
2018-02-21 17:05:26 +01:00
Joffrey F 8fd9d3c99e GenericResources was introduced in 1.32
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-20 17:11:27 -08:00
Joffrey F f40079d85d Merge branch 'BYU-PCCL-master' 2018-02-20 16:40:55 -08:00
Joffrey F 9b6b306e17 Code cleanup and version guards
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-20 16:25:17 -08:00
William Myers 820de848fa Add support for generic resources to docker.types.Resources
- Add support for dict and list generic_resources parameter
- Add generic_resources integration test

Signed-off-by: William Myers <mwilliammyers@gmail.com>
2018-02-20 16:25:17 -08:00
Joffrey F 759833c174
Merge pull request #1919 from docker/1912-pull-sha-tag
Fix DockerClient pull bug when pulling image by digest
2018-02-20 15:01:13 -08:00
Joffrey F cc455d7fd5 Fix DockerClient pull bug when pulling image by digest
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-20 14:51:49 -08:00
mefyl 181c1c8eb9 Revert "Correctly support absolute paths in .dockerignore"
This reverts commit 34d50483e2.

Signed-off-by: mefyl <quentin.hocquet@docker.com>
2018-02-19 13:37:35 +01:00
Joffrey F ba0e5332de
Merge pull request #1910 from docker/bump_credstore
Bump docker-pycreds to 0.2.2 (pass support)
2018-02-14 16:25:42 -08:00
Joffrey F 4c708f568c Fix test_login flakes
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-14 16:22:33 -08:00
Joffrey F 08803743c5
Merge pull request #1906 from docker/1352-data_stream_control
Add chunk_size parameter to data downloading methods
2018-02-14 16:22:02 -08:00
Joffrey F 581ccc9f7e Add chunk_size parameter to data downloading methods (export, get_archive, save)
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-14 16:07:19 -08:00
Joffrey F dbcf04388a
Merge pull request #1908 from docker/1861-credstore_login
Fix authconfig resolution when credStore is used combined with login()
2018-02-14 16:04:47 -08:00
Joffrey F 5e28dcaace
Merge pull request #1909 from yongtang/somevolume-cleanup
Clean up created volume from test_run_with_named_volume
2018-02-14 16:04:06 -08:00
Joffrey F 15ae1f09f8 Bump docker-pycreds to 0.2.2 (pass support)
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-14 16:02:04 -08:00
Yong Tang cbbc37ac7b Clean up created volume from test_run_with_named_volume
This fix adds the volume id to the list so that it could be
cleaned up on test teardown.

The issue was originally from https://github.com/moby/moby/pull/36292
where an additional `somevolume` pre-exists in tests.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2018-02-14 13:01:16 +00:00
Joffrey F 3498b63fb0 Fix authconfig resolution when credStore is used combined with login()
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-13 18:55:56 -08:00
Joffrey F 14eec99bed
Merge pull request #1907 from docker/c5622_device_cgroup_rules
Add support for device_cgroup_rules parameter in host config
2018-02-13 17:18:36 -08:00
Joffrey F 48e45afe88 Add support for device_cgroup_rules parameter in host config
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-13 17:05:16 -08:00
Joffrey F 9e75609aec
Merge pull request #1904 from docker/c5672-dockerignore-abspath
Correctly support absolute paths in .dockerignore
2018-02-12 15:44:58 -08:00
Joffrey F 34d50483e2 Correctly support absolute paths in .dockerignore
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-12 14:59:41 -08:00
Joffrey F c9ee0222fa
Merge pull request #1902 from docker/3.0.1-release
3.0.1 release
2018-02-05 14:09:37 -08:00
Joffrey F 8649f48a4c Bump 3.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-05 13:44:57 -08:00
Joffrey F 6de7bab22f Rewrite access check in create_archive with EAFP
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-05 13:38:32 -08:00
Joffrey F 539b321bd1 Add login data to the right subdict in auth_configs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-05 13:38:19 -08:00
Joffrey F a60011ca3a Add workaround for bpo-32713
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-05 13:38:03 -08:00
Joffrey F 7c19772eb6
Merge pull request #1901 from docker/1899-create_archive_fix
Rewrite access check in create_archive with EAFP
2018-02-05 13:37:01 -08:00
Joffrey F 58639aecfa Rewrite access check in create_archive with EAFP
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-05 13:11:19 -08:00
Joffrey F 855b71eabe
Merge pull request #1896 from docker/1895-login-auths
Add login data to the right subdict in auth_configs
2018-02-02 10:29:33 -08:00
Joffrey F f00e76cac9
Merge pull request #1897 from docker/c5618-negative-mtime-tar
Add workaround for bpo-32713
2018-02-01 17:12:45 -08:00
Joffrey F 04bf470f6e Add workaround for bpo-32713
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-01 16:51:36 -08:00
Joffrey F 83d185d695 Add login data to the right subdict in auth_configs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-02-01 16:02:09 -08:00
Joffrey F 05d34ed1fb 3.1.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 17:58:23 -08:00
Joffrey F 91bc75cc92
Merge pull request #1891 from docker/3.0.0-release
3.0.0 release
2018-01-31 17:48:45 -08:00
Joffrey F 9a87f80f85 Docs fixes
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 17:28:53 -08:00
Joffrey F 3aba34fd08 Bump 3.0.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 17:28:53 -08:00
Joffrey F 644b9f4f1d
Merge pull request #1890 from docker/wait_return
Update wait to always return a dict
2018-01-31 17:03:35 -08:00
Joffrey F 7fabcdaa4c Update wait to always return a dict
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 16:52:26 -08:00
Joffrey F 0a86ff0bcc
Merge pull request #1889 from docker/1441-pull-repository-name
Rename `name` parameter in `pull` method to `repository`
2018-01-31 15:41:08 -08:00
Joffrey F bf2ea4dcb0 Rename `name` parameter in `pull` method to `repository`
for consistency with APIClient naming

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 15:26:09 -08:00
Joffrey F ea44212969
Merge pull request #1888 from docker/1884-create_volumes_win32
Correctly parse volumes with Windows paths
2018-01-31 15:25:49 -08:00
Joffrey F 82e57a4c15
Merge pull request #1887 from docker/cleanup_deprecated
Cleanup / remove deprecated features
2018-01-31 15:15:36 -08:00
Joffrey F 209ae2423d Correctly parse volumes with Windows paths
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 15:12:15 -08:00
Joffrey F df8422d079 Refuse API version < 1.21 ; Remove associated code paths
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 14:42:01 -08:00
Joffrey F b180b8770a Remove parameters and methods marked as deprecated
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 13:14:21 -08:00
Joffrey F 42b2548e5d
Merge pull request #1886 from docker/1878-publishmode
Add support for publish mode for endpointspec ports
2018-01-31 13:05:31 -08:00
Joffrey F 5347c168d0 Add support for publish mode for endpointspec ports
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-31 12:42:11 -08:00
Joffrey F 0750337f6a
Merge pull request #1885 from docker/improve_authconfig_genconfig_separation
Improve separation between auth_configs and general_configs
2018-01-31 11:31:11 -08:00
Joffrey F ccbde11c8d Improve separation between auth_configs and general_configs
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-30 18:42:38 -08:00
Joffrey F 75e2e8ad81
Merge pull request #1879 from docker/mtsmfm-master
Add support for detachKeys configuration
2018-01-30 18:38:35 -08:00
Joffrey F e304f91b46 Update detach tests to work with AF_INET as well
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-30 17:16:23 -08:00
Fumiaki MATSUSHIMA dd858648a0 Use config.json for detachKeys
Signed-off-by: Fumiaki Matsushima <mtsmfm@gmail.com>
2018-01-30 17:16:23 -08:00
Joffrey F 2e8f1f798a
Merge pull request #1883 from docker/1761-dockerclient-pull
Properly support pulling all tags in DockerClient.images.pull
2018-01-30 17:02:04 -08:00
Joffrey F 17aa31456d Properly support pulling all tags in DockerClient.images.pull
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-30 16:47:04 -08:00
Joffrey F a05922e949
Merge pull request #1881 from docker/pytest-asserts
Use pytest asserts
2018-01-30 16:29:07 -08:00
Joffrey F 3422211309 Use pytest asserts
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-30 14:26:24 -08:00
Joffrey F de88ab39c0
Merge pull request #1880 from docker/1841-tar-broken-symlinks
Do not break when archiving broken symlinks
2018-01-29 19:11:23 -08:00
Joffrey F 4e34300379 Do not break when archiving broken symlinks
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-29 18:27:12 -08:00
Joffrey F 4ff296247b Merge branch 'funkyfuture-container_exec_run' 2018-01-29 16:35:19 -08:00
Joffrey F 947c47f609 Move ExecResult definition to models.containers
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-29 16:34:03 -08:00
Joffrey F 600cc15cbc Merge branch 'container_exec_run' of https://github.com/funkyfuture/docker-py into funkyfuture-container_exec_run
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-29 16:29:04 -08:00
Joffrey F 5728eebf79
Merge pull request #1874 from docker/1774-export-methods
Update save / export methods to return data generators
2018-01-29 16:19:45 -08:00
Frank Sachsenheim a63b726d40 Container.exec_run returns a namedtuple w/ attrs exit_code & output
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2018-01-28 01:44:28 +01:00
Frank Sachsenheim ad208dfd29 Container.exec_run returns None as exit_code if stream or socket
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2018-01-28 01:43:42 +01:00
Joffrey F 9c0332eb2e
Merge pull request #1875 from docker/1702-build-logs-dockerclient
ImageCollection.build now also returns build logs
2018-01-26 16:32:29 -08:00
Joffrey F 388f291b13 Update save / export methods to return data generators
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 16:23:55 -08:00
Joffrey F 631cc3c121 ImageCollection.build now also returns build logs along with the built image reference
BuildError.build_logs has a copy of the logs generator

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 15:59:46 -08:00
Joffrey F deb8222d69
Merge pull request #1873 from docker/hongbin-image-load
Return Image objects in ImageCollection.load
2018-01-26 14:45:09 -08:00
Joffrey F 84d454551c
Merge pull request #1872 from docker/hnq90-add_exit_code_to_exec_run
Also return exit code in exec_run
2018-01-26 14:35:45 -08:00
Joffrey F 8b5a52ae0c Error handling in ImageCollection.load
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 14:34:20 -08:00
Joffrey F 601c5a41d2 Merge branch 'image-load' of https://github.com/hongbin/docker-py into hongbin-image-load
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 14:25:11 -08:00
Joffrey F 6e6eaece81 Return tuple instead of dict in exec_run
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 14:21:23 -08:00
Joffrey F b0cc4b5520 Merge branch 'add_exit_code_to_exec_run' of https://github.com/hnq90/docker-py into hnq90-add_exit_code_to_exec_run 2018-01-26 14:13:15 -08:00
Joffrey F 04eb7a2a99
Merge pull request #1867 from docker/bump_api_version_1.35
Bump default API version to 1.35
2018-01-26 14:11:07 -08:00
Joffrey F abd60aedc7 Bump default API version to 1.35
Add ContainerSpec.isolation support
Add until support in logs
Add condition support in wait
Add workdir support in exec_create

Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 13:56:01 -08:00
Joffrey F 9538258371
Merge pull request #1871 from docker/fix-appveyor
Fix appveyor tests
2018-01-26 13:45:10 -08:00
Joffrey F a5490ad0be Fix appveyor tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-26 13:44:31 -08:00
Joffrey F ba46201ca6
Merge pull request #1869 from mccalluc/patch-1
Replace missing "^" with "e"
2018-01-26 11:54:22 -08:00
mccalluc 24bd5d8e53
Replace missing "^" with "e"
Signed-off-by: Chuck McCallum <mccallucc+github@gmail.com>
2018-01-26 10:44:15 -05:00
Joffrey F 9e2148dcc4
Merge pull request #1865 from docker/dperny-change-tls-default
Change default TLS version
2018-01-25 13:08:12 -08:00
Joffrey F a15a1d2fdd
Merge pull request #1856 from docker/1855-platform-option
Add support for experimental platform flag in build and pull
2018-01-24 18:12:50 -08:00
Joffrey F f85f31a91a
Merge pull request #1849 from johannespostler/1516-endport-port-documentation
Switch ports in documentation for EndpointSpec (#1516)
2018-01-24 18:09:43 -08:00
Joffrey F 4590e2a816
Merge pull request #1846 from feliperuhland/issue-1734-scale-method
Added scale method to the Service model.
2018-01-24 18:08:35 -08:00
Joffrey F bab7ca3cde Don't use PROTOCOL_TLSv1_2 directly to avoid ImportErrors
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-24 18:05:10 -08:00
Drew Erny 500286d51e Change default TLS version
Detects if python has an up-to-date version of OpenSSL that supports
TLSv1.2. If it does, choose that as the default TLS version, instead of
TLSv1. The Docker Engine and the majority of other Docker API servers
should suppot TLSv1.2, and if they do not, the user can manually set a
different (lower) version.

Signed-off-by: Drew Erny <drew.erny@docker.com>
2018-01-24 18:05:10 -08:00
Joffrey F 766d890558
Merge pull request #1866 from docker/jenkins-update
Shift test matrix forward
2018-01-24 18:04:42 -08:00
Joffrey F ccd79323da Shift test matrix forward
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-24 11:39:43 -08:00
Joffrey F f95b958429 Add support for experimental platform flag in build and pull
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-23 16:59:09 -08:00
Joffrey F bc8ada2f74
Merge pull request #1863 from docker/python3.6
Python 3.6 support
2018-01-22 18:28:18 -08:00
Joffrey F 0acef5f6d2 Add Python 3.6 testing
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-22 18:08:01 -08:00
Joffrey F a28b9ffd85
Merge pull request #1859 from rycus86/service_network_regression
Fix service network regression on API < 1.25
2018-01-12 14:49:19 -08:00
Viktor Adam e75a03fd6d Fix regression on API < 1.25
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2018-01-12 22:18:53 +00:00
Joffrey F bf5e7702df
Merge pull request #1853 from docker/1852-dockerignore
Ignore dockerignore lines that contain only whitespace
2018-01-03 13:37:39 -08:00
Joffrey F bf06a361e2 Ignore dockerignore lines that contain only whitespace
Signed-off-by: Joffrey F <joffrey@docker.com>
2018-01-03 12:16:21 -08:00
Felipe Ruhland 663c6089e9 Fix test to make sure the initial mode is replicated
Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2018-01-03 00:21:56 -02:00
Johannes Postler 1bb4155dcb Switch ports in documentation for EndpointSpec
Signed-off-by: Johannes Postler <johannes.postler@uibk.ac.at>
2017-12-27 17:01:49 +01:00
Felipe Ruhland 0e0a852680 Ensure that global containers are not scaled
Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2017-12-26 18:30:28 -02:00
Felipe Ruhland edb9e3c2ae Added scale method to the Service model.
Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2017-12-21 23:13:18 -02:00
Joffrey F 190d95c61c Merge branch 'qazbnm456-master' 2017-12-19 14:38:55 -08:00
Joffrey F 758344fdf4 Formatting
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-19 14:38:38 -08:00
Joffrey F 0a55ff3a41 Merge branch 'master' of https://github.com/qazbnm456/docker-py into qazbnm456-master 2017-12-19 14:37:44 -08:00
Joffrey F 9fc45f108a 2.8.0 dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-19 14:37:17 -08:00
Joffrey F 518655287a Merge branch 'release' 2017-12-19 14:36:48 -08:00
Joffrey F 5bed7b8f0d
Merge pull request #1838 from docker/2.7.0-release
2.7.0 release
2017-12-19 14:25:53 -08:00
Joffrey F 228764ac87
Merge pull request #1840 from docker/1813-autoremove-error
Don't attempt to retrieve container's stderr if `auto_remove` was set
2017-12-19 14:19:37 -08:00
Joffrey F 598f16771c Don't attempt to retrieve container's stderr if `auto_remove` was set
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-19 13:51:47 -08:00
Joffrey F 2250fa2ebd Don't attempt to retrieve container's stderr if `auto_remove` was set
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-19 13:50:32 -08:00
Joffrey F f10c008aa5 Bump 2.7.0 + changelog
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-18 18:21:51 -08:00
Joffrey F ac68a36a89
Merge pull request #1727 from mbelang/join-swarn-default-listen-address
Add join_swarm default listen address
2017-12-18 17:16:41 -08:00
Joffrey F 5736436966
Merge pull request #1828 from pkit/fix_error_from_httpex
fixes create_api_error_from_http_exception()
2017-12-18 14:26:47 -08:00
Constantine Peresypkin b20f800db6 fixes create_api_error_from_http_exception()
`create_api_error_from_http_exception()` is never tested in the original code
and will fail miserably when fed with empty `HTTPError` object
see fixes in requests for this behaviour: https://github.com/requests/requests/pull/3179

Signed-off-by: Constantine Peresypkin <pconstantine@gmail.com>
2017-12-18 17:15:48 +02:00
Boik adbb3079dd make the error message clearer
Signed-off-by: Boik <qazbnm456@gmail.com>
2017-12-16 09:31:27 +08:00
Joffrey F bf699c7ef7
Merge pull request #1836 from docker/1813-run-autoremove
Retrieve container logs before container exits / is removed
2017-12-14 17:45:18 -08:00
Joffrey F 1fd59586d1
Merge pull request #1837 from feliperuhland/fix_default_api_version
Updated DEFAULT API VERSION in docstrings.
2017-12-14 16:54:33 -08:00
Joffrey F 6b8dfe4249 Retrieve container logs before container exits / is removed
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-14 16:53:44 -08:00
Felipe Ruhland b6d0dc1e5a Fixed DEFAULT API VERSION in docstrings.
Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
2017-12-14 22:39:34 -02:00
Joffrey F 8cfd4cb39f
Merge pull request #1807 from rycus86/update_service_from_prev_spec
Update service from prev spec
2017-12-14 12:44:36 -08:00
Joffrey F 644a82542b
Merge pull request #1834 from mhank/1823-support-update-order
Add support for order property when updating a service
2017-12-14 12:40:20 -08:00
Michael Hankin 49d09583aa Correct default value of order parameter
Signed-off-by: Michael Hankin <mjhankin1@gmail.com>
2017-12-14 08:58:26 -06:00
Viktor Adam a66c89247a Renaming new argument
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-12-14 09:55:36 +00:00
Joffrey F 20b5b58bb0
Merge pull request #1835 from docker/1758-url-quote-path
Fix URL-quoting for resource names containing spaces
2017-12-13 19:09:13 -08:00
Joffrey F 1df979a58f Merge branch 'tz70s-master'
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-13 19:07:24 -08:00
Joffrey F 445cb18723 Add integration test for CPU realtime options
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-13 19:06:29 -08:00
Joffrey F d7bc8ac2b8 Merge branch 'master' of https://github.com/tz70s/docker-py into tz70s-master
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-13 18:50:07 -08:00
Joffrey F 6c74292d3d
Merge pull request #1789 from timvisee/chardet-fix
Require at least requests v2.14.2 to update old chardet
2017-12-13 18:37:01 -08:00
Joffrey F 7db76737ca Fix URL-quoting for resource names containing spaces
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-12-13 18:32:59 -08:00
Joffrey F 6f77e458d2
Merge pull request #1816 from Anvil/honor-stoptimeout
Fix for #1815: make APIClient.stop honor container StopTimeout value
2017-12-13 16:45:35 -08:00
Joffrey F aad0c76002
Merge pull request #1812 from rycus86/greedy_network_list
Fetch network details with network lists greedily
2017-12-13 16:33:06 -08:00
Joffrey F a916bfdde2
Merge pull request #1830 from mhank/1822-reformat-hosts
Fix format in which hosts are being stored for Swarm services
2017-12-13 16:26:42 -08:00
Michael Hankin 61bc8bea7f Add support for order property when updating a service
Signed-off-by: Michael Hankin <mjhankin1@gmail.com>
2017-12-12 15:49:07 -06:00
Joffrey F d8f996f969
Merge pull request #1825 from docker/fix-context-building
Fix common issues with build context creation: inaccessible files and FIFOs
2017-12-11 14:50:21 -08:00
Joffrey F b4eb3b9ce8
Merge pull request #1831 from asottile/patch-1
container: fix docstring for containers()
2017-12-07 14:07:34 -08:00
Anthony Sottile 9d23278643 container: fix docstring for containers()
Signed-off-by: Anthony Sottile <asottile@umich.edu>
2017-12-07 13:53:25 -08:00
Michael Hankin 0134939c2c Change format in which hosts are being stored for Swarm services
Signed-off-by: Michael Hankin <mhank@users.noreply.github.com>
2017-12-05 21:19:37 -06:00
Michael Hankin 8d770b012d Change format of extra hosts
Signed-off-by: Michael Hankin <mjhankin1@gmail.com>
2017-12-03 14:54:28 -06:00
Joffrey F 5c5705045b Fix common issues with build context creation: inaccessible files and fifos
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-29 16:42:28 -08:00
Joffrey F 94e3d3dcb9
Merge pull request #1819 from alexvy86/alexvy86-patch-1
Add missing call to string format in log message
2017-11-21 14:06:14 -08:00
Viktor Adam 36ed843e2b Only allow greedy queries on the model
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-21 21:59:11 +00:00
Alex Villarreal 6cce101f01
Add missing call to string format in log message
Signed-off-by: Alejandro Villarreal <alex@alexvy86.com>
2017-11-21 10:07:02 -06:00
Damien Nadé f3dbd017f8 Fix for #1815: make APIClient.stop honor container StopTimeout value
Signed-off-by: Damien Nadé <anvil.github@livna.org>
2017-11-21 10:30:43 +01:00
Joffrey F 58c02ca963
Merge pull request #1798 from docker/unlock_swarm_support
Unlock swarm support
2017-11-20 16:58:17 -08:00
Viktor Adam 2878900a71 Fixing integration tests
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-19 21:03:07 +00:00
Viktor Adam 7829b728a4 Fetch network details with network lists greedily
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-16 23:15:31 +00:00
Viktor Adam 828b865bd7 Fix resetting ContainerSpec properties to None
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-15 18:30:05 +00:00
Viktor Adam c78e73bf7a Attempting to make service update tests less flaky
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-15 08:17:16 +00:00
Viktor Adam b2d08e64bc Service model update changes
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-14 23:32:19 +00:00
Viktor Adam 6e5eb2eba7 Update service using previous spec
Signed-off-by: Viktor Adam <rycus86@gmail.com>
2017-11-14 21:10:23 +00:00
Joffrey F 1d6b5b2032
Merge pull request #1805 from thaJeztah/fix-swarm-update-test
Remove test_update_swarm_name
2017-11-13 19:06:25 -08:00
Sebastiaan van Stijn e6cc3c1540
Remove test_update_swarm_name
Docker currently only supports the "default" cluster
in Swarm-mode, and an upcoming SwarmKit release
will produce an error if the name of the cluster
is updated, causing the test to fail.

Given that renaming the cluster is not supported,
this patch removes the test

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2017-11-14 02:47:49 +01:00
HuyNQ 436306f09d
Add exit code to exec_run
Signed-off-by: HuyNQ <huy@huynq.net>
2017-11-13 14:11:21 +07:00
Joffrey F c7f1b5f84f dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-08 17:04:53 -08:00
Joffrey F d400795634
Merge pull request #1802 from docker/2.6.1-release
2.6.1 release
2017-11-08 16:50:52 -08:00
Joffrey F 2008f52660 2.6.1 release
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-08 16:43:56 -08:00
Joffrey F aafae3dd86 dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-08 16:41:03 -08:00
Joffrey F 21d2c65277 Merge branch 'release' of github.com:docker/docker-py
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-08 16:40:39 -08:00
Joffrey F 700fbef42b Fix broken unbuffered streaming with Py3
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-08 16:29:56 -08:00
Joffrey F 3bd053a4b7 Add unlock methods to Swarm model
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:44:54 -08:00
Joffrey F aa3c4f026d Add unlock_swarm and get_unlock_key to APIClient
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:19:07 -08:00
Joffrey F 65ba043d15 Update test engine versions in Jenkinsfile
Signed-off-by: Joffrey F <joffrey@docker.com>

Conflicts:
	Jenkinsfile
2017-11-07 15:18:26 -08:00
Joffrey F 3bad05136a Bump 2.6.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F fe6c9a64b0 Style fixes. Copied docs to APIClient as well
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Martin Monperrus 3470968937 explain the socket parameter of exec_run
Signed-off-by: Martin Monperrus <martin.monperrus@gnieh.org>
2017-11-07 15:18:26 -08:00
Joffrey F af0071403c Add support for insert_defaults in inspect_service
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F ecca6e0740 Update SwarmSpec to include new parameters
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F a0f6758c76 Add support for scope filter in inspect_network
Fix missing scope implementation in create_network

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F 6e1f9333d3 Oops
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F 9756a4ec4c Fix build tests to not rely on internet connectivity
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F e055729104 Disable buffering based on presence of Connection Upgrade headers
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Chris Harris 047c67b31e Prevent data loss when attaching to container
The use of buffering within httplib.HTTPResponse can cause data
to be lost. socket.makefile() is called without a bufsize, which
causes a buffer to be used when recieving data. The attach
methods do a HTTP upgrade to tcp before the raw socket is using
to stream data from the container. The problem is that if the
container starts stream data while httplib/http.client is reading
the response to the attach request part of the data ends will end
up in the buffer of fileobject created within the HTTPResponse
object. This data is lost as after the attach request data is
read directly from the raw socket.

Signed-off-by: Chris Harris <chris.harris@kitware.com>
2017-11-07 15:18:26 -08:00
Joffrey F 114512a9bf Doc fixes
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F a0853622f9 Add support for secret driver in create_secret
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Alessandro Baldo 80985cb5b2 Improve docs for service list filters
- add "label" and "mode" to the list of available filter keys in the high-level service API
- add "label" and "mode" to the list of available filter keys in the low-level service API
- add integration tests

Signed-off-by: Alessandro Baldo <git@baldoalessandro.net>
2017-11-07 15:18:26 -08:00
Joffrey F 2cb78062b1 More ContainerSpec tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F b1301637cf Add support for configs management
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F cd47a1f9f5 Add support for new ContainerSpec parameters
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Erik Johnson bb437e921e Fix indentation in docstring
The incorrect indentation causes improper formatting when the docs
are published.

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-11-07 15:18:26 -08:00
Joffrey F 53582a9cf5 Add support for extra_hosts option in build
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F cdf9acb185 Pin flake8 version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F 5d1b652246 Add support for mounts in HostConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F eee9cbbf08 Add support for new types and options to docker.types.Mount
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Jan Losinski 8742609391 Fix simple documentation copy/paste error.
Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>
2017-11-07 15:18:26 -08:00
Joffrey F f94fae3aa8 Remove superfluous version validation
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Steve Clark 1d77ef9e53 Adding swarm id_attribute to match docker output
Swarm id is returned in a attribute with the key ID. The swarm model was using the default behaviour and looking for Id.
Signed-off-by: Steve Clark <steve@cobe.io>
2017-11-07 15:18:26 -08:00
brett55 ba66b09e2b Fix docs, incorrect param name
Signed-off-by: brett55 <bjcull2@gmail.com>
2017-11-07 15:18:26 -08:00
Joffrey F 7107e265b1 Do not interrupt streaming when encountering 0-length frames
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F a49d73e9df Fix prune_images docstring
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F 303b303855 Use unambiguous advertise-addr when initializing a swarm
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F f470955a77 Shift test matrix forward
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-07 15:18:26 -08:00
Joffrey F f238fe5554 Style fixes. Copied docs to APIClient as well
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-06 17:10:42 -08:00
Martin Monperrus 05f40f0381 explain the socket parameter of exec_run
Signed-off-by: Martin Monperrus <martin.monperrus@gnieh.org>
2017-11-06 17:10:42 -08:00
Joffrey F 1a4b181344 Add support for insert_defaults in inspect_service
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-06 16:30:02 -08:00
Joffrey F 11a260225c Update SwarmSpec to include new parameters
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-03 16:01:33 -07:00
Joffrey F 1ce93ac6e7 Add support for scope filter in inspect_network
Fix missing scope implementation in create_network

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-02 16:10:43 -07:00
Joffrey F ca7a6132a4 Oops
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-02 14:10:13 -07:00
Joffrey F d5094a8126 Fix build tests to not rely on internet connectivity
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-02 14:06:05 -07:00
Joffrey F 1359eb1100 Disable buffering based on presence of Connection Upgrade headers
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-02 13:02:32 -07:00
Chris Harris f8b5bc62df Prevent data loss when attaching to container
The use of buffering within httplib.HTTPResponse can cause data
to be lost. socket.makefile() is called without a bufsize, which
causes a buffer to be used when recieving data. The attach
methods do a HTTP upgrade to tcp before the raw socket is using
to stream data from the container. The problem is that if the
container starts stream data while httplib/http.client is reading
the response to the attach request part of the data ends will end
up in the buffer of fileobject created within the HTTPResponse
object. This data is lost as after the attach request data is
read directly from the raw socket.

Signed-off-by: Chris Harris <chris.harris@kitware.com>
2017-11-02 13:02:32 -07:00
timvisee ff86324c4f
Require at least requests v2.14.2 to fix chardet
Signed-off-by: timvisee <timvisee@gmail.com>
2017-11-02 14:30:18 +01:00
Joffrey F b99f4f2c69 Doc fixes
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-01 18:56:41 -07:00
Joffrey F c0a075810e Add support for secret driver in create_secret
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-11-01 18:56:41 -07:00
Alessandro Baldo 76b138a0a1 Improve docs for service list filters
- add "label" and "mode" to the list of available filter keys in the high-level service API
- add "label" and "mode" to the list of available filter keys in the low-level service API
- add integration tests

Signed-off-by: Alessandro Baldo <git@baldoalessandro.net>
2017-11-01 15:18:05 -07:00
Joffrey F bb148380e1 More ContainerSpec tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-26 23:06:09 -07:00
Joffrey F 856414bf85 Add support for configs management
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-26 23:06:09 -07:00
Joffrey F 601d6be526 Add support for new ContainerSpec parameters
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-26 23:06:09 -07:00
Erik Johnson 10ea65f5ab Fix indentation in docstring
The incorrect indentation causes improper formatting when the docs
are published.

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-10-26 11:47:43 -07:00
Joffrey F 378bd76377 Update test engine versions in Jenkinsfile
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-25 17:05:09 -07:00
Joffrey F 93f2ab1530 Add support for extra_hosts option in build
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-25 15:09:39 -07:00
Joffrey F 0d21b5b254 Pin flake8 version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-24 18:59:01 -07:00
Joffrey F 5552deed86 Add support for mounts in HostConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-24 18:59:01 -07:00
Joffrey F 877fc817d7 Add support for new types and options to docker.types.Mount
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-24 18:59:01 -07:00
Jan Losinski 8cb5b52c3f Fix simple documentation copy/paste error.
Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>
2017-10-16 18:23:50 -07:00
Joffrey F ec9356d3a0 Remove superfluous version validation
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-10-02 12:50:04 -07:00
Steve Clark ca435af52e Adding swarm id_attribute to match docker output
Swarm id is returned in a attribute with the key ID. The swarm model was using the default behaviour and looking for Id.
Signed-off-by: Steve Clark <steve@cobe.io>
2017-09-21 22:40:10 -07:00
brett55 be3900b806 Fix docs, incorrect param name
Signed-off-by: brett55 <bjcull2@gmail.com>
2017-09-21 22:34:58 -07:00
Hongbin Lu 35ceefe1f1 Return Image objects on image.load
In before, image.load returns what Docker API returns, which is
a text stream. This commits propose an improvement for returning
more useful information, which is a list of Image objects being
loaded.

Signed-off-by: Hongbin Lu <hongbin.lu@huawei.com>
2017-09-10 14:43:33 -04:00
Joffrey F 37fbc8b4fd Do not interrupt streaming when encountering 0-length frames
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-31 16:41:15 -07:00
Joffrey F 2671d87843 Fix prune_images docstring
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-31 16:09:52 -07:00
Joffrey F 3c9c8b181c Use unambiguous advertise-addr when initializing a swarm
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-31 13:17:12 -07:00
Maxime Belanger 7fa2cb7be3 Add join_swarm default listen address
Since the docker CLI adds a default listen address (0.0.0.0:2377)
when joining a node to the swarm, the docker-py api will support
the same behavior to easy configuration.

Signed-off-by: Maxime Belanger <maxime.b.belanger@gmail.com>
2017-08-29 08:38:16 -04:00
Joffrey F e9fe077681 Bump 2.5.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-22 17:00:11 -07:00
Joffrey F 0c2b4e4d3a Always send attach request as streaming
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-22 17:00:11 -07:00
Veli-Matti Lintu fc6773d673 Commit d798afca made changes for the handling of '**' patterns in
.dockerignore. This causes an IndexError with patterns ending
with '**', e.g. 'subdir/**'. This adds a missing boundary check
before checking for trailing '/'.

Signed-off-by: Veli-Matti Lintu <veli-matti.lintu@nosto.com>
2017-08-22 17:00:11 -07:00
Joffrey F ba7580d6b9 Bump 2.6.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-22 17:00:11 -07:00
Joffrey F 89195146ad Always send attach request as streaming
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-21 15:56:19 -07:00
Veli-Matti Lintu 3df0653493 Commit d798afca made changes for the handling of '**' patterns in
.dockerignore. This causes an IndexError with patterns ending
with '**', e.g. 'subdir/**'. This adds a missing boundary check
before checking for trailing '/'.

Signed-off-by: Veli-Matti Lintu <veli-matti.lintu@nosto.com>
2017-08-21 12:01:50 -07:00
Joffrey F 477f236c71 Bump 2.6.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:52:13 -07:00
Joffrey F c55a330090 Merge branch 'release' of github.com:docker/docker-py
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:51:49 -07:00
Joffrey F 8d14709c18 Changelog typo
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:50:20 -07:00
Joffrey F 9b6ff333ac Bump 2.5.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F 7d559a957c Update default API version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F 921aba107b Update test versions
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F d9df2a8b75 Fix handling of non-multiplexed (TTY) streams over upgraded sockets
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Gabriel Féron a6065df64d Add support for the `squash` flag when building
Also added a test that compares the number of layers in the default mode, and with the new flag

Signed-off-by: Gabriel Féron <feron.gabriel@gmail.com>
2017-08-17 13:38:40 -07:00
Joffrey F d5c4ce203a Use better version comparison function
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
David Steines 6b59dc6271 Allow detach and remove for api version >= 1.25 and use auto_remove when both are set. Continue raising an exception for api versions <1.25.
Signed-off-by: David Steines <d.steines@gmail.com>
2017-08-17 13:38:40 -07:00
adrianliaw 2a6926b5ab Use collection's get method inside ImageCollection's list method
Signed-off-by: Adrian Liaw <adrianliaw2000@gmail.com>
2017-08-17 13:38:40 -07:00
Joffrey F b4802ea126 Handle untyped ContainerSpec dict in _check_api_features
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F d49c136d04 Daemon expects full URL of hub in auth config dict in build payload
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Ying b54c76c3c1 Upgrade tox and virtualenv in appveyor to make sure we have the latest pip.
Signed-off-by: Ying <ying.li@docker.com>
2017-08-17 13:38:40 -07:00
cyli 380914aaaa If we're pinning exact versions of things for requirements.txt, pin
all dependencies of dependencies as well so we can get a consistent build.

Signed-off-by: cyli <cyli@twistedmatrix.com>
2017-08-17 13:38:40 -07:00
cyli 0494c4f262 Require "requests[security]" if the `[tls]` option is selected, which also installs:
pyOpenSSL, cryptography, idna

and installs cryptography's version of openssl in Mac OS (which by default has an
ancient version of openssl that doesn't support TLS 1.2).

Signed-off-by: cyli <cyli@twistedmatrix.com>
2017-08-17 13:38:40 -07:00
Joffrey F 7f5739dc02 Leading slash in .dockerignore should be ignored
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F 7139e2d8f1 Return generator for output of load_image endpoint
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Cecile Tonglet 9e793806ff Return the result of the API when using remove_image and load_image
Those calls return result that can be used by the developers.

Signed-off-by: Cecile Tonglet <cecile.tonglet@gmail.com>
2017-08-17 13:38:40 -07:00
Joffrey F f3374959b7 Improve ContainerError message compute
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Artem Bolshakov 62fda980e4 client.containers.run returns None if none of json-file or journald logging drivers used
Signed-off-by: Artem Bolshakov <either.free@gmail.com>
2017-08-17 13:38:40 -07:00
Andreas Backx 48377d52e9 Added wait to the Container class documentation.
The container class documentation did not automatically document the `Container.wait` method.

Signed-off-by: Andreas Backx <andreas@backx.org>
2017-08-17 13:38:40 -07:00
Erik Johnson f7e7a8564e Fix domainname documentation in create_container function
It looks like this was probably originally copypasta'ed from dns_search
and not edited afterward.

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-08-17 13:38:40 -07:00
Joffrey F bf15e27d6d Temporarily - do not run py33 tests on travis
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Jakub Goszczurny bf9d06db25 Generating regexp from .dockerignore file in a similar way as docker-ce.
Signed-off-by: Jakub Goszczurny <szczurmys@o2.pl>
2017-08-17 13:38:40 -07:00
Dima Spivak 48b5c07c3a client.networks.create check_duplicates docs not reflective of behavior
Fixes #1693

Signed-off-by: Dima Spivak <dima@spivak.ch>
2017-08-17 13:38:40 -07:00
Brandon Jackson 9abcaccb89 By not specifying a specific tag, the example would download every Ubuntu tag that exists.
This oversight caused my machine to run out of disk space holding all the image diffs.

Signed-off-by: Brandon Jackson <usbrandon@gmail.com>
2017-08-17 13:38:40 -07:00
Matthew Berry a23cd3d8e8 Fix #1673 check resource error in container network API
Container network functions checked 'image' as resource ID and not
'container'.  This caused a traceback when using container as named
argument.

Signed-off-by: Matthew Berry <mtberry89@gmail.com>
2017-08-17 13:38:40 -07:00
Joffrey F e0c7e4d60e dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F 2b128077c1 Shift test matrix forward
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 13:38:40 -07:00
Joffrey F 13b9349216 Fix handling of non-multiplexed (TTY) streams over upgraded sockets
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-17 12:02:59 -07:00
Joffrey F 6f6c29ce36 Merge branch 'gferon-experimental-flags'
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-15 18:10:11 -07:00
Gabriel Féron 76eb0298c6 Add support for the `squash` flag when building
Also added a test that compares the number of layers in the default mode, and with the new flag

Signed-off-by: Gabriel Féron <feron.gabriel@gmail.com>
2017-08-15 18:09:39 -07:00
Joffrey F fe2e120705 Merge branch 'master' of github.com:docker/docker-py 2017-08-15 17:42:51 -07:00
Joffrey F 67b58b81e0 Merge branch 'davidsteines-1477_detach_and_remove_together' 2017-08-15 17:42:16 -07:00
Joffrey F b78fa6405a Use better version comparison function
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-15 17:40:07 -07:00
David Steines e17a545aa5 Allow detach and remove for api version >= 1.25 and use auto_remove when both are set. Continue raising an exception for api versions <1.25.
Signed-off-by: David Steines <d.steines@gmail.com>
2017-08-15 17:38:34 -07:00
adrianliaw 05e5db5853 Use collection's get method inside ImageCollection's list method
Signed-off-by: Adrian Liaw <adrianliaw2000@gmail.com>
2017-08-15 17:37:04 -07:00
Joffrey F 18acd569a1 Handle untyped ContainerSpec dict in _check_api_features
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-15 17:22:25 -07:00
Joffrey F e9fab1432b Daemon expects full URL of hub in auth config dict in build payload
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-15 15:59:33 -07:00
Ying 35f29d08d7 Upgrade tox and virtualenv in appveyor to make sure we have the latest pip.
Signed-off-by: Ying <ying.li@docker.com>
2017-08-15 15:45:51 -07:00
cyli c163375591 If we're pinning exact versions of things for requirements.txt, pin
all dependencies of dependencies as well so we can get a consistent build.

Signed-off-by: cyli <cyli@twistedmatrix.com>
2017-08-15 15:45:51 -07:00
cyli 3b95da3ea4 Require "requests[security]" if the `[tls]` option is selected, which also installs:
pyOpenSSL, cryptography, idna

and installs cryptography's version of openssl in Mac OS (which by default has an
ancient version of openssl that doesn't support TLS 1.2).

Signed-off-by: cyli <cyli@twistedmatrix.com>
2017-08-15 15:45:51 -07:00
Joffrey F 92a2e48e17 Leading slash in .dockerignore should be ignored
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-15 15:40:16 -07:00
Joffrey F 5e4a69bbda Return generator for output of load_image endpoint
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-15 14:58:29 -07:00
Cecile Tonglet 56dc7db069 Return the result of the API when using remove_image and load_image
Those calls return result that can be used by the developers.

Signed-off-by: Cecile Tonglet <cecile.tonglet@gmail.com>
2017-08-15 14:43:32 -07:00
Tzu-Chiao Yeh d74f1bc380 Fix #1575 - Add cpu_rt_period and cpu_rt_runtime args
Add cpu_rt_period and cpu_rt_runtime in hostconfig with version(1.25), types(int) checks.
Also add version and type checks in dockertype unit test.

Signed-off-by: Tzu-Chiao Yeh <su3g4284zo6y7@gmail.com>
2017-08-13 09:01:50 +00:00
Joffrey F 369168e29c Merge branch 'bolshakov-bugfix/run-container-with-syslog-driver'
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-07 12:06:42 -07:00
Joffrey F 8bcf2f27fb Improve ContainerError message compute
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-07 12:06:07 -07:00
Artem Bolshakov b8fd821336 client.containers.run returns None if none of json-file or journald logging drivers used
Signed-off-by: Artem Bolshakov <either.free@gmail.com>
2017-08-07 12:02:02 -07:00
Andreas Backx 1a923c561f Added wait to the Container class documentation.
The container class documentation did not automatically document the `Container.wait` method.

Signed-off-by: Andreas Backx <andreas@backx.org>
2017-08-07 11:49:51 -07:00
Erik Johnson 8a6b168467 Fix domainname documentation in create_container function
It looks like this was probably originally copypasta'ed from dns_search
and not edited afterward.

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-08-07 11:49:21 -07:00
Joffrey F bcfd6dadd1 Temporarily - do not run py33 tests on travis
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-08-01 13:49:48 -07:00
Jakub Goszczurny d798afca7e Generating regexp from .dockerignore file in a similar way as docker-ce.
Signed-off-by: Jakub Goszczurny <szczurmys@o2.pl>
2017-08-01 13:47:45 -07:00
Dima Spivak c2925a384b client.networks.create check_duplicates docs not reflective of behavior
Fixes #1693

Signed-off-by: Dima Spivak <dima@spivak.ch>
2017-07-31 15:40:41 -07:00
Brandon Jackson d68996f953 By not specifying a specific tag, the example would download every Ubuntu tag that exists.
This oversight caused my machine to run out of disk space holding all the image diffs.

Signed-off-by: Brandon Jackson <usbrandon@gmail.com>
2017-07-18 11:20:52 -07:00
Matthew Berry c9960c78b0 Fix #1673 check resource error in container network API
Container network functions checked 'image' as resource ID and not
'container'.  This caused a traceback when using container as named
argument.

Signed-off-by: Matthew Berry <mtberry89@gmail.com>
2017-07-14 09:31:16 -07:00
Joffrey F 6fe1c7f18f Merge pull request #1664 from docker/jfile-17.06-rc
Shift test matrix forward
2017-07-03 16:33:18 -07:00
Joffrey F eb0d80646a Merge pull request #1672 from docker/2.4.2-release
2.4.2 release
2017-06-28 13:41:57 -07:00
Joffrey F 43f87e9f63 Bump 2.4.2
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-28 13:32:18 -07:00
Joffrey F 14e6184814 Compose 1.14.0 hack
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-28 13:31:46 -07:00
Joffrey F 03b78b8152 Merge pull request #1671 from shin-/1668-split-port-2
Compose 1.14.0 hack - split_port fix
2017-06-28 13:30:53 -07:00
Joffrey F 48957e726b Compose 1.14.0 hack
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-28 13:26:04 -07:00
Joffrey F 65e01f24e4 Merge pull request #1670 from docker/2.4.1-release
2.4.1 release
2017-06-28 12:38:05 -07:00
Joffrey F 3d84dbee59 Bump 2.4.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-28 12:25:10 -07:00
Joffrey F 50a60717f0 split_port should not break when passed a non-string argument
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-28 12:22:34 -07:00
Joffrey F 9d09a137f5 Merge pull request #1669 from shin-/1668-split-port
split_port should not break when passed a non-string argument
2017-06-28 12:21:35 -07:00
Joffrey F a8722fb0c2 split_port should not break when passed a non-string argument
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-28 12:06:03 -07:00
Joffrey F e1344382a7 Merge pull request #1667 from docker/bump-2.5.0-dev
Bump 2.5.0 dev
2017-06-27 18:07:30 -07:00
Joffrey F f611eaf9e3 dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-27 18:06:12 -07:00
Joffrey F 706e2cad65 Merge pull request #1665 from docker/2.4.0-release
2.4.0 release
2017-06-27 17:56:28 -07:00
Joffrey F f4a4982ae0 Shift test matrix forward
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-27 12:28:16 -07:00
Joffrey F 1ad6859600 Bump 2.4.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-22 17:17:13 -07:00
Joffrey F 15030cb680 Merge pull request #1661 from shin-/1622-service-tty
Add support for ContainerSpec.TTY
2017-06-22 16:39:35 -07:00
Joffrey F be8c144841 Merge pull request #1662 from docker/1633-credhelpers-support
Support credHelpers section in config.json
2017-06-22 16:39:08 -07:00
Joffrey F 28e76a6fbc Merge pull request #1663 from shin-/qazbnm456-correct_description_of_dns_opt_of_create_container
Correct the description of dns_opt option of create_container
2017-06-22 12:39:32 -07:00
Boik 015fe1cf5e Correct the description of dns_opt option of create_container
Signed-off-by: Boik <qazbnm456@gmail.com>
2017-06-22 12:23:38 -07:00
Joffrey F b9e5863e48 Merge pull request #1640 from zero57/add_attrs_for_pickling
Add attributes for pickling
2017-06-22 12:00:16 -07:00
Joffrey F 320c810471 Support credHelpers section in config.json
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-22 11:51:31 -07:00
Joffrey F 06d2553b9c Add support for ContainerSpec.TTY
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-21 16:29:25 -07:00
Joffrey F a3b1059839 Merge pull request #1658 from docker/1397-build-network
Add network_mode support to Client.build
2017-06-20 16:51:00 -07:00
Joffrey F a962578e51 Merge pull request #1659 from docker/moby33735
Make sure data is written in prune test so space can be reclaimed
2017-06-20 16:29:18 -07:00
Joffrey F 9b9fb0aa01 Make sure data is written in prune test so space can be reclaimed
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-20 16:07:15 -07:00
An Ha 0165a343d5 Add attributes for pickling
When using the multiprocessing module, it throws an AttributeError,
complaining that the object does not have the attribute used. This adds
the missing attributes and allows them to be pickled.

Signed-off-by: An Ha <zero579911@gmail.com>
2017-06-20 09:39:17 -04:00
Joffrey F 39bb78ac69 Add network_mode support to Client.build
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-19 15:50:28 -07:00
Joffrey F bb82bcf784 Merge pull request #1626 from datwiz/images-build-error-1625
fix #1625 where ImageCollection.build() could return with incorrect image id
2017-06-19 15:20:17 -07:00
Joffrey F ce8a6ea442 Merge pull request #1620 from docker/healthcheck-start-period
Add support for start_period in Healthcheck spec
2017-06-19 15:12:26 -07:00
Joffrey F 75e850e531 Merge pull request #1649 from shin-/1639-exec-id-check-resource
Update check_resource decorator to account for new resource names
2017-06-19 14:56:23 -07:00
Joffrey F 1ea6618b09 Add support for start_period in Healthcheck spec
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-16 17:02:59 -07:00
Joffrey F 8645d1d41b Merge pull request #1617 from docker/create-ingress-network
Add support for ingress in create_network
2017-06-16 12:06:56 -07:00
Joffrey F 0ac926b112 Merge pull request #1629 from shin-/1610-docfix
Fix misleading build method docs
2017-06-16 12:05:50 -07:00
Joffrey F 2086c20ce1 Merge pull request #1631 from madhuri-rai07/master
Add support for ``runtime`` config
2017-06-16 12:05:15 -07:00
Joffrey F 87d5cd1b0a Merge pull request #1632 from kaiyou/master
allow ipv6 :: notation in split_port (using re)
2017-06-16 11:57:52 -07:00
Joffrey F e50eacd9ea Merge pull request #1648 from ChrsMark/master
Raising error in case of invalid value of since kwarg on Container.logs
2017-06-16 11:49:30 -07:00
Joffrey F a9d4c7e2b6 Merge pull request #1653 from osallou/master
Closes #1588, image.tag does not return anything
2017-06-16 11:32:25 -07:00
Olivier Sallou d638829f73 Closes #1588, image.tag does not return anything
This patch returns the check made against api when tagging an image as stated in documentation

Signed-off-by: Olivier Sallou <olivier.sallou@irisa.fr>
2017-06-16 17:49:43 +02:00
Chris Mark c03a009e2d
Raising error in case of invalid value of since kwarg on Container.logs
Signed-off-by: Chris Mark <chrismarkou92@gmail.com>
2017-06-16 18:30:24 +03:00
Joffrey F d33e9ad030 Update check_resource decorator to account for new resource names
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-15 18:34:00 -07:00
Joffrey F 8fc6540fea Merge pull request #1647 from docker/1642-dockerclient-secrets
DockerClient.secrets should be a @property
2017-06-15 18:18:25 -07:00
Joffrey F 1eef700eb7 Merge pull request #1634 from grahamlyons/readtimeout_calling_container_stop
Ensure default timeout is used by API Client
2017-06-14 15:18:10 -07:00
Joffrey F b0c30c8ac4 DockerClient.secrets should be a @property
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-06-14 12:20:47 -07:00
Joffrey F be0a15a89c Merge pull request #1646 from mattoberle/patch-1
excludes requests 2.18.0 from compatible versions
2017-06-14 12:13:03 -07:00
Joffrey F d643a3b997 Merge pull request #1644 from bboreham/test-pull-latest
Only pull the 'latest' tag when testing images
2017-06-14 12:12:54 -07:00
Matt Oberle ae1f596d37 excludes requests 2.18.0 from compatible versions
The 2.18.0 version of requests breaks compatibility with docker-py:
https://github.com/requests/requests/issues/4160

[This block](https://github.com/shazow/urllib3/blob/master/urllib3/connectionpool.py#L292) of code from urllib3 fails:
```python
    def _get_timeout(self, timeout):
        """ Helper that always returns a :class:`urllib3.util.Timeout` """
        if timeout is _Default:
            return self.timeout.clone()

        if isinstance(timeout, Timeout):
            return timeout.clone()
        else:
            # User passed us an int/float. This is for backwards compatibility,
            # can be removed later
            return Timeout.from_float(timeout)
```

In the case of requests version 2.18.0:
`timeout` was an instance of `urllib3.util.timeout.Timeout`
`Timeout` was an instance of `requests.packages.urllib3.util.timeout.Timeout`

When the `isinstance(timeout, Timeout)` check fails the `urllib3.util.timeout.Timeout` object is passed as the `connection` argument to `requests.packages.urllib3.util.timeout.Timeout.from_float`.

Signed-off-by: Matt Oberle <matt.r.oberle@gmail.com>
2017-06-14 14:44:56 -04:00
Bryan Boreham 234296171f Only pull the 'latest' tag when testing images
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
2017-06-14 14:05:26 +00:00
grahamlyons ff993dd858 Move default `timeout` into `from_env`
We'd like to be able to pass `None` as a value for `timeout` because
it has meaning to the `requests` library
(http://docs.python-requests.org/en/master/user/advanced/#timeouts)

Signed-off-by: grahamlyons <graham@grahamlyons.com>
2017-06-09 09:52:49 +01:00
grahamlyons ee75a1c2e3 Ensure default timeout is used by API Client
The `from_env` method on the `docker` module passed `None` as the
value for the `timeout` keyword argument which overrode the default
value in the initialiser, taken from `constants` module.

This sets the default in the initialiser to `None` and adds logic
to set that, in the same way that `version` is handled.

Signed-off-by: grahamlyons <graham@grahamlyons.com>
2017-06-08 14:39:17 +01:00
Madhuri Kumari 612c0f3d0d Fix test cases for ``runtime`` config
Signed-off-by: Madhuri Kumari <madhuri.kumari@intel.com>
2017-06-07 10:47:27 +05:30
kaiyou 0c1271350d Add a specific unit test for splitting port with IPv6
The test was copied from ccec87ca2c

Signed-off-by: kaiyou <pierre@jaury.eu>
2017-06-05 18:21:33 +02:00
kaiyou 5dd91cd4aa Rewrite the split_port function using re
In the case of a defined format with specific parts, a regular
expression with named capturing bits make reasoning about the
parts simpler than imlementing a parser from scratch.

Signed-off-by: kaiyou <pierre@jaury.eu>
2017-06-05 18:21:21 +02:00
Madhuri Kumari 6ae24b9e60 Add support for ``runtime`` in container create and run API 2017-06-01 15:09:46 +00:00
Joffrey F 9eecfb0d2f Fix misleading build method docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-30 11:45:00 -07:00
Chris Ottinger 1223fc144f new integration task linting for #1625
Signed-off-by: Chris Ottinger <chris.ottinger@team.telstra.com>
2017-05-27 11:24:58 +10:00
Chris Ottinger 6ef9d426eb added integration test for #1625 for ImageCollection.build() that verfies that the build method uses the last success message for extracting the image id
Signed-off-by: Chris Ottinger <chris.ottinger@team.telstra.com>
2017-05-27 10:29:36 +10:00
Chris Ottinger 45aec93089 fix #1625 where ImageCollection.build() could return early with incorrect image_id depending on docer build output Signed-off-by: Chris Ottinger <chris.ottinger@team.telstra.com> 2017-05-27 00:21:19 +10:00
Joffrey F dc2b24dcdd Merge pull request #1621 from allencloud/update-swarm-remove-test-status-code-from-500-to-400
update node remove test status code from 500 to >= 400
2017-05-22 12:09:07 -07:00
allencloud 41aae65ab2 update swarm remove test status code from 500 to >= 400
Signed-off-by: allencloud <allen.sun@daocloud.io>
2017-05-18 10:06:58 +08:00
Joffrey F bc69b1834e Merge pull request #1619 from docker/AlexeyRokhin-master
fix type checking for nano_cpus
2017-05-17 16:56:39 -07:00
Alexey Rokhin f6f5652eb2 fix type checking for nano_cpus
Signed-off-by: Alexey Rokhin <arokhin@mail.ru>
2017-05-17 16:06:23 -07:00
Joffrey F fb16d14544 Merge pull request #1615 from docker/service-placement
Add support for placement preferences and platforms in TaskTemplate
2017-05-17 15:25:40 -07:00
Joffrey F ff718f5dac Add support for ingress in create_network
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-17 15:25:10 -07:00
Joffrey F 7af7e1b73a Merge pull request #1612 from lawliet89/build-stage
Add `target` argument to image building
2017-05-17 15:01:33 -07:00
Joffrey F 9cc021dfa6 Add support for placement preferences and platforms in TaskTemplate
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-17 13:48:30 -07:00
Joffrey F 7880c5af1d dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-16 17:19:37 -07:00
Joffrey F 0832898507 Merge pull request #1614 from docker/2.3.0-release
2.3.0 release
2017-05-16 17:12:41 -07:00
Joffrey F ba334f8bd5 Bump 2.3.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-16 14:53:41 -07:00
Yong Wen Chua e4093ab258 Add `target` argument to image building
This is related to the multi-stage image building
that was introduced in 17.05 (API 1.29).

This allows a user to specify the stage of a multi-stage
Dockerfile to build for, rather than the final stage.

Signed-off-by: Yong Wen Chua <me@yongwen.xyz>
2017-05-16 16:13:54 +08:00
Joffrey F db542e71ee Merge pull request #1606 from ymyzk/fix-docstring
Fix docstring of ImageCollection.get
2017-05-15 14:00:05 -07:00
Joffrey F 2aa63dd9a6 Merge pull request #1605 from allencloud/update-test-status-code-from-500-to-400
update docker-py test status code from 500 to 400
2017-05-15 12:18:51 -07:00
Yusuke Miyazaki 6ea1ea8a51 Fix docstring of ImageCollection.get
Signed-off-by: Yusuke Miyazaki <miyazaki.dev@gmail.com>
2017-05-14 05:31:21 +09:00
allencloud 717459db0e update docker-py test status code from 500 to 400
Signed-off-by: allencloud <allen.sun@daocloud.io>
2017-05-13 09:31:42 +08:00
Joffrey F cf68ebcdd8 Merge pull request #1604 from docker/1433-run-networks
Replace erroneous networks argument in containers.run
2017-05-12 15:29:04 -07:00
Joffrey F 95297dc2e7 Replace erroneous networks argument in containers.run with singular
network equivalent.

Small docfixes

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-12 14:28:27 -07:00
Joffrey F 007ab677a1 Merge pull request #1599 from docker/test_17.05_engine
Adjust tests and add newest engine version to Jenkinsfile
2017-05-09 18:01:20 -07:00
Joffrey F 6ed0c01018 Adjust tests and add newest engine version to Jenkinsfile
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-09 17:18:46 -07:00
Joffrey F 2bdaf7f857 Merge pull request #1598 from docker/init_path_removed
init_path removed in Engine 17.05
2017-05-09 17:01:47 -07:00
Joffrey F bf60e2a330 init_path removed in Engine 17.05
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-09 16:16:10 -07:00
Joffrey F 4e217b5cc4 Merge pull request #1596 from docker/1585-pull-tag
Include tag in images.get after pulling if provided separately
2017-05-09 14:06:24 -07:00
Joffrey F c6ddea469f Include tag in images.get after pulling if provided separately
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-09 12:24:40 -07:00
Joffrey F 05741a160e Merge branch 'Niboo-issue1567' 2017-05-08 14:14:36 -07:00
Joffrey F f27ecf3f88 Add ContainerSpec mounts test
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-08 14:13:59 -07:00
Joffrey F 370cdb6dc5 Merge branch 'issue1567' of https://github.com/Niboo/docker-py into Niboo-issue1567
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-08 14:02:13 -07:00
Antoine Verlant 933a303ede Fix the way the list of mounts is made for service.
Signed-off-by: Antoine Verlant <antoine@niboo.be>
2017-05-08 10:09:36 +02:00
Joffrey F a453aeff5a Merge branch 'aaronthebaron-1577-multi-success-message' 2017-05-05 15:11:24 -07:00
Joffrey F 431f7c6432 Improve build result detection
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-05 15:08:38 -07:00
Joffrey F e19aad860c Merge branch '1577-multi-success-message' of https://github.com/aaronthebaron/docker-py into aaronthebaron-1577-multi-success-message 2017-05-05 15:01:16 -07:00
Joffrey F 36b2d8149b Merge pull request #1590 from alfred-landrum/denied-error
Update image create error parsing
2017-05-05 11:36:52 -07:00
Alfred Landrum 02c5914d29
Update image create error parsing
Support new error message returned for image creation in:
https://github.com/moby/moby/pull/33005

Signed-off-by: Alfred Landrum <alfred@leakybucket.org>
2017-05-04 16:22:18 -07:00
Aaron Cowdin a164f4661b Better error handling, itterate on json stream directly.
Signed-off-by: Aaron Cowdin <aaron.cowdin@gmail.com>
2017-05-03 13:10:01 -07:00
Joffrey F 0a94e5a945 Merge branch 'TomasTomecek-add-env-support-to-exec' 2017-05-02 17:09:36 -07:00
Joffrey F c6030027f5 Modernize exec_api.py
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-02 17:09:09 -07:00
Aaron Cowdin 7dffc46234 Add integration tests
Signed-off-by: Aaron Cowdin <aaron.cowdin@gmail.com>
2017-05-02 17:01:34 -07:00
Joffrey F 13dfb13858 Merge branch 'add-env-support-to-exec' of https://github.com/TomasTomecek/docker-py into TomasTomecek-add-env-support-to-exec
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-05-02 16:38:40 -07:00
Joffrey F 67f12bd114 Merge pull request #1583 from delcypher/cpuset_fixes
CPUset* parameter fixes
2017-05-02 14:52:47 -07:00
Joffrey F 35b8c0a750 Merge pull request #1586 from terminalmage/refresh_credentials
Add function to refresh credentials from config.json
2017-05-02 14:46:22 -07:00
Erik Johnson 550c31e2b7 Move reload_config func into the APIClient
Also revert an incorrect change in the DaemonApiMixin's login func

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-05-02 16:26:35 -05:00
Joffrey F 0872f27def Merge pull request #1587 from terminalmage/docs
Documentation fixes for login func
2017-05-02 13:57:20 -07:00
Erik Johnson 0f843414e5 Add a reload_config function to the DaemonApiMixin
This allows the client to reload the config.json for an existing
APIClient instance.

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-05-02 15:10:44 -05:00
Erik Johnson 3a4fa79e1c Documentation fixes for login func
This makes a small tweak to the grammar of the documentation for the
reauth argument, and also updates the dockercfg_path docs for accuracy.

Signed-off-by: Erik Johnson <palehose@gmail.com>
2017-05-02 14:57:32 -05:00
Dan Liew 2a0a7adece Fix typo s/CpuSetCpus/CpusetCpus/
According to Docker's API documentation [1]. The parameter name
is `CpusetCpus` not `CpuSetCpus`.

[1] https://docs.docker.com/engine/api/v1.25/#operation/ContainerCreate

Signed-off-by: Dan Liew <daniel.liew@imperial.ac.uk>
2017-05-01 14:56:40 +01:00
Dan Liew b9ca8755bb Add missing support for `CpusetMems` parameter to HostConfig.
Signed-off-by: Dan Liew <daniel.liew@imperial.ac.uk>
2017-05-01 14:56:40 +01:00
Tomas Tomecek 4633dac580 exec: add support for `Env`
Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2017-04-29 08:56:51 +02:00
Aaron Cowdin 59ba27068b Handle multiple success messages during image building.
Signed-off-by: Aaron Cowdin <aaron.cowdin@gmail.com>
2017-04-28 15:18:59 -07:00
Joffrey F 72b9b72359 Merge pull request #1570 from AlexeyRokhin/master
Add cpu_count, cpu_percent, nano_cpus parameters to container HostConfig.
2017-04-28 14:16:25 -07:00
Alexey Rokhin c2f83d558e cpus renamed to nano_cpus. Type and scale of nano_cpus are changed. Comments for new parameters are changed.
Signed-off-by: Alexey Rokhin <arokhin@mail.ru>
2017-04-28 15:55:44 +03:00
Joffrey F d19572aae3 Merge pull request #1493 from funkyfuture/model_properties
Adds a few model properties
2017-04-27 16:21:02 -07:00
Joffrey F dec80d91c0 Merge pull request #1518 from smiller171/patch-1
Add License to PyPi metadata
2017-04-27 16:11:55 -07:00
Joffrey F d2ebc6ade4 Merge branch 'lyager-connect_argparse' 2017-04-27 15:47:35 -07:00
Joffrey F 16d32b40e6 Formatting
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-04-27 15:47:25 -07:00
Jesper L. Nielsen 9412e21f1a Network model functions 'connect' and 'disconnect' did not accept or passthrough keyword arguments.
Signed-off-by: Jesper L. Nielsen <lyager@gmail.com>
2017-04-27 15:47:25 -07:00
Joffrey F bd84bebfa9 Merge pull request #1574 from Coderhypo/master
fix can't get a dict when Containers is None
2017-04-27 15:43:45 -07:00
Joffrey F 55ef7acd26 Merge branch 'aashutoshrathi-restart_policy_typo' 2017-04-27 15:41:16 -07:00
Aashutosh Rathi c5cc23884a Update services.py
Signed-off-by: Aashutosh Rathi <aashutoshrathi@gmail.com>
2017-04-27 15:33:24 -07:00
Joffrey F 8ffa09b4b6 Merge pull request #1576 from robkooper/1572-replicas-0
Fix if replicas is set to 0, Fixes #1572
2017-04-27 15:30:36 -07:00
Rob Kooper 5f9a599b0f Fix if replicas is set to 0, Fixes #1572
Signed-off-by: Rob Kooper <kooper@illinois.edu>
2017-04-26 22:50:17 -05:00
hhHypo 2d026fd1e5 fix can't get a dict when Containers is None
Signed-off-by: hhHypo <i@ihypo.net>
2017-04-26 01:51:43 +08:00
Alexey Rokhin 3f7d622143 Add cpu_count, cpu_percent, cpus parameters to container HostConfig.
Signed-off-by: Alexey Rokhin <arokhin@mail.ru>
2017-04-19 15:07:02 +03:00
Frank Sachsenheim 9536c8653d Sorts model attributes in api docs alphabetically
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2017-04-15 15:46:52 +02:00
Frank Sachsenheim 659090fc99 Adds an 'image' property to the container model
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2017-04-15 15:46:52 +02:00
Frank Sachsenheim b585ec59a8 Adds a 'labels' property to the image model
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2017-04-15 15:46:52 +02:00
Frank Sachsenheim 1cd56b9f0c Adds a 'labels' property to the container model
The Docker API seems to respond with a 'null' value for the 'Labels'
attribute from containers that were created with older Docker versions.
An empty dictionary is returned in this case.

Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2017-04-15 15:46:52 +02:00
Frank Sachsenheim 6529fa599c Makes docs builds faster and ensures proper ownership
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
2017-04-15 15:46:52 +02:00
Joffrey F f127a9ffdc Merge pull request #1558 from shin-/sanimej-verbose
Add 'verbose' option for network inspect API
2017-04-11 16:25:14 -07:00
Joffrey F e506a2b8ea Standardize handling of verbose param in inspect_network
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-04-10 16:03:13 -07:00
Santhosh Manohar abd5370d87 Add 'verbose' option for network inspect api
Signed-off-by: Santhosh Manohar <santhosh@docker.com>
2017-04-10 16:03:13 -07:00
Joffrey F ffc3769920 Merge pull request #1557 from ewanbarr/patch-1
Minor typo correction
2017-04-10 12:14:33 -07:00
ewanbarr 112dc12bc0 Minor typo correction
The stdout argument name was repeated in the run method docstring. The second should be replaced by stderr.

Signed-off-by: Ewan Barr <ewan.d.barr@googlmail.com>
2017-04-08 14:20:45 +02:00
Joffrey F f8609c7462 Merge pull request #1554 from peter-slovak/fix-docs-container-cpu-opts
Fix docs container cpu opts
2017-04-06 16:18:14 -07:00
Joffrey F 19ef2ddccb Merge pull request #1547 from shin-/1543-volume-driver-moved
Add support for volume_driver in HostConfig
2017-04-06 16:11:23 -07:00
Peter Slovak c80762d376 removed duplicate mem_limit arg desc; type now consistent accross models (float->int)
Signed-off-by: Peter Slovak <peter.slovak@websupport.sk>
2017-04-07 00:38:14 +02:00
Peter Slovak 1f609208fd docs renames: cpu_group->cpu_period, cpu_period->cpu_quota
Signed-off-by: Peter Slovak <peter.slovak@websupport.sk>
2017-04-07 00:37:45 +02:00
Joffrey F 3076a9ac40 2.3.0-dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-04-05 17:07:43 -07:00
Joffrey F 79edcc28f7 Add support for volume_driver in HostConfig
Some cleanup in ContainerConfig + warning if volume_driver is provided (API>1.20)

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-04-05 17:05:08 -07:00
Joffrey F d12b5bb5e6 Merge pull request #1544 from shin-/1522-default_api_version_docs
Update mentions of the default API version in docs
2017-04-04 11:42:33 -07:00
Joffrey F eea1271cd0 Update mentions of the default API version in docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-04-03 16:45:09 -07:00
Joffrey F 62a49196a0 Merge pull request #1540 from docker/appveyor
Add appveyor to CI suite to run unit tests on Windows
2017-03-29 15:55:13 -07:00
Joffrey F 73d8097b3d Fix test issues
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-29 15:39:48 -07:00
Joffrey F 856971ed51 Merge pull request #1537 from shin-/add-integration-test-target
Add 17.04 (CE) RC1 to list of engine versions to be tested
2017-03-29 15:30:51 -07:00
Joffrey F 7fa30a713e Add appveyor.yml config
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-28 16:29:41 -07:00
Joffrey F 09813334c1 Add 17.04 (CE) RC1 to list of engine versions to be tested
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-28 16:22:35 -07:00
Joffrey F 277a6e13c2 Add reload() in docs for Container and Secret classes
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-28 16:00:29 -07:00
Joffrey F c0c25c07ca Merge pull request #1528 from shin-/events_no_timeout
Set infinite timeout for the `events` method
2017-03-28 12:06:37 -07:00
Joffrey F c5d35026ce Set infinite timeout for the `events` method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-27 15:57:36 -07:00
Joffrey F cb68acbaae Merge pull request #1524 from alex-dr/fix-apierror-status
Fix APIError status_code property for client/server errors
2017-03-22 15:29:23 -07:00
alex-dr e0e7404380 Fix APIError status_code property for client/server errors
requests.Response objects evaluate as falsy when the status_code
attribute is in the 400-500 range. Therefore we are assured that
prior to this change, APIError would show `is_server_error() == False`
when generated with a 500-level response and `is_client_error() == False`
when generated with a 400-level response. This is not desirable.

Added some seemingly dry (not DRY) unit tests to ensure nothing silly
slips back in here.

Signed-off-by: alex-dr <alex@datarobot.com>
2017-03-22 00:49:07 -04:00
Joffrey F 3d8b20a906 Merge pull request #1446 from shin-/service-logs
Add service_logs command to APIClient and logs command to models.Service
2017-03-21 13:57:25 -07:00
Joffrey F 04c662bd23 Bump 2.2.0, update changelog
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-21 12:33:45 -07:00
Joffrey F b7fbbb56c7 Remove unsupported --experimental flag from Jenkinsfile
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-18 15:20:20 -07:00
Joffrey F aeb5479fd5 Use experimental engine for testing in Jenkins/Makefile
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-17 18:30:33 -07:00
Scott Miller 279b058752
Add License to PyPi metadata
Signed-off-by: Scott Miller <scott@millergeek.xyz>
2017-03-17 13:39:55 -04:00
Joffrey F daac15c1fa Add service_logs integration test
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-13 17:29:04 -07:00
Joffrey F be463bb27e Add service_logs command to APIClient and logs command to models.Service
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-13 16:55:30 -07:00
Joffrey F 24f75ea212 Merge pull request #1500 from shin-/fix_split_port_empty_string
Raise an error when passing an empty string to split_port
2017-03-13 11:59:52 -07:00
Joffrey F 4011fa7d5c Merge pull request #1505 from AntaresS/documentation-fix
documentation change
2017-03-09 16:17:43 -08:00
Joffrey F 54b3c364cb Raise an error when passing an empty string to split_port
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-09 16:12:48 -08:00
Joffrey F c2d114c067 Move LinksTest to appropriate file
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-09 16:12:22 -08:00
Joffrey F 12f1a6957e Merge pull request #1501 from max8899/fix/split_port
fix: Missing exception handling in split_port when no container port
2017-03-09 16:11:53 -08:00
Anda Xu eb91d709cb documentation change
Signed-off-by: Anda Xu <anda.xu@docker.com>
2017-03-09 13:53:43 -08:00
Lei Gong eba20084f6 fix: Missing exception handling in split_port when no container port
"localhost:host_port:" case will raise TypeError exception directly

Catch the "TypeError" and give proper error message

* docker/utils/ports.py

Signed-off-by: Lei Gong <xue177125184@gmail.com>
2017-03-09 16:28:34 +08:00
Joffrey F fa52824363 Merge pull request #1481 from shin-/system_df
Add df method
2017-03-06 11:08:41 -08:00
Joffrey F 11873993eb Merge pull request #1480 from shin-/bump-default-api-version
Bump default API version to 1.26
2017-03-06 11:08:16 -08:00
Joffrey F 830b9edce8 Merge branch 'tmad-container-init' 2017-03-01 14:02:50 -08:00
Joffrey F c0c3cb4497 Docstring fixes for init and init_path
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-01 14:02:35 -08:00
Tomasz Madycki 8c6534d7be Add init_path parameter to container HostConfig
Signed-off-by: Tomasz Madycki <tomasz.madycki@gmail.com>
2017-03-01 14:02:35 -08:00
Tomasz Madycki 13b5f785a7 Add init parameter to container HostConfig
Signed-off-by: Tomasz Madycki <tomasz.madycki@gmail.com>
2017-03-01 14:02:35 -08:00
Joffrey F d59b6b99cc Merge pull request #1479 from shin-/plugin-upgrade
Add upgrade_plugin method
2017-03-01 13:52:46 -08:00
Joffrey F 4273d3f63d Bump default API version to 1.26
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-01 13:52:07 -08:00
Joffrey F cfb14fa78f Add df method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-03-01 13:51:39 -08:00
Joffrey F 4a08d04aef Merge pull request #1490 from ripcurld0/change_rm_error_msg
Update assert in test_create_with_restart_policy
2017-03-01 11:54:13 -08:00
Boaz Shuster 5dced6579a Update assert in test_create_with_restart_policy
In https://github.com/docker/docker/pull/30870 a new
error message is displayed if the container is restarting.

To make "test_create_with_restart_policy" pass against the
above change, the test checks that the error message contains
"You cannot remove " instead of
"You cannot remove a running container"

Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
2017-03-01 15:36:32 +02:00
Joffrey F c35a6283a0 Merge pull request #1484 from BenDoan/master
removed unused/typoed param from models.containers.list docstring
2017-02-27 13:01:15 -08:00
Ben Doan 820af34940
removed unused/typoed param from models.containers.list docstring
Signed-off-by: Ben Doan <ben@bendoan.me>
2017-02-26 18:41:13 -06:00
Joffrey F 5268a31116 Add Plugin.upgrade to documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-23 18:15:40 -08:00
Joffrey F 48ac772994 Add upgrade_plugin method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-23 17:27:04 -08:00
Joffrey F f387ae46d7 Merge pull request #1467 from crierr/master
Allow port range like 8000-8010:80
2017-02-22 15:27:42 -08:00
Joffrey F f9f77c4c2f Merge pull request #1473 from Anvil/event-http-headers
Allow events daemon command to read config.json
2017-02-21 12:11:58 -08:00
Joffrey F ae8c716376 Merge pull request #1466 from nkrabshuis/master
Add ability to set 'Hostname' on a Service.
2017-02-21 12:11:39 -08:00
Damien Nadé f36ef399ad Fixed events command related unit tests by passing a timeout value
Signed-off-by: Damien Nadé <github@livna.org>
2017-02-21 18:21:10 +01:00
Damien Nadé b587139d3c Allow events daemon command to read config.json
Signed-off-by: Damien Nadé <github@livna.org>
2017-02-21 17:53:02 +01:00
SeungJin Oh 60e7fd93a8 passing flake8 test
Signed-off-by: SeungJin Oh <crierr@naver.com>
2017-02-20 09:35:07 +09:00
SeungJin Oh 8e47f29720 check NoneType before using
Signed-off-by: SeungJin Oh <crierr@naver.com>
2017-02-20 09:32:36 +09:00
crierr cfc11515bc Allow port range like 8000-8010:80
Signed-off-by: SeungJin Oh <crierr@naver.com>
2017-02-20 02:09:33 +09:00
Nils Krabshuis 9ec31ffa27 Flake8: Fix indent.
Signed-off-by: Nils Krabshuis <nils.krabshuis@redwood.com>
2017-02-19 06:26:16 +01:00
Nils Krabshuis 44c31e47e0 Add ability to set 'Hostname' on a Service.
Signed-off-by: Nils Krabshuis <nils.krabshuis@redwood.com>
2017-02-19 06:18:26 +01:00
Joffrey F b791aa10fa Bump dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-16 16:54:45 -08:00
Joffrey F a90e3e442c Bump version 2.1.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-16 16:54:12 -08:00
Joffrey F 1042b06e50 Add missing secrets doc
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-16 16:53:19 -08:00
Joffrey F e0b6cdfcf6 Merge pull request #1460 from shin-/fix-cache-from
Rename cachefrom -> cache_from
2017-02-16 13:35:58 -08:00
Joffrey F 14caaad657 Merge pull request #1461 from shin-/fix-storage-opt-test
Add xfail mark to storageopt test
2017-02-16 13:35:33 -08:00
Joffrey F 0a97df1abc Rename cachefrom -> cache_from
Fix cache_from integration test
Fix image ID detection in ImageCollection.build

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-15 19:13:24 -08:00
Joffrey F 3a9c83509c Add xfail mark to storageopt test
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-15 19:02:31 -08:00
Joffrey F 4a50784ad4 Merge pull request #1459 from shin-/1300-storageopts
Add support for storage_opt in host_config
2017-02-15 18:12:31 -08:00
Joffrey F afcbeb5e4f Merge pull request #1449 from shin-/secrets-api
Implement secrets API
2017-02-15 18:08:25 -08:00
Joffrey F 469b12a3c5 Merge pull request #1455 from shin-/1117-dockerignore-globstar
Add support for recursive wildcard pattern in .dockerignore
2017-02-15 18:08:09 -08:00
Joffrey F ece3b19782 Add support for storage_opt in host_config
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-15 17:43:24 -08:00
Joffrey F 20c6fe31e0 Add support for recursive wildcard pattern in .dockerignore
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-14 18:29:37 -08:00
Joffrey F e8a86e40cc Add tests for secret API implementation
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-13 17:06:25 -08:00
Joffrey F d1038c422b Add support for secrets in ContainerSpec
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-13 17:05:58 -08:00
Joffrey F 52bae3ca2c Implement secrets API
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-13 17:05:58 -08:00
Joffrey F 35f37a0936 Merge pull request #1432 from shin-/plugins
Plugins API
2017-02-13 13:20:53 -08:00
Joffrey F 2255847b22 Merge pull request #1447 from shin-/update_jenkinsfile
Bump test engine version
2017-02-13 13:19:49 -08:00
Joffrey F e1ad3186ef Add create_plugin implementation
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-09 17:58:05 -08:00
Joffrey F 9ac3666c27 Bump test engine version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-08 18:08:12 -08:00
Joffrey F 6114024aa3 Merge pull request #1439 from bfirsh/fix-various-volume-bugs
Fix various volume bugs
2017-02-07 17:15:25 -08:00
Ben Firshman f83993de0a
Fix passing volumes to run with no host path
Technically we shouldn't be passing them as binds, but the daemon
doesn't seem to mind.

Fixes #1380

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2017-02-07 19:22:36 +01:00
Ben Firshman 956fe1cac1
Fix volume path passed by run to create_container
Seems like this is pretty much ignored by Docker, so it wasn't
causing any visible issues, except when a volume name was used
instead of a path.

Also, added integration tests.

Ref #1380

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2017-02-07 19:22:35 +01:00
Joffrey F 96a9eaced6 Merge pull request #1344 from psviderski/fix/logs_performance
Dramatically increase get logs performance
2017-02-06 17:01:58 -08:00
Joffrey F cd05d8d53d Fix _post_json behavior
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-03 19:53:58 -08:00
Joffrey F 42b9358458 Merge pull request #1425 from shin-/prunes
Prunes
2017-02-03 19:49:54 -08:00
Joffrey F 14d81d96c1 Plugins API documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-03 19:47:34 -08:00
Joffrey F 39f6a89b69 Add plugin API implementation to DockerClient
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-03 19:46:58 -08:00
Joffrey F 9296971e4c APIClient implementation of plugin methods
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-03 19:45:59 -08:00
Joffrey F b3ea1fb942 Merge pull request #1429 from shin-/fix_remove_network_test
Improve robustness of remove_network integration test
2017-01-30 19:13:22 -08:00
Joffrey F a8cdc6bf34 Merge pull request #1427 from shin-/rmb938-patch-2
Optional name param in create_volume
2017-01-30 18:56:48 -08:00
Joffrey F 62e223208f Reference new methods in docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 18:54:18 -08:00
Joffrey F 83b45b7d54 Add prune_networks method
Ensure all integration tests use the same version of the busybox image

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 18:54:18 -08:00
Joffrey F 89d3803344 Add prune_volumes method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 18:53:46 -08:00
Joffrey F 7f0c2e7531 Add prune_images method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 18:53:46 -08:00
Joffrey F f2a867f04b Add prune_containers method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 18:53:46 -08:00
Joffrey F bf41c7fa67 Improve robustness of remove_network integration test
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 18:52:11 -08:00
Joffrey F d3798b157c Merge pull request #1354 from bfirsh/remote-api-to-engine-api
Change "Remote API" to "Engine API"
2017-01-30 12:00:08 -08:00
Joffrey F 39bee3f4be Merge pull request #1377 from realab/chunked-images-save
provide best practice for Image.save
2017-01-30 11:59:30 -08:00
Joffrey F 08aac9d571 Merge pull request #1341 from pacoxu/patch-1
Scope is added in volume after docker 1.12
2017-01-30 11:59:00 -08:00
Joffrey F bf49438a21 Optional name on VolumeCollection.create
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 11:55:59 -08:00
Joffrey F d57c0c3fc2 Merge branch 'patch-2' of https://github.com/rmb938/docker-py into rmb938-patch-2
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 11:54:06 -08:00
Joffrey F fd1ab6cef4 Merge pull request #1424 from shin-/service_params_1.25
Add new (1.25) service params
2017-01-30 11:51:29 -08:00
Ben Firshman 00de2055f9
Change "Remote API" to "Engine API"
This is currently inconsistent, but mostly called "Engine API".
For the release of Docker 1.13, this will be "Engine API" all
over the Engine documentation, too.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2017-01-30 17:16:47 +01:00
Joffrey F d22e2fec6f Add support for force_update in TaskTemplate
Add min version checks in create_service and update_service

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-27 17:19:18 -08:00
Joffrey F fc5cd1a914 Add support for max_failure_ratio and monitor in UpdateConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-27 16:40:05 -08:00
Joffrey F d1b51c3967 Merge pull request #1421 from shin-/add_stop_timeout
Add stop_timeout to create_container
2017-01-27 16:39:32 -08:00
Joffrey F 847f209865 Add stop_timeout to create_container
Fix requires_api_version test decorator

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-27 16:00:18 -08:00
Joffrey F 0186456f3c Merge pull request #1413 from docker/force_remove_volume
Add 'force' parameter in remove_volume
2017-01-26 14:40:00 -08:00
Joffrey F 2d93674903 Merge pull request #1419 from docker/remove_obsolete_search_test
Remove integration test for APIClient.search method
2017-01-26 14:34:10 -08:00
Joffrey F a24b114af3 Add 'force' parameter in remove_volume
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-26 14:24:52 -08:00
Joffrey F 64519a2b20 Merge pull request #1415 from docker/autoremove_support
Add support for auto_remove in HostConfig
2017-01-26 14:24:23 -08:00
Joffrey F 432730ab29 Merge pull request #1417 from graingert/cachefrom
This adds the cache-from build option (docker/docker#26839) and fixes #1382.
2017-01-26 14:23:05 -08:00
Joffrey F 62c94f9634 Remove integration test for APIClient.search method
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-26 14:07:41 -08:00
Thomas Grainger 0d9adcdfdc
Add cachefrom to build docstring
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2017-01-26 11:22:46 +00:00
Thomas Schaaf 686d8e9536
Implement cachefrom
Signed-off-by: Thomas Schaaf <schaaf@komola.de>
2017-01-26 11:20:01 +00:00
Joffrey F c031e54117 Merge pull request #1414 from docker/config_test_api_version
Allow configuring API version for integration test with env var
2017-01-25 18:43:20 -08:00
Joffrey F a1d550a14c Allow configuring API version for integration test with env var
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-25 16:52:26 -08:00
Joffrey F 848b7aa6a4 Add support for auto_remove in HostConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-25 16:45:59 -08:00
Joffrey F 4ff77dc1c9 Merge pull request #1412 from docker/1359-swarm-init
Fix Swarm model init to correctly pass arguments through to init_swarm
2017-01-25 15:40:56 -08:00
Joffrey F 3e5bb7b0e6 Fix Swarm model init to correctly pass arguments through to init_swarm
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-25 15:28:43 -08:00
Joffrey F 39deace7c6 Merge pull request #1410 from bayazee/master
Remove duplicate line in exec_run documentation
2017-01-25 13:13:16 -08:00
Joffrey F ff83cf406d Merge pull request #1408 from docker/1407-tar-ignore-sockets
Ignore socket files in utils.tar
2017-01-25 12:37:46 -08:00
Joffrey F 93877241f9 Fix ImageNotFound detection
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-25 12:02:53 -08:00
Mehdi Bayazee df7e709fb6 Remove duplicate line in exec_run documentation
Signed-off-by: Mehdi Bayazee <bayazee@gmail.com>
2017-01-25 13:08:10 +01:00
Joffrey F e87ed38f69 Ignore socket files in utils.tar
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-24 18:00:42 -08:00
Joffrey F 8ca5b2b392 Fix milestone link
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-20 14:09:52 -08:00
Joffrey F 886e6ff9ea Bump 2.0.2
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-20 14:09:46 -08:00
Joffrey F c7412c5a30 Merge pull request #1403 from docker/update_test_engine_versions
Update dockerVersions
2017-01-20 14:02:45 -08:00
Joffrey F fbea15861e Update dockerVersions
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-19 18:05:11 -08:00
Joffrey F 32392b7df0 Merge pull request #1390 from docker/1388-format-service-mode
Convert mode argument to valid structure in create_service
2017-01-19 17:42:17 -08:00
Joffrey F 06e8081799 Convert mode argument to valid structure in create_service
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-19 16:23:32 -08:00
Joffrey F 5f0b469a09 Merge pull request #1398 from docker/docs-fixes
Fix a number of docs formatting issues
2017-01-19 16:19:57 -08:00
Joffrey F bcb869b27f Merge pull request #1399 from docker/1395-docker-py-conflict
Prevent issues when installing docker and docker-py in the same environment
2017-01-19 16:19:28 -08:00
Joffrey F bb665257ed Merge pull request #1393 from aebm/master
Fix #1351
2017-01-19 11:55:14 -08:00
Joffrey F e9691db91b Prevent issues when installing docker and docker-py in the same environment
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-18 16:26:22 -08:00
Joffrey F 7db5f7ebcc Merge pull request #1389 from docker/fix-stream-helper
Use json_stream function in decoded _stream_helper
2017-01-18 15:40:47 -08:00
Joffrey F 66d5733398 Fix a number of docs formatting issues
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-18 15:38:53 -08:00
Ben Firshman 468bb1c545 Merge pull request #1347 from fcurella/hash
Make resources hashable, so that they can be added to `set`s
2017-01-18 16:49:35 +01:00
Alejandro E. Brito Monedero 95b6fddd14 Fix #1351
* Fix TypeError when getting the tags property from an image that has
  no tags. Ex: An image pulled by cryptohash. It is handled like when
  the image doesn't have defined the RepoTags member.

Signed-off-by: Alejandro E. Brito Monedero <alejandro.monedero@gmail.com>
2017-01-16 08:48:41 +01:00
Joffrey F aed1af6f6f Merge pull request #1392 from graingert/case-pypi-correctly
case PyPI correctly
2017-01-13 17:00:48 -08:00
Thomas Grainger f0ceca4713
case PyPI correctly
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2017-01-13 10:00:41 +00:00
Joffrey F fb6c9a8295 Use json_stream function in decoded _stream_helper
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-11 17:24:50 -08:00
Joffrey F 91a185d7a5 Bump 2.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-09 15:57:29 -08:00
Joffrey F 56cfe0bf09 Merge pull request #1385 from docker/1376-parse-mount-type
Detect mount type in parse_mount_string
2017-01-09 15:25:03 -08:00
Joffrey F 40089a781c Detect mount type in parse_mount_string
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-09 15:13:09 -08:00
Joffrey F 07b20ce660 Merge pull request #1384 from docker/dzimine-dz-fix-mount_options
Fix parse_mount_string
2017-01-09 14:46:43 -08:00
Joffrey F 180dd69974 Raise InvalidArgument exception when invalid arguments are provided
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-09 14:34:25 -08:00
Joffrey F a960731999 Additional parse_mount_string tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-09 14:33:58 -08:00
Joffrey F 155b95d143 Merge branch 'dz-fix-mount_options' of https://github.com/dzimine/docker-py into dzimine-dz-fix-mount_options
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-09 14:19:25 -08:00
Joffrey F 4d982641c4 Merge pull request #1379 from docker/compose-4302-dockerignore-windows
Accept / as a path separator in dockerignore patterns on all platforms
2017-01-09 13:45:28 -08:00
Joffrey F 9450442c8c Accept / as a path separator in dockerignore patterns on all platforms
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-06 16:37:15 -08:00
realityone 2ba802dfbe
provide best practice for Image.save
Signed-off-by: realityone <realityone@me.com>
2017-01-06 11:44:58 +08:00
Joffrey F 6d871990d2 Merge pull request #1362 from qazbnm456/add_filters_to_networks
Add filters option to NetworkApiMixin.networks
2017-01-05 11:44:13 -08:00
Lobsiinvok 9047263354 Add filters option to NetworkApiMixin.networks
Signed-off-by: Boik <qazbnm456@gmail.com>
2017-01-05 09:23:26 +08:00
Dmitri 59ccd8a782 Fix readonly in mounts.
Signed-off-by: Dmitri Zimine dz@stackstorm.com
2016-12-28 23:43:15 -08:00
Joffrey F edd3045ef1 Merge pull request #1350 from docker/changelog-update
Changelog update
2016-12-12 16:55:04 -08:00
Joffrey F 4219ebc9a1 Bump version number to next dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-12 14:30:21 -08:00
Joffrey F f008f34424 Remove development version warning from README
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-12 14:29:33 -08:00
Joffrey F 7b8809eb07 Bump version and update Changelog
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-12 14:29:13 -08:00
Joffrey F 95413dd176 Merge pull request #1332 from docker/docker_sdk_rename
Rename all meaningful occurrences of docker-py to docker-sdk-python
2016-12-12 13:53:27 -08:00
Joffrey F 769ca5a76a Rename non-URL occurrences of docker-py to "Docker SDK for Python"
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-12 13:28:49 -08:00
Joffrey F c6d1c2dc84 Merge pull request #1342 from docker/jenkinsfile
Add Jenkinsfile for integration tests matrix
2016-12-08 16:42:38 -08:00
Joffrey F 48c5cd82fc Prevent Swarm address conflicts
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-08 14:50:05 -08:00
Joffrey F 3fb48d111b Add Jenkinsfile for integration tests matrix
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-08 12:12:01 -08:00
Flavio Curella 6f239fbf29 Make resources hashable, so that they can be added to `set`s
Signed-off-by: Flavio Curella <flavio.curella@gmail.com>
2016-12-08 12:19:30 -06:00
徐俊杰 b9c48dca2c Scope is added in volume after docker 1.12
Signed-off-by: pacoxu <paco.xu@daocloud.io>

add ut test for volume scope and no specified name create
Signed-off-by: Paco Xu <paco.xu@daocloud.io>

try to fix ut failure of volume creation
Signed-off-by: Paco Xu <paco.xu@daocloud.io>

try to fix ut failure of volume creation
Signed-off-by: Paco Xu <paco.xu@daocloud.io>

Scope is added in volume after docker 1.12
 Signed-off-by: pacoxu <paco.xu@daocloud.io>

Scope is added in volume after docker 1.12
 Signed-off-by: pacoxu <paco.xu@daocloud.io>
2016-12-08 10:31:44 +08:00
Joffrey F d024b1bd78 Merge pull request #1338 from docker/remove_node
Implement swarm node removal
2016-12-07 15:37:17 -08:00
Joffrey F 281b5558b5 Merge pull request #1340 from docker/dnephin-add-attachable
Add attachable option in create_network
2016-12-07 15:36:43 -08:00
Joffrey F 738cfdcdf9 Update code and tests for Engine 1.13 compatibility
Makefile now runs tests against Docker 1.13 RC

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-07 14:51:14 -08:00
Joffrey F c239e40504 Implement swarm node removal
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-07 12:24:18 -08:00
Pavel Sviderski 2b88e9cddb increase logs performance, do not copy bytes object
Signed-off-by: Pavel Sviderski <pavel@psviderski.name>
2016-12-07 18:12:12 +08:00
Joffrey F b71f34e948 Fix typo in create_network
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-06 11:26:53 -08:00
Ryan Belgrave 16d0f96bc5
Name is not required when creating a docker volume
Signed-off-by: Ryan Belgrave <Ryan.Belgrave@target.com>
2016-12-06 10:46:02 -06:00
Ben Firshman 9050e1c6e0 Merge pull request #1339 from docker/min_version_1.21
Minimum version 1.24 -> 1.21
2016-12-06 15:50:20 +01:00
Joffrey F 993001bc49 Minimum version 1.24 -> 1.21
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-05 16:53:21 -08:00
Daniel Nephin 2b85fbf120 Add attachable.
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2016-12-05 17:54:18 -05:00
Ben Firshman dd8ad21c88 Merge pull request #1272 from TomasTomecek/1271-fix-detach-in-exec-start
exec: fix running with detach=True
2016-12-05 11:00:10 +00:00
Joffrey F c02493cf18 Merge pull request #1331 from aanand/fix-auth-config-path-windows
Fix auth config path on Windows
2016-12-02 18:07:08 -08:00
Joffrey F d56b2d3dc8 Merge pull request #1315 from bfirsh/rename-docker-py-to-docker-sdk-python
Start to rename docker-py to docker-sdk-python
2016-12-02 15:20:34 -08:00
Joffrey F 32cd0161b6 Merge pull request #1330 from docker/walkerlee-master
Add options to IPAMConfig
2016-12-02 15:18:41 -08:00
Joffrey F fbc9f9b5e9 Merge pull request #1327 from docker/compose4171_build_auth_headers
Properly fill out auth headers in APIClient.build when using a credstore
2016-12-02 15:08:48 -08:00
Joffrey F 3fe014475c Merge pull request #1329 from docker/manics-patch-1
Use format_environment to convert env in ContainerSpec
2016-12-02 15:08:27 -08:00
Joffrey F 1d59aeca4b Add options to IPAMConfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-02 15:04:05 -08:00
Joffrey F fd4c01aa99 Merge branch 'master' of https://github.com/walkerlee/docker-py into walkerlee-master
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-02 14:57:57 -08:00
Joffrey F 88b733b0f4 Merge branch 'patch-1' of https://github.com/manics/docker-py into manics-patch-1
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-02 14:50:40 -08:00
Joffrey F 9f2f93de0e Merge pull request #1324 from docker/requests_2.12.2
Exclude requests==2.12.2 from dependencies
2016-12-02 11:27:03 -08:00
Aanand Prasad fb4969f744 Fix auth config path on Windows
The Engine client looks *only* at the USERPROFILE environment variable
on Windows, so we should do that too.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-12-02 18:02:09 +00:00
Ben Firshman dfa4b76989 Merge pull request #1328 from docker/ssladapter_transport_module
Move ssladapter to transport module
2016-12-02 14:44:03 +00:00
Ben Firshman ff6601cf64 Merge pull request #1319 from docker/config_types
Move config type creation from docker.utils functions to classes in docker.types
2016-12-02 14:35:43 +00:00
Joffrey F 4539644667 Move ssladapter to transport module
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-01 18:04:40 -08:00
Joffrey F d042c6aeda Properly fill out auth headers in APIClient.build when using
a credentials store

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-01 18:04:15 -08:00
Joffrey F 01c33c0f68 Client -> DockerClient
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-01 18:02:16 -08:00
Joffrey F 993f298e85 Move config type creation from docker.utils functions to classes in
docker.types

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-01 16:06:41 -08:00
Ben Firshman e7d78d10f6 Merge pull request #1303 from aanand/helpful-containers-warning
Show a helpful warning when people try to call `client.containers()`
2016-12-01 11:11:46 +00:00
Joffrey F 239673a51c Merge pull request #1308 from docker/docker_client
Rename Client -> DockerClient
2016-11-30 15:30:40 -08:00
Joffrey F 176346bd95 Exclude requests==2.12.2 from dependencies
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-30 15:23:41 -08:00
Tomas Tomecek 515db1f6fd exec: fix running with detach=True
Fixes #1271

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-11-29 16:04:52 +01:00
Ben Firshman 6a16edee3e Merge pull request #1277 from bodnarbm/do-not-traverse-ignored-directories-with-no-potential-exceptions
Do not traverse excluded directories that are not prefixes of dockerignore exceptions.
2016-11-29 10:09:43 +00:00
Joffrey F f5ac10c469 Rename Client -> DockerClient
Replace references to old Client with APIClient
Moved contents of services.md to appropriate locations

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-28 15:28:04 -08:00
Joffrey F 52376e4b24 Merge pull request #1250 from mmerickel/fix/1211
do not assume that read will consume the number of bytes requested
2016-11-28 14:00:32 -08:00
Joffrey F 9643253c50 Merge pull request #1297 from docker/stepanstipl-allow_custom_pid_mode
Allow custom pid mode
2016-11-28 14:00:07 -08:00
Joffrey F 75e9d357f7 Merge pull request #1309 from bfirsh/remove-maintainer-from-dockerfiles
Remove MAINTAINER from Dockerfiles
2016-11-28 13:14:40 -08:00
Joffrey F 115f39e96e Merge pull request #1316 from bfirsh/add-example-for-tag
Add example for tag()
2016-11-28 13:14:02 -08:00
Joffrey F 4e08a5cb9e Merge pull request #1317 from bfirsh/fix-environment-variable-file-with-new-lines
Fix parsing for an environment file with newlines
2016-11-28 12:06:38 -08:00
Joffrey F 44e57fb95d Re-enable pid_mode checks for API < 1.24
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-28 12:01:25 -08:00
Aanand Prasad 8c27dd5233
Show a helpful warning when people try to call `client.containers()`
People upgrading to docker-py 2.0 without being aware of the new client
API will likely try to call the old `containers()` method. This adds a
helpful warning telling them to use APIClient to get the old API.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-28 19:43:49 +00:00
Stepan Stipl 7ef48c3769 Allow custom PID mode for the container
Docker added support for sharing PID namespaces with other containers
since version 1.12 (see https://github.com/docker/docker/pull/22481).

Signed-off-by: Stepan Stipl <stepan@stipl.net>
2016-11-28 11:42:00 -08:00
Jon Cotton 4a7c772daf
Fix parsing for an environment file with newlines
Fixes the new, purposely broken test added in the previous commit.

Signed-off-by: Jon Cotton <jc@finaltransfer.net>
2016-11-28 19:41:13 +00:00
Ben Firshman 29215a0ad9
Add example for tag()
Carrying #1120. Thanks @Faylixe!

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 19:38:29 +00:00
Joffrey F f051f7e90a Merge pull request #1314 from bfirsh/specify-encoding-for-readme
Specify encoding when loading readme
2016-11-28 11:33:43 -08:00
Michael Merickel dbd704e68d do not assume that read will consume the number of bytes requested
The issue is that ``os.read`` does not always read the expected number of
bytes, and thus we are moving to the next frame too early causing drift
in the byte stream. When the reading drifts, it starts reading garbage
as the next frame size. The some examples of frame sizes were
4032897957 bytes, etc. Values this large were causing the exceptions
from ``os.read``.

fixes #1211

Signed-off-by: Michael Merickel <michael@merickel.org>
2016-11-28 13:31:12 -06:00
Joffrey F f36c28926c Merge pull request #1305 from bfirsh/update-setup-py
Update setup.py and things
2016-11-28 11:29:42 -08:00
Ben Firshman 3518c9f631 Merge pull request #822 from docker/no_start_config
Remove support for host_config in Client.start
2016-11-28 19:05:09 +00:00
Joffrey F 5eacb986d7
Remove support for host_config in Client.start
Any additional arguments passed to start will raise a
DeprecatedMethod (DockerException) exception.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-28 18:34:09 +00:00
Ben Firshman 94083f25ac
Start to rename docker-py to docker-sdk-python
Pretty much everything except renaming the GitHub repo and
documentation, which is not actually done yet. Nearer the release
we can do a search/replace for all that stuff.

Ref #1310

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 16:45:59 +00:00
Ben Firshman fc9f7e2b2f
Bump version to 2.0.0-dev
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 15:11:01 +00:00
Ben Firshman 6d770a65d7
Use find_packages in setup.py
It was missing docker.models, and this will fix it forever more.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 15:11:01 +00:00
Ben Firshman 04e9437986
Update setup.py details
Move from "docker-py" package to "docker".

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 15:11:01 +00:00
Ben Firshman e04c4ad83f
Update readme to say "Docker Engine API"
It's not the Docker API.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 15:10:58 +00:00
Aanand Prasad 4c8c761bc1 Merge pull request #1307 from docker/bfirsh_maintainer
Add Ben to MAINTAINERS
2016-11-28 14:45:34 +00:00
Ben Firshman a658e14e8b
Specify encoding when loading readme
Loading readme fails when system locale is not utf-8.

Potentially replaces #1313

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-28 14:38:38 +00:00
Brandon Bodnar 9fc8b3a730 Add unit tests for should_check_directory.
Signed-off-by: Brandon Bodnar <bodnarbm@gmail.com>
2016-11-26 21:36:54 -05:00
Brandon Bodnar e2eb4a3158 Prevent traversing excluded directories with no possible dockerignore exceptions
Fixes an issue where all files in a rather large excluded folder are traversed and examined when creating the build context for potential exception to the exclusion, even though the exclusion rule is for a completely unrelated folder.

Signed-off-by: Brandon Bodnar <bodnarbm@gmail.com>
2016-11-26 21:17:18 -05:00
Ben Firshman b4c02393b2
Remove MAINTAINER from Dockerfiles
It was deprecated in https://github.com/docker/docker/pull/25466

(Sorry @shin- ;)

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-24 13:32:20 +00:00
Joffrey F 037ead974b Add Ben to MAINTAINERS
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-23 11:37:33 -08:00
Joffrey F c66c7f8b0a Merge pull request #1306 from bfirsh/mmmmmm-vector-graphics
Use SVG for build status badge
2016-11-23 11:30:20 -08:00
Joffrey F 30f3a0299e Merge pull request #1304 from bfirsh/fix-documentation-link
Fix documentation link in readme
2016-11-23 11:28:52 -08:00
Ben Firshman af67add683
Add warning about development version to readme
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-23 18:07:33 +00:00
Ben Firshman aafcf5a7fe
Change package in readme back to docker-py
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-23 18:02:23 +00:00
Ben Firshman afea2ca269
Use SVG for build status badge
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-23 15:21:56 +00:00
Ben Firshman c96848eb9c
Fix documentation link in readme
The rest of the readme is wrong until we release 2.0, but at
least the documentation points to the right place.

Closes #1302

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-23 14:47:46 +00:00
Joffrey F 8478491cf8 Merge pull request #1186 from bfirsh/two-point-oh
A new user-focused API
2016-11-22 16:41:52 -08:00
Joffrey F 0591477642 Merge pull request #1301 from biniambekele/master
Fix ContainerApiMixin.copy with dict container arg
2016-11-22 16:29:51 -08:00
biniambekele a38644fc0e Fix ContainerApiMixin.copy with dict container arg
Signed-off-by: biniambekele <biniambekele@users.noreply.github.com>
2016-11-22 15:17:45 -05:00
Ben Firshman b5f7d380d0
Add helpful error for APIClient methods on Client
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:05:43 +00:00
Ben Firshman c7a3aa7e44
Add new Sphinx documentation
Initial work thanks to @aanand.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:05:43 +00:00
Ben Firshman 1984f68730
Add new user-focused API
See #1086

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:05:43 +00:00
Ben Firshman f32c0c1709
Add docstrings to low-level API
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:04 +00:00
Ben Firshman ed959f2144
Move contributing docs to CONTRIBUTING.md
CONTRIBUTING.md is the place that GitHub expects it to be.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:04 +00:00
Ben Firshman d98a879016
Add random_name test helper
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:04 +00:00
Ben Firshman 6334312e47
Split out base integration test for APIClient
So the cleanup stuff can be reused for model tests.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:04 +00:00
Ben Firshman 39900c558c
Move APIClient tests into single file
For some reason this was spread across two files.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:04 +00:00
Ben Firshman e055a1c813
Rename DockerClientTest to BaseAPIClientTest
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:04 +00:00
Ben Firshman dac7174ff2
Make ping return bool instead of string
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman 9daa320454
Rename Client to APIClient
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman c7903f084e
Remove AutoVersionClient
Just do Client(version='auto').

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman d5bc7dc99a
Drop support for Python 2.6
Because it's ancient. If you're still using it, you can use an old
version of docker-py.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman b49cacced0
Make docker.utils.ports a single file
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman 19eefcf705
Make docker.ssladaptor a single file
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman 2c9d1110f0
Make docker.auth a single file
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:03 +00:00
Ben Firshman 81dfc475b3
Drop support for API versions <1.24
Implemented as just a warning. Actual removal of code will follow
sometime in the future.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-22 17:03:01 +00:00
Joffrey F 7c7688cba9 Merge pull request #1266 from bfirsh/add-rm-to-makefile-docker-run
Add --rm to docker run in Makefile
2016-11-21 11:30:02 -08:00
Ben Firshman 087a049b06
Add --rm to docker run in Makefile
So tests don't leave containers all over the place. The downside
is this makes it a bit harder to debug a test's filesystem -
you'll have to remove the "--rm" and run the test again.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-21 14:07:39 +00:00
Joffrey F f12b618ee9 Merge pull request #1236 from docker/host_config_isolation
Add support for isolation param in host config
2016-11-17 17:42:57 -08:00
Aanand Prasad 2ff7371ae7 Merge pull request #1294 from aanand/add-healthcheck
Add support for passing healthcheck to create_container
2016-11-16 16:12:05 +00:00
Aanand Prasad e4b6d0dca6 Convert dicts to Healthcheck objects, string commands to CMD-SHELL lists
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-16 16:04:17 +00:00
Aanand Prasad 6bb7844ab3 Rework healthcheck integration test
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-16 16:04:17 +00:00
Jamie Greeff b4f2b5fa70 Add support for passing healthcheck to create_container
Signed-off-by: Jamie Greeff <jamie@greeff.me>
2016-11-16 16:04:17 +00:00
Joffrey F f262dd6da9 Merge pull request #1281 from TomasTomecek/1265-ssl-test-no-sslX-support-in-openssl
ssl,test: OpenSSL may not support ssl2
2016-11-14 12:02:55 -08:00
Joffrey F 558ec261e4 Merge pull request #1296 from aanand/fix-flake8
Fix linting error
2016-11-14 11:58:11 -08:00
Aanand Prasad c66c2d6fa5 Fix linting error
This seems to have been ignored by older versions of flake8, and fixed
in version 3.1.0 or 3.1.1.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-14 18:20:13 +00:00
Tomas Tomecek 9a485b30ee ssl,test: OpenSSL may not support ssl2
Fixes #1265

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-11-14 09:05:26 +01:00
Joffrey F 2ca68f3d08 Merge pull request #1292 from liubin/master
Fix DriverConfig JSON key
2016-11-11 12:38:04 -08:00
Simon Li cb967ef682 Add test for creating service with env
Signed-off-by: Simon Li <orpheus+devel@gmail.com>
2016-11-11 16:29:43 +00:00
Simon Li 6fad0855b5 Use format_environment to convert env in ContainerSpec
Signed-off-by: Simon Li <orpheus+devel@gmail.com>
2016-11-11 16:11:18 +00:00
bin liu d6ffe9aa0d fix JSON key typo, it should not be underscores, but should be camelCase with first letter capital
Signed-off-by: bin liu <liubin0329@gmail.com>
2016-11-11 20:19:43 +08:00
Joffrey F e1518bf2a7 Merge pull request #1263 from rmb938/labelshm
Add labels and shmsize arguments to the image build
2016-11-09 10:54:59 -08:00
Ryan Belgrave 98e2e1fcd6
Add labels and shmsize arguments to the image build
Signed-off-by: Ryan Belgrave <Ryan.Belgrave@target.com>
2016-11-08 09:45:32 -06:00
Joffrey F bd10874bc9 Merge pull request #1290 from bfirsh/fix-broken-unit-test
Fix broken unit test
2016-11-07 13:52:10 -08:00
Ben Firshman 3c7c231983
Fix broken unit test
Introduced by https://github.com/docker/docker-py/pull/1230

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-11-07 12:20:20 -08:00
Joffrey F f745c8e7c5 Merge pull request #1230 from LabattFoodService/updateNode
enable setting of node labels #1225
2016-11-07 10:47:55 -08:00
Joffrey F ef76c8552c Merge pull request #1239 from docker/1212-fix_create_service
Fix several create_service arguments
2016-11-04 17:55:10 -07:00
Joffrey F 3ac73a285b Fix endpoint spec and networks params in update_service
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-04 15:10:12 -07:00
Joffrey F be2ae8df36 WIP
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-04 15:10:12 -07:00
Joffrey F 65d900eccb Merge pull request #1285 from docker/1284-settimeout-fix
Fix NpipeSocket.settimeout to match expected behavior
2016-11-02 16:35:25 -07:00
Joffrey F 422bc2beb2 Fix NpipeSocket.settimeout to match expected behavior
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-02 16:28:23 -07:00
Joffrey F 4119fa93bd Merge pull request #1283 from aboch/ip
Changes for current docker-py to pass in docker master
2016-11-02 11:44:22 -07:00
Alessandro Boch 54586053b1 Changes for service tests to pass in docker master
- update config structure has new members
- service name update is no longer supported

Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-11-01 16:56:37 -07:00
Aanand Prasad 8bf5be6455 Merge pull request #1274 from docker/npipe-socket-busy-retry
Implement retry logic when the npipe open procedure fails
2016-10-27 20:01:45 +01:00
Joffrey F 163a1ce371 Implement retry logic when the npipe open procedure fails
with ERROR_PIPE_BUSY

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-26 18:04:25 -07:00
Walker Lee a3981f891d
Add docker network IPAM options parameter
Signed-off-by: Walker Lee <walkerlee.tw@gmail.com>
2016-10-27 00:17:05 +08:00
Joffrey F c7dabbfa37 Merge pull request #1258 from docker/win32-test-fixes
Win32 test fixes
2016-10-14 17:10:59 -07:00
Joffrey F 9a10447b40 Merge pull request #1242 from YorikSar/master
Support requests versions from 2.11.1 onwards
2016-10-14 16:56:45 -07:00
Joffrey F 9b35c74f0e Fix dockerignore exclusion logic on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-14 16:02:28 -07:00
Joffrey F cec3fe7c31 Update tests to avoid failures on Windows platforms
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-14 16:02:28 -07:00
Joffrey F 9fc06b197b Merge pull request #1254 from docker/npipe-advanced
Several fixes to npipe support
2016-10-14 16:01:53 -07:00
Joffrey F 14634fb50a Merge pull request #1256 from docker/format_env_unicode_bug
Do not break when calling format_environment with unicode values
2016-10-13 12:39:47 -07:00
Joffrey F 3566e7c2f3 Merge pull request #1255 from docker/base_url_trailing_slash
Remove trailing slashes in result of utils.parse_host
2016-10-13 12:39:22 -07:00
Joffrey F 1ed2938030 Merge pull request #1257 from bfirsh/remove-dead-code
Remove dead code in import_image_from_data
2016-10-13 10:44:14 -07:00
Ben Firshman 6768477edf
Remove dead code in import_image_from_data
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-10-13 10:48:32 +02:00
Joffrey F 059f61bf5a Do not break when calling format_environment with unicode values
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-12 17:52:43 -07:00
Joffrey F 05f1060824 Remove trailing slashes in result of utils.parse_host
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-12 16:06:43 -07:00
Joffrey F c76ec15d9b Several fixes to npipe support
- Fix _get_raw_response_socket to always return the NpipeSocket object
- Override NpipeHTTPConnectionPool._get_conn to avoid crash in urllib3
- Fix NpipeSocket.recv_into for Python 2
- Do not call select() on NpipeSocket objects

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-12 13:23:27 -07:00
Joffrey F 6f7392ea09 Do not allow bufsize to be 0 in NpipeSocket.makefile()
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-11 15:16:43 -07:00
Joffrey F 008730c670 Merge pull request #1248 from docker/setup-py-fixes
Add missing long_description and maintainer fields to setup.py
2016-10-05 16:45:50 -07:00
Joffrey F f4cb91eb02 Add missing long_description and maintainer fields to setup.py
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-05 15:27:36 -07:00
Joffrey F 9957af9d57 Merge pull request #1243 from mattjegan/master
Fix syntax in README required by RST
2016-10-05 11:27:34 -07:00
Joffrey F dc8cf2b8e7 Merge pull request #1226 from TomasTomecek/remove-ipaddress-dep
document ipaddress dependency
2016-10-05 11:26:54 -07:00
Joffrey F 531fdc77e8 Merge branch 'api-docs-update' 2016-10-05 11:21:31 -07:00
Joffrey F b22e390e56 Merge branch 'TomasTomecek-improve-version-mismatcj' 2016-10-05 11:19:23 -07:00
Joffrey F f52203601b Merge branch 'TomasTomecek-improve-version-mismatcj' 2016-10-05 11:15:29 -07:00
Joffrey F 230d8c7efe Removed non-existent FAQ page from mkdocs.yml
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-05 11:15:09 -07:00
Tomas Tomecek 790d7525f0 document how to recover from api version mismatch
Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-10-05 09:33:32 +02:00
Tomas Tomecek aa2bd80ebb document requirement for ipaddress module
Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-10-05 09:32:33 +02:00
Joffrey F b65de73afe Update adapters to use pool_connections instead of num_pools
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-04 12:19:33 -07:00
Pierre Tardy 8239032463
fix for got an unexpected keyword argument 'num_pools'
requests's HTTPAdapter API is pool_connections for number of connection of the pool

Signed-off-by: Pierre Tardy <tardyp@gmail.com>
2016-10-04 13:13:31 +02:00
mattjegan daec55d4e1 Fix syntax in README required by RST
Before the readme is converted to rst it required an extra character to convert with no errors. Signed-off-by: Matthew Egan <matthewj.egan@hotmail.com>
2016-10-04 13:38:01 +11:00
Joffrey F 89a1ffa77b Merge pull request #1217 from bfirsh/reorganisation-base-tests
Move BaseTestCase to BaseIntegrationTest
2016-10-03 11:36:02 -07:00
Yuriy Taraday b00e321b58 Support requests versions from 2.11.1 onwards
Bug #1155 has been fixed starting with requests 2.11.1 and excluding it
from dependencies causes failures when using latest versions of both
libs together in our project.

Signed-off-by: Yuriy Taraday <yorik.sar@gmail.com>
2016-10-03 18:46:28 +03:00
Ben Firshman 69e992ec48
Move requires_api_version to helpers
Because it's a helper, not a base thing. In preparation for
moving/deleting the unit test base classes.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-10-03 11:58:08 +01:00
Ben Firshman 7339d77043
Move BaseTestCase to BaseIntegrationTest
Because two things called `BaseTestCase` is quite confusing.
I haven't bothered refactoring the other `BaseTestCase` because
that disappears anyway when we drop Python 2.6 support.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-10-03 11:58:08 +01:00
Ben Firshman 8cb186b623
Add timeout to from_env
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-10-03 11:58:08 +01:00
Joffrey F 49997d040b Add support for isolation param in host config
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-29 16:34:36 -07:00
Joffrey F 2b34e0b8e4 Merge pull request #1224 from mferon/addRestartPolicyUpdateSupport
Add support for restart policy update
2016-09-29 14:53:53 -07:00
Joffrey F ce52e091e1 Merge pull request #1232 from pacoxu/typo_paco
replace on_failure with on-failure
2016-09-29 11:36:42 -07:00
Joffrey F 81945c0901 Merge pull request #1234 from aboch/ip
Adjust test_create_network_with_ipam_config
2016-09-29 11:25:12 -07:00
Alessandro Boch a864059b83 Adjust test_create_network_with_ipam_config
- to account for API change: IPAM class will now
  also include a Data class, besides Config.

Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-09-29 09:49:58 -07:00
徐俊杰 65ad1545e8 replace on_failure with on-failure
Signed-off-by:  徐俊杰<roollingstone@gmail.com>
Signed-off-by: XuPaco <roollingstone@gmail.com>
2016-09-29 11:01:51 +08:00
Maxime Feron a665c8c443 Add support for restart policy update
Signed-off-by: Maxime Feron <maxime.feron@corp.ovh.com>
2016-09-28 10:21:59 +02:00
Joffrey F 52c2cc8453 Merge pull request #1228 from christianbundy/synthesize-execute-bit
Synthesize execute permission bit
2016-09-27 15:47:22 -07:00
Christian Bundy a718ab690e
Pass file object to Tarfile.addfile()
This resolves an issue where TarFile.gettarinfo() doesn't include the
file object, meaning that TarFile.addfile(TarFile.gettarinfo()) doesn't
pass the test suite. Instead, this uses an open() within a try...except
block to include a file object for each file without passing a file
object when the path is a directory.

Signed-off-by: Christian Bundy <christianbundy@fraction.io>
2016-09-27 21:39:30 +00:00
Nathan Shirlberg 6ef14932d0 enable setting of node labels #1225
Added update_node function to enable setting labels on nodes.  This
exposes the Update a Node function from the Docker API and should
enable promoting/demoting manager nodes inside a swarm.

Signed-off-by: Nathan Shirlberg <nshirlberg@labattfood.com>
2016-09-27 11:26:26 -05:00
Sebastian Schwarz cbd2ba52af Synthesize executable bit on Windows
The build context is tarred up on the client and then sent to the Docker
daemon.  However Windows permissions don't match the Unix ones.

Therefore we have to mark all files as executable when creating a build
context on Windows, like `docker build` already does:
https://github.com/docker/docker/issues/11047.

Signed-off-by: Sebastian Schwarz <seschwar@gmail.com>
2016-09-27 00:11:31 +00:00
Joffrey F 803ff5030e Merge branch 'release' 2016-09-19 18:00:27 -07:00
Joffrey F fc481c4cd1 Merge pull request #1220 from docker/1.10.3-release
1.10.3 release
2016-09-16 12:09:14 -07:00
Joffrey F 64fba723dd Number of pools in adapter is configurable
Default increased from 10 to 25

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-16 11:55:08 -07:00
Joffrey F 06b6a62faa Add support for identity tokens in config file.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-16 11:54:50 -07:00
Joffrey F e4cf97bc7b Bump version
Update Changelog

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-16 11:54:06 -07:00
Joffrey F 1e939be5fb Merge pull request #1210 from docker/identity-token-support
Add support for identity tokens in config file
2016-09-16 11:47:48 -07:00
Joffrey F d731a4315c Add support for identity tokens in config file.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-15 14:28:09 -07:00
Joffrey F 9141e9496d Merge pull request #1215 from bfirsh/autopep8
Fix a few pep8 issues
2016-09-14 14:08:13 -07:00
Joffrey F 48b7835a92 Merge pull request #1216 from bfirsh/makefile-improvements
Makefile improvements
2016-09-14 14:06:52 -07:00
Joffrey F 230bc18bfd Merge pull request #1208 from docker/1207-configurable-num-pools
Number of pools in adapter is configurable
2016-09-14 11:10:25 -07:00
Joffrey F 89afee94fd Merge pull request #1213 from bfirsh/parse-json-errors
Parse JSON API errors
2016-09-14 11:09:55 -07:00
Joffrey F ad350b95b1 Merge pull request #1214 from bfirsh/ignore-not-in-swarm-error-when-leaving
Ignore not in swarm error when force leaving
2016-09-14 11:08:49 -07:00
Ben Firshman 71b0b7761a
Add make shell to open a Python shell
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-14 17:15:10 +01:00
Ben Firshman 1a57f8800e
Add file arg to integration tests
make integration-test file=models_services_test.py

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-14 17:14:58 +01:00
Ben Firshman 6220636536
Fix a few pep8 issues
autopep8 --in-place --recursive --experimental -aaa --ignore E309 .

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-14 16:54:54 +01:00
Ben Firshman ca51ad29a5
Ignore not in swarm error when force leaving
Real errors were getting swallowed in these tests, producing
other confusing cascading errors. This makes it much easier to
make sure a node is not in a Swarm, while also handling other
errors correctly.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-14 16:00:03 +01:00
Ben Firshman dcd01f0f48
Parse JSON API errors
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-14 14:54:40 +01:00
Joffrey F be7d0f0184 Number of pools in adapter is configurable
Default increased from 10 to 25

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-12 17:43:50 -07:00
Joffrey F e833881577 Merge pull request #1202 from docker/1.10.2-release
1.10.2 release
2016-09-11 19:11:18 -07:00
Joffrey F 2ad403c78b Bump docker-pycreds dependency ; bump patch number
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-11 19:01:39 -07:00
Joffrey F c2b4c8e2e2 Merge pull request #1198 from docker/1.10.1-release
1.10.1 release
2016-09-09 17:08:26 -07:00
Joffrey F 8abb8eecfc Re-add docker.utils.types module for backwards compatibility
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-09 16:56:19 -07:00
Joffrey F e676840945 Merge pull request #1197 from docker/1196-docker.utils.types
Re-add docker.utils.types module for backwards compatibility
2016-09-09 16:55:49 -07:00
Joffrey F 7167189486 Bump version + Update Changelog
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-09 16:55:10 -07:00
Joffrey F a6fb7a2064 Re-add docker.utils.types module for backwards compatibility
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-09 16:50:03 -07:00
Joffrey F 72e7afe17a dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-09 16:43:54 -07:00
Joffrey F e045331e32 Merge pull request #1190 from docker/1.10.0-release
1.10.0 release
2016-09-09 14:08:18 -07:00
Joffrey F 3eb93f6662 Bump version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-08 12:00:25 -07:00
Joffrey F 15ac73a22d Merge pull request #1087 from docker/1076-dns-fix
Remove default adapters when connecting through a unix socket.
2016-09-08 11:59:37 -07:00
Joffrey F e6601e2e55 Remove default adapters when connecting through a unix socket.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-08 11:20:48 -07:00
Joffrey F df50df38f9 Merge pull request #1191 from bfirsh/fix-makefile-phony
Add .PHONY for each makefile instruction
2016-09-08 10:12:13 -07:00
Ben Firshman 0648923596
Add .PHONY for each makefile instruction
Makes it much easier to keep this maintained properly. See also:

http://clarkgrubb.com/makefile-style-guide#phony-targets

Replaces #1164

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-08 15:42:44 +01:00
Joffrey F 717ec945db Merge pull request #1189 from docker/1188-npipesocket-makefile
Handle bufsize < 0 in makefile() as a substitute for default
2016-09-07 18:06:24 -07:00
Joffrey F 0430d00f2f Handle bufsize < 0 in makefile() as a substitute for default
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-07 17:49:07 -07:00
Joffrey F a44d65be37 Merge pull request #1187 from bfirsh/fix-broken-mac-address-unit-test
Fix unit test which doesn't do anything
2016-09-07 11:29:48 -07:00
Ben Firshman 0cdf737625
Fix unit test which doesn't do anything
It also overrode the fake API inspect endpoint with a broken
response.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-07 11:40:19 +02:00
Joffrey F 08da5bfdfc Merge pull request #1092 from docker/1064-import-changes
Add support for changes in import_image*
2016-09-06 16:00:00 -07:00
Joffrey F 75497e0752 Add test for import_image with changes param
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-06 15:38:44 -07:00
Joffrey F 65fb5be4cd Add support for changes param in import_image* methods
Reduce code duplication in import_image* methods

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-06 15:38:44 -07:00
Joffrey F fab4a06c8a Merge pull request #1181 from docker/credstore-support
Add credentials store support
2016-09-06 15:37:57 -07:00
Joffrey F 219a8699f9 Better credentials store error handling in resolve_authconfig
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-06 15:17:36 -07:00
Joffrey F fbe1686e62 Add credentials store support
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-06 15:17:36 -07:00
Joffrey F 545c5ac3cc Merge pull request #1184 from bfirsh/fix-licenses
Fix licenses
2016-09-06 10:30:33 -07:00
Joffrey F d9e868ab74 Merge pull request #1185 from bfirsh/make-docs
Add make docs command for building docs
2016-09-06 10:27:35 -07:00
Ben Firshman 291470146f
Add make docs command for building docs
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-05 19:23:04 +02:00
Ben Firshman 3769c089e8
Fix licenses
* Complete main LICENSE
* Remove unnecessary licenses from individual files

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-09-05 17:48:09 +02:00
Joffrey F fff71e9dbf Merge pull request #1180 from kanaka/patch-1
Fix Mount bind type sanity check
2016-09-02 13:43:28 -07:00
Joel Martin 9799c2d69b Fix Mount bind type sanity check
any() expects a single collection argument, not a list of arguments.

Signed-off-by: Joel Martin <github@martintribe.org>
2016-09-02 15:32:52 -05:00
Joffrey F 235964607d Merge pull request #1178 from docker/1105-network-api
Network labels, EnableIPv6 flag, force disconnect
2016-09-01 12:17:28 -07:00
Joffrey F 6552076856 Add support for force disconnect
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-31 18:44:36 -07:00
Joffrey F a665dfb375 Add support for labels and enable_ipv6 in create_network
Tests + docs

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-31 18:26:16 -07:00
Joffrey F 24bfb99e05 Merge pull request #1167 from docker/1075-from-env-version
Support version parameter in `Client.from_env`
2016-08-25 14:59:46 -07:00
Joffrey F 764d7b38c4 Support version parameter in `Client.from_env`
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-25 14:44:13 -07:00
Joffrey F 2ef02df2f0 Merge pull request #1168 from docker/aiden0z-master
Support pids_limit in HostConfig
2016-08-25 14:38:22 -07:00
Joffrey F 3419145701 Merge pull request #1172 from fermayo/fix-utf8-envvars
Fix creating containers with env vars with unicode characters
2016-08-25 12:41:20 -07:00
fermayo 5bedd32a69 Fix creating containers with env vars with unicode characters
Signed-off-by: Fernando Mayo <fernando@docker.com>
2016-08-25 13:36:02 +02:00
Joffrey F 902c7a76cc Docs and tests for pids_limit.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-23 17:05:08 -07:00
Joffrey F bf2235bc12 Merge branch 'master' of https://github.com/aiden0z/docker-py into aiden0z-master 2016-08-23 17:02:40 -07:00
Joffrey F fb41965272 Merge pull request #1082 from masci/fix_stream_helper
Invoke self._result passing `json=True` when `decode=True`
2016-08-23 15:34:35 -07:00
Joffrey F d33e069552 Merge branch 'DaoCloud-feature/memory_support' 2016-08-23 15:32:50 -07:00
Kay Yan fc72ac66e9 support MemoryReservation and KernelMemory
Signed-off-by: Kay Yan <kay.yan@daocloud.io>
2016-08-23 15:32:06 -07:00
Joffrey F 7b7e07e63b Merge branch 'srikalyan-master' 2016-08-23 15:16:29 -07:00
Joffrey F 797f1edc20 Merge branch 'master' of https://github.com/srikalyan/docker-py into srikalyan-master 2016-08-23 15:16:15 -07:00
Joffrey F 3709c709f3 Merge branch 'joshpurvis-jp-cpushares' 2016-08-23 15:12:48 -07:00
Joffrey F 0e4314a872 Merge branch 'jp-cpushares' of https://github.com/joshpurvis/docker-py into joshpurvis-jp-cpushares 2016-08-23 15:12:30 -07:00
Joffrey F abd461150a Merge pull request #1081 from tescalada/master
1059-Fixing a bug with multiple json objects
2016-08-23 15:10:56 -07:00
Joffrey F 0acdd19665 Merge pull request #1131 from Knetic/dnsopts
Implemented dns_opt support (from api 1.21)
2016-08-23 15:04:25 -07:00
Joffrey F c5a81002c6 Merge pull request #1127 from docker/1085-service-support
Service support implementation
2016-08-23 14:58:43 -07:00
Joffrey F 775b581c04 Private images support in create_service / update_service
Refactor auth header computation

Add tasks methods and documentation.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-23 14:52:07 -07:00
Joffrey F 7d5a1eeb7a Add services documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-22 17:45:10 -07:00
Joffrey F f53cdc3a07 Rename LogDriver to DriverConfig for genericity
The class can be used for both log driver and volume driver specs. Use
a name that reflects this.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-22 16:11:48 -07:00
Joffrey F 1e2c58de9e Add new pages to mkdocs index
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-19 17:02:33 -07:00
Joffrey F 8e97cb7857 Services API documentation (WIP)
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-19 16:51:39 -07:00
Joffrey F 97094e4ea3 New docker.types subpackage containing advanced config dictionary types
Tests and docs updated to match
docker.utils.types has been moved to docker.types

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-19 16:51:13 -07:00
Joffrey F 02e99e4967 Service API integration tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-17 18:42:52 -07:00
Joffrey F 172e95d52f Swarm service API implementation
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-17 12:21:34 -07:00
Brian Goff 0f47db7fcc Remove references to "ExecutionDriver"
Docker no longer has an `ExecutionDriver` as of Docker 1.11.
The field in the `docker info` API will not be present in 1.13.

Found this while working on docker/docker#25721

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-08-17 12:20:13 -07:00
Tomas Tomecek 3062ae4348 docker client consistency: don't quote ':/'
E.g.

docker client

`/v1.21/images/localhost:5000/busybox/push?tag=`

docker-py

`/v1.21/images/localhost%3A5000%2Fbusybox/push`

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-08-17 12:20:13 -07:00
Joffrey F 95d9306d2a Exclude requests 2.11 from setup.py to work around unicode bug
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-17 12:20:13 -07:00
Joffrey F e2655f6584 Merge pull request #1162 from cpuguy83/remove_execdriver_refs
Remove references to "ExecutionDriver"
2016-08-16 11:29:50 -07:00
Brian Goff 0416338bae Remove references to "ExecutionDriver"
Docker no longer has an `ExecutionDriver` as of Docker 1.11.
The field in the `docker info` API will not be present in 1.13.

Found this while working on docker/docker#25721

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-08-16 13:36:42 -04:00
Josh Purvis 7d147c8ca1 Move cpu_shares and cpuset_cpu to HostConfig when API >= 1.18
Signed-off-by: Josh Purvis <joshua.purvis@gmail.com>
2016-08-15 16:33:58 -04:00
Joffrey F a75553b3ca Add `nodes` and `inspect_node` methods
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-11 17:47:02 -07:00
Daniel Nephin 7de30c3a9b Merge pull request #1142 from TomasTomecek/dont-url-encode-repository-name
docker client consistency: don't quote ':/'
2016-08-10 14:52:07 -04:00
Tomas Tomecek 08b284ab39 docker client consistency: don't quote ':/'
E.g.

docker client

`/v1.21/images/localhost:5000/busybox/push?tag=`

docker-py

`/v1.21/images/localhost%3A5000%2Fbusybox/push`

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-08-10 09:30:19 +02:00
Joffrey F 876e7b49da Merge pull request #1156 from docker/1155-requests-bug
Exclude requests 2.11 from setup.py to work around unicode bug
2016-08-09 13:34:53 -07:00
Joffrey F a28a0d2355 Exclude requests 2.11 from setup.py to work around unicode bug
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-09 13:20:17 -07:00
George Lester 93b4b4134e Implemented dns_opt support (from api 1.21)
Signed-off-by: George Lester <glester491@gmail.com>
2016-08-07 14:23:22 -07:00
Joffrey F e1774c4c5b Reference swarm methods in api.md file.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-04 17:05:25 -07:00
Joffrey F 0f70b6a38b Add support for custom name in SwarmSpec
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-04 16:48:21 -07:00
Joffrey F fdfe582b76 Update Swarm API docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-04 15:12:43 -07:00
Joffrey F 25db440c96 Update arguments for several Swarm API methods
Add Client.update_swarm method
Add test for Client.update_swarm

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-04 15:11:13 -07:00
Joffrey F df31f9a8ce Update Swarm documentation
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-03 18:00:52 -07:00
Joffrey F 1f055796a8 Add new init_swarm test with custom spec
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-03 18:00:29 -07:00
Joffrey F 07563cfe3f Update swarm methods to include newly added parameters
Rename swarm methods to be more explicit
Utility methods / types to create swarm spec objects

Integration tests

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-03 16:58:26 -07:00
minzhang 9fdc8d476d Added support for docker swarm api version 1.24.
3 API are added
swarm_init()
swarm_leave()
swarm_join()

Signed-off-by: Min Zhang <virgilerin@gmail.com>

Signed-off-by: Min Zhang <virgilerin@gmail.com>
2016-08-03 16:57:44 -07:00
minzhang 44868fa0fa Added support for docker swarm api version 1.24.
3 API are added
swarm_init()
swarm_leave()
swarm_join()

Signed-off-by: Min Zhang<minzhang.work@gmail.com>

Signed-off-by: Min Zhang <virgilerin@gmail.com>
2016-08-03 16:57:44 -07:00
Joffrey F 20b29d048e Merge pull request #1151 from docker/test_fixes_1.12
Test fixes and updated Makefile for 1.12 testing
2016-08-03 16:57:21 -07:00
Joffrey F 9d48b4f603 Test fixes and updated Makefile for 1.12 testing
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-03 16:48:41 -07:00
Daniel Nephin 67098f38df Merge pull request #1150 from docker/1148-update-headers-fix
Avoid crashing in update_headers decorator when headers kwarg is None
2016-08-02 22:05:27 -04:00
Joffrey F ae7cb4b99f Avoid crashing in update_headers decorator when headers kwarg is None
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-02 17:25:50 -07:00
Joffrey F 650cc70e93 Merge pull request #1145 from jtakkala/1144-sysctl-support
Add support for sysctl when creating container
2016-08-01 17:32:18 -07:00
Jari Takkala dec29e1c10 Add support for sysctl when creating container
Closes #1144

Signed-off-by: Jari Takkala <jtakkala@gmail.com>
2016-08-01 23:43:52 +01:00
Joffrey F f99dc45d82 Merge pull request #1146 from aanand/config-path-debug
More explicit debug for config path logic
2016-08-01 10:59:32 -07:00
Tristan Escalada f8b843b127 1059-Fixing a bug with multiple json objects
This splits the text by CRLF and then json.loads each part
independently instead of attempting the parse the whole string.

Signed-off-by: Tristan Escalada <tristan@escalada.us>
2016-08-01 11:05:32 -04:00
Aanand Prasad f006da6a43 More explicit debug for config path logic
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-08-01 14:52:39 +01:00
Joffrey F 8a6b1843c3 Merge pull request #1143 from docker/1135-ipv6-docker-host
Add support for IPv6 docker host connections.
2016-07-28 12:51:44 -07:00
Joffrey F 723d144db5 Add support for IPv6 docker host connections.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-27 18:42:14 -07:00
Joffrey F 2d3bda84de dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-26 15:48:29 -07:00
Joffrey F a4a27d80f0 Merge branch 'release' 2016-07-26 15:46:51 -07:00
Joffrey F e7198ad94e Merge pull request #1137 from aanand/default-to-npipe-on-windows
Default to npipe address on Windows
2016-07-26 15:45:09 -07:00
Joffrey F dc164c71be Merge pull request #1140 from docker/1.9.0-release
Bump to 1.9.0
2016-07-26 12:21:12 -07:00
Joffrey F 5b1e556474 Bump to 1.9.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-26 12:11:32 -07:00
Ben Firshman ae86949188 Set custom user agent on client
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-07-26 11:57:21 -07:00
Aanand Prasad 0e68b0a429 Default to npipe address on Windows
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-26 11:39:09 +01:00
Aanand Prasad 106c08faba Merge pull request #1139 from docker/compose-3757-linklocal-fix
Send LinkLocalIPs as part of IPAMConfig dictionary
2016-07-26 11:07:48 +01:00
Joffrey F cea7376086 Send LinkLocalIPs as part of IPAMConfig dictionary
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-25 15:04:04 -07:00
Aanand Prasad 30644d8ae0 Merge pull request #1133 from kmala/master
Add optional auth config to docker push
2016-07-22 19:43:42 +01:00
Keerthan Reddy Mala 1294d3c410
Add unit tests
Signed-off-by: Keerthan Reddy Mala <kmala@deis.com>
2016-07-22 10:04:32 -06:00
Keerthan Reddy Mala 9b63bed6a0
Add optional auth config to docker push
Signed-off-by: Keerthan Reddy Mala <kmala@deis.com>
2016-07-22 10:04:31 -06:00
Aanand Prasad 01cb969215 Merge pull request #1125 from bfirsh/user-agent
Set custom user agent on client
2016-07-22 14:55:19 +01:00
Ben Firshman bd73225e14
Set custom user agent on client
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-07-20 15:04:54 -07:00
Aanand Prasad e15ba7400a Merge pull request #1130 from aanand/support-tcp-upgrade
Support for TCP upgrade
2016-07-18 17:03:20 +01:00
Aanand Prasad 267021e453 Rename read methods for clarity
read_socket() is now just read(), because its behaviour is consistent
with `os.read` et al.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 18:58:57 -04:00
Aanand Prasad 69832627f8 Rename read_iter() to frames_iter()
This makes it more clearly high-level and distinct from the raw
data-reading functions

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:41:59 -04:00
Aanand Prasad 9fb2caecb9 Rename next_packet_size to next_frame_size
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad 456bfa1c1d Reorder socket.py methods
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad 472a7ffce8 Remove unused imports
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad ce2b60ecf6 Document all socket utility methods
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad 3e2f4a6142 Refactors
- `read_data()` raises an exception instead of asserting `False`
- `next_packet_size()` uses `read_data()`
- Renamed `packet_size` arg to `n` for consistency

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad 43158cfe3f Move read_loop() into docker.utils.socket.read_iter()
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad b100666a3c Remove duplicated methods from container.py
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Aanand Prasad 73f06e3335 Move socket-reading test helpers into docker.utils.socket
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-13 17:08:17 -04:00
Joffrey F e64ba8f2b9 Mock read_from_socket method
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-13 17:08:17 -04:00
Joffrey F 76ed9c37cd Read from socket after sending TCP upgrade headers.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-13 17:08:17 -04:00
David Gageot 5464cf2bea Add hijack hints for non-detached exec api calls
Signed-off-by: David Gageot <david@gageot.net>
2016-07-13 17:08:17 -04:00
David Gageot 6dec639a1a Add hijack hints for attach api calls
Signed-off-by: David Gageot <david@gageot.net>
2016-07-13 17:08:16 -04:00
Daniel Nephin b511352bea Merge pull request #1115 from TomasTomecek/create-volume-support-labels
volumes,create: support adding labels
2016-07-13 13:44:37 -04:00
Tomas Tomecek 8f8a3d0ed2 volumes,create: support adding labels
Fixes #1102

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-07-13 08:41:45 +02:00
Aanand Prasad 1f34b4896a Merge pull request #1119 from Mobelux/fix-build-with-auth
Pass X-Registry-Auth when building an image
2016-07-12 16:38:06 -04:00
Justin Michalicek e8ea79dfdb Change double underscore in test case names for _set_auth_headers
* Change test__set_auth_headers_* methods to test_set_auth_headers_*

Signed-off-by: Justin Michalicek <jmichalicek@gmail.com>
2016-07-12 10:06:34 -04:00
Justin Michalicek f7807bdb52 Update build unit tests
* Test that the request from build when the client has
  auth configs contains the correct X-Registry-Config header
* Test that BuildApiMixin._set_auth_headers() updates the passed
  in headers dict with auth data from the client
* Test that BuildApiMixin._set_auth_headers() leaves headers dict intact
  when there is no _auth_config on the client.

Signed-off-by: Justin Michalicek <jmichalicek@gmail.com>
2016-07-12 10:06:34 -04:00
Justin Michalicek 66e7af9353 Pass X-Registry-Auth when building an image
* Initialize headers variable in BuildApiMixin.build() as a dict rather
  than as None.  This way the correct object gets passed to
  _set_auth_headers() even if no headers were set in build()

* Changing object from None to {} in BuildApiMixin._set_auth_headers()
  removed because it changes the object reference, so has no effect on
  calling code.

Signed-off-by: Justin Michalicek <jmichalicek@gmail.com>
2016-07-12 10:06:34 -04:00
Joffrey F 5e47026a9b Merge pull request #1122 from Faylixe/patch-3
Update api.md
2016-07-08 13:11:35 -07:00
Faylixe c8c6f0073e Removed superfluous sentence
Signed-off-by: Faylixe <felix.voituret@gmail.com>
Signed-off-by: Félix Voituret <felix.voituret@gmail.com>
2016-07-08 21:46:02 +02:00
Faylixe 6d347cd894 Update api.md
Added ``buildargs`` parameter to ``build`` documentation

Signed-off-by: Faylixe <felix.voituret@gmail.com>
2016-07-08 10:44:49 +02:00
Srikalyan Swayampakula b5d3556bce Added support for user namespace.
Signed-off-by: Srikalyan Swayampakula <srikalyansswayam@gmail.com>
2016-06-30 15:25:17 -07:00
Joffrey F 0f15c6599d Bump to 1.9.0-rc2
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 14:54:37 -07:00
Joffrey F e8ef5e513b Merge pull request #1111 from docker/1.9.0-release
Cherry-pick signal fix into 1.9.0 release branch
2016-06-28 14:53:06 -07:00
Joffrey F 0d8624b49b Add integration tests for different types of kill signals
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 13:29:37 -07:00
Joffrey F 4ed90bc8b8 Fix network aliases test with Engine 1.12
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 13:29:37 -07:00
Joffrey F 900703ef2f signal in Client.kill can be a string containing the signal's name
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 13:29:37 -07:00
Aanand Prasad 94f8dd31be Merge pull request #1109 from docker/signal-str
signal in Client.kill can be a string containing the signal's name
2016-06-28 13:03:38 -07:00
Joffrey F d96d848bb4 Add integration tests for different types of kill signals
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 12:03:44 -07:00
Joffrey F 1132368be1 Fix network aliases test with Engine 1.12
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 11:05:01 -07:00
Joffrey F 5480493662 signal in Client.kill can be a string containing the signal's name
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 11:03:52 -07:00
Joffrey F 986a14a152 Merge pull request #1108 from docker/1107-link-local-ips
Add support for link-local IPs in endpoint config
2016-06-27 12:30:14 -07:00
Joffrey F 0de366da3d Add support for link-local IPs in endpoint config
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-24 15:17:58 -07:00
Aiden Luo 7d9bb6d209 fix #1094, support PidsLimit in host config
Signed-off-by: Aiden Luo <aiden0xz@gmail.com>
2016-06-17 11:20:39 +08:00
Joffrey F 9010d59450 Merge pull request #1096 from docker/1.9.0-release
Release (candidate) 1.9.0
2016-06-16 12:53:45 -07:00
Joffrey F a2160145cf 1.9.0 RC1
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-16 12:46:46 -07:00
Joffrey F 538a1db9dd Merge pull request #1066 from yunzhu-li/blkio-control
Add support for Block IO constraints in HostConfig
2016-06-15 14:26:49 -07:00
Joffrey F 787f3f5a16 Merge pull request #1079 from docker/1024-npipe-support
npipe support
2016-06-14 12:05:35 -07:00
Joffrey F 080b4711f2 Merge pull request #1083 from docker/1042-ip-networking-config
Support ipv4_address and ipv6_address in create_endpoint_config
2016-06-13 18:02:58 -07:00
Joffrey F f4de376341 Merge pull request #1090 from docker/1080-inspect-image-docs
Fix param name for inspect_image in API docs
2016-06-13 18:02:06 -07:00
Joffrey F d991db5b45 Expand on the 1-network limit in create_container
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-13 17:58:10 -07:00
Joffrey F fc4bfde0d6 Unify endpoint config creation when using connect_container_to_network
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-13 17:58:10 -07:00
Joffrey F b6fa986293 Add ipv[46]_address params to create_endpoint_config.
Update networks documentation with exhaustive API docs

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-13 17:58:10 -07:00
Joffrey F b050544237 Fix param name for inspect_image in API docs
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-09 13:01:29 -07:00
Joffrey F a8746f7a99 Remove obsolete, commented out code
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-08 17:02:33 -07:00
Joffrey F 299ffadb95 Merge pull request #1084 from adamchainz/readthedocs.io
Convert readthedocs links for their .org -> .io migration for hosted projects
2016-06-08 10:17:58 -07:00
Adam Chainz 7f255cd295 Convert readthedocs links for their .org -> .io migration for hosted projects
As per [their blog post of the 27th April](https://blog.readthedocs.com/securing-subdomains/) ‘Securing subdomains’:

> Starting today, Read the Docs will start hosting projects from subdomains on the domain readthedocs.io, instead of on readthedocs.org. This change addresses some security concerns around site cookies while hosting user generated data on the same domain as our dashboard.

Test Plan: Manually visited all the links I’ve modified.

Signed-off-by: Adam Chainz <adam@adamj.eu>
2016-06-08 03:48:04 +01:00
Massimiliano Pippi 86d1b8fb83 invoke self._result with json=True if decode=True
Signed-off-by: Massimiliano Pippi <massi@datadoghq.com>
2016-06-07 10:32:02 -04:00
yunzhu-li 896d36ea1d
Add support for Block IO constraints in HostConfig
This adds support for Block IO constraint options:
    - blkio-weight
    - blkio-weight-device
    - device-read-bps
    - device-write-bps
    - device-read-iops
    - device-write-iops

Signed-off-by: yunzhu-li <contact@yunzhu.li>
2016-06-05 23:30:44 -04:00
Joffrey F 0176fa171f Update parse_host and tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-02 18:21:29 -07:00
Joffrey F d922713923 Reorganize docker.transport package
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-02 17:59:50 -07:00
Joffrey F b5d9312f9a npipe support cleanup
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-02 17:59:50 -07:00
Joffrey F 4a8832ca8b pypiwin32 added to requirements
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-02 17:59:50 -07:00
Joffrey F a34e0cbfaa Experimental npipe:// support
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-02 17:59:50 -07:00
Daniel Nephin 88811a2659 Merge pull request #1071 from graingert/support-py35
support Python 3.5
2016-05-25 14:56:06 -04:00
Thomas Grainger 98093544a7
support new Py3.5 Enum signals
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2016-05-19 18:19:33 +01:00
Thomas Grainger 7e24304934
update docs to py3.5
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2016-05-19 18:04:46 +01:00
Thomas Grainger e0b9cb2a8c
support Python 3.5
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2016-05-19 17:59:34 +01:00
Joffrey F 26f2b696ab Merge pull request #1068 from jgiannuzzi/internal_networks
Add support for creating internal networks
2016-05-18 13:39:28 -07:00
Jonathan Giannuzzi 98b41fee3c Add support for creating internal networks
Signed-off-by: Jonathan Giannuzzi <jonathan@giannuzzi.be>
2016-05-18 16:25:43 +02:00
Joffrey F 966dfac3b5 Merge pull request #1065 from aanand/fix-dockerignore-path-traversal
Resolve path traversal in .dockerignore patterns
2016-05-16 14:09:50 -07:00
Aanand Prasad 5ebf4b8ec7 Resolve path traversal in .dockerignore patterns
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-05-16 15:55:06 +01:00
Joffrey F 8b416796d5 Merge pull request #1057 from kevinfrommelt/socket-timeout
Don't set socket timeout if it's already disabled when streaming
2016-05-10 15:01:50 -07:00
Kevin Frommelt 2826dd51e7 Don't set socket timeout if it's already disabled when streaming
Signed-off-by: Kevin Frommelt <kevin.frommelt@gmail.com>
2016-05-10 10:23:14 -05:00
Joffrey F b98e240958 Merge pull request #1051 from docker/1.8.1-release
1.8.1 release
2016-04-29 15:20:19 -07:00
Joffrey F d6e70e2c40 Update ChangeLog and version.py (1.8.1)
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-28 17:15:20 -07:00
Joffrey F 5df7b317e4 Merge pull request #1050 from docker/1044-fix-login-default
Let server-side determine which serveraddress to use when unspecified
2016-04-28 17:07:11 -07:00
Joffrey F 50a6a47186 Let server-side determine which serveraddress to use when none is specified
in login()

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-28 16:53:01 -07:00
Joffrey F 3c02fc4cc7 Merge pull request #1004 from klj613/allow-equals-character-in-env-file
makes it possible to have '=' in the env file
2016-04-27 16:27:28 -07:00
Joffrey F 237f5318f2 Removed obsolete env var in integration-dind target command
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-26 14:32:49 -07:00
Joffrey F 02803afac4 Add -dev suffix to version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-22 15:01:58 -07:00
Joffrey F 4d0a3d9cc5 Merge pull request #1039 from docker/felixonmars-backports
Use backports.ssl_match_hostname
2016-04-21 13:52:38 -07:00
Joffrey F d80e75f5ea Merge pull request #1017 from SakuraSound/container-docs
Added extra filtering options to containers command in ClientAPI
2016-04-20 10:25:56 -07:00
Joir-dan Gumbs 1c8ce07785 Added link to docker ps documentation
Signed-off-by: Joir-dan Gumbs <jdagumbs@gmail.com>
2016-04-19 23:19:55 -07:00
Joffrey F c76a914e01 Only install ipaddress if python version < 3.3
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-19 17:15:51 -07:00
Joir-dan Gumbs 923536a168 rebased documentation changes against master fork
Signed-off-by: Joir-dan Gumbs <jdagumbs@gmail.com>
2016-04-18 21:39:55 -07:00
Felix Yan cba2e973ec Require ipaddress on Python < 3.5
Signed-off-by: Felix Yan <felixonmars@archlinux.org>
2016-04-08 00:36:54 +08:00
Felix Yan 9da5493135 Use backports.ssl_match_hostname
The py2-ipaddress module unfortunately conflicts with the pypi:ipaddress module, which is in the dependency tree of widely used pyOpenSSL. I think it would be a good idea to use a well maintained backport of the Python 3.5 implementation of match_hostname() instead of duplicating the effort and maintain another.

All tests are passing here.

Signed-off-by: Felix Yan <felixonmars@archlinux.org>
2016-04-08 00:36:46 +08:00
Joffrey F fdd118706a Merge pull request #1025 from docker/1.8.0-release
1.8.0 release
2016-04-06 13:20:42 -07:00
Joffrey F 267bd34426 Bump version to 1.8.0
Add RC bugfixes to the changelog.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-05 16:21:16 -07:00
Joffrey F f68a4f957d Merge pull request #1022 from docker/1021-empty-auth
Don't raise InvalidConfigError when auth dict doesn't have an 'auth' key
2016-04-05 15:00:32 -07:00
Joffrey F 541edd7ffb Don't raise InvalidConfigError when auth dict doesn't have an 'auth' key
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-05 14:05:33 -07:00
Joffrey F e743254b42 Merge pull request #1020 from mschnitzer/fix_little_error
Remove not needed dot in README.md
2016-04-05 10:48:37 -07:00
Manuel Schnitzer 1112e1e314 Remove not needed dot in README.md
Signed-off-by: Manuel Schnitzer <mschnitzer@suse.de>
2016-04-05 12:44:11 +02:00
Joffrey F 035e9e1c91 Bump RC
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-31 17:48:56 -07:00
Joffrey F 77625150bc Merge pull request #1018 from aanand/fix-py2-ipaddress-dependency
Fix py2-ipaddress dependency
2016-03-31 17:47:55 -07:00
Aanand Prasad 26cd4d6f2e Fix py2-ipaddress dependency
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-31 18:22:18 +01:00
Joffrey F 14423d2b54 Bump RC
Signed-off-by: Joffrey F <joffrey@docker.com>
Signed-off-by: Joir-dan Gumbs <jgumbs@us.ibm.com>
2016-03-30 22:25:45 -07:00
Joir-dan Gumbs d6b42c480e Added extra filtering options to containers command in ClientAPI
Signed-off-by: Joir-dan Gumbs <jdagumbs@gmail.com>
Signed-off-by: Joir-dan Gumbs <jgumbs@us.ibm.com>
2016-03-30 22:25:20 -07:00
Joffrey F b19321da9c Bump RC
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-30 17:18:04 -07:00
Joffrey F 3162c7835c Merge pull request #1015 from aanand/fix-port-binding-doc
Improve port binding docs
2016-03-30 11:39:33 -07:00
Joffrey F 88b5ed781c Merge branch 'master' of github.com:docker/docker-py 2016-03-30 11:37:52 -07:00
Joffrey F 241793b101 Use pip environment markers for conditional dependencies
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-30 11:37:17 -07:00
Joffrey F 079ed9f786 Bump RC
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-30 10:56:17 -07:00
Joffrey F 88790781cd Merge pull request #1013 from docker/hostname_ip_matching
Hostname IP matching
2016-03-30 10:54:03 -07:00
Aanand Prasad 449e037de3 Improve port binding docs
- Reword a sentence that was wrong ("container" and "host" were the
  wrong way round)

- Put the multiple-ports example before the multiple-IPs example

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-30 11:23:07 +01:00
Joffrey F ac3d4aae2c Different requirements.txt in Dockerfile-py3
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-29 17:36:10 -07:00
Joffrey F a6c1d7b751 flake8 fixes
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-29 17:09:37 -07:00
Joffrey F c5a92e0822 Tests for match_hostname backport
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-29 17:09:26 -07:00
Joffrey F 0a5815bcad Add match_hostname implementation and monkey-patch for py<3.5
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-29 17:08:31 -07:00
Joffrey F b0e234eb0c Add py2-ipaddress dependency for python 2.x
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-29 17:06:36 -07:00
Joffrey F 01cf62b4a3 Merge pull request #1011 from tomleb/master
Specify default value of stop's timeout
2016-03-24 14:28:10 -07:00
tomleb 5234784760 Specify default value of stop's timeout
Signed-off-by: Tom Lebreux <tomlebreux@hotmail.com>
2016-03-23 19:37:54 -04:00
Kristian Lewis Jones 6eaf8ce721 makes it possible to have '=' in the env file
note that the docker command line flag --env-file also allows '=' in the env file

Signed-off-by: Kristian Lewis Jones <klj613@kristianlewisjones.com>
2016-03-22 10:00:47 +00:00
225 changed files with 31352 additions and 9484 deletions

View File

@ -13,5 +13,4 @@ html/*
__pycache__
# Compiled Documentation
site/
Makefile
docs/_build

View File

@ -9,3 +9,6 @@ max_line_length = 80
[*.md]
trim_trailing_whitespace = false
[*.{yaml,yml}]
indent_size = 2

72
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,72 @@
name: Python package
on: [push, pull_request]
env:
DOCKER_BUILDKIT: '1'
FORCE_COLOR: 1
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- run: pip install -U ruff==0.1.8
- name: Run ruff
run: ruff docker tests
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- run: pip3 install build && python -m build .
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist
unit-tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
pip3 install '.[ssh,dev]'
- name: Run unit tests
run: |
docker logout
rm -rf ~/.docker
py.test -v --cov=docker tests/unit
integration-tests:
runs-on: ubuntu-latest
strategy:
matrix:
variant: [ "integration-dind", "integration-dind-ssl", "integration-dind-ssh" ]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: make ${{ matrix.variant }}
run: |
docker logout
rm -rf ~/.docker
make ${{ matrix.variant }}

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

@ -0,0 +1,53 @@
name: Release
on:
workflow_dispatch:
inputs:
tag:
description: "Release Tag WITHOUT `v` Prefix (e.g. 6.0.0)"
required: true
dry-run:
description: 'Dry run'
required: false
type: boolean
default: true
env:
DOCKER_BUILDKIT: '1'
FORCE_COLOR: 1
jobs:
publish:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Generate Package
run: |
pip3 install build
python -m build .
env:
# This is also supported by Hatch; see
# https://github.com/ofek/hatch-vcs#version-source-environment-variables
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ inputs.tag }}
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
if: '! inputs.dry-run'
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Create GitHub release
uses: ncipollo/release-action@v1
if: '! inputs.dry-run'
with:
artifacts: "dist/*"
generateReleaseNotes: true
draft: true
commit: ${{ github.sha }}
token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ inputs.tag }}

6
.gitignore vendored
View File

@ -10,9 +10,13 @@ dist
html/*
# Compiled Documentation
site/
_build/
README.rst
# setuptools_scm
_version.py
env/
venv/
.idea/
*.iml

17
.readthedocs.yml Normal file
View File

@ -0,0 +1,17 @@
version: 2
sphinx:
configuration: docs/conf.py
build:
os: ubuntu-22.04
tools:
python: '3.12'
python:
install:
- method: pip
path: .
extra_requirements:
- ssh
- docs

View File

@ -1,14 +0,0 @@
sudo: false
language: python
python:
- "2.7"
env:
- TOX_ENV=py26
- TOX_ENV=py27
- TOX_ENV=py33
- TOX_ENV=py34
- TOX_ENV=flake8
install:
- pip install tox
script:
- tox -e $TOX_ENV

View File

@ -1,5 +1,8 @@
# Contributing guidelines
See the [Docker contributing guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md).
The following is specific to Docker SDK for Python.
Thank you for your interest in the project. We look forward to your
contribution. In order to make the process as fast and streamlined as possible,
here is a set of guidelines we recommend you follow.
@ -7,28 +10,29 @@ here is a set of guidelines we recommend you follow.
## Reporting issues
We do our best to ensure bugs don't creep up in our releases, but some may
still slip through. If you encounter one while using docker-py, please create
an issue [in the tracker](https://github.com/docker/docker-py/issues/new) with
still slip through. If you encounter one while using the SDK, please
create an issue
[in the tracker](https://github.com/docker/docker-py/issues/new) with
the following information:
- docker-py version, docker version and python version
- SDK version, Docker version and python version
```
pip freeze | grep docker-py && python --version && docker version
pip freeze | grep docker && python --version && docker version
```
- OS, distribution and OS version
- The issue you're encountering including a stacktrace if applicable
- If possible, steps or a code snippet to reproduce the issue
To save yourself time, please be sure to check our
[documentation](http://docker-py.readthedocs.org/) and use the
[search function](https://github.com/docker/docker-py/search) to find out if
it has already been addressed, or is currently being looked at.
[documentation](https://docker-py.readthedocs.io/) and use the
[search function](https://github.com/docker/docker-py/search) to find
out if it has already been addressed, or is currently being looked at.
## Submitting pull requests
Do you have a fix for an existing issue, or want to add a new functionality
to docker-py? We happily welcome pull requests. Here are a few tips to make
the review process easier on both the maintainers and yourself.
to the SDK? We happily welcome pull requests. Here are a few tips to
make the review process easier on both the maintainers and yourself.
### 1. Sign your commits
@ -40,7 +44,7 @@ paragraph in the Docker contribution guidelines.
Before we can review your pull request, please ensure that nothing has been
broken by your changes by running the test suite. You can do so simply by
running `make test` in the project root. This also includes coding style using
`flake8`
`ruff`
### 3. Write clear, self-contained commits
@ -84,11 +88,10 @@ to reach out and ask questions. We will do our best to answer and help out.
## Development environment
If you're looking contribute to docker-py but are new to the project or Python,
here are the steps to get you started.
If you're looking contribute to Docker SDK for Python but are new to the
project or Python, here are the steps to get you started.
1. Fork [https://github.com/docker/docker-py](https://github.com/docker/docker-py)
to your username.
1. Fork https://github.com/docker/docker-py to your username.
2. Clone your forked repository locally with
`git clone git@github.com:yourusername/docker-py.git`.
3. Configure a
@ -100,3 +103,33 @@ here are the steps to get you started.
5. Run `python setup.py develop` to install the dev version of the project
and required dependencies. We recommend you do so inside a
[virtual environment](http://docs.python-guide.org/en/latest/dev/virtualenvs)
## Running the tests & Code Quality
To get the source source code and run the unit tests, run:
```
$ git clone git://github.com/docker/docker-py.git
$ cd docker-py
$ make test
```
## Building the docs
```
$ make docs
$ open _build/index.html
```
## Release Checklist
Before a new release, please go through the following checklist:
* Bump version in docker/version.py
* Add a release note in docs/change_log.md
* Git tag the version
* Upload to pypi
## Vulnerability Reporting
For any security issues, please do NOT file an issue or pull request on github!
Please contact [security@docker.com](mailto:security@docker.com) or read [the
Docker security page](https://www.docker.com/resources/security/).

View File

@ -1,14 +1,13 @@
FROM python:2.7
MAINTAINER Joffrey F <joffrey@docker.com>
# syntax=docker/dockerfile:1
RUN mkdir /home/docker-py
WORKDIR /home/docker-py
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}
ADD requirements.txt /home/docker-py/requirements.txt
RUN pip install -r requirements.txt
WORKDIR /src
COPY . .
ADD test-requirements.txt /home/docker-py/test-requirements.txt
RUN pip install -r test-requirements.txt
ADD . /home/docker-py
RUN pip install .
ARG VERSION=0.0.0.dev0
RUN --mount=type=cache,target=/cache/pip \
PIP_CACHE_DIR=/cache/pip \
SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION} \
pip install .[ssh]

22
Dockerfile-docs Normal file
View File

@ -0,0 +1,22 @@
# syntax=docker/dockerfile:1
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}
ARG uid=1000
ARG gid=1000
RUN addgroup --gid $gid sphinx \
&& useradd --uid $uid --gid $gid -M sphinx
WORKDIR /src
COPY . .
ARG VERSION=0.0.0.dev0
RUN --mount=type=cache,target=/cache/pip \
PIP_CACHE_DIR=/cache/pip \
SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION} \
pip install .[ssh,docs]
USER sphinx

View File

@ -1,14 +0,0 @@
FROM python:3.4
MAINTAINER Joffrey F <joffrey@docker.com>
RUN mkdir /home/docker-py
WORKDIR /home/docker-py
ADD requirements.txt /home/docker-py/requirements.txt
RUN pip install -r requirements.txt
ADD test-requirements.txt /home/docker-py/test-requirements.txt
RUN pip install -r test-requirements.txt
ADD . /home/docker-py
RUN pip install .

13
LICENSE
View File

@ -176,18 +176,7 @@
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2016 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Docker-py maintainers file
# Docker SDK for Python maintainers file
#
# This file describes who runs the docker/docker-py project and how.
# This is a living document - if you see something out of date or missing, speak up!
@ -11,11 +11,19 @@
[Org]
[Org."Core maintainers"]
people = [
"glours",
"milas",
]
[Org.Alumni]
people = [
"aiordache",
"aanand",
"bfirsh",
"dnephin",
"mnowster",
"mpetazzoni",
"shin-",
"ulyssessouza",
]
[people]
@ -31,11 +39,31 @@
Email = "aanand@docker.com"
GitHub = "aanand"
[people.aiordache]
Name = "Anca Iordache"
Email = "anca.iordache@docker.com"
GitHub = "aiordache"
[people.bfirsh]
Name = "Ben Firshman"
Email = "b@fir.sh"
GitHub = "bfirsh"
[people.dnephin]
Name = "Daniel Nephin"
Email = "dnephin@gmail.com"
GitHub = "dnephin"
[people.glours]
Name = "Guillaume Lours"
Email = "705411+glours@users.noreply.github.com"
GitHub = "glours"
[people.milas]
Name = "Milas Bowman"
Email = "devnull@milas.dev"
GitHub = "milas"
[people.mnowster]
Name = "Mazz Mosley"
Email = "mazz@houseofmnowster.com"
@ -50,3 +78,8 @@
Name = "Joffrey F"
Email = "joffrey@docker.com"
GitHub = "shin-"
[people.ulyssessouza]
Name = "Ulysses Domiciano Souza"
Email = "ulysses.souza@docker.com"
GitHub = "ulyssessouza"

View File

@ -1,7 +0,0 @@
include test-requirements.txt
include requirements.txt
include README.md
include README.rst
include LICENSE
recursive-include tests *.py
recursive-include tests/unit/testdata *

193
Makefile
View File

@ -1,48 +1,189 @@
.PHONY: all build test integration-test unit-test build-py3 unit-test-py3 integration-test-py3
TEST_API_VERSION ?= 1.45
TEST_ENGINE_VERSION ?= 26.1
ifeq ($(OS),Windows_NT)
PLATFORM := Windows
else
PLATFORM := $(shell sh -c 'uname -s 2>/dev/null || echo Unknown')
endif
ifeq ($(PLATFORM),Linux)
uid_args := "--build-arg uid=$(shell id -u) --build-arg gid=$(shell id -g)"
endif
SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER ?= $(shell git describe --match '[0-9]*' --dirty='.m' --always --tags 2>/dev/null | sed -r 's/-([0-9]+)/.dev\1/' | sed 's/-/+/')
ifeq ($(SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER),)
SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER = "0.0.0.dev0"
endif
.PHONY: all
all: test
.PHONY: clean
clean:
rm -rf tests/__pycache__
rm -rf tests/*/__pycache__
docker rm -vf dpy-dind
-docker rm -f dpy-dind dpy-dind-certs dpy-dind-ssl
find -name "__pycache__" | xargs rm -rf
.PHONY: build-dind-ssh
build-dind-ssh:
docker build \
--pull \
-t docker-dind-ssh \
-f tests/Dockerfile-ssh-dind \
--build-arg VERSION=${SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER} \
--build-arg ENGINE_VERSION=${TEST_ENGINE_VERSION} \
--build-arg API_VERSION=${TEST_API_VERSION} \
.
.PHONY: build
build:
docker build -t docker-py .
docker build \
--pull \
-t docker-sdk-python3 \
-f tests/Dockerfile \
--build-arg VERSION=${SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER} \
.
build-py3:
docker build -t docker-py3 -f Dockerfile-py3 .
.PHONY: build-docs
build-docs:
docker build \
-t docker-sdk-python-docs \
-f Dockerfile-docs \
--build-arg VERSION=${SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER} \
$(uid_args) \
.
.PHONY: build-dind-certs
build-dind-certs:
docker build -t dpy-dind-certs -f tests/Dockerfile-dind-certs .
docker build \
-t dpy-dind-certs \
-f tests/Dockerfile-dind-certs \
--build-arg VERSION=${SETUPTOOLS_SCM_PRETEND_VERSION_DOCKER} \
.
test: flake8 unit-test unit-test-py3 integration-dind integration-dind-ssl
.PHONY: test
test: ruff unit-test integration-dind integration-dind-ssl
.PHONY: unit-test
unit-test: build
docker run docker-py py.test tests/unit
unit-test-py3: build-py3
docker run docker-py3 py.test tests/unit
docker run -t --rm docker-sdk-python3 py.test tests/unit
.PHONY: integration-test
integration-test: build
docker run -v /var/run/docker.sock:/var/run/docker.sock docker-py py.test tests/integration
docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 py.test -v tests/integration/${file}
integration-test-py3: build-py3
docker run -v /var/run/docker.sock:/var/run/docker.sock docker-py3 py.test tests/integration
.PHONY: setup-network
setup-network:
docker network inspect dpy-tests || docker network create dpy-tests
integration-dind: build build-py3
.PHONY: integration-dind
integration-dind: build setup-network
docker rm -vf dpy-dind || :
docker run -d --name dpy-dind --env="DOCKER_HOST=tcp://localhost:2375" --privileged dockerswarm/dind:1.10.3 docker daemon -H tcp://0.0.0.0:2375
docker run --env="DOCKER_HOST=tcp://docker:2375" --link=dpy-dind:docker docker-py py.test tests/integration
docker run --env="DOCKER_HOST=tcp://docker:2375" --link=dpy-dind:docker docker-py3 py.test tests/integration
docker run \
--detach \
--name dpy-dind \
--network dpy-tests \
--pull=always \
--privileged \
docker:${TEST_ENGINE_VERSION}-dind \
dockerd -H tcp://0.0.0.0:2375 --experimental
# Wait for Docker-in-Docker to come to life
docker run \
--network dpy-tests \
--rm \
--tty \
busybox \
sh -c 'while ! nc -z dpy-dind 2375; do sleep 1; done'
docker run \
--env="DOCKER_HOST=tcp://dpy-dind:2375" \
--env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}" \
--network dpy-tests \
--rm \
--tty \
docker-sdk-python3 \
py.test tests/integration/${file}
docker rm -vf dpy-dind
integration-dind-ssl: build-dind-certs build build-py3
.PHONY: integration-dind-ssh
integration-dind-ssh: build-dind-ssh build setup-network
docker rm -vf dpy-dind-ssh || :
docker run -d --network dpy-tests --name dpy-dind-ssh --privileged \
docker-dind-ssh dockerd --experimental
# start SSH daemon for known key
docker exec dpy-dind-ssh sh -c "/usr/sbin/sshd -h /etc/ssh/known_ed25519 -p 22"
docker exec dpy-dind-ssh sh -c "/usr/sbin/sshd -h /etc/ssh/unknown_ed25519 -p 2222"
docker run \
--tty \
--rm \
--env="DOCKER_HOST=ssh://dpy-dind-ssh" \
--env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}" \
--env="UNKNOWN_DOCKER_SSH_HOST=ssh://dpy-dind-ssh:2222" \
--network dpy-tests \
docker-sdk-python3 py.test tests/ssh/${file}
docker rm -vf dpy-dind-ssh
.PHONY: integration-dind-ssl
integration-dind-ssl: build-dind-certs build setup-network
docker rm -vf dpy-dind-certs dpy-dind-ssl || :
docker run -d --name dpy-dind-certs dpy-dind-certs
docker run -d --env="DOCKER_HOST=tcp://localhost:2375" --env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --volumes-from dpy-dind-certs --name dpy-dind-ssl -v /tmp --privileged dockerswarm/dind:1.10.3 docker daemon --tlsverify --tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem --tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375
docker run --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --link=dpy-dind-ssl:docker docker-py py.test tests/integration
docker run --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375" --env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --link=dpy-dind-ssl:docker docker-py3 py.test tests/integration
docker run \
--detach \
--env="DOCKER_CERT_PATH=/certs" \
--env="DOCKER_HOST=tcp://localhost:2375" \
--env="DOCKER_TLS_VERIFY=1" \
--name dpy-dind-ssl \
--network dpy-tests \
--network-alias docker \
--pull=always \
--privileged \
--volume /tmp \
--volumes-from dpy-dind-certs \
docker:${TEST_ENGINE_VERSION}-dind \
dockerd \
--tlsverify \
--tlscacert=/certs/ca.pem \
--tlscert=/certs/server-cert.pem \
--tlskey=/certs/server-key.pem \
-H tcp://0.0.0.0:2375 \
--experimental
# Wait for Docker-in-Docker to come to life
docker run \
--network dpy-tests \
--rm \
--tty \
busybox \
sh -c 'while ! nc -z dpy-dind-ssl 2375; do sleep 1; done'
docker run \
--env="DOCKER_CERT_PATH=/certs" \
--env="DOCKER_HOST=tcp://docker:2375" \
--env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}" \
--env="DOCKER_TLS_VERIFY=1" \
--network dpy-tests \
--rm \
--volumes-from dpy-dind-ssl \
--tty \
docker-sdk-python3 \
py.test tests/integration/${file}
docker rm -vf dpy-dind-ssl dpy-dind-certs
flake8: build
docker run docker-py flake8 docker tests
.PHONY: ruff
ruff: build
docker run -t --rm docker-sdk-python3 ruff docker tests
.PHONY: docs
docs: build-docs
docker run --rm -t -v `pwd`:/src docker-sdk-python-docs sphinx-build docs docs/_build
.PHONY: shell
shell: build
docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 python

View File

@ -1,26 +1,76 @@
docker-py
=========
# Docker SDK for Python
[![Build Status](https://travis-ci.org/docker/docker-py.png)](https://travis-ci.org/docker/docker-py)
[![Build Status](https://github.com/docker/docker-py/actions/workflows/ci.yml/badge.svg)](https://github.com/docker/docker-py/actions/workflows/ci.yml)
A Python library for the Docker Remote API. It does everything the `docker` command does, but from within Python  run containers, manage them, pull/push images, etc.
A Python library for the Docker Engine API. It lets you do anything the `docker` command does, but from within Python apps run containers, manage containers, manage Swarms, etc.
Installation
------------
## Installation
The latest stable version is always available on PyPi.
The latest stable version [is available on PyPI](https://pypi.python.org/pypi/docker/). Install with pip:
pip install docker-py
pip install docker
Documentation
------------
> Older versions (< 6.0) required installing `docker[tls]` for SSL/TLS support.
> This is no longer necessary and is a no-op, but is supported for backwards compatibility.
[![Documentation Status](https://readthedocs.org/projects/docker-py/badge/?version=latest)](https://readthedocs.org/projects/docker-py/?badge=latest)
## Usage
[Read the full documentation here.](http://docker-py.readthedocs.org/en/latest/).
The source is available in the `docs/` directory.
Connect to Docker using the default socket or the configuration in your environment:
```python
import docker
client = docker.from_env()
```
License
-------
Docker is licensed under the Apache License, Version 2.0. See LICENSE for full license text
You can run containers:
```python
>>> client.containers.run("ubuntu:latest", "echo hello world")
'hello world\n'
```
You can run containers in the background:
```python
>>> client.containers.run("bfirsh/reticulate-splines", detach=True)
<Container '45e6d2de7c54'>
```
You can manage containers:
```python
>>> client.containers.list()
[<Container '45e6d2de7c54'>, <Container 'db18e4f20eaa'>, ...]
>>> container = client.containers.get('45e6d2de7c54')
>>> container.attrs['Config']['Image']
"bfirsh/reticulate-splines"
>>> container.logs()
"Reticulating spline 1...\n"
>>> container.stop()
```
You can stream logs:
```python
>>> for line in container.logs(stream=True):
... print(line.strip())
Reticulating spline 2...
Reticulating spline 3...
...
```
You can manage images:
```python
>>> client.images.pull('nginx')
<Image 'nginx'>
>>> client.images.list()
[<Image 'ubuntu'>, <Image 'nginx'>, ...]
```
[Read the full documentation](https://docker-py.readthedocs.io) to see everything you can do.

View File

@ -1,20 +1,7 @@
# Copyright 2013 dotCloud inc.
from .api import APIClient
from .client import DockerClient, from_env
from .context import Context, ContextAPI
from .tls import TLSConfig
from .version import __version__
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .version import version, version_info
__version__ = version
__title__ = 'docker-py'
from .client import Client, AutoVersionClient, from_env # flake8: noqa
__title__ = 'docker'

View File

@ -1,8 +1 @@
# flake8: noqa
from .build import BuildApiMixin
from .container import ContainerApiMixin
from .daemon import DaemonApiMixin
from .exec_api import ExecApiMixin
from .image import ImageApiMixin
from .volume import VolumeApiMixin
from .network import NetworkApiMixin
from .client import APIClient

View File

@ -1,38 +1,140 @@
import json
import logging
import os
import re
import json
from .. import constants
from .. import errors
from .. import auth
from .. import utils
import random
from .. import auth, constants, errors, utils
log = logging.getLogger(__name__)
class BuildApiMixin(object):
class BuildApiMixin:
def build(self, path=None, tag=None, quiet=False, fileobj=None,
nocache=False, rm=False, stream=False, timeout=None,
nocache=False, rm=False, timeout=None,
custom_context=False, encoding=None, pull=False,
forcerm=False, dockerfile=None, container_limits=None,
decode=False, buildargs=None, gzip=False):
remote = context = headers = None
decode=False, buildargs=None, gzip=False, shmsize=None,
labels=None, cache_from=None, target=None, network_mode=None,
squash=None, extra_hosts=None, platform=None, isolation=None,
use_config_proxy=True):
"""
Similar to the ``docker build`` command. Either ``path`` or ``fileobj``
needs to be set. ``path`` can be a local path (to a directory
containing a Dockerfile) or a remote URL. ``fileobj`` must be a
readable file-like object to a Dockerfile.
If you have a tar file for the Docker build context (including a
Dockerfile) already, pass a readable file-like object to ``fileobj``
and also pass ``custom_context=True``. If the stream is compressed
also, set ``encoding`` to the correct value (e.g ``gzip``).
Example:
>>> from io import BytesIO
>>> from docker import APIClient
>>> dockerfile = '''
... # Shared Volume
... FROM busybox:buildroot-2014.02
... VOLUME /data
... CMD ["/bin/sh"]
... '''
>>> f = BytesIO(dockerfile.encode('utf-8'))
>>> cli = APIClient(base_url='tcp://127.0.0.1:2375')
>>> response = [line for line in cli.build(
... fileobj=f, rm=True, tag='yourname/volume'
... )]
>>> response
['{"stream":" ---\\u003e a9eb17255234\\n"}',
'{"stream":"Step 1 : VOLUME /data\\n"}',
'{"stream":" ---\\u003e Running in abdc1e6896c6\\n"}',
'{"stream":" ---\\u003e 713bca62012e\\n"}',
'{"stream":"Removing intermediate container abdc1e6896c6\\n"}',
'{"stream":"Step 2 : CMD [\\"/bin/sh\\"]\\n"}',
'{"stream":" ---\\u003e Running in dba30f2a1a7e\\n"}',
'{"stream":" ---\\u003e 032b8b2855fc\\n"}',
'{"stream":"Removing intermediate container dba30f2a1a7e\\n"}',
'{"stream":"Successfully built 032b8b2855fc\\n"}']
Args:
path (str): Path to the directory containing the Dockerfile
fileobj: A file object to use as the Dockerfile. (Or a file-like
object)
tag (str): A tag to add to the final image
quiet (bool): Whether to return the status
nocache (bool): Don't use the cache when set to ``True``
rm (bool): Remove intermediate containers. The ``docker build``
command now defaults to ``--rm=true``, but we have kept the old
default of `False` to preserve backward compatibility
timeout (int): HTTP timeout
custom_context (bool): Optional if using ``fileobj``
encoding (str): The encoding for a stream. Set to ``gzip`` for
compressing
pull (bool): Downloads any updates to the FROM image in Dockerfiles
forcerm (bool): Always remove intermediate containers, even after
unsuccessful builds
dockerfile (str): path within the build context to the Dockerfile
gzip (bool): If set to ``True``, gzip compression/encoding is used
buildargs (dict): A dictionary of build arguments
container_limits (dict): A dictionary of limits applied to each
container created by the build process. Valid keys:
- memory (int): set memory limit for build
- memswap (int): Total memory (memory + swap), -1 to disable
swap
- cpushares (int): CPU shares (relative weight)
- cpusetcpus (str): CPUs in which to allow execution, e.g.,
``"0-3"``, ``"0,1"``
decode (bool): If set to ``True``, the returned stream will be
decoded into dicts on the fly. Default ``False``
shmsize (int): Size of `/dev/shm` in bytes. The size must be
greater than 0. If omitted the system uses 64MB
labels (dict): A dictionary of labels to set on the image
cache_from (:py:class:`list`): A list of images used for build
cache resolution
target (str): Name of the build-stage to build in a multi-stage
Dockerfile
network_mode (str): networking mode for the run commands during
build
squash (bool): Squash the resulting images layers into a
single layer.
extra_hosts (dict): Extra hosts to add to /etc/hosts in building
containers, as a mapping of hostname to IP address.
platform (str): Platform in the format ``os[/arch[/variant]]``
isolation (str): Isolation technology used during build.
Default: `None`.
use_config_proxy (bool): If ``True``, and if the docker client
configuration file (``~/.docker/config.json`` by default)
contains a proxy configuration, the corresponding environment
variables will be set in the container being built.
Returns:
A generator for the build output.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
``TypeError``
If neither ``path`` nor ``fileobj`` is specified.
"""
remote = context = None
headers = {}
container_limits = container_limits or {}
buildargs = buildargs or {}
if path is None and fileobj is None:
raise TypeError("Either path or fileobj needs to be provided.")
if gzip and encoding is not None:
raise errors.DockerException(
'Can not use custom encoding if gzip is enabled'
)
if tag is not None:
if not utils.match_tag(tag):
raise errors.DockerException(
f"invalid tag '{tag}': invalid reference format"
)
for key in container_limits.keys():
if key not in constants.CONTAINER_LIMITS_KEYS:
raise errors.DockerException(
'Invalid container_limits key {0}'.format(key)
f"invalid tag '{tag}': invalid reference format"
)
if custom_context:
if not fileobj:
raise TypeError("You must specify fileobj with custom_context")
@ -48,24 +150,17 @@ class BuildApiMixin(object):
dockerignore = os.path.join(path, '.dockerignore')
exclude = None
if os.path.exists(dockerignore):
with open(dockerignore, 'r') as f:
exclude = list(filter(bool, f.read().splitlines()))
with open(dockerignore) as f:
exclude = list(filter(
lambda x: x != '' and x[0] != '#',
[line.strip() for line in f.read().splitlines()]
))
dockerfile = process_dockerfile(dockerfile, path)
context = utils.tar(
path, exclude=exclude, dockerfile=dockerfile, gzip=gzip
)
encoding = 'gzip' if gzip else encoding
if utils.compare_version('1.8', self._version) >= 0:
stream = True
if dockerfile and utils.compare_version('1.17', self._version) < 0:
raise errors.InvalidVersion(
'dockerfile was only introduced in API version 1.17'
)
if utils.compare_version('1.19', self._version) < 0:
pull = 1 if pull else 0
u = self._url('/build')
params = {
't': tag,
@ -79,70 +174,209 @@ class BuildApiMixin(object):
}
params.update(container_limits)
if use_config_proxy:
proxy_args = self._proxy_configs.get_environment()
for k, v in proxy_args.items():
buildargs.setdefault(k, v)
if buildargs:
if utils.version_gte(self._version, '1.21'):
params.update({'buildargs': json.dumps(buildargs)})
params.update({'buildargs': json.dumps(buildargs)})
if shmsize:
if utils.version_gte(self._version, '1.22'):
params.update({'shmsize': shmsize})
else:
raise errors.InvalidVersion(
'buildargs was only introduced in API version 1.21'
'shmsize was only introduced in API version 1.22'
)
if labels:
if utils.version_gte(self._version, '1.23'):
params.update({'labels': json.dumps(labels)})
else:
raise errors.InvalidVersion(
'labels was only introduced in API version 1.23'
)
if cache_from:
if utils.version_gte(self._version, '1.25'):
params.update({'cachefrom': json.dumps(cache_from)})
else:
raise errors.InvalidVersion(
'cache_from was only introduced in API version 1.25'
)
if target:
if utils.version_gte(self._version, '1.29'):
params.update({'target': target})
else:
raise errors.InvalidVersion(
'target was only introduced in API version 1.29'
)
if network_mode:
if utils.version_gte(self._version, '1.25'):
params.update({'networkmode': network_mode})
else:
raise errors.InvalidVersion(
'network_mode was only introduced in API version 1.25'
)
if squash:
if utils.version_gte(self._version, '1.25'):
params.update({'squash': squash})
else:
raise errors.InvalidVersion(
'squash was only introduced in API version 1.25'
)
if extra_hosts is not None:
if utils.version_lt(self._version, '1.27'):
raise errors.InvalidVersion(
'extra_hosts was only introduced in API version 1.27'
)
if isinstance(extra_hosts, dict):
extra_hosts = utils.format_extra_hosts(extra_hosts)
params.update({'extrahosts': extra_hosts})
if platform is not None:
if utils.version_lt(self._version, '1.32'):
raise errors.InvalidVersion(
'platform was only introduced in API version 1.32'
)
params['platform'] = platform
if isolation is not None:
if utils.version_lt(self._version, '1.24'):
raise errors.InvalidVersion(
'isolation was only introduced in API version 1.24'
)
params['isolation'] = isolation
if context is not None:
headers = {'Content-Type': 'application/tar'}
if encoding:
headers['Content-Encoding'] = encoding
if utils.compare_version('1.9', self._version) >= 0:
self._set_auth_headers(headers)
self._set_auth_headers(headers)
response = self._post(
u,
data=context,
params=params,
headers=headers,
stream=stream,
stream=True,
timeout=timeout,
)
if context is not None and not custom_context:
context.close()
if stream:
return self._stream_helper(response, decode=decode)
else:
output = self._result(response)
srch = r'Successfully built ([0-9a-f]+)'
match = re.search(srch, output)
if not match:
return None, output
return match.group(1), output
return self._stream_helper(response, decode=decode)
@utils.minimum_version('1.31')
def prune_builds(self, filters=None, keep_storage=None, all=None):
"""
Delete the builder cache
Args:
filters (dict): Filters to process on the prune list.
Needs Docker API v1.39+
Available filters:
- dangling (bool): When set to true (or 1), prune only
unused and untagged images.
- until (str): Can be Unix timestamps, date formatted
timestamps, or Go duration strings (e.g. 10m, 1h30m) computed
relative to the daemon's local time.
keep_storage (int): Amount of disk space in bytes to keep for cache.
Needs Docker API v1.39+
all (bool): Remove all types of build cache.
Needs Docker API v1.39+
Returns:
(dict): A dictionary containing information about the operation's
result. The ``SpaceReclaimed`` key indicates the amount of
bytes of disk space reclaimed.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url("/build/prune")
if (filters, keep_storage, all) != (None, None, None) \
and utils.version_lt(self._version, '1.39'):
raise errors.InvalidVersion(
'`filters`, `keep_storage`, and `all` args are only available '
'for API version > 1.38'
)
params = {}
if filters is not None:
params['filters'] = utils.convert_filters(filters)
if keep_storage is not None:
params['keep-storage'] = keep_storage
if all is not None:
params['all'] = all
return self._result(self._post(url, params=params), True)
def _set_auth_headers(self, headers):
log.debug('Looking for auth config')
# If we don't have any auth data so far, try reloading the config
# file one more time in case anything showed up in there.
if not self._auth_configs:
if not self._auth_configs or self._auth_configs.is_empty:
log.debug("No auth config in memory - loading from filesystem")
self._auth_configs = auth.load_config()
self._auth_configs = auth.load_config(
credstore_env=self.credstore_env
)
# Send the full auth configuration (if any exists), since the build
# could use any (or all) of the registries.
if self._auth_configs:
auth_data = self._auth_configs.get_all_credentials()
# See https://github.com/docker/docker-py/issues/1683
if (auth.INDEX_URL not in auth_data and
auth.INDEX_NAME in auth_data):
auth_data[auth.INDEX_URL] = auth_data.get(auth.INDEX_NAME, {})
log.debug(
'Sending auth config ({0})'.format(
', '.join(repr(k) for k in self._auth_configs.keys())
)
"Sending auth config (%s)",
', '.join(repr(k) for k in auth_data),
)
if headers is None:
headers = {}
if utils.compare_version('1.19', self._version) >= 0:
if auth_data:
headers['X-Registry-Config'] = auth.encode_header(
self._auth_configs
auth_data
)
else:
headers['X-Registry-Config'] = auth.encode_header({
'configs': self._auth_configs
})
else:
log.debug('No auth config found')
def process_dockerfile(dockerfile, path):
if not dockerfile:
return (None, None)
abs_dockerfile = dockerfile
if not os.path.isabs(dockerfile):
abs_dockerfile = os.path.join(path, dockerfile)
if constants.IS_WINDOWS_PLATFORM and path.startswith(
constants.WINDOWS_LONGPATH_PREFIX):
normpath = os.path.normpath(
abs_dockerfile[len(constants.WINDOWS_LONGPATH_PREFIX):])
abs_dockerfile = f'{constants.WINDOWS_LONGPATH_PREFIX}{normpath}'
if (os.path.splitdrive(path)[0] != os.path.splitdrive(abs_dockerfile)[0] or
os.path.relpath(abs_dockerfile, path).startswith('..')):
# Dockerfile not in context - read data to insert into tar later
with open(abs_dockerfile) as df:
return (
f'.dockerfile.{random.getrandbits(160):x}',
df.read()
)
# Dockerfile is inside the context - return path relative to context root
if dockerfile == abs_dockerfile:
# Only calculate relpath if necessary to avoid errors
# on Windows client -> Linux Docker
# see https://github.com/docker/compose/issues/5969
dockerfile = os.path.relpath(abs_dockerfile, path)
return (dockerfile, None)

532
docker/api/client.py Normal file
View File

@ -0,0 +1,532 @@
import json
import struct
import urllib
from functools import partial
import requests
import requests.adapters
import requests.exceptions
from .. import auth
from ..constants import (
DEFAULT_MAX_POOL_SIZE,
DEFAULT_NUM_POOLS,
DEFAULT_NUM_POOLS_SSH,
DEFAULT_TIMEOUT_SECONDS,
DEFAULT_USER_AGENT,
IS_WINDOWS_PLATFORM,
MINIMUM_DOCKER_API_VERSION,
STREAM_HEADER_SIZE_BYTES,
)
from ..errors import (
DockerException,
InvalidVersion,
TLSParameterError,
create_api_error_from_http_exception,
)
from ..tls import TLSConfig
from ..transport import UnixHTTPAdapter
from ..utils import check_resource, config, update_headers, utils
from ..utils.json_stream import json_stream
from ..utils.proxy import ProxyConfig
from ..utils.socket import consume_socket_output, demux_adaptor, frames_iter
from .build import BuildApiMixin
from .config import ConfigApiMixin
from .container import ContainerApiMixin
from .daemon import DaemonApiMixin
from .exec_api import ExecApiMixin
from .image import ImageApiMixin
from .network import NetworkApiMixin
from .plugin import PluginApiMixin
from .secret import SecretApiMixin
from .service import ServiceApiMixin
from .swarm import SwarmApiMixin
from .volume import VolumeApiMixin
try:
from ..transport import NpipeHTTPAdapter
except ImportError:
pass
try:
from ..transport import SSHHTTPAdapter
except ImportError:
pass
class APIClient(
requests.Session,
BuildApiMixin,
ConfigApiMixin,
ContainerApiMixin,
DaemonApiMixin,
ExecApiMixin,
ImageApiMixin,
NetworkApiMixin,
PluginApiMixin,
SecretApiMixin,
ServiceApiMixin,
SwarmApiMixin,
VolumeApiMixin):
"""
A low-level client for the Docker Engine API.
Example:
>>> import docker
>>> client = docker.APIClient(base_url='unix://var/run/docker.sock')
>>> client.version()
{u'ApiVersion': u'1.33',
u'Arch': u'amd64',
u'BuildTime': u'2017-11-19T18:46:37.000000000+00:00',
u'GitCommit': u'f4ffd2511c',
u'GoVersion': u'go1.9.2',
u'KernelVersion': u'4.14.3-1-ARCH',
u'MinAPIVersion': u'1.12',
u'Os': u'linux',
u'Version': u'17.10.0-ce'}
Args:
base_url (str): URL to the Docker server. For example,
``unix:///var/run/docker.sock`` or ``tcp://127.0.0.1:1234``.
version (str): The version of the API to use. Set to ``auto`` to
automatically detect the server's version. Default: ``1.35``
timeout (int): Default timeout for API calls, in seconds.
tls (bool or :py:class:`~docker.tls.TLSConfig`): Enable TLS. Pass
``True`` to enable it with default options, or pass a
:py:class:`~docker.tls.TLSConfig` object to use custom
configuration.
user_agent (str): Set a custom user agent for requests to the server.
credstore_env (dict): Override environment variables when calling the
credential store process.
use_ssh_client (bool): If set to `True`, an ssh connection is made
via shelling out to the ssh client. Ensure the ssh client is
installed and configured on the host.
max_pool_size (int): The maximum number of connections
to save in the pool.
"""
__attrs__ = requests.Session.__attrs__ + ['_auth_configs',
'_general_configs',
'_version',
'base_url',
'timeout']
def __init__(self, base_url=None, version=None,
timeout=DEFAULT_TIMEOUT_SECONDS, tls=False,
user_agent=DEFAULT_USER_AGENT, num_pools=None,
credstore_env=None, use_ssh_client=False,
max_pool_size=DEFAULT_MAX_POOL_SIZE):
super().__init__()
if tls and not base_url:
raise TLSParameterError(
'If using TLS, the base_url argument must be provided.'
)
self.base_url = base_url
self.timeout = timeout
self.headers['User-Agent'] = user_agent
self._general_configs = config.load_general_config()
proxy_config = self._general_configs.get('proxies', {})
try:
proxies = proxy_config[base_url]
except KeyError:
proxies = proxy_config.get('default', {})
self._proxy_configs = ProxyConfig.from_dict(proxies)
self._auth_configs = auth.load_config(
config_dict=self._general_configs, credstore_env=credstore_env,
)
self.credstore_env = credstore_env
base_url = utils.parse_host(
base_url, IS_WINDOWS_PLATFORM, tls=bool(tls)
)
# SSH has a different default for num_pools to all other adapters
num_pools = num_pools or DEFAULT_NUM_POOLS_SSH if \
base_url.startswith('ssh://') else DEFAULT_NUM_POOLS
if base_url.startswith('http+unix://'):
self._custom_adapter = UnixHTTPAdapter(
base_url, timeout, pool_connections=num_pools,
max_pool_size=max_pool_size
)
self.mount('http+docker://', self._custom_adapter)
self._unmount('http://', 'https://')
# host part of URL should be unused, but is resolved by requests
# module in proxy_bypass_macosx_sysconf()
self.base_url = 'http+docker://localhost'
elif base_url.startswith('npipe://'):
if not IS_WINDOWS_PLATFORM:
raise DockerException(
'The npipe:// protocol is only supported on Windows'
)
try:
self._custom_adapter = NpipeHTTPAdapter(
base_url, timeout, pool_connections=num_pools,
max_pool_size=max_pool_size
)
except NameError as err:
raise DockerException(
'Install pypiwin32 package to enable npipe:// support'
) from err
self.mount('http+docker://', self._custom_adapter)
self.base_url = 'http+docker://localnpipe'
elif base_url.startswith('ssh://'):
try:
self._custom_adapter = SSHHTTPAdapter(
base_url, timeout, pool_connections=num_pools,
max_pool_size=max_pool_size, shell_out=use_ssh_client
)
except NameError as err:
raise DockerException(
'Install paramiko package to enable ssh:// support'
) from err
self.mount('http+docker://ssh', self._custom_adapter)
self._unmount('http://', 'https://')
self.base_url = 'http+docker://ssh'
else:
# Use SSLAdapter for the ability to specify SSL version
if isinstance(tls, TLSConfig):
tls.configure_client(self)
elif tls:
self._custom_adapter = requests.adapters.HTTPAdapter(
pool_connections=num_pools)
self.mount('https://', self._custom_adapter)
self.base_url = base_url
# version detection needs to be after unix adapter mounting
if version is None or (isinstance(
version,
str
) and version.lower() == 'auto'):
self._version = self._retrieve_server_version()
else:
self._version = version
if not isinstance(self._version, str):
raise DockerException(
'Version parameter must be a string or None. '
f'Found {type(version).__name__}'
)
if utils.version_lt(self._version, MINIMUM_DOCKER_API_VERSION):
raise InvalidVersion(
f'API versions below {MINIMUM_DOCKER_API_VERSION} are '
f'no longer supported by this library.'
)
def _retrieve_server_version(self):
try:
return self.version(api_version=False)["ApiVersion"]
except KeyError as ke:
raise DockerException(
'Invalid response from docker daemon: key "ApiVersion"'
' is missing.'
) from ke
except Exception as e:
raise DockerException(
f'Error while fetching server API version: {e}'
) from e
def _set_request_timeout(self, kwargs):
"""Prepare the kwargs for an HTTP request by inserting the timeout
parameter, if not already present."""
kwargs.setdefault('timeout', self.timeout)
return kwargs
@update_headers
def _post(self, url, **kwargs):
return self.post(url, **self._set_request_timeout(kwargs))
@update_headers
def _get(self, url, **kwargs):
return self.get(url, **self._set_request_timeout(kwargs))
@update_headers
def _put(self, url, **kwargs):
return self.put(url, **self._set_request_timeout(kwargs))
@update_headers
def _delete(self, url, **kwargs):
return self.delete(url, **self._set_request_timeout(kwargs))
def _url(self, pathfmt, *args, **kwargs):
for arg in args:
if not isinstance(arg, str):
raise ValueError(
f'Expected a string but found {arg} ({type(arg)}) instead'
)
quote_f = partial(urllib.parse.quote, safe="/:")
args = map(quote_f, args)
formatted_path = pathfmt.format(*args)
if kwargs.get('versioned_api', True):
return f'{self.base_url}/v{self._version}{formatted_path}'
else:
return f'{self.base_url}{formatted_path}'
def _raise_for_status(self, response):
"""Raises stored :class:`APIError`, if one occurred."""
try:
response.raise_for_status()
except requests.exceptions.HTTPError as e:
raise create_api_error_from_http_exception(e) from e
def _result(self, response, json=False, binary=False):
assert not (json and binary)
self._raise_for_status(response)
if json:
return response.json()
if binary:
return response.content
return response.text
def _post_json(self, url, data, **kwargs):
# Go <1.1 can't unserialize null to a string
# so we do this disgusting thing here.
data2 = {}
if data is not None and isinstance(data, dict):
for k, v in iter(data.items()):
if v is not None:
data2[k] = v
elif data is not None:
data2 = data
if 'headers' not in kwargs:
kwargs['headers'] = {}
kwargs['headers']['Content-Type'] = 'application/json'
return self._post(url, data=json.dumps(data2), **kwargs)
def _attach_params(self, override=None):
return override or {
'stdout': 1,
'stderr': 1,
'stream': 1
}
@check_resource('container')
def _attach_websocket(self, container, params=None):
url = self._url("/containers/{0}/attach/ws", container)
req = requests.Request("POST", url, params=self._attach_params(params))
full_url = req.prepare().url
full_url = full_url.replace("http://", "ws://", 1)
full_url = full_url.replace("https://", "wss://", 1)
return self._create_websocket_connection(full_url)
def _create_websocket_connection(self, url):
try:
import websocket
return websocket.create_connection(url)
except ImportError as ie:
raise DockerException(
'The `websocket-client` library is required '
'for using websocket connections. '
'You can install the `docker` library '
'with the [websocket] extra to install it.'
) from ie
def _get_raw_response_socket(self, response):
self._raise_for_status(response)
if self.base_url == "http+docker://localnpipe":
sock = response.raw._fp.fp.raw.sock
elif self.base_url.startswith('http+docker://ssh'):
sock = response.raw._fp.fp.channel
else:
sock = response.raw._fp.fp.raw
if self.base_url.startswith("https://"):
sock = sock._sock
try:
# Keep a reference to the response to stop it being garbage
# collected. If the response is garbage collected, it will
# close TLS sockets.
sock._response = response
except AttributeError:
# UNIX sockets can't have attributes set on them, but that's
# fine because we won't be doing TLS over them
pass
return sock
def _stream_helper(self, response, decode=False):
"""Generator for data coming from a chunked-encoded HTTP response."""
if response.raw._fp.chunked:
if decode:
yield from json_stream(self._stream_helper(response, False))
else:
reader = response.raw
while not reader.closed:
# this read call will block until we get a chunk
data = reader.read(1)
if not data:
break
if reader._fp.chunk_left:
data += reader.read(reader._fp.chunk_left)
yield data
else:
# Response isn't chunked, meaning we probably
# encountered an error immediately
yield self._result(response, json=decode)
def _multiplexed_buffer_helper(self, response):
"""A generator of multiplexed data blocks read from a buffered
response."""
buf = self._result(response, binary=True)
buf_length = len(buf)
walker = 0
while True:
if buf_length - walker < STREAM_HEADER_SIZE_BYTES:
break
header = buf[walker:walker + STREAM_HEADER_SIZE_BYTES]
_, length = struct.unpack_from('>BxxxL', header)
start = walker + STREAM_HEADER_SIZE_BYTES
end = start + length
walker = end
yield buf[start:end]
def _multiplexed_response_stream_helper(self, response):
"""A generator of multiplexed data blocks coming from a response
stream."""
# Disable timeout on the underlying socket to prevent
# Read timed out(s) for long running processes
socket = self._get_raw_response_socket(response)
self._disable_socket_timeout(socket)
while True:
header = response.raw.read(STREAM_HEADER_SIZE_BYTES)
if not header:
break
_, length = struct.unpack('>BxxxL', header)
if not length:
continue
data = response.raw.read(length)
if not data:
break
yield data
def _stream_raw_result(self, response, chunk_size=1, decode=True):
''' Stream result for TTY-enabled container and raw binary data'''
self._raise_for_status(response)
# Disable timeout on the underlying socket to prevent
# Read timed out(s) for long running processes
socket = self._get_raw_response_socket(response)
self._disable_socket_timeout(socket)
yield from response.iter_content(chunk_size, decode)
def _read_from_socket(self, response, stream, tty=True, demux=False):
"""Consume all data from the socket, close the response and return the
data. If stream=True, then a generator is returned instead and the
caller is responsible for closing the response.
"""
socket = self._get_raw_response_socket(response)
gen = frames_iter(socket, tty)
if demux:
# The generator will output tuples (stdout, stderr)
gen = (demux_adaptor(*frame) for frame in gen)
else:
# The generator will output strings
gen = (data for (_, data) in gen)
if stream:
return gen
else:
try:
# Wait for all frames, concatenate them, and return the result
return consume_socket_output(gen, demux=demux)
finally:
response.close()
def _disable_socket_timeout(self, socket):
""" Depending on the combination of python version and whether we're
connecting over http or https, we might need to access _sock, which
may or may not exist; or we may need to just settimeout on socket
itself, which also may or may not have settimeout on it. To avoid
missing the correct one, we try both.
We also do not want to set the timeout if it is already disabled, as
you run the risk of changing a socket that was non-blocking to
blocking, for example when using gevent.
"""
sockets = [socket, getattr(socket, '_sock', None)]
for s in sockets:
if not hasattr(s, 'settimeout'):
continue
timeout = -1
if hasattr(s, 'gettimeout'):
timeout = s.gettimeout()
# Don't change the timeout if it is already disabled.
if timeout is None or timeout == 0.0:
continue
s.settimeout(None)
@check_resource('container')
def _check_is_tty(self, container):
cont = self.inspect_container(container)
return cont['Config']['Tty']
def _get_result(self, container, stream, res):
return self._get_result_tty(stream, res, self._check_is_tty(container))
def _get_result_tty(self, stream, res, is_tty):
# We should also use raw streaming (without keep-alives)
# if we're dealing with a tty-enabled container.
if is_tty:
return self._stream_raw_result(res) if stream else \
self._result(res, binary=True)
self._raise_for_status(res)
sep = b''
if stream:
return self._multiplexed_response_stream_helper(res)
else:
return sep.join(
list(self._multiplexed_buffer_helper(res))
)
def _unmount(self, *args):
for proto in args:
self.adapters.pop(proto)
def get_adapter(self, url):
try:
return super().get_adapter(url)
except requests.exceptions.InvalidSchema as e:
if self._custom_adapter:
return self._custom_adapter
else:
raise e
@property
def api_version(self):
return self._version
def reload_config(self, dockercfg_path=None):
"""
Force a reload of the auth configuration
Args:
dockercfg_path (str): Use a custom path for the Docker config file
(default ``$HOME/.docker/config.json`` if present,
otherwise ``$HOME/.dockercfg``)
Returns:
None
"""
self._auth_configs = auth.load_config(
dockercfg_path, credstore_env=self.credstore_env
)

92
docker/api/config.py Normal file
View File

@ -0,0 +1,92 @@
import base64
from .. import utils
class ConfigApiMixin:
@utils.minimum_version('1.30')
def create_config(self, name, data, labels=None, templating=None):
"""
Create a config
Args:
name (string): Name of the config
data (bytes): Config data to be stored
labels (dict): A mapping of labels to assign to the config
templating (dict): dictionary containing the name of the
templating driver to be used expressed as
{ name: <templating_driver_name>}
Returns (dict): ID of the newly created config
"""
if not isinstance(data, bytes):
data = data.encode('utf-8')
data = base64.b64encode(data)
data = data.decode('ascii')
body = {
'Data': data,
'Name': name,
'Labels': labels,
'Templating': templating
}
url = self._url('/configs/create')
return self._result(
self._post_json(url, data=body), True
)
@utils.minimum_version('1.30')
@utils.check_resource('id')
def inspect_config(self, id):
"""
Retrieve config metadata
Args:
id (string): Full ID of the config to inspect
Returns (dict): A dictionary of metadata
Raises:
:py:class:`docker.errors.NotFound`
if no config with that ID exists
"""
url = self._url('/configs/{0}', id)
return self._result(self._get(url), True)
@utils.minimum_version('1.30')
@utils.check_resource('id')
def remove_config(self, id):
"""
Remove a config
Args:
id (string): Full ID of the config to remove
Returns (boolean): True if successful
Raises:
:py:class:`docker.errors.NotFound`
if no config with that ID exists
"""
url = self._url('/configs/{0}', id)
res = self._delete(url)
self._raise_for_status(res)
return True
@utils.minimum_version('1.30')
def configs(self, filters=None):
"""
List configs
Args:
filters (dict): A map of filters to process on the configs
list. Available filters: ``names``
Returns (list): A list of configs
"""
url = self._url('/configs')
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
return self._result(self._get(url, params=params), True)

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,64 @@
import os
import warnings
from datetime import datetime
from ..auth import auth
from ..constants import INSECURE_REGISTRY_DEPRECATION_WARNING
from ..utils import utils
from .. import auth, types, utils
class DaemonApiMixin(object):
class DaemonApiMixin:
@utils.minimum_version('1.25')
def df(self):
"""
Get data usage information.
Returns:
(dict): A dictionary representing different resource categories
and their respective data usage.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/system/df')
return self._result(self._get(url), True)
def events(self, since=None, until=None, filters=None, decode=None):
"""
Get real-time events from the server. Similar to the ``docker events``
command.
Args:
since (UTC datetime or int): Get events from this point
until (UTC datetime or int): Get events until this point
filters (dict): Filter the events by event time, container or image
decode (bool): If set to true, stream will be decoded into dicts on
the fly. False by default.
Returns:
A :py:class:`docker.types.daemon.CancellableStream` generator
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> for event in client.events(decode=True)
... print(event)
{u'from': u'image/with:tag',
u'id': u'container-id',
u'status': u'start',
u'time': 1423339459}
...
or
>>> events = client.events()
>>> for event in events:
... print(event)
>>> # and cancel from another thread
>>> events.close()
"""
if isinstance(since, datetime):
since = utils.datetime_to_timestamp(since)
@ -23,35 +73,66 @@ class DaemonApiMixin(object):
'until': until,
'filters': filters
}
url = self._url('/events')
return self._stream_helper(
self.get(self._url('/events'), params=params, stream=True),
decode=decode
)
response = self._get(url, params=params, stream=True, timeout=None)
stream = self._stream_helper(response, decode=decode)
return types.CancellableStream(stream, response)
def info(self):
"""
Display system-wide information. Identical to the ``docker info``
command.
Returns:
(dict): The info as a dict
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self._result(self._get(self._url("/info")), True)
def login(self, username, password=None, email=None, registry=None,
reauth=False, insecure_registry=False, dockercfg_path=None):
if insecure_registry:
warnings.warn(
INSECURE_REGISTRY_DEPRECATION_WARNING.format('login()'),
DeprecationWarning
)
reauth=False, dockercfg_path=None):
"""
Authenticate with a registry. Similar to the ``docker login`` command.
Args:
username (str): The registry username
password (str): The plaintext password
email (str): The email for the registry account
registry (str): URL to the registry. E.g.
``https://index.docker.io/v1/``
reauth (bool): Whether or not to refresh existing authentication on
the Docker server.
dockercfg_path (str): Use a custom path for the Docker config file
(default ``$HOME/.docker/config.json`` if present,
otherwise ``$HOME/.dockercfg``)
Returns:
(dict): The response from the login request
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
# If we don't have any auth data so far, try reloading the config file
# one more time in case anything showed up in there.
# If dockercfg_path is passed check to see if the config file exists,
# if so load that config.
if dockercfg_path and os.path.exists(dockercfg_path):
self._auth_configs = auth.load_config(dockercfg_path)
elif not self._auth_configs:
self._auth_configs = auth.load_config()
self._auth_configs = auth.load_config(
dockercfg_path, credstore_env=self.credstore_env
)
elif not self._auth_configs or self._auth_configs.is_empty:
self._auth_configs = auth.load_config(
credstore_env=self.credstore_env
)
registry = registry or auth.INDEX_URL
authcfg = auth.resolve_authconfig(self._auth_configs, registry)
authcfg = self._auth_configs.resolve_authconfig(registry)
# If we found an existing auth config for this registry and username
# combination, we can return it immediately unless reauth is requested.
if authcfg and authcfg.get('username', None) == username \
@ -67,12 +148,34 @@ class DaemonApiMixin(object):
response = self._post_json(self._url('/auth'), data=req_data)
if response.status_code == 200:
self._auth_configs[registry] = req_data
self._auth_configs.add_auth(registry or auth.INDEX_NAME, req_data)
return self._result(response, json=True)
def ping(self):
return self._result(self._get(self._url('/_ping')))
"""
Checks the server is responsive. An exception will be raised if it
isn't responding.
Returns:
(bool) The response from the server.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self._result(self._get(self._url('/_ping'))) == 'OK'
def version(self, api_version=True):
"""
Returns version information from the server. Similar to the ``docker
version`` command.
Returns:
(dict): The server version information
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url("/version", versioned_api=api_version)
return self._result(self._get(url), json=True)

View File

@ -1,25 +1,54 @@
import six
from .. import errors
from .. import utils
from .. import errors, utils
from ..types import CancellableStream
class ExecApiMixin(object):
@utils.minimum_version('1.15')
@utils.check_resource
class ExecApiMixin:
@utils.check_resource('container')
def exec_create(self, container, cmd, stdout=True, stderr=True,
stdin=False, tty=False, privileged=False, user=''):
if privileged and utils.compare_version('1.19', self._version) < 0:
stdin=False, tty=False, privileged=False, user='',
environment=None, workdir=None, detach_keys=None):
"""
Sets up an exec instance in a running container.
Args:
container (str): Target container where exec instance will be
created
cmd (str or list): Command to be executed
stdout (bool): Attach to stdout. Default: ``True``
stderr (bool): Attach to stderr. Default: ``True``
stdin (bool): Attach to stdin. Default: ``False``
tty (bool): Allocate a pseudo-TTY. Default: False
privileged (bool): Run as privileged.
user (str): User to execute command as. Default: root
environment (dict or list): A dictionary or a list of strings in
the following format ``["PASSWORD=xxx"]`` or
``{"PASSWORD": "xxx"}``.
workdir (str): Path to working directory for this exec session
detach_keys (str): Override the key sequence for detaching
a container. Format is a single character `[a-Z]`
or `ctrl-<value>` where `<value>` is one of:
`a-z`, `@`, `^`, `[`, `,` or `_`.
~/.docker/config.json is used by default.
Returns:
(dict): A dictionary with an exec ``Id`` key.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if environment is not None and utils.version_lt(self._version, '1.25'):
raise errors.InvalidVersion(
'Privileged exec is not supported in API < 1.19'
'Setting environment for exec is not supported in API < 1.25'
)
if user and utils.compare_version('1.19', self._version) < 0:
raise errors.InvalidVersion(
'User-specific exec is not supported in API < 1.19'
)
if isinstance(cmd, six.string_types):
if isinstance(cmd, str):
cmd = utils.split_command(cmd)
if isinstance(environment, dict):
environment = utils.utils.format_environment(environment)
data = {
'Container': container,
'User': user,
@ -28,22 +57,55 @@ class ExecApiMixin(object):
'AttachStdin': stdin,
'AttachStdout': stdout,
'AttachStderr': stderr,
'Cmd': cmd
'Cmd': cmd,
'Env': environment,
}
if workdir is not None:
if utils.version_lt(self._version, '1.35'):
raise errors.InvalidVersion(
'workdir is not supported for API version < 1.35'
)
data['WorkingDir'] = workdir
if detach_keys:
data['detachKeys'] = detach_keys
elif 'detachKeys' in self._general_configs:
data['detachKeys'] = self._general_configs['detachKeys']
url = self._url('/containers/{0}/exec', container)
res = self._post_json(url, data=data)
return self._result(res, True)
@utils.minimum_version('1.16')
def exec_inspect(self, exec_id):
"""
Return low-level information about an exec command.
Args:
exec_id (str): ID of the exec instance
Returns:
(dict): Dictionary of values returned by the endpoint.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if isinstance(exec_id, dict):
exec_id = exec_id.get('Id')
res = self._get(self._url("/exec/{0}/json", exec_id))
return self._result(res, True)
@utils.minimum_version('1.15')
def exec_resize(self, exec_id, height=None, width=None):
"""
Resize the tty session used by the specified exec command.
Args:
exec_id (str): ID of the exec instance
height (int): Height of tty session
width (int): Width of tty session
"""
if isinstance(exec_id, dict):
exec_id = exec_id.get('Id')
@ -52,24 +114,63 @@ class ExecApiMixin(object):
res = self._post(url, params=params)
self._raise_for_status(res)
@utils.minimum_version('1.15')
@utils.check_resource('exec_id')
def exec_start(self, exec_id, detach=False, tty=False, stream=False,
socket=False):
socket=False, demux=False):
"""
Start a previously set up exec instance.
Args:
exec_id (str): ID of the exec instance
detach (bool): If true, detach from the exec command.
Default: False
tty (bool): Allocate a pseudo-TTY. Default: False
stream (bool): Return response data progressively as an iterator
of strings, rather than a single string.
socket (bool): Return the connection socket to allow custom
read/write operations. Must be closed by the caller when done.
demux (bool): Return stdout and stderr separately
Returns:
(generator or str or tuple): If ``stream=True``, a generator
yielding response chunks. If ``socket=True``, a socket object for
the connection. A string containing response data otherwise. If
``demux=True``, a tuple with two elements of type byte: stdout and
stderr.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
# we want opened socket if socket == True
if socket:
stream = True
if isinstance(exec_id, dict):
exec_id = exec_id.get('Id')
data = {
'Tty': tty,
'Detach': detach
}
res = self._post_json(
self._url('/exec/{0}/start', exec_id), data=data, stream=stream
)
headers = {} if detach else {
'Connection': 'Upgrade',
'Upgrade': 'tcp'
}
res = self._post_json(
self._url('/exec/{0}/start', exec_id),
headers=headers,
data=data,
stream=True
)
if detach:
try:
return self._result(res)
finally:
res.close()
if socket:
return self._get_raw_response_socket(res)
return self._get_result_tty(stream, res, tty)
output = self._read_from_socket(res, stream, tty=tty, demux=demux)
if stream:
return CancellableStream(output, res)
else:
return output

View File

@ -1,39 +1,96 @@
import logging
import six
import warnings
import os
from ..auth import auth
from ..constants import INSECURE_REGISTRY_DEPRECATION_WARNING
from .. import utils
from .. import errors
from .. import auth, errors, utils
from ..constants import DEFAULT_DATA_CHUNK_SIZE
log = logging.getLogger(__name__)
class ImageApiMixin(object):
class ImageApiMixin:
@utils.check_resource
def get_image(self, image):
@utils.check_resource('image')
def get_image(self, image, chunk_size=DEFAULT_DATA_CHUNK_SIZE):
"""
Get a tarball of an image. Similar to the ``docker save`` command.
Args:
image (str): Image name to get
chunk_size (int): The number of bytes returned by each iteration
of the generator. If ``None``, data will be streamed as it is
received. Default: 2 MB
Returns:
(generator): A stream of raw archive data.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> image = client.api.get_image("busybox:latest")
>>> f = open('/tmp/busybox-latest.tar', 'wb')
>>> for chunk in image:
>>> f.write(chunk)
>>> f.close()
"""
res = self._get(self._url("/images/{0}/get", image), stream=True)
self._raise_for_status(res)
return res.raw
return self._stream_raw_result(res, chunk_size, False)
@utils.check_resource
@utils.check_resource('image')
def history(self, image):
"""
Show the history of an image.
Args:
image (str): The image to show history for
Returns:
(list): The history of the image
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
res = self._get(self._url("/images/{0}/history", image))
return self._result(res, True)
def images(self, name=None, quiet=False, all=False, viz=False,
filters=None):
if viz:
if utils.compare_version('1.7', self._version) >= 0:
raise Exception('Viz output is not supported in API >= 1.7!')
return self._result(self._get(self._url("images/viz")))
def images(self, name=None, quiet=False, all=False, filters=None):
"""
List images. Similar to the ``docker images`` command.
Args:
name (str): Only show images belonging to the repository ``name``
quiet (bool): Only return numeric IDs as a list.
all (bool): Show intermediate image layers. By default, these are
filtered out.
filters (dict): Filters to be processed on the image list.
Available filters:
- ``dangling`` (bool)
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
Returns:
(dict or list): A list if ``quiet=True``, otherwise a dict.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {
'filter': name,
'only_ids': 1 if quiet else 0,
'all': 1 if all else 0,
}
if name:
if utils.version_lt(self._version, '1.25'):
# only use "filter" on API 1.24 and under, as it is deprecated
params['filter'] = name
else:
if filters:
filters['reference'] = name
else:
filters = {'reference': name}
if filters:
params['filters'] = utils.convert_filters(filters)
res = self._result(self._get(self._url("/images/json"), params=params),
@ -42,121 +99,305 @@ class ImageApiMixin(object):
return [x['Id'] for x in res]
return res
def import_image(self, src=None, repository=None, tag=None, image=None):
if src:
if isinstance(src, six.string_types):
try:
result = self.import_image_from_file(
src, repository=repository, tag=tag)
except IOError:
result = self.import_image_from_url(
src, repository=repository, tag=tag)
else:
result = self.import_image_from_data(
src, repository=repository, tag=tag)
elif image:
result = self.import_image_from_image(
image, repository=repository, tag=tag)
else:
raise Exception("Must specify a src or image")
def import_image(self, src=None, repository=None, tag=None, image=None,
changes=None, stream_src=False):
"""
Import an image. Similar to the ``docker import`` command.
return result
If ``src`` is a string or unicode string, it will first be treated as a
path to a tarball on the local system. If there is an error reading
from that file, ``src`` will be treated as a URL instead to fetch the
image from. You can also pass an open file handle as ``src``, in which
case the data will be read from that file.
def import_image_from_data(self, data, repository=None, tag=None):
u = self._url("/images/create")
params = {
'fromSrc': '-',
'repo': repository,
'tag': tag
}
headers = {
'Content-Type': 'application/tar',
}
return self._result(
self._post(u, data=data, params=params, headers=headers))
If ``src`` is unset but ``image`` is set, the ``image`` parameter will
be taken as the name of an existing image to import from.
def import_image_from_file(self, filename, repository=None, tag=None):
u = self._url("/images/create")
params = {
'fromSrc': '-',
'repo': repository,
'tag': tag
}
headers = {
'Content-Type': 'application/tar',
}
with open(filename, 'rb') as f:
return self._result(
self._post(u, data=f, params=params, headers=headers,
timeout=None))
def import_image_from_stream(self, stream, repository=None, tag=None):
u = self._url("/images/create")
params = {
'fromSrc': '-',
'repo': repository,
'tag': tag
}
headers = {
'Content-Type': 'application/tar',
'Transfer-Encoding': 'chunked',
}
return self._result(
self._post(u, data=stream, params=params, headers=headers))
def import_image_from_url(self, url, repository=None, tag=None):
u = self._url("/images/create")
params = {
'fromSrc': url,
'repo': repository,
'tag': tag
}
return self._result(
self._post(u, data=None, params=params))
def import_image_from_image(self, image, repository=None, tag=None):
u = self._url("/images/create")
params = {
'fromImage': image,
'repo': repository,
'tag': tag
}
return self._result(
self._post(u, data=None, params=params))
@utils.check_resource
def insert(self, image, url, path):
if utils.compare_version('1.12', self._version) >= 0:
raise errors.DeprecatedMethod(
'insert is not available for API version >=1.12'
Args:
src (str or file): Path to tarfile, URL, or file-like object
repository (str): The repository to create
tag (str): The tag to apply
image (str): Use another image like the ``FROM`` Dockerfile
parameter
"""
if not (src or image):
raise errors.DockerException(
'Must specify src or image to import from'
)
api_url = self._url("/images/{0}/insert", image)
params = {
'url': url,
'path': path
}
return self._result(self._post(api_url, params=params))
u = self._url('/images/create')
@utils.check_resource
params = _import_image_params(
repository, tag, image,
src=(src if isinstance(src, str) else None),
changes=changes
)
headers = {'Content-Type': 'application/tar'}
if image or params.get('fromSrc') != '-': # from image or URL
return self._result(
self._post(u, data=None, params=params)
)
elif isinstance(src, str): # from file path
with open(src, 'rb') as f:
return self._result(
self._post(
u, data=f, params=params, headers=headers, timeout=None
)
)
else: # from raw data
if stream_src:
headers['Transfer-Encoding'] = 'chunked'
return self._result(
self._post(u, data=src, params=params, headers=headers)
)
def import_image_from_data(self, data, repository=None, tag=None,
changes=None):
"""
Like :py:meth:`~docker.api.image.ImageApiMixin.import_image`, but
allows importing in-memory bytes data.
Args:
data (bytes collection): Bytes collection containing valid tar data
repository (str): The repository to create
tag (str): The tag to apply
"""
u = self._url('/images/create')
params = _import_image_params(
repository, tag, src='-', changes=changes
)
headers = {'Content-Type': 'application/tar'}
return self._result(
self._post(
u, data=data, params=params, headers=headers, timeout=None
)
)
def import_image_from_file(self, filename, repository=None, tag=None,
changes=None):
"""
Like :py:meth:`~docker.api.image.ImageApiMixin.import_image`, but only
supports importing from a tar file on disk.
Args:
filename (str): Full path to a tar file.
repository (str): The repository to create
tag (str): The tag to apply
Raises:
IOError: File does not exist.
"""
return self.import_image(
src=filename, repository=repository, tag=tag, changes=changes
)
def import_image_from_stream(self, stream, repository=None, tag=None,
changes=None):
return self.import_image(
src=stream, stream_src=True, repository=repository, tag=tag,
changes=changes
)
def import_image_from_url(self, url, repository=None, tag=None,
changes=None):
"""
Like :py:meth:`~docker.api.image.ImageApiMixin.import_image`, but only
supports importing from a URL.
Args:
url (str): A URL pointing to a tar file.
repository (str): The repository to create
tag (str): The tag to apply
"""
return self.import_image(
src=url, repository=repository, tag=tag, changes=changes
)
def import_image_from_image(self, image, repository=None, tag=None,
changes=None):
"""
Like :py:meth:`~docker.api.image.ImageApiMixin.import_image`, but only
supports importing from another image, like the ``FROM`` Dockerfile
parameter.
Args:
image (str): Image name to import from
repository (str): The repository to create
tag (str): The tag to apply
"""
return self.import_image(
image=image, repository=repository, tag=tag, changes=changes
)
@utils.check_resource('image')
def inspect_image(self, image):
"""
Get detailed information about an image. Similar to the ``docker
inspect`` command, but only for images.
Args:
image (str): The image to inspect
Returns:
(dict): Similar to the output of ``docker inspect``, but as a
single dict
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self._result(
self._get(self._url("/images/{0}/json", image)), True
)
def load_image(self, data):
res = self._post(self._url("/images/load"), data=data)
@utils.minimum_version('1.30')
@utils.check_resource('image')
def inspect_distribution(self, image, auth_config=None):
"""
Get image digest and platform information by contacting the registry.
Args:
image (str): The image name to inspect
auth_config (dict): Override the credentials that are found in the
config for this request. ``auth_config`` should contain the
``username`` and ``password`` keys to be valid.
Returns:
(dict): A dict containing distribution data
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
registry, _ = auth.resolve_repository_name(image)
headers = {}
if auth_config is None:
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
else:
log.debug('Sending supplied auth config')
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
url = self._url("/distribution/{0}/json", image)
return self._result(
self._get(url, headers=headers), True
)
def load_image(self, data, quiet=None):
"""
Load an image that was previously saved using
:py:meth:`~docker.api.image.ImageApiMixin.get_image` (or ``docker
save``). Similar to ``docker load``.
Args:
data (binary): Image data to be loaded.
quiet (boolean): Suppress progress details in response.
Returns:
(generator): Progress output as JSON objects. Only available for
API version >= 1.23
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {}
if quiet is not None:
if utils.version_lt(self._version, '1.23'):
raise errors.InvalidVersion(
'quiet is not supported in API version < 1.23'
)
params['quiet'] = quiet
res = self._post(
self._url("/images/load"), data=data, params=params, stream=True
)
if utils.version_gte(self._version, '1.23'):
return self._stream_helper(res, decode=True)
self._raise_for_status(res)
def pull(self, repository, tag=None, stream=False,
insecure_registry=False, auth_config=None, decode=False):
if insecure_registry:
warnings.warn(
INSECURE_REGISTRY_DEPRECATION_WARNING.format('pull()'),
DeprecationWarning
)
@utils.minimum_version('1.25')
def prune_images(self, filters=None):
"""
Delete unused images
Args:
filters (dict): Filters to process on the prune list.
Available filters:
- dangling (bool): When set to true (or 1), prune only
unused and untagged images.
Returns:
(dict): A dict containing a list of deleted image IDs and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url("/images/prune")
params = {}
if filters is not None:
params['filters'] = utils.convert_filters(filters)
return self._result(self._post(url, params=params), True)
def pull(self, repository, tag=None, stream=False, auth_config=None,
decode=False, platform=None, all_tags=False):
"""
Pulls an image. Similar to the ``docker pull`` command.
Args:
repository (str): The repository to pull
tag (str): The tag to pull. If ``tag`` is ``None`` or empty, it
is set to ``latest``.
stream (bool): Stream the output as a generator. Make sure to
consume the generator, otherwise pull might get cancelled.
auth_config (dict): Override the credentials that are found in the
config for this request. ``auth_config`` should contain the
``username`` and ``password`` keys to be valid.
decode (bool): Decode the JSON data from the server into dicts.
Only applies with ``stream=True``
platform (str): Platform in the format ``os[/arch[/variant]]``
all_tags (bool): Pull all image tags, the ``tag`` parameter is
ignored.
Returns:
(generator or str): The output
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> resp = client.api.pull('busybox', stream=True, decode=True)
... for line in resp:
... print(json.dumps(line, indent=4))
{
"status": "Pulling image (latest) from busybox",
"progressDetail": {},
"id": "e72ac664f4f0"
}
{
"status": "Pulling image (latest) from busybox, endpoint: ...",
"progressDetail": {},
"id": "e72ac664f4f0"
}
"""
repository, image_tag = utils.parse_repository_tag(repository)
tag = tag or image_tag or 'latest'
if all_tags:
tag = None
if not tag:
repository, tag = utils.parse_repository_tag(repository)
registry, repo_name = auth.resolve_repository_name(repository)
params = {
@ -165,32 +406,20 @@ class ImageApiMixin(object):
}
headers = {}
if utils.compare_version('1.5', self._version) >= 0:
# If we don't have any auth data so far, try reloading the config
# file one more time in case anything showed up in there.
if auth_config is None:
log.debug('Looking for auth config')
if not self._auth_configs:
log.debug(
"No auth config in memory - loading from filesystem"
)
self._auth_configs = auth.load_config()
authcfg = auth.resolve_authconfig(self._auth_configs, registry)
# Do not fail here if no authentication exists for this
# specific registry as we can have a readonly pull. Just
# put the header if we can.
if authcfg:
log.debug('Found auth config')
# auth_config needs to be a dict in the format used by
# auth.py username , password, serveraddress, email
headers['X-Registry-Auth'] = auth.encode_header(
authcfg
)
else:
log.debug('No auth config found')
else:
log.debug('Sending supplied auth config')
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
if auth_config is None:
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
else:
log.debug('Sending supplied auth config')
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
if platform is not None:
if utils.version_lt(self._version, '1.32'):
raise errors.InvalidVersion(
'platform was only introduced in API version 1.32'
)
params['platform'] = platform
response = self._post(
self._url('/images/create'), params=params, headers=headers,
@ -204,14 +433,44 @@ class ImageApiMixin(object):
return self._result(response)
def push(self, repository, tag=None, stream=False,
insecure_registry=False, decode=False):
if insecure_registry:
warnings.warn(
INSECURE_REGISTRY_DEPRECATION_WARNING.format('push()'),
DeprecationWarning
)
def push(self, repository, tag=None, stream=False, auth_config=None,
decode=False):
"""
Push an image or a repository to the registry. Similar to the ``docker
push`` command.
Args:
repository (str): The repository to push to
tag (str): An optional tag to push
stream (bool): Stream the output as a blocking generator
auth_config (dict): Override the credentials that are found in the
config for this request. ``auth_config`` should contain the
``username`` and ``password`` keys to be valid.
decode (bool): Decode the JSON data from the server into dicts.
Only applies with ``stream=True``
Returns:
(generator or str): The output from the server.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> resp = client.api.push(
... 'yourname/app',
... stream=True,
... decode=True,
... )
... for line in resp:
... print(line)
{'status': 'Pushing repository yourname/app (1 tags)'}
{'status': 'Pushing','progressDetail': {}, 'id': '511136ea3c5a'}
{'status': 'Image already pushed, skipping', 'progressDetail':{},
'id': '511136ea3c5a'}
...
"""
if not tag:
repository, tag = utils.parse_repository_tag(repository)
registry, repo_name = auth.resolve_repository_name(repository)
@ -221,18 +480,13 @@ class ImageApiMixin(object):
}
headers = {}
if utils.compare_version('1.5', self._version) >= 0:
# If we don't have any auth data so far, try reloading the config
# file one more time in case anything showed up in there.
if not self._auth_configs:
self._auth_configs = auth.load_config()
authcfg = auth.resolve_authconfig(self._auth_configs, registry)
# Do not fail here if no authentication exists for this specific
# registry as we can have a readonly pull. Just put the header if
# we can.
if authcfg:
headers['X-Registry-Auth'] = auth.encode_header(authcfg)
if auth_config is None:
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
else:
log.debug('Sending supplied auth config')
headers['X-Registry-Auth'] = auth.encode_header(auth_config)
response = self._post_json(
u, None, headers=headers, stream=stream, params=params
@ -245,20 +499,68 @@ class ImageApiMixin(object):
return self._result(response)
@utils.check_resource
@utils.check_resource('image')
def remove_image(self, image, force=False, noprune=False):
"""
Remove an image. Similar to the ``docker rmi`` command.
Args:
image (str): The image to remove
force (bool): Force removal of the image
noprune (bool): Do not delete untagged parents
"""
params = {'force': force, 'noprune': noprune}
res = self._delete(self._url("/images/{0}", image), params=params)
self._raise_for_status(res)
return self._result(res, True)
def search(self, term, limit=None):
"""
Search for images on Docker Hub. Similar to the ``docker search``
command.
Args:
term (str): A term to search for.
limit (int): The maximum number of results to return.
Returns:
(list of dicts): The response of the search.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {'term': term}
if limit is not None:
params['limit'] = limit
def search(self, term):
return self._result(
self._get(self._url("/images/search"), params={'term': term}),
self._get(self._url("/images/search"), params=params),
True
)
@utils.check_resource
@utils.check_resource('image')
def tag(self, image, repository, tag=None, force=False):
"""
Tag an image into a repository. Similar to the ``docker tag`` command.
Args:
image (str): The image to tag
repository (str): The repository to set for the tag
tag (str): The tag name
force (bool): Force
Returns:
(bool): ``True`` if successful
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> client.api.tag('ubuntu', 'localhost:5000/ubuntu', 'latest',
force=True)
"""
params = {
'tag': tag,
'repo': repository,
@ -268,3 +570,32 @@ class ImageApiMixin(object):
res = self._post(url, params=params)
self._raise_for_status(res)
return res.status_code == 201
def is_file(src):
try:
return (
isinstance(src, str) and
os.path.isfile(src)
)
except TypeError: # a data string will make isfile() raise a TypeError
return False
def _import_image_params(repo, tag, image=None, src=None,
changes=None):
params = {
'repo': repo,
'tag': tag,
}
if image:
params['fromImage'] = image
elif src and not is_file(src):
params['fromSrc'] = src
else:
params['fromSrc'] = '-'
if changes:
params['changes'] = changes
return params

View File

@ -1,28 +1,97 @@
import json
from .. import utils
from ..errors import InvalidVersion
from ..utils import check_resource, minimum_version, normalize_links
from ..utils import version_lt
from ..utils import check_resource, minimum_version, version_lt
class NetworkApiMixin(object):
@minimum_version('1.21')
def networks(self, names=None, ids=None):
filters = {}
class NetworkApiMixin:
def networks(self, names=None, ids=None, filters=None):
"""
List networks. Similar to the ``docker network ls`` command.
Args:
names (:py:class:`list`): List of names to filter by
ids (:py:class:`list`): List of ids to filter by
filters (dict): Filters to be processed on the network list.
Available filters:
- ``driver=[<driver-name>]`` Matches a network's driver.
- ``label=[<key>]``, ``label=[<key>=<value>]`` or a list of
such.
- ``type=["custom"|"builtin"]`` Filters networks by type.
Returns:
(dict): List of network objects.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if filters is None:
filters = {}
if names:
filters['name'] = names
if ids:
filters['id'] = ids
params = {'filters': json.dumps(filters)}
params = {'filters': utils.convert_filters(filters)}
url = self._url("/networks")
res = self._get(url, params=params)
return self._result(res, json=True)
@minimum_version('1.21')
def create_network(self, name, driver=None, options=None, ipam=None,
check_duplicate=None):
check_duplicate=None, internal=False, labels=None,
enable_ipv6=False, attachable=None, scope=None,
ingress=None):
"""
Create a network. Similar to the ``docker network create``.
Args:
name (str): Name of the network
driver (str): Name of the driver used to create the network
options (dict): Driver options as a key-value dictionary
ipam (IPAMConfig): Optional custom IP scheme for the network.
check_duplicate (bool): Request daemon to check for networks with
same name. Default: ``None``.
internal (bool): Restrict external access to the network. Default
``False``.
labels (dict): Map of labels to set on the network. Default
``None``.
enable_ipv6 (bool): Enable IPv6 on the network. Default ``False``.
attachable (bool): If enabled, and the network is in the global
scope, non-service containers on worker nodes will be able to
connect to the network.
scope (str): Specify the network's scope (``local``, ``global`` or
``swarm``)
ingress (bool): If set, create an ingress network which provides
the routing-mesh in swarm mode.
Returns:
(dict): The created network reference object
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
A network using the bridge driver:
>>> client.api.create_network("network1", driver="bridge")
You can also create more advanced networks with custom IPAM
configurations. For example, setting the subnet to
``192.168.52.0/24`` and gateway address to ``192.168.52.254``.
.. code-block:: python
>>> ipam_pool = docker.types.IPAMPool(
subnet='192.168.52.0/24',
gateway='192.168.52.254'
)
>>> ipam_config = docker.types.IPAMConfig(
pool_configs=[ipam_pool]
)
>>> client.api.create_network("network1", driver="bridge",
ipam=ipam_config)
"""
if options is not None and not isinstance(options, dict):
raise TypeError('options must be a dictionary')
@ -31,59 +100,178 @@ class NetworkApiMixin(object):
'Driver': driver,
'Options': options,
'IPAM': ipam,
'CheckDuplicate': check_duplicate
'CheckDuplicate': check_duplicate,
}
if labels is not None:
if version_lt(self._version, '1.23'):
raise InvalidVersion(
'network labels were introduced in API 1.23'
)
if not isinstance(labels, dict):
raise TypeError('labels must be a dictionary')
data["Labels"] = labels
if enable_ipv6:
if version_lt(self._version, '1.23'):
raise InvalidVersion(
'enable_ipv6 was introduced in API 1.23'
)
data['EnableIPv6'] = True
if internal:
if version_lt(self._version, '1.22'):
raise InvalidVersion('Internal networks are not '
'supported in API version < 1.22')
data['Internal'] = True
if attachable is not None:
if version_lt(self._version, '1.24'):
raise InvalidVersion(
'attachable is not supported in API version < 1.24'
)
data['Attachable'] = attachable
if ingress is not None:
if version_lt(self._version, '1.29'):
raise InvalidVersion(
'ingress is not supported in API version < 1.29'
)
data['Ingress'] = ingress
if scope is not None:
if version_lt(self._version, '1.30'):
raise InvalidVersion(
'scope is not supported in API version < 1.30'
)
data['Scope'] = scope
url = self._url("/networks/create")
res = self._post_json(url, data=data)
return self._result(res, json=True)
@minimum_version('1.21')
@minimum_version('1.25')
def prune_networks(self, filters=None):
"""
Delete unused networks
Args:
filters (dict): Filters to process on the prune list.
Returns:
(dict): A dict containing a list of deleted network names and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
url = self._url('/networks/prune')
return self._result(self._post(url, params=params), True)
@check_resource('net_id')
def remove_network(self, net_id):
"""
Remove a network. Similar to the ``docker network rm`` command.
Args:
net_id (str): The network's id
"""
url = self._url("/networks/{0}", net_id)
res = self._delete(url)
self._raise_for_status(res)
@minimum_version('1.21')
def inspect_network(self, net_id):
@check_resource('net_id')
def inspect_network(self, net_id, verbose=None, scope=None):
"""
Get detailed information about a network.
Args:
net_id (str): ID of network
verbose (bool): Show the service details across the cluster in
swarm mode.
scope (str): Filter the network by scope (``swarm``, ``global``
or ``local``).
"""
params = {}
if verbose is not None:
if version_lt(self._version, '1.28'):
raise InvalidVersion('verbose was introduced in API 1.28')
params['verbose'] = verbose
if scope is not None:
if version_lt(self._version, '1.31'):
raise InvalidVersion('scope was introduced in API 1.31')
params['scope'] = scope
url = self._url("/networks/{0}", net_id)
res = self._get(url)
res = self._get(url, params=params)
return self._result(res, json=True)
@check_resource
@minimum_version('1.21')
@check_resource('container')
def connect_container_to_network(self, container, net_id,
ipv4_address=None, ipv6_address=None,
aliases=None, links=None):
aliases=None, links=None,
link_local_ips=None, driver_opt=None,
mac_address=None):
"""
Connect a container to a network.
Args:
container (str): container-id/name to be connected to the network
net_id (str): network id
aliases (:py:class:`list`): A list of aliases for this endpoint.
Names in that list can be used within the network to reach the
container. Defaults to ``None``.
links (:py:class:`list`): A list of links for this endpoint.
Containers declared in this list will be linked to this
container. Defaults to ``None``.
ipv4_address (str): The IP address of this container on the
network, using the IPv4 protocol. Defaults to ``None``.
ipv6_address (str): The IP address of this container on the
network, using the IPv6 protocol. Defaults to ``None``.
link_local_ips (:py:class:`list`): A list of link-local
(IPv4/IPv6) addresses.
mac_address (str): The MAC address of this container on the
network. Defaults to ``None``.
"""
data = {
"Container": container,
"EndpointConfig": {
"Aliases": aliases,
"Links": normalize_links(links) if links else None,
},
"EndpointConfig": self.create_endpoint_config(
aliases=aliases, links=links, ipv4_address=ipv4_address,
ipv6_address=ipv6_address, link_local_ips=link_local_ips,
driver_opt=driver_opt,
mac_address=mac_address
),
}
# IPv4 or IPv6 or neither:
if ipv4_address or ipv6_address:
if version_lt(self._version, '1.22'):
raise InvalidVersion('IP address assignment is not '
'supported in API version < 1.22')
data['EndpointConfig']['IPAMConfig'] = dict()
if ipv4_address:
data['EndpointConfig']['IPAMConfig']['IPv4Address'] = \
ipv4_address
if ipv6_address:
data['EndpointConfig']['IPAMConfig']['IPv6Address'] = \
ipv6_address
url = self._url("/networks/{0}/connect", net_id)
res = self._post_json(url, data=data)
self._raise_for_status(res)
@check_resource
@minimum_version('1.21')
def disconnect_container_from_network(self, container, net_id):
data = {"container": container}
@check_resource('container')
def disconnect_container_from_network(self, container, net_id,
force=False):
"""
Disconnect a container from a network.
Args:
container (str): container ID or name to be disconnected from the
network
net_id (str): network ID
force (bool): Force the container to disconnect from a network.
Default: ``False``
"""
data = {"Container": container}
if force:
if version_lt(self._version, '1.22'):
raise InvalidVersion(
'Forced disconnect was introduced in API 1.22'
)
data['Force'] = force
url = self._url("/networks/{0}/disconnect", net_id)
res = self._post_json(url, data=data)
self._raise_for_status(res)

261
docker/api/plugin.py Normal file
View File

@ -0,0 +1,261 @@
from .. import auth, utils
class PluginApiMixin:
@utils.minimum_version('1.25')
@utils.check_resource('name')
def configure_plugin(self, name, options):
"""
Configure a plugin.
Args:
name (string): The name of the plugin. The ``:latest`` tag is
optional, and is the default if omitted.
options (dict): A key-value mapping of options
Returns:
``True`` if successful
"""
url = self._url('/plugins/{0}/set', name)
data = options
if isinstance(data, dict):
data = [f'{k}={v}' for k, v in data.items()]
res = self._post_json(url, data=data)
self._raise_for_status(res)
return True
@utils.minimum_version('1.25')
def create_plugin(self, name, plugin_data_dir, gzip=False):
"""
Create a new plugin.
Args:
name (string): The name of the plugin. The ``:latest`` tag is
optional, and is the default if omitted.
plugin_data_dir (string): Path to the plugin data directory.
Plugin data directory must contain the ``config.json``
manifest file and the ``rootfs`` directory.
gzip (bool): Compress the context using gzip. Default: False
Returns:
``True`` if successful
"""
url = self._url('/plugins/create')
with utils.create_archive(
root=plugin_data_dir, gzip=gzip,
files=set(utils.build.walk(plugin_data_dir, []))
) as archv:
res = self._post(url, params={'name': name}, data=archv)
self._raise_for_status(res)
return True
@utils.minimum_version('1.25')
def disable_plugin(self, name, force=False):
"""
Disable an installed plugin.
Args:
name (string): The name of the plugin. The ``:latest`` tag is
optional, and is the default if omitted.
force (bool): To enable the force query parameter.
Returns:
``True`` if successful
"""
url = self._url('/plugins/{0}/disable', name)
res = self._post(url, params={'force': force})
self._raise_for_status(res)
return True
@utils.minimum_version('1.25')
def enable_plugin(self, name, timeout=0):
"""
Enable an installed plugin.
Args:
name (string): The name of the plugin. The ``:latest`` tag is
optional, and is the default if omitted.
timeout (int): Operation timeout (in seconds). Default: 0
Returns:
``True`` if successful
"""
url = self._url('/plugins/{0}/enable', name)
params = {'timeout': timeout}
res = self._post(url, params=params)
self._raise_for_status(res)
return True
@utils.minimum_version('1.25')
def inspect_plugin(self, name):
"""
Retrieve plugin metadata.
Args:
name (string): The name of the plugin. The ``:latest`` tag is
optional, and is the default if omitted.
Returns:
A dict containing plugin info
"""
url = self._url('/plugins/{0}/json', name)
return self._result(self._get(url), True)
@utils.minimum_version('1.25')
def pull_plugin(self, remote, privileges, name=None):
"""
Pull and install a plugin. After the plugin is installed, it can be
enabled using :py:meth:`~enable_plugin`.
Args:
remote (string): Remote reference for the plugin to install.
The ``:latest`` tag is optional, and is the default if
omitted.
privileges (:py:class:`list`): A list of privileges the user
consents to grant to the plugin. Can be retrieved using
:py:meth:`~plugin_privileges`.
name (string): Local name for the pulled plugin. The
``:latest`` tag is optional, and is the default if omitted.
Returns:
An iterable object streaming the decoded API logs
"""
url = self._url('/plugins/pull')
params = {
'remote': remote,
}
if name:
params['name'] = name
headers = {}
registry, repo_name = auth.resolve_repository_name(remote)
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
response = self._post_json(
url, params=params, headers=headers, data=privileges,
stream=True
)
self._raise_for_status(response)
return self._stream_helper(response, decode=True)
@utils.minimum_version('1.25')
def plugins(self):
"""
Retrieve a list of installed plugins.
Returns:
A list of dicts, one per plugin
"""
url = self._url('/plugins')
return self._result(self._get(url), True)
@utils.minimum_version('1.25')
def plugin_privileges(self, name):
"""
Retrieve list of privileges to be granted to a plugin.
Args:
name (string): Name of the remote plugin to examine. The
``:latest`` tag is optional, and is the default if omitted.
Returns:
A list of dictionaries representing the plugin's
permissions
"""
params = {
'remote': name,
}
headers = {}
registry, repo_name = auth.resolve_repository_name(name)
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
url = self._url('/plugins/privileges')
return self._result(
self._get(url, params=params, headers=headers), True
)
@utils.minimum_version('1.25')
@utils.check_resource('name')
def push_plugin(self, name):
"""
Push a plugin to the registry.
Args:
name (string): Name of the plugin to upload. The ``:latest``
tag is optional, and is the default if omitted.
Returns:
``True`` if successful
"""
url = self._url('/plugins/{0}/pull', name)
headers = {}
registry, repo_name = auth.resolve_repository_name(name)
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
res = self._post(url, headers=headers)
self._raise_for_status(res)
return self._stream_helper(res, decode=True)
@utils.minimum_version('1.25')
@utils.check_resource('name')
def remove_plugin(self, name, force=False):
"""
Remove an installed plugin.
Args:
name (string): Name of the plugin to remove. The ``:latest``
tag is optional, and is the default if omitted.
force (bool): Disable the plugin before removing. This may
result in issues if the plugin is in use by a container.
Returns:
``True`` if successful
"""
url = self._url('/plugins/{0}', name)
res = self._delete(url, params={'force': force})
self._raise_for_status(res)
return True
@utils.minimum_version('1.26')
@utils.check_resource('name')
def upgrade_plugin(self, name, remote, privileges):
"""
Upgrade an installed plugin.
Args:
name (string): Name of the plugin to upgrade. The ``:latest``
tag is optional and is the default if omitted.
remote (string): Remote reference to upgrade to. The
``:latest`` tag is optional and is the default if omitted.
privileges (:py:class:`list`): A list of privileges the user
consents to grant to the plugin. Can be retrieved using
:py:meth:`~plugin_privileges`.
Returns:
An iterable object streaming the decoded API logs
"""
url = self._url('/plugins/{0}/upgrade', name)
params = {
'remote': remote,
}
headers = {}
registry, repo_name = auth.resolve_repository_name(remote)
header = auth.get_config_header(self, registry)
if header:
headers['X-Registry-Auth'] = header
response = self._post_json(
url, params=params, headers=headers, data=privileges,
stream=True
)
self._raise_for_status(response)
return self._stream_helper(response, decode=True)

98
docker/api/secret.py Normal file
View File

@ -0,0 +1,98 @@
import base64
from .. import errors, utils
class SecretApiMixin:
@utils.minimum_version('1.25')
def create_secret(self, name, data, labels=None, driver=None):
"""
Create a secret
Args:
name (string): Name of the secret
data (bytes): Secret data to be stored
labels (dict): A mapping of labels to assign to the secret
driver (DriverConfig): A custom driver configuration. If
unspecified, the default ``internal`` driver will be used
Returns (dict): ID of the newly created secret
"""
if not isinstance(data, bytes):
data = data.encode('utf-8')
data = base64.b64encode(data)
data = data.decode('ascii')
body = {
'Data': data,
'Name': name,
'Labels': labels
}
if driver is not None:
if utils.version_lt(self._version, '1.31'):
raise errors.InvalidVersion(
'Secret driver is only available for API version > 1.31'
)
body['Driver'] = driver
url = self._url('/secrets/create')
return self._result(
self._post_json(url, data=body), True
)
@utils.minimum_version('1.25')
@utils.check_resource('id')
def inspect_secret(self, id):
"""
Retrieve secret metadata
Args:
id (string): Full ID of the secret to inspect
Returns (dict): A dictionary of metadata
Raises:
:py:class:`docker.errors.NotFound`
if no secret with that ID exists
"""
url = self._url('/secrets/{0}', id)
return self._result(self._get(url), True)
@utils.minimum_version('1.25')
@utils.check_resource('id')
def remove_secret(self, id):
"""
Remove a secret
Args:
id (string): Full ID of the secret to remove
Returns (boolean): True if successful
Raises:
:py:class:`docker.errors.NotFound`
if no secret with that ID exists
"""
url = self._url('/secrets/{0}', id)
res = self._delete(url)
self._raise_for_status(res)
return True
@utils.minimum_version('1.25')
def secrets(self, filters=None):
"""
List secrets
Args:
filters (dict): A map of filters to process on the secrets
list. Available filters: ``names``
Returns (list): A list of secrets
"""
url = self._url('/secrets')
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
return self._result(self._get(url, params=params), True)

486
docker/api/service.py Normal file
View File

@ -0,0 +1,486 @@
from .. import auth, errors, utils
from ..types import ServiceMode
def _check_api_features(version, task_template, update_config, endpoint_spec,
rollback_config):
def raise_version_error(param, min_version):
raise errors.InvalidVersion(
f'{param} is not supported in API version < {min_version}'
)
if update_config is not None:
if utils.version_lt(version, '1.25'):
if 'MaxFailureRatio' in update_config:
raise_version_error('UpdateConfig.max_failure_ratio', '1.25')
if 'Monitor' in update_config:
raise_version_error('UpdateConfig.monitor', '1.25')
if utils.version_lt(version, '1.28'):
if update_config.get('FailureAction') == 'rollback':
raise_version_error(
'UpdateConfig.failure_action rollback', '1.28'
)
if utils.version_lt(version, '1.29'):
if 'Order' in update_config:
raise_version_error('UpdateConfig.order', '1.29')
if rollback_config is not None:
if utils.version_lt(version, '1.28'):
raise_version_error('rollback_config', '1.28')
if utils.version_lt(version, '1.29'):
if 'Order' in update_config:
raise_version_error('RollbackConfig.order', '1.29')
if endpoint_spec is not None:
if utils.version_lt(version, '1.32') and 'Ports' in endpoint_spec:
if any(p.get('PublishMode') for p in endpoint_spec['Ports']):
raise_version_error('EndpointSpec.Ports[].mode', '1.32')
if task_template is not None:
if 'ForceUpdate' in task_template and utils.version_lt(
version, '1.25'):
raise_version_error('force_update', '1.25')
if task_template.get('Placement'):
if utils.version_lt(version, '1.30'):
if task_template['Placement'].get('Platforms'):
raise_version_error('Placement.platforms', '1.30')
if utils.version_lt(version, '1.27'):
if task_template['Placement'].get('Preferences'):
raise_version_error('Placement.preferences', '1.27')
if task_template.get('ContainerSpec'):
container_spec = task_template.get('ContainerSpec')
if utils.version_lt(version, '1.25'):
if container_spec.get('TTY'):
raise_version_error('ContainerSpec.tty', '1.25')
if container_spec.get('Hostname') is not None:
raise_version_error('ContainerSpec.hostname', '1.25')
if container_spec.get('Hosts') is not None:
raise_version_error('ContainerSpec.hosts', '1.25')
if container_spec.get('Groups') is not None:
raise_version_error('ContainerSpec.groups', '1.25')
if container_spec.get('DNSConfig') is not None:
raise_version_error('ContainerSpec.dns_config', '1.25')
if container_spec.get('Healthcheck') is not None:
raise_version_error('ContainerSpec.healthcheck', '1.25')
if utils.version_lt(version, '1.28'):
if container_spec.get('ReadOnly') is not None:
raise_version_error('ContainerSpec.dns_config', '1.28')
if container_spec.get('StopSignal') is not None:
raise_version_error('ContainerSpec.stop_signal', '1.28')
if utils.version_lt(version, '1.30'):
if container_spec.get('Configs') is not None:
raise_version_error('ContainerSpec.configs', '1.30')
if container_spec.get('Privileges') is not None:
raise_version_error('ContainerSpec.privileges', '1.30')
if utils.version_lt(version, '1.35'):
if container_spec.get('Isolation') is not None:
raise_version_error('ContainerSpec.isolation', '1.35')
if utils.version_lt(version, '1.38'):
if container_spec.get('Init') is not None:
raise_version_error('ContainerSpec.init', '1.38')
if task_template.get('Resources'):
if utils.version_lt(version, '1.32'):
if task_template['Resources'].get('GenericResources'):
raise_version_error('Resources.generic_resources', '1.32')
def _merge_task_template(current, override):
merged = current.copy()
if override is not None:
for ts_key, ts_value in override.items():
if ts_key == 'ContainerSpec':
if 'ContainerSpec' not in merged:
merged['ContainerSpec'] = {}
for cs_key, cs_value in override['ContainerSpec'].items():
if cs_value is not None:
merged['ContainerSpec'][cs_key] = cs_value
elif ts_value is not None:
merged[ts_key] = ts_value
return merged
class ServiceApiMixin:
@utils.minimum_version('1.24')
def create_service(
self, task_template, name=None, labels=None, mode=None,
update_config=None, networks=None, endpoint_config=None,
endpoint_spec=None, rollback_config=None
):
"""
Create a service.
Args:
task_template (TaskTemplate): Specification of the task to start as
part of the new service.
name (string): User-defined name for the service. Optional.
labels (dict): A map of labels to associate with the service.
Optional.
mode (ServiceMode): Scheduling mode for the service (replicated
or global). Defaults to replicated.
update_config (UpdateConfig): Specification for the update strategy
of the service. Default: ``None``
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
networks (:py:class:`list`): List of network names or IDs or
:py:class:`~docker.types.NetworkAttachmentConfig` to attach the
service to. Default: ``None``.
endpoint_spec (EndpointSpec): Properties that can be configured to
access and load balance a service. Default: ``None``.
Returns:
A dictionary containing an ``ID`` key for the newly created
service.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
_check_api_features(
self._version, task_template, update_config, endpoint_spec,
rollback_config
)
url = self._url('/services/create')
headers = {}
image = task_template.get('ContainerSpec', {}).get('Image', None)
if image is None:
raise errors.DockerException(
'Missing mandatory Image key in ContainerSpec'
)
if mode and not isinstance(mode, dict):
mode = ServiceMode(mode)
registry, repo_name = auth.resolve_repository_name(image)
auth_header = auth.get_config_header(self, registry)
if auth_header:
headers['X-Registry-Auth'] = auth_header
if utils.version_lt(self._version, '1.25'):
networks = networks or task_template.pop('Networks', None)
data = {
'Name': name,
'Labels': labels,
'TaskTemplate': task_template,
'Mode': mode,
'Networks': utils.convert_service_networks(networks),
'EndpointSpec': endpoint_spec
}
if update_config is not None:
data['UpdateConfig'] = update_config
if rollback_config is not None:
data['RollbackConfig'] = rollback_config
return self._result(
self._post_json(url, data=data, headers=headers), True
)
@utils.minimum_version('1.24')
@utils.check_resource('service')
def inspect_service(self, service, insert_defaults=None):
"""
Return information about a service.
Args:
service (str): Service name or ID.
insert_defaults (boolean): If true, default values will be merged
into the service inspect output.
Returns:
(dict): A dictionary of the server-side representation of the
service, including all relevant properties.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/services/{0}', service)
params = {}
if insert_defaults is not None:
if utils.version_lt(self._version, '1.29'):
raise errors.InvalidVersion(
'insert_defaults is not supported in API version < 1.29'
)
params['insertDefaults'] = insert_defaults
return self._result(self._get(url, params=params), True)
@utils.minimum_version('1.24')
@utils.check_resource('task')
def inspect_task(self, task):
"""
Retrieve information about a task.
Args:
task (str): Task ID
Returns:
(dict): Information about the task.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/tasks/{0}', task)
return self._result(self._get(url), True)
@utils.minimum_version('1.24')
@utils.check_resource('service')
def remove_service(self, service):
"""
Stop and remove a service.
Args:
service (str): Service name or ID
Returns:
``True`` if successful.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/services/{0}', service)
resp = self._delete(url)
self._raise_for_status(resp)
return True
@utils.minimum_version('1.24')
def services(self, filters=None, status=None):
"""
List services.
Args:
filters (dict): Filters to process on the nodes list. Valid
filters: ``id``, ``name`` , ``label`` and ``mode``.
Default: ``None``.
status (bool): Include the service task count of running and
desired tasks. Default: ``None``.
Returns:
A list of dictionaries containing data about each service.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {
'filters': utils.convert_filters(filters) if filters else None
}
if status is not None:
if utils.version_lt(self._version, '1.41'):
raise errors.InvalidVersion(
'status is not supported in API version < 1.41'
)
params['status'] = status
url = self._url('/services')
return self._result(self._get(url, params=params), True)
@utils.minimum_version('1.25')
@utils.check_resource('service')
def service_logs(self, service, details=False, follow=False, stdout=False,
stderr=False, since=0, timestamps=False, tail='all',
is_tty=None):
"""
Get log stream for a service.
Note: This endpoint works only for services with the ``json-file``
or ``journald`` logging drivers.
Args:
service (str): ID or name of the service
details (bool): Show extra details provided to logs.
Default: ``False``
follow (bool): Keep connection open to read logs as they are
sent by the Engine. Default: ``False``
stdout (bool): Return logs from ``stdout``. Default: ``False``
stderr (bool): Return logs from ``stderr``. Default: ``False``
since (int): UNIX timestamp for the logs staring point.
Default: 0
timestamps (bool): Add timestamps to every log line.
tail (string or int): Number of log lines to be returned,
counting from the current end of the logs. Specify an
integer or ``'all'`` to output all log lines.
Default: ``all``
is_tty (bool): Whether the service's :py:class:`ContainerSpec`
enables the TTY option. If omitted, the method will query
the Engine for the information, causing an additional
roundtrip.
Returns (generator): Logs for the service.
"""
params = {
'details': details,
'follow': follow,
'stdout': stdout,
'stderr': stderr,
'since': since,
'timestamps': timestamps,
'tail': tail
}
url = self._url('/services/{0}/logs', service)
res = self._get(url, params=params, stream=True)
if is_tty is None:
is_tty = self.inspect_service(
service
)['Spec']['TaskTemplate']['ContainerSpec'].get('TTY', False)
return self._get_result_tty(True, res, is_tty)
@utils.minimum_version('1.24')
def tasks(self, filters=None):
"""
Retrieve a list of tasks.
Args:
filters (dict): A map of filters to process on the tasks list.
Valid filters: ``id``, ``name``, ``service``, ``node``,
``label`` and ``desired-state``.
Returns:
(:py:class:`list`): List of task dictionaries.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {
'filters': utils.convert_filters(filters) if filters else None
}
url = self._url('/tasks')
return self._result(self._get(url, params=params), True)
@utils.minimum_version('1.24')
@utils.check_resource('service')
def update_service(self, service, version, task_template=None, name=None,
labels=None, mode=None, update_config=None,
networks=None, endpoint_config=None,
endpoint_spec=None, fetch_current_spec=False,
rollback_config=None):
"""
Update a service.
Args:
service (string): A service identifier (either its name or service
ID).
version (int): The version number of the service object being
updated. This is required to avoid conflicting writes.
task_template (TaskTemplate): Specification of the updated task to
start as part of the service.
name (string): New name for the service. Optional.
labels (dict): A map of labels to associate with the service.
Optional.
mode (ServiceMode): Scheduling mode for the service (replicated
or global). Defaults to replicated.
update_config (UpdateConfig): Specification for the update strategy
of the service. Default: ``None``.
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
networks (:py:class:`list`): List of network names or IDs or
:py:class:`~docker.types.NetworkAttachmentConfig` to attach the
service to. Default: ``None``.
endpoint_spec (EndpointSpec): Properties that can be configured to
access and load balance a service. Default: ``None``.
fetch_current_spec (boolean): Use the undefined settings from the
current specification of the service. Default: ``False``
Returns:
A dictionary containing a ``Warnings`` key.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
_check_api_features(
self._version, task_template, update_config, endpoint_spec,
rollback_config
)
if fetch_current_spec:
inspect_defaults = True
if utils.version_lt(self._version, '1.29'):
inspect_defaults = None
current = self.inspect_service(
service, insert_defaults=inspect_defaults
)['Spec']
else:
current = {}
url = self._url('/services/{0}/update', service)
data = {}
headers = {}
data['Name'] = current.get('Name') if name is None else name
data['Labels'] = current.get('Labels') if labels is None else labels
if mode is not None:
if not isinstance(mode, dict):
mode = ServiceMode(mode)
data['Mode'] = mode
else:
data['Mode'] = current.get('Mode')
data['TaskTemplate'] = _merge_task_template(
current.get('TaskTemplate', {}), task_template
)
container_spec = data['TaskTemplate'].get('ContainerSpec', {})
image = container_spec.get('Image', None)
if image is not None:
registry, repo_name = auth.resolve_repository_name(image)
auth_header = auth.get_config_header(self, registry)
if auth_header:
headers['X-Registry-Auth'] = auth_header
if update_config is not None:
data['UpdateConfig'] = update_config
else:
data['UpdateConfig'] = current.get('UpdateConfig')
if rollback_config is not None:
data['RollbackConfig'] = rollback_config
else:
data['RollbackConfig'] = current.get('RollbackConfig')
if networks is not None:
converted_networks = utils.convert_service_networks(networks)
if utils.version_lt(self._version, '1.25'):
data['Networks'] = converted_networks
else:
data['TaskTemplate']['Networks'] = converted_networks
elif utils.version_lt(self._version, '1.25'):
data['Networks'] = current.get('Networks')
elif data['TaskTemplate'].get('Networks') is None:
current_task_template = current.get('TaskTemplate', {})
current_networks = current_task_template.get('Networks')
if current_networks is None:
current_networks = current.get('Networks')
if current_networks is not None:
data['TaskTemplate']['Networks'] = current_networks
if endpoint_spec is not None:
data['EndpointSpec'] = endpoint_spec
else:
data['EndpointSpec'] = current.get('EndpointSpec')
resp = self._post_json(
url, data=data, params={'version': version}, headers=headers
)
return self._result(resp, json=True)

462
docker/api/swarm.py Normal file
View File

@ -0,0 +1,462 @@
import http.client as http_client
import logging
from .. import errors, types, utils
from ..constants import DEFAULT_SWARM_ADDR_POOL, DEFAULT_SWARM_SUBNET_SIZE
log = logging.getLogger(__name__)
class SwarmApiMixin:
def create_swarm_spec(self, *args, **kwargs):
"""
Create a :py:class:`docker.types.SwarmSpec` instance that can be used
as the ``swarm_spec`` argument in
:py:meth:`~docker.api.swarm.SwarmApiMixin.init_swarm`.
Args:
task_history_retention_limit (int): Maximum number of tasks
history stored.
snapshot_interval (int): Number of logs entries between snapshot.
keep_old_snapshots (int): Number of snapshots to keep beyond the
current snapshot.
log_entries_for_slow_followers (int): Number of log entries to
keep around to sync up slow followers after a snapshot is
created.
heartbeat_tick (int): Amount of ticks (in seconds) between each
heartbeat.
election_tick (int): Amount of ticks (in seconds) needed without a
leader to trigger a new election.
dispatcher_heartbeat_period (int): The delay for an agent to send
a heartbeat to the dispatcher.
node_cert_expiry (int): Automatic expiry for nodes certificates.
external_cas (:py:class:`list`): Configuration for forwarding
signing requests to an external certificate authority. Use
a list of :py:class:`docker.types.SwarmExternalCA`.
name (string): Swarm's name
labels (dict): User-defined key/value metadata.
signing_ca_cert (str): The desired signing CA certificate for all
swarm node TLS leaf certificates, in PEM format.
signing_ca_key (str): The desired signing CA key for all swarm
node TLS leaf certificates, in PEM format.
ca_force_rotate (int): An integer whose purpose is to force swarm
to generate a new signing CA certificate and key, if none have
been specified.
autolock_managers (boolean): If set, generate a key and use it to
lock data stored on the managers.
log_driver (DriverConfig): The default log driver to use for tasks
created in the orchestrator.
Returns:
:py:class:`docker.types.SwarmSpec`
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> spec = client.api.create_swarm_spec(
snapshot_interval=5000, log_entries_for_slow_followers=1200
)
>>> client.api.init_swarm(
advertise_addr='eth0', listen_addr='0.0.0.0:5000',
force_new_cluster=False, swarm_spec=spec
)
"""
ext_ca = kwargs.pop('external_ca', None)
if ext_ca:
kwargs['external_cas'] = [ext_ca]
return types.SwarmSpec(self._version, *args, **kwargs)
@utils.minimum_version('1.24')
def get_unlock_key(self):
"""
Get the unlock key for this Swarm manager.
Returns:
A ``dict`` containing an ``UnlockKey`` member
"""
return self._result(self._get(self._url('/swarm/unlockkey')), True)
@utils.minimum_version('1.24')
def init_swarm(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
force_new_cluster=False, swarm_spec=None,
default_addr_pool=None, subnet_size=None,
data_path_addr=None, data_path_port=None):
"""
Initialize a new Swarm using the current connected engine as the first
node.
Args:
advertise_addr (string): Externally reachable address advertised
to other nodes. This can either be an address/port combination
in the form ``192.168.1.1:4567``, or an interface followed by a
port number, like ``eth0:4567``. If the port number is omitted,
the port number from the listen address is used. If
``advertise_addr`` is not specified, it will be automatically
detected when possible. Default: None
listen_addr (string): Listen address used for inter-manager
communication, as well as determining the networking interface
used for the VXLAN Tunnel Endpoint (VTEP). This can either be
an address/port combination in the form ``192.168.1.1:4567``,
or an interface followed by a port number, like ``eth0:4567``.
If the port number is omitted, the default swarm listening port
is used. Default: '0.0.0.0:2377'
force_new_cluster (bool): Force creating a new Swarm, even if
already part of one. Default: False
swarm_spec (dict): Configuration settings of the new Swarm. Use
``APIClient.create_swarm_spec`` to generate a valid
configuration. Default: None
default_addr_pool (list of strings): Default Address Pool specifies
default subnet pools for global scope networks. Each pool
should be specified as a CIDR block, like '10.0.0.0/8'.
Default: None
subnet_size (int): SubnetSize specifies the subnet size of the
networks created from the default subnet pool. Default: None
data_path_addr (string): Address or interface to use for data path
traffic. For example, 192.168.1.1, or an interface, like eth0.
data_path_port (int): Port number to use for data path traffic.
Acceptable port range is 1024 to 49151. If set to ``None`` or
0, the default port 4789 will be used. Default: None
Returns:
(str): The ID of the created node.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/swarm/init')
if swarm_spec is not None and not isinstance(swarm_spec, dict):
raise TypeError('swarm_spec must be a dictionary')
if default_addr_pool is not None:
if utils.version_lt(self._version, '1.39'):
raise errors.InvalidVersion(
'Address pool is only available for API version >= 1.39'
)
# subnet_size becomes 0 if not set with default_addr_pool
if subnet_size is None:
subnet_size = DEFAULT_SWARM_SUBNET_SIZE
if subnet_size is not None:
if utils.version_lt(self._version, '1.39'):
raise errors.InvalidVersion(
'Subnet size is only available for API version >= 1.39'
)
# subnet_size is ignored if set without default_addr_pool
if default_addr_pool is None:
default_addr_pool = DEFAULT_SWARM_ADDR_POOL
data = {
'AdvertiseAddr': advertise_addr,
'ListenAddr': listen_addr,
'DefaultAddrPool': default_addr_pool,
'SubnetSize': subnet_size,
'ForceNewCluster': force_new_cluster,
'Spec': swarm_spec,
}
if data_path_addr is not None:
if utils.version_lt(self._version, '1.30'):
raise errors.InvalidVersion(
'Data address path is only available for '
'API version >= 1.30'
)
data['DataPathAddr'] = data_path_addr
if data_path_port is not None:
if utils.version_lt(self._version, '1.40'):
raise errors.InvalidVersion(
'Data path port is only available for '
'API version >= 1.40'
)
data['DataPathPort'] = data_path_port
response = self._post_json(url, data=data)
return self._result(response, json=True)
@utils.minimum_version('1.24')
def inspect_swarm(self):
"""
Retrieve low-level information about the current swarm.
Returns:
A dictionary containing data about the swarm.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/swarm')
return self._result(self._get(url), True)
@utils.check_resource('node_id')
@utils.minimum_version('1.24')
def inspect_node(self, node_id):
"""
Retrieve low-level information about a swarm node
Args:
node_id (string): ID of the node to be inspected.
Returns:
A dictionary containing data about this node.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/nodes/{0}', node_id)
return self._result(self._get(url), True)
@utils.minimum_version('1.24')
def join_swarm(self, remote_addrs, join_token, listen_addr='0.0.0.0:2377',
advertise_addr=None, data_path_addr=None):
"""
Make this Engine join a swarm that has already been created.
Args:
remote_addrs (:py:class:`list`): Addresses of one or more manager
nodes already participating in the Swarm to join.
join_token (string): Secret token for joining this Swarm.
listen_addr (string): Listen address used for inter-manager
communication if the node gets promoted to manager, as well as
determining the networking interface used for the VXLAN Tunnel
Endpoint (VTEP). Default: ``'0.0.0.0:2377``
advertise_addr (string): Externally reachable address advertised
to other nodes. This can either be an address/port combination
in the form ``192.168.1.1:4567``, or an interface followed by a
port number, like ``eth0:4567``. If the port number is omitted,
the port number from the listen address is used. If
AdvertiseAddr is not specified, it will be automatically
detected when possible. Default: ``None``
data_path_addr (string): Address or interface to use for data path
traffic. For example, 192.168.1.1, or an interface, like eth0.
Returns:
``True`` if the request went through.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
data = {
'RemoteAddrs': remote_addrs,
'ListenAddr': listen_addr,
'JoinToken': join_token,
'AdvertiseAddr': advertise_addr,
}
if data_path_addr is not None:
if utils.version_lt(self._version, '1.30'):
raise errors.InvalidVersion(
'Data address path is only available for '
'API version >= 1.30'
)
data['DataPathAddr'] = data_path_addr
url = self._url('/swarm/join')
response = self._post_json(url, data=data)
self._raise_for_status(response)
return True
@utils.minimum_version('1.24')
def leave_swarm(self, force=False):
"""
Leave a swarm.
Args:
force (bool): Leave the swarm even if this node is a manager.
Default: ``False``
Returns:
``True`` if the request went through.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/swarm/leave')
response = self._post(url, params={'force': force})
# Ignore "this node is not part of a swarm" error
if force and response.status_code == http_client.NOT_ACCEPTABLE:
return True
# FIXME: Temporary workaround for 1.13.0-rc bug
# https://github.com/docker/docker/issues/29192
if force and response.status_code == http_client.SERVICE_UNAVAILABLE:
return True
self._raise_for_status(response)
return True
@utils.minimum_version('1.24')
def nodes(self, filters=None):
"""
List swarm nodes.
Args:
filters (dict): Filters to process on the nodes list. Valid
filters: ``id``, ``name``, ``membership`` and ``role``.
Default: ``None``
Returns:
A list of dictionaries containing data about each swarm node.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/nodes')
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
return self._result(self._get(url, params=params), True)
@utils.check_resource('node_id')
@utils.minimum_version('1.24')
def remove_node(self, node_id, force=False):
"""
Remove a node from the swarm.
Args:
node_id (string): ID of the node to be removed.
force (bool): Force remove an active node. Default: `False`
Raises:
:py:class:`docker.errors.NotFound`
If the node referenced doesn't exist in the swarm.
:py:class:`docker.errors.APIError`
If the server returns an error.
Returns:
`True` if the request was successful.
"""
url = self._url('/nodes/{0}', node_id)
params = {
'force': force
}
res = self._delete(url, params=params)
self._raise_for_status(res)
return True
@utils.minimum_version('1.24')
def unlock_swarm(self, key):
"""
Unlock a locked swarm.
Args:
key (string): The unlock key as provided by
:py:meth:`get_unlock_key`
Raises:
:py:class:`docker.errors.InvalidArgument`
If the key argument is in an incompatible format
:py:class:`docker.errors.APIError`
If the server returns an error.
Returns:
`True` if the request was successful.
Example:
>>> key = client.api.get_unlock_key()
>>> client.unlock_swarm(key)
"""
if isinstance(key, dict):
if 'UnlockKey' not in key:
raise errors.InvalidArgument('Invalid unlock key format')
else:
key = {'UnlockKey': key}
url = self._url('/swarm/unlock')
res = self._post_json(url, data=key)
self._raise_for_status(res)
return True
@utils.minimum_version('1.24')
def update_node(self, node_id, version, node_spec=None):
"""
Update the node's configuration
Args:
node_id (string): ID of the node to be updated.
version (int): The version number of the node object being
updated. This is required to avoid conflicting writes.
node_spec (dict): Configuration settings to update. Any values
not provided will be removed. Default: ``None``
Returns:
`True` if the request went through.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> node_spec = {'Availability': 'active',
'Name': 'node-name',
'Role': 'manager',
'Labels': {'foo': 'bar'}
}
>>> client.api.update_node(node_id='24ifsmvkjbyhk', version=8,
node_spec=node_spec)
"""
url = self._url('/nodes/{0}/update?version={1}', node_id, str(version))
res = self._post_json(url, data=node_spec)
self._raise_for_status(res)
return True
@utils.minimum_version('1.24')
def update_swarm(self, version, swarm_spec=None,
rotate_worker_token=False,
rotate_manager_token=False,
rotate_manager_unlock_key=False):
"""
Update the Swarm's configuration
Args:
version (int): The version number of the swarm object being
updated. This is required to avoid conflicting writes.
swarm_spec (dict): Configuration settings to update. Use
:py:meth:`~docker.api.swarm.SwarmApiMixin.create_swarm_spec` to
generate a valid configuration. Default: ``None``.
rotate_worker_token (bool): Rotate the worker join token. Default:
``False``.
rotate_manager_token (bool): Rotate the manager join token.
Default: ``False``.
rotate_manager_unlock_key (bool): Rotate the manager unlock key.
Default: ``False``.
Returns:
``True`` if the request went through.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url('/swarm/update')
params = {
'rotateWorkerToken': rotate_worker_token,
'rotateManagerToken': rotate_manager_token,
'version': version
}
if rotate_manager_unlock_key:
if utils.version_lt(self._version, '1.25'):
raise errors.InvalidVersion(
'Rotate manager unlock key '
'is only available for API version >= 1.25'
)
params['rotateManagerUnlockKey'] = rotate_manager_unlock_key
response = self._post_json(url, data=swarm_spec, params=params)
self._raise_for_status(response)
return True

View File

@ -1,17 +1,74 @@
from .. import utils
from .. import errors, utils
class VolumeApiMixin(object):
@utils.minimum_version('1.21')
class VolumeApiMixin:
def volumes(self, filters=None):
"""
List volumes currently registered by the docker daemon. Similar to the
``docker volume ls`` command.
Args:
filters (dict): Server-side list filtering options.
Returns:
(dict): Dictionary with list of volume objects as value of the
``Volumes`` key.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> client.api.volumes()
{u'Volumes': [{u'Driver': u'local',
u'Mountpoint': u'/var/lib/docker/volumes/foobar/_data',
u'Name': u'foobar'},
{u'Driver': u'local',
u'Mountpoint': u'/var/lib/docker/volumes/baz/_data',
u'Name': u'baz'}]}
"""
params = {
'filters': utils.convert_filters(filters) if filters else None
}
url = self._url('/volumes')
return self._result(self._get(url, params=params), True)
@utils.minimum_version('1.21')
def create_volume(self, name, driver=None, driver_opts=None):
def create_volume(self, name=None, driver=None, driver_opts=None,
labels=None):
"""
Create and register a named volume
Args:
name (str): Name of the volume
driver (str): Name of the driver used to create the volume
driver_opts (dict): Driver options as a key-value dictionary
labels (dict): Labels to set on the volume
Returns:
(dict): The created volume reference object
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> volume = client.api.create_volume(
... name='foobar',
... driver='local',
... driver_opts={'foo': 'bar', 'baz': 'false'},
... labels={"key": "value"},
... )
... print(volume)
{u'Driver': u'local',
u'Labels': {u'key': u'value'},
u'Mountpoint': u'/var/lib/docker/volumes/foobar/_data',
u'Name': u'foobar',
u'Scope': u'local'}
"""
url = self._url('/volumes/create')
if driver_opts is not None and not isinstance(driver_opts, dict):
raise TypeError('driver_opts must be a dictionary')
@ -21,15 +78,86 @@ class VolumeApiMixin(object):
'Driver': driver,
'DriverOpts': driver_opts,
}
if labels is not None:
if utils.compare_version('1.23', self._version) < 0:
raise errors.InvalidVersion(
'volume labels were introduced in API 1.23'
)
if not isinstance(labels, dict):
raise TypeError('labels must be a dictionary')
data["Labels"] = labels
return self._result(self._post_json(url, data=data), True)
@utils.minimum_version('1.21')
def inspect_volume(self, name):
"""
Retrieve volume info by name.
Args:
name (str): volume name
Returns:
(dict): Volume information dictionary
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> client.api.inspect_volume('foobar')
{u'Driver': u'local',
u'Mountpoint': u'/var/lib/docker/volumes/foobar/_data',
u'Name': u'foobar'}
"""
url = self._url('/volumes/{0}', name)
return self._result(self._get(url), True)
@utils.minimum_version('1.21')
def remove_volume(self, name):
url = self._url('/volumes/{0}', name)
@utils.minimum_version('1.25')
def prune_volumes(self, filters=None):
"""
Delete unused volumes
Args:
filters (dict): Filters to process on the prune list.
Returns:
(dict): A dict containing a list of deleted volume names and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
url = self._url('/volumes/prune')
return self._result(self._post(url, params=params), True)
def remove_volume(self, name, force=False):
"""
Remove a volume. Similar to the ``docker volume rm`` command.
Args:
name (str): The volume's name
force (bool): Force removal of volumes that were already removed
out of band by the volume driver plugin.
Raises:
:py:class:`docker.errors.APIError`
If volume failed to remove.
"""
params = {}
if force:
if utils.version_lt(self._version, '1.25'):
raise errors.InvalidVersion(
'force removal was introduced in API 1.25'
)
params = {'force': force}
url = self._url('/volumes/{0}', name, params=params)
resp = self._delete(url)
self._raise_for_status(resp)

378
docker/auth.py Normal file
View File

@ -0,0 +1,378 @@
import base64
import json
import logging
from . import credentials, errors
from .utils import config
INDEX_NAME = 'docker.io'
INDEX_URL = f'https://index.{INDEX_NAME}/v1/'
TOKEN_USERNAME = '<token>'
log = logging.getLogger(__name__)
def resolve_repository_name(repo_name):
if '://' in repo_name:
raise errors.InvalidRepository(
f'Repository name cannot contain a scheme ({repo_name})'
)
index_name, remote_name = split_repo_name(repo_name)
if index_name[0] == '-' or index_name[-1] == '-':
raise errors.InvalidRepository(
f'Invalid index name ({index_name}). '
'Cannot begin or end with a hyphen.'
)
return resolve_index_name(index_name), remote_name
def resolve_index_name(index_name):
index_name = convert_to_hostname(index_name)
if index_name == f"index.{INDEX_NAME}":
index_name = INDEX_NAME
return index_name
def get_config_header(client, registry):
log.debug('Looking for auth config')
if not client._auth_configs or client._auth_configs.is_empty:
log.debug(
"No auth config in memory - loading from filesystem"
)
client._auth_configs = load_config(credstore_env=client.credstore_env)
authcfg = resolve_authconfig(
client._auth_configs, registry, credstore_env=client.credstore_env
)
# Do not fail here if no authentication exists for this
# specific registry as we can have a readonly pull. Just
# put the header if we can.
if authcfg:
log.debug('Found auth config')
# auth_config needs to be a dict in the format used by
# auth.py username , password, serveraddress, email
return encode_header(authcfg)
log.debug('No auth config found')
return None
def split_repo_name(repo_name):
parts = repo_name.split('/', 1)
if len(parts) == 1 or (
'.' not in parts[0] and ':' not in parts[0] and parts[0] != 'localhost'
):
# This is a docker index repo (ex: username/foobar or ubuntu)
return INDEX_NAME, repo_name
return tuple(parts)
def get_credential_store(authconfig, registry):
if not isinstance(authconfig, AuthConfig):
authconfig = AuthConfig(authconfig)
return authconfig.get_credential_store(registry)
class AuthConfig(dict):
def __init__(self, dct, credstore_env=None):
if 'auths' not in dct:
dct['auths'] = {}
self.update(dct)
self._credstore_env = credstore_env
self._stores = {}
@classmethod
def parse_auth(cls, entries, raise_on_error=False):
"""
Parses authentication entries
Args:
entries: Dict of authentication entries.
raise_on_error: If set to true, an invalid format will raise
InvalidConfigFile
Returns:
Authentication registry.
"""
conf = {}
for registry, entry in entries.items():
if not isinstance(entry, dict):
log.debug(
f'Config entry for key {registry} is not auth config'
)
# We sometimes fall back to parsing the whole config as if it
# was the auth config by itself, for legacy purposes. In that
# case, we fail silently and return an empty conf if any of the
# keys is not formatted properly.
if raise_on_error:
raise errors.InvalidConfigFile(
f'Invalid configuration for registry {registry}'
)
return {}
if 'identitytoken' in entry:
log.debug(f'Found an IdentityToken entry for registry {registry}')
conf[registry] = {
'IdentityToken': entry['identitytoken']
}
continue # Other values are irrelevant if we have a token
if 'auth' not in entry:
# Starting with engine v1.11 (API 1.23), an empty dictionary is
# a valid value in the auths config.
# https://github.com/docker/compose/issues/3265
log.debug(
f'Auth data for {registry} is absent. '
f'Client might be using a credentials store instead.'
)
conf[registry] = {}
continue
username, password = decode_auth(entry['auth'])
log.debug(
f'Found entry (registry={registry!r}, username={username!r})'
)
conf[registry] = {
'username': username,
'password': password,
'email': entry.get('email'),
'serveraddress': registry,
}
return conf
@classmethod
def load_config(cls, config_path, config_dict, credstore_env=None):
"""
Loads authentication data from a Docker configuration file in the given
root directory or if config_path is passed use given path.
Lookup priority:
explicit config_path parameter > DOCKER_CONFIG environment
variable > ~/.docker/config.json > ~/.dockercfg
"""
if not config_dict:
config_file = config.find_config_file(config_path)
if not config_file:
return cls({}, credstore_env)
try:
with open(config_file) as f:
config_dict = json.load(f)
except (OSError, KeyError, ValueError) as e:
# Likely missing new Docker config file or it's in an
# unknown format, continue to attempt to read old location
# and format.
log.debug(e)
return cls(_load_legacy_config(config_file), credstore_env)
res = {}
if config_dict.get('auths'):
log.debug("Found 'auths' section")
res.update({
'auths': cls.parse_auth(
config_dict.pop('auths'), raise_on_error=True
)
})
if config_dict.get('credsStore'):
log.debug("Found 'credsStore' section")
res.update({'credsStore': config_dict.pop('credsStore')})
if config_dict.get('credHelpers'):
log.debug("Found 'credHelpers' section")
res.update({'credHelpers': config_dict.pop('credHelpers')})
if res:
return cls(res, credstore_env)
log.debug(
"Couldn't find auth-related section ; attempting to interpret "
"as auth-only file"
)
return cls({'auths': cls.parse_auth(config_dict)}, credstore_env)
@property
def auths(self):
return self.get('auths', {})
@property
def creds_store(self):
return self.get('credsStore', None)
@property
def cred_helpers(self):
return self.get('credHelpers', {})
@property
def is_empty(self):
return (
not self.auths and not self.creds_store and not self.cred_helpers
)
def resolve_authconfig(self, registry=None):
"""
Returns the authentication data from the given auth configuration for a
specific registry. As with the Docker client, legacy entries in the
config with full URLs are stripped down to hostnames before checking
for a match. Returns None if no match was found.
"""
if self.creds_store or self.cred_helpers:
store_name = self.get_credential_store(registry)
if store_name is not None:
log.debug(
f'Using credentials store "{store_name}"'
)
cfg = self._resolve_authconfig_credstore(registry, store_name)
if cfg is not None:
return cfg
log.debug('No entry in credstore - fetching from auth dict')
# Default to the public index server
registry = resolve_index_name(registry) if registry else INDEX_NAME
log.debug(f"Looking for auth entry for {repr(registry)}")
if registry in self.auths:
log.debug(f"Found {repr(registry)}")
return self.auths[registry]
for key, conf in self.auths.items():
if resolve_index_name(key) == registry:
log.debug(f"Found {repr(key)}")
return conf
log.debug("No entry found")
return None
def _resolve_authconfig_credstore(self, registry, credstore_name):
if not registry or registry == INDEX_NAME:
# The ecosystem is a little schizophrenic with index.docker.io VS
# docker.io - in that case, it seems the full URL is necessary.
registry = INDEX_URL
log.debug(f"Looking for auth entry for {repr(registry)}")
store = self._get_store_instance(credstore_name)
try:
data = store.get(registry)
res = {
'ServerAddress': registry,
}
if data['Username'] == TOKEN_USERNAME:
res['IdentityToken'] = data['Secret']
else:
res.update({
'Username': data['Username'],
'Password': data['Secret'],
})
return res
except credentials.CredentialsNotFound:
log.debug('No entry found')
return None
except credentials.StoreError as e:
raise errors.DockerException(
f'Credentials store error: {repr(e)}'
) from e
def _get_store_instance(self, name):
if name not in self._stores:
self._stores[name] = credentials.Store(
name, environment=self._credstore_env
)
return self._stores[name]
def get_credential_store(self, registry):
if not registry or registry == INDEX_NAME:
registry = INDEX_URL
return self.cred_helpers.get(registry) or self.creds_store
def get_all_credentials(self):
auth_data = self.auths.copy()
if self.creds_store:
# Retrieve all credentials from the default store
store = self._get_store_instance(self.creds_store)
for k in store.list().keys():
auth_data[k] = self._resolve_authconfig_credstore(
k, self.creds_store
)
auth_data[convert_to_hostname(k)] = auth_data[k]
# credHelpers entries take priority over all others
for reg, store_name in self.cred_helpers.items():
auth_data[reg] = self._resolve_authconfig_credstore(
reg, store_name
)
auth_data[convert_to_hostname(reg)] = auth_data[reg]
return auth_data
def add_auth(self, reg, data):
self['auths'][reg] = data
def resolve_authconfig(authconfig, registry=None, credstore_env=None):
if not isinstance(authconfig, AuthConfig):
authconfig = AuthConfig(authconfig, credstore_env)
return authconfig.resolve_authconfig(registry)
def convert_to_hostname(url):
return url.replace('http://', '').replace('https://', '').split('/', 1)[0]
def decode_auth(auth):
if isinstance(auth, str):
auth = auth.encode('ascii')
s = base64.b64decode(auth)
login, pwd = s.split(b':', 1)
return login.decode('utf8'), pwd.decode('utf8')
def encode_header(auth):
auth_json = json.dumps(auth).encode('ascii')
return base64.urlsafe_b64encode(auth_json)
def parse_auth(entries, raise_on_error=False):
"""
Parses authentication entries
Args:
entries: Dict of authentication entries.
raise_on_error: If set to true, an invalid format will raise
InvalidConfigFile
Returns:
Authentication registry.
"""
return AuthConfig.parse_auth(entries, raise_on_error)
def load_config(config_path=None, config_dict=None, credstore_env=None):
return AuthConfig.load_config(config_path, config_dict, credstore_env)
def _load_legacy_config(config_file):
log.debug("Attempting to parse legacy auth file format")
try:
data = []
with open(config_file) as f:
for line in f.readlines():
data.append(line.strip().split(' = ')[1])
if len(data) < 2:
# Not enough data
raise errors.InvalidConfigFile(
'Invalid or empty configuration file!'
)
username, password = decode_auth(data[0])
return {'auths': {
INDEX_NAME: {
'username': username,
'password': password,
'email': data[1],
'serveraddress': INDEX_URL,
}
}}
except Exception as e:
log.debug(e)
log.debug("All parsing attempts failed - returning empty config")
return {}

View File

@ -1,8 +0,0 @@
from .auth import (
INDEX_NAME,
INDEX_URL,
encode_header,
load_config,
resolve_authconfig,
resolve_repository_name,
) # flake8: noqa

View File

@ -1,230 +0,0 @@
# Copyright 2013 dotCloud inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import base64
import json
import logging
import os
import six
from .. import errors
INDEX_NAME = 'docker.io'
INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)
DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')
LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'
log = logging.getLogger(__name__)
def resolve_repository_name(repo_name):
if '://' in repo_name:
raise errors.InvalidRepository(
'Repository name cannot contain a scheme ({0})'.format(repo_name)
)
index_name, remote_name = split_repo_name(repo_name)
if index_name[0] == '-' or index_name[-1] == '-':
raise errors.InvalidRepository(
'Invalid index name ({0}). Cannot begin or end with a'
' hyphen.'.format(index_name)
)
return resolve_index_name(index_name), remote_name
def resolve_index_name(index_name):
index_name = convert_to_hostname(index_name)
if index_name == 'index.' + INDEX_NAME:
index_name = INDEX_NAME
return index_name
def split_repo_name(repo_name):
parts = repo_name.split('/', 1)
if len(parts) == 1 or (
'.' not in parts[0] and ':' not in parts[0] and parts[0] != 'localhost'
):
# This is a docker index repo (ex: username/foobar or ubuntu)
return INDEX_NAME, repo_name
return tuple(parts)
def resolve_authconfig(authconfig, registry=None):
"""
Returns the authentication data from the given auth configuration for a
specific registry. As with the Docker client, legacy entries in the config
with full URLs are stripped down to hostnames before checking for a match.
Returns None if no match was found.
"""
# Default to the public index server
registry = resolve_index_name(registry) if registry else INDEX_NAME
log.debug("Looking for auth entry for {0}".format(repr(registry)))
if registry in authconfig:
log.debug("Found {0}".format(repr(registry)))
return authconfig[registry]
for key, config in six.iteritems(authconfig):
if resolve_index_name(key) == registry:
log.debug("Found {0}".format(repr(key)))
return config
log.debug("No entry found")
return None
def convert_to_hostname(url):
return url.replace('http://', '').replace('https://', '').split('/', 1)[0]
def decode_auth(auth):
if isinstance(auth, six.string_types):
auth = auth.encode('ascii')
s = base64.b64decode(auth)
login, pwd = s.split(b':', 1)
return login.decode('utf8'), pwd.decode('utf8')
def encode_header(auth):
auth_json = json.dumps(auth).encode('ascii')
return base64.urlsafe_b64encode(auth_json)
def parse_auth(entries, raise_on_error=False):
"""
Parses authentication entries
Args:
entries: Dict of authentication entries.
raise_on_error: If set to true, an invalid format will raise
InvalidConfigFile
Returns:
Authentication registry.
"""
conf = {}
for registry, entry in six.iteritems(entries):
if not (isinstance(entry, dict) and 'auth' in entry):
log.debug(
'Config entry for key {0} is not auth config'.format(registry)
)
# We sometimes fall back to parsing the whole config as if it was
# the auth config by itself, for legacy purposes. In that case, we
# fail silently and return an empty conf if any of the keys is not
# formatted properly.
if raise_on_error:
raise errors.InvalidConfigFile(
'Invalid configuration for registry {0}'.format(registry)
)
return {}
username, password = decode_auth(entry['auth'])
log.debug(
'Found entry (registry={0}, username={1})'
.format(repr(registry), repr(username))
)
conf[registry] = {
'username': username,
'password': password,
'email': entry.get('email'),
'serveraddress': registry,
}
return conf
def find_config_file(config_path=None):
environment_path = os.path.join(
os.environ.get('DOCKER_CONFIG'),
os.path.basename(DOCKER_CONFIG_FILENAME)
) if os.environ.get('DOCKER_CONFIG') else None
paths = [
config_path, # 1
environment_path, # 2
os.path.join(os.path.expanduser('~'), DOCKER_CONFIG_FILENAME), # 3
os.path.join(
os.path.expanduser('~'), LEGACY_DOCKER_CONFIG_FILENAME
) # 4
]
for path in paths:
if path and os.path.exists(path):
return path
return None
def load_config(config_path=None):
"""
Loads authentication data from a Docker configuration file in the given
root directory or if config_path is passed use given path.
Lookup priority:
explicit config_path parameter > DOCKER_CONFIG environment variable >
~/.docker/config.json > ~/.dockercfg
"""
config_file = find_config_file(config_path)
if not config_file:
log.debug("File doesn't exist")
return {}
try:
with open(config_file) as f:
data = json.load(f)
res = {}
if data.get('auths'):
log.debug("Found 'auths' section")
res.update(parse_auth(data['auths'], raise_on_error=True))
if data.get('HttpHeaders'):
log.debug("Found 'HttpHeaders' section")
res.update({'HttpHeaders': data['HttpHeaders']})
if res:
return res
else:
log.debug("Couldn't find 'auths' or 'HttpHeaders' sections")
f.seek(0)
return parse_auth(json.load(f))
except (IOError, KeyError, ValueError) as e:
# Likely missing new Docker config file or it's in an
# unknown format, continue to attempt to read old location
# and format.
log.debug(e)
log.debug("Attempting to parse legacy auth file format")
try:
data = []
with open(config_file) as f:
for line in f.readlines():
data.append(line.strip().split(' = ')[1])
if len(data) < 2:
# Not enough data
raise errors.InvalidConfigFile(
'Invalid or empty configuration file!'
)
username, password = decode_auth(data[0])
return {
INDEX_NAME: {
'username': username,
'password': password,
'email': data[1],
'serveraddress': INDEX_URL,
}
}
except Exception as e:
log.debug(e)
pass
log.debug("All parsing attempts failed - returning empty config")
return {}

View File

@ -1,349 +1,222 @@
# Copyright 2013 dotCloud inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import struct
import sys
import requests
import requests.exceptions
import six
import websocket
from .api.client import APIClient
from .constants import DEFAULT_MAX_POOL_SIZE, DEFAULT_TIMEOUT_SECONDS
from .models.configs import ConfigCollection
from .models.containers import ContainerCollection
from .models.images import ImageCollection
from .models.networks import NetworkCollection
from .models.nodes import NodeCollection
from .models.plugins import PluginCollection
from .models.secrets import SecretCollection
from .models.services import ServiceCollection
from .models.swarm import Swarm
from .models.volumes import VolumeCollection
from .utils import kwargs_from_env
from . import api
from . import constants
from . import errors
from .auth import auth
from .unixconn import unixconn
from .ssladapter import ssladapter
from .utils import utils, check_resource, update_headers, kwargs_from_env
from .tls import TLSConfig
class DockerClient:
"""
A client for communicating with a Docker server.
Example:
def from_env(**kwargs):
return Client.from_env(**kwargs)
>>> import docker
>>> client = docker.DockerClient(base_url='unix://var/run/docker.sock')
class Client(
requests.Session,
api.BuildApiMixin,
api.ContainerApiMixin,
api.DaemonApiMixin,
api.ExecApiMixin,
api.ImageApiMixin,
api.VolumeApiMixin,
api.NetworkApiMixin):
def __init__(self, base_url=None, version=None,
timeout=constants.DEFAULT_TIMEOUT_SECONDS, tls=False):
super(Client, self).__init__()
if tls and not base_url:
raise errors.TLSParameterError(
'If using TLS, the base_url argument must be provided.'
)
self.base_url = base_url
self.timeout = timeout
self._auth_configs = auth.load_config()
base_url = utils.parse_host(base_url, sys.platform, tls=bool(tls))
if base_url.startswith('http+unix://'):
self._custom_adapter = unixconn.UnixAdapter(base_url, timeout)
self.mount('http+docker://', self._custom_adapter)
self.base_url = 'http+docker://localunixsocket'
else:
# Use SSLAdapter for the ability to specify SSL version
if isinstance(tls, TLSConfig):
tls.configure_client(self)
elif tls:
self._custom_adapter = ssladapter.SSLAdapter()
self.mount('https://', self._custom_adapter)
self.base_url = base_url
# version detection needs to be after unix adapter mounting
if version is None:
self._version = constants.DEFAULT_DOCKER_API_VERSION
elif isinstance(version, six.string_types):
if version.lower() == 'auto':
self._version = self._retrieve_server_version()
else:
self._version = version
else:
raise errors.DockerException(
'Version parameter must be a string or None. Found {0}'.format(
type(version).__name__
)
)
Args:
base_url (str): URL to the Docker server. For example,
``unix:///var/run/docker.sock`` or ``tcp://127.0.0.1:1234``.
version (str): The version of the API to use. Set to ``auto`` to
automatically detect the server's version. Default: ``1.35``
timeout (int): Default timeout for API calls, in seconds.
tls (bool or :py:class:`~docker.tls.TLSConfig`): Enable TLS. Pass
``True`` to enable it with default options, or pass a
:py:class:`~docker.tls.TLSConfig` object to use custom
configuration.
user_agent (str): Set a custom user agent for requests to the server.
credstore_env (dict): Override environment variables when calling the
credential store process.
use_ssh_client (bool): If set to `True`, an ssh connection is made
via shelling out to the ssh client. Ensure the ssh client is
installed and configured on the host.
max_pool_size (int): The maximum number of connections
to save in the pool.
"""
def __init__(self, *args, **kwargs):
self.api = APIClient(*args, **kwargs)
@classmethod
def from_env(cls, **kwargs):
return cls(**kwargs_from_env(**kwargs))
def _retrieve_server_version(self):
try:
return self.version(api_version=False)["ApiVersion"]
except KeyError:
raise errors.DockerException(
'Invalid response from docker daemon: key "ApiVersion"'
' is missing.'
)
except Exception as e:
raise errors.DockerException(
'Error while fetching server API version: {0}'.format(e)
)
def _set_request_timeout(self, kwargs):
"""Prepare the kwargs for an HTTP request by inserting the timeout
parameter, if not already present."""
kwargs.setdefault('timeout', self.timeout)
return kwargs
@update_headers
def _post(self, url, **kwargs):
return self.post(url, **self._set_request_timeout(kwargs))
@update_headers
def _get(self, url, **kwargs):
return self.get(url, **self._set_request_timeout(kwargs))
@update_headers
def _put(self, url, **kwargs):
return self.put(url, **self._set_request_timeout(kwargs))
@update_headers
def _delete(self, url, **kwargs):
return self.delete(url, **self._set_request_timeout(kwargs))
def _url(self, pathfmt, *args, **kwargs):
for arg in args:
if not isinstance(arg, six.string_types):
raise ValueError(
'Expected a string but found {0} ({1}) '
'instead'.format(arg, type(arg))
)
args = map(six.moves.urllib.parse.quote_plus, args)
if kwargs.get('versioned_api', True):
return '{0}/v{1}{2}'.format(
self.base_url, self._version, pathfmt.format(*args)
)
else:
return '{0}{1}'.format(self.base_url, pathfmt.format(*args))
def _raise_for_status(self, response, explanation=None):
"""Raises stored :class:`APIError`, if one occurred."""
try:
response.raise_for_status()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
raise errors.NotFound(e, response, explanation=explanation)
raise errors.APIError(e, response, explanation=explanation)
def _result(self, response, json=False, binary=False):
assert not (json and binary)
self._raise_for_status(response)
if json:
return response.json()
if binary:
return response.content
return response.text
def _post_json(self, url, data, **kwargs):
# Go <1.1 can't unserialize null to a string
# so we do this disgusting thing here.
data2 = {}
if data is not None:
for k, v in six.iteritems(data):
if v is not None:
data2[k] = v
if 'headers' not in kwargs:
kwargs['headers'] = {}
kwargs['headers']['Content-Type'] = 'application/json'
return self._post(url, data=json.dumps(data2), **kwargs)
def _attach_params(self, override=None):
return override or {
'stdout': 1,
'stderr': 1,
'stream': 1
}
@check_resource
def _attach_websocket(self, container, params=None):
url = self._url("/containers/{0}/attach/ws", container)
req = requests.Request("POST", url, params=self._attach_params(params))
full_url = req.prepare().url
full_url = full_url.replace("http://", "ws://", 1)
full_url = full_url.replace("https://", "wss://", 1)
return self._create_websocket_connection(full_url)
def _create_websocket_connection(self, url):
return websocket.create_connection(url)
def _get_raw_response_socket(self, response):
self._raise_for_status(response)
if six.PY3:
sock = response.raw._fp.fp.raw
if self.base_url.startswith("https://"):
sock = sock._sock
else:
sock = response.raw._fp.fp._sock
try:
# Keep a reference to the response to stop it being garbage
# collected. If the response is garbage collected, it will
# close TLS sockets.
sock._response = response
except AttributeError:
# UNIX sockets can't have attributes set on them, but that's
# fine because we won't be doing TLS over them
pass
return sock
def _stream_helper(self, response, decode=False):
"""Generator for data coming from a chunked-encoded HTTP response."""
if response.raw._fp.chunked:
reader = response.raw
while not reader.closed:
# this read call will block until we get a chunk
data = reader.read(1)
if not data:
break
if reader._fp.chunk_left:
data += reader.read(reader._fp.chunk_left)
if decode:
if six.PY3:
data = data.decode('utf-8')
data = json.loads(data)
yield data
else:
# Response isn't chunked, meaning we probably
# encountered an error immediately
yield self._result(response)
def _multiplexed_buffer_helper(self, response):
"""A generator of multiplexed data blocks read from a buffered
response."""
buf = self._result(response, binary=True)
walker = 0
while True:
if len(buf[walker:]) < 8:
break
_, length = struct.unpack_from('>BxxxL', buf[walker:])
start = walker + constants.STREAM_HEADER_SIZE_BYTES
end = start + length
walker = end
yield buf[start:end]
def _multiplexed_response_stream_helper(self, response):
"""A generator of multiplexed data blocks coming from a response
stream."""
# Disable timeout on the underlying socket to prevent
# Read timed out(s) for long running processes
socket = self._get_raw_response_socket(response)
self._disable_socket_timeout(socket)
while True:
header = response.raw.read(constants.STREAM_HEADER_SIZE_BYTES)
if not header:
break
_, length = struct.unpack('>BxxxL', header)
if not length:
continue
data = response.raw.read(length)
if not data:
break
yield data
def _stream_raw_result_old(self, response):
''' Stream raw output for API versions below 1.6 '''
self._raise_for_status(response)
for line in response.iter_lines(chunk_size=1,
decode_unicode=True):
# filter out keep-alive new lines
if line:
yield line
def _stream_raw_result(self, response):
''' Stream result for TTY-enabled container above API 1.6 '''
self._raise_for_status(response)
for out in response.iter_content(chunk_size=1, decode_unicode=True):
yield out
def _disable_socket_timeout(self, socket):
""" Depending on the combination of python version and whether we're
connecting over http or https, we might need to access _sock, which
may or may not exist; or we may need to just settimeout on socket
itself, which also may or may not have settimeout on it.
To avoid missing the correct one, we try both.
"""
if hasattr(socket, "settimeout"):
socket.settimeout(None)
if hasattr(socket, "_sock") and hasattr(socket._sock, "settimeout"):
socket._sock.settimeout(None)
Return a client configured from environment variables.
def _get_result(self, container, stream, res):
cont = self.inspect_container(container)
return self._get_result_tty(stream, res, cont['Config']['Tty'])
The environment variables used are the same as those used by the
Docker command-line client. They are:
def _get_result_tty(self, stream, res, is_tty):
# Stream multi-plexing was only introduced in API v1.6. Anything
# before that needs old-style streaming.
if utils.compare_version('1.6', self._version) < 0:
return self._stream_raw_result_old(res)
.. envvar:: DOCKER_HOST
# We should also use raw streaming (without keep-alives)
# if we're dealing with a tty-enabled container.
if is_tty:
return self._stream_raw_result(res) if stream else \
self._result(res, binary=True)
The URL to the Docker host.
self._raise_for_status(res)
sep = six.binary_type()
if stream:
return self._multiplexed_response_stream_helper(res)
else:
return sep.join(
[x for x in self._multiplexed_buffer_helper(res)]
)
.. envvar:: DOCKER_TLS_VERIFY
def get_adapter(self, url):
try:
return super(Client, self).get_adapter(url)
except requests.exceptions.InvalidSchema as e:
if self._custom_adapter:
return self._custom_adapter
else:
raise e
Verify the host against a CA certificate.
.. envvar:: DOCKER_CERT_PATH
A path to a directory containing TLS certificates to use when
connecting to the Docker host.
Args:
version (str): The version of the API to use. Set to ``auto`` to
automatically detect the server's version. Default: ``auto``
timeout (int): Default timeout for API calls, in seconds.
max_pool_size (int): The maximum number of connections
to save in the pool.
environment (dict): The environment to read environment variables
from. Default: the value of ``os.environ``
credstore_env (dict): Override environment variables when calling
the credential store process.
use_ssh_client (bool): If set to `True`, an ssh connection is
made via shelling out to the ssh client. Ensure the ssh
client is installed and configured on the host.
Example:
>>> import docker
>>> client = docker.from_env()
.. _`SSL version`:
https://docs.python.org/3.5/library/ssl.html#ssl.PROTOCOL_TLSv1
"""
timeout = kwargs.pop('timeout', DEFAULT_TIMEOUT_SECONDS)
max_pool_size = kwargs.pop('max_pool_size', DEFAULT_MAX_POOL_SIZE)
version = kwargs.pop('version', None)
use_ssh_client = kwargs.pop('use_ssh_client', False)
return cls(
timeout=timeout,
max_pool_size=max_pool_size,
version=version,
use_ssh_client=use_ssh_client,
**kwargs_from_env(**kwargs)
)
# Resources
@property
def configs(self):
"""
An object for managing configs on the server. See the
:doc:`configs documentation <configs>` for full details.
"""
return ConfigCollection(client=self)
@property
def api_version(self):
return self._version
def containers(self):
"""
An object for managing containers on the server. See the
:doc:`containers documentation <containers>` for full details.
"""
return ContainerCollection(client=self)
@property
def images(self):
"""
An object for managing images on the server. See the
:doc:`images documentation <images>` for full details.
"""
return ImageCollection(client=self)
@property
def networks(self):
"""
An object for managing networks on the server. See the
:doc:`networks documentation <networks>` for full details.
"""
return NetworkCollection(client=self)
@property
def nodes(self):
"""
An object for managing nodes on the server. See the
:doc:`nodes documentation <nodes>` for full details.
"""
return NodeCollection(client=self)
@property
def plugins(self):
"""
An object for managing plugins on the server. See the
:doc:`plugins documentation <plugins>` for full details.
"""
return PluginCollection(client=self)
@property
def secrets(self):
"""
An object for managing secrets on the server. See the
:doc:`secrets documentation <secrets>` for full details.
"""
return SecretCollection(client=self)
@property
def services(self):
"""
An object for managing services on the server. See the
:doc:`services documentation <services>` for full details.
"""
return ServiceCollection(client=self)
@property
def swarm(self):
"""
An object for managing a swarm on the server. See the
:doc:`swarm documentation <swarm>` for full details.
"""
return Swarm(client=self)
@property
def volumes(self):
"""
An object for managing volumes on the server. See the
:doc:`volumes documentation <volumes>` for full details.
"""
return VolumeCollection(client=self)
# Top-level methods
def events(self, *args, **kwargs):
return self.api.events(*args, **kwargs)
events.__doc__ = APIClient.events.__doc__
def df(self):
return self.api.df()
df.__doc__ = APIClient.df.__doc__
def info(self, *args, **kwargs):
return self.api.info(*args, **kwargs)
info.__doc__ = APIClient.info.__doc__
def login(self, *args, **kwargs):
return self.api.login(*args, **kwargs)
login.__doc__ = APIClient.login.__doc__
def ping(self, *args, **kwargs):
return self.api.ping(*args, **kwargs)
ping.__doc__ = APIClient.ping.__doc__
def version(self, *args, **kwargs):
return self.api.version(*args, **kwargs)
version.__doc__ = APIClient.version.__doc__
def close(self):
return self.api.close()
close.__doc__ = APIClient.close.__doc__
def __getattr__(self, name):
s = [f"'DockerClient' object has no attribute '{name}'"]
# If a user calls a method on APIClient, they
if hasattr(APIClient, name):
s.append("In Docker SDK for Python 2.0, this method is now on the "
"object APIClient. See the low-level API section of the "
"documentation for more details.")
raise AttributeError(' '.join(s))
class AutoVersionClient(Client):
def __init__(self, *args, **kwargs):
if 'version' in kwargs and kwargs['version']:
raise errors.DockerException(
'Can not specify version for AutoVersionClient'
)
kwargs['version'] = 'auto'
super(AutoVersionClient, self).__init__(*args, **kwargs)
from_env = DockerClient.from_env

View File

@ -1,10 +1,45 @@
DEFAULT_DOCKER_API_VERSION = '1.22'
import sys
from .version import __version__
DEFAULT_DOCKER_API_VERSION = '1.45'
MINIMUM_DOCKER_API_VERSION = '1.24'
DEFAULT_TIMEOUT_SECONDS = 60
STREAM_HEADER_SIZE_BYTES = 8
CONTAINER_LIMITS_KEYS = [
'memory', 'memswap', 'cpushares', 'cpusetcpus'
]
DEFAULT_HTTP_HOST = "127.0.0.1"
DEFAULT_UNIX_SOCKET = "http+unix:///var/run/docker.sock"
DEFAULT_NPIPE = 'npipe:////./pipe/docker_engine'
BYTE_UNITS = {
'b': 1,
'k': 1024,
'm': 1024 * 1024,
'g': 1024 * 1024 * 1024
}
INSECURE_REGISTRY_DEPRECATION_WARNING = \
'The `insecure_registry` argument to {} ' \
'is deprecated and non-functional. Please remove it.'
IS_WINDOWS_PLATFORM = (sys.platform == 'win32')
WINDOWS_LONGPATH_PREFIX = '\\\\?\\'
DEFAULT_USER_AGENT = f"docker-sdk-python/{__version__}"
DEFAULT_NUM_POOLS = 25
# The OpenSSH server default value for MaxSessions is 10 which means we can
# use up to 9, leaving the final session for the underlying SSH connection.
# For more details see: https://github.com/docker/docker-py/issues/2246
DEFAULT_NUM_POOLS_SSH = 9
DEFAULT_MAX_POOL_SIZE = 10
DEFAULT_DATA_CHUNK_SIZE = 1024 * 2048
DEFAULT_SWARM_ADDR_POOL = ['10.0.0.0/8']
DEFAULT_SWARM_SUBNET_SIZE = 24

View File

@ -0,0 +1,2 @@
from .api import ContextAPI
from .context import Context

206
docker/context/api.py Normal file
View File

@ -0,0 +1,206 @@
import json
import os
from docker import errors
from .config import (
METAFILE,
get_current_context_name,
get_meta_dir,
write_context_name_to_docker_config,
)
from .context import Context
class ContextAPI:
"""Context API.
Contains methods for context management:
create, list, remove, get, inspect.
"""
DEFAULT_CONTEXT = Context("default", "swarm")
@classmethod
def create_context(
cls, name, orchestrator=None, host=None, tls_cfg=None,
default_namespace=None, skip_tls_verify=False):
"""Creates a new context.
Returns:
(Context): a Context object.
Raises:
:py:class:`docker.errors.MissingContextParameter`
If a context name is not provided.
:py:class:`docker.errors.ContextAlreadyExists`
If a context with the name already exists.
:py:class:`docker.errors.ContextException`
If name is default.
Example:
>>> from docker.context import ContextAPI
>>> ctx = ContextAPI.create_context(name='test')
>>> print(ctx.Metadata)
{
"Name": "test",
"Metadata": {},
"Endpoints": {
"docker": {
"Host": "unix:///var/run/docker.sock",
"SkipTLSVerify": false
}
}
}
"""
if not name:
raise errors.MissingContextParameter("name")
if name == "default":
raise errors.ContextException(
'"default" is a reserved context name')
ctx = Context.load_context(name)
if ctx:
raise errors.ContextAlreadyExists(name)
endpoint = "docker"
if orchestrator and orchestrator != "swarm":
endpoint = orchestrator
ctx = Context(name, orchestrator)
ctx.set_endpoint(
endpoint, host, tls_cfg,
skip_tls_verify=skip_tls_verify,
def_namespace=default_namespace)
ctx.save()
return ctx
@classmethod
def get_context(cls, name=None):
"""Retrieves a context object.
Args:
name (str): The name of the context
Example:
>>> from docker.context import ContextAPI
>>> ctx = ContextAPI.get_context(name='test')
>>> print(ctx.Metadata)
{
"Name": "test",
"Metadata": {},
"Endpoints": {
"docker": {
"Host": "unix:///var/run/docker.sock",
"SkipTLSVerify": false
}
}
}
"""
if not name:
name = get_current_context_name()
if name == "default":
return cls.DEFAULT_CONTEXT
return Context.load_context(name)
@classmethod
def contexts(cls):
"""Context list.
Returns:
(Context): List of context objects.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
names = []
for dirname, dirnames, fnames in os.walk(get_meta_dir()):
for filename in fnames + dirnames:
if filename == METAFILE:
try:
data = json.load(
open(os.path.join(dirname, filename)))
names.append(data["Name"])
except Exception as e:
raise errors.ContextException(
f"Failed to load metafile {filename}: {e}",
) from e
contexts = [cls.DEFAULT_CONTEXT]
for name in names:
contexts.append(Context.load_context(name))
return contexts
@classmethod
def get_current_context(cls):
"""Get current context.
Returns:
(Context): current context object.
"""
return cls.get_context()
@classmethod
def set_current_context(cls, name="default"):
ctx = cls.get_context(name)
if not ctx:
raise errors.ContextNotFound(name)
err = write_context_name_to_docker_config(name)
if err:
raise errors.ContextException(
f'Failed to set current context: {err}')
@classmethod
def remove_context(cls, name):
"""Remove a context. Similar to the ``docker context rm`` command.
Args:
name (str): The name of the context
Raises:
:py:class:`docker.errors.MissingContextParameter`
If a context name is not provided.
:py:class:`docker.errors.ContextNotFound`
If a context with the name does not exist.
:py:class:`docker.errors.ContextException`
If name is default.
Example:
>>> from docker.context import ContextAPI
>>> ContextAPI.remove_context(name='test')
>>>
"""
if not name:
raise errors.MissingContextParameter("name")
if name == "default":
raise errors.ContextException(
'context "default" cannot be removed')
ctx = Context.load_context(name)
if not ctx:
raise errors.ContextNotFound(name)
if name == get_current_context_name():
write_context_name_to_docker_config(None)
ctx.remove()
@classmethod
def inspect_context(cls, name="default"):
"""Remove a context. Similar to the ``docker context inspect`` command.
Args:
name (str): The name of the context
Raises:
:py:class:`docker.errors.MissingContextParameter`
If a context name is not provided.
:py:class:`docker.errors.ContextNotFound`
If a context with the name does not exist.
Example:
>>> from docker.context import ContextAPI
>>> ContextAPI.remove_context(name='test')
>>>
"""
if not name:
raise errors.MissingContextParameter("name")
if name == "default":
return cls.DEFAULT_CONTEXT()
ctx = Context.load_context(name)
if not ctx:
raise errors.ContextNotFound(name)
return ctx()

81
docker/context/config.py Normal file
View File

@ -0,0 +1,81 @@
import hashlib
import json
import os
from docker import utils
from docker.constants import DEFAULT_UNIX_SOCKET, IS_WINDOWS_PLATFORM
from docker.utils.config import find_config_file
METAFILE = "meta.json"
def get_current_context_name():
name = "default"
docker_cfg_path = find_config_file()
if docker_cfg_path:
try:
with open(docker_cfg_path) as f:
name = json.load(f).get("currentContext", "default")
except Exception:
return "default"
return name
def write_context_name_to_docker_config(name=None):
if name == 'default':
name = None
docker_cfg_path = find_config_file()
config = {}
if docker_cfg_path:
try:
with open(docker_cfg_path) as f:
config = json.load(f)
except Exception as e:
return e
current_context = config.get("currentContext", None)
if current_context and not name:
del config["currentContext"]
elif name:
config["currentContext"] = name
else:
return
try:
with open(docker_cfg_path, "w") as f:
json.dump(config, f, indent=4)
except Exception as e:
return e
def get_context_id(name):
return hashlib.sha256(name.encode('utf-8')).hexdigest()
def get_context_dir():
return os.path.join(os.path.dirname(find_config_file() or ""), "contexts")
def get_meta_dir(name=None):
meta_dir = os.path.join(get_context_dir(), "meta")
if name:
return os.path.join(meta_dir, get_context_id(name))
return meta_dir
def get_meta_file(name):
return os.path.join(get_meta_dir(name), METAFILE)
def get_tls_dir(name=None, endpoint=""):
context_dir = get_context_dir()
if name:
return os.path.join(context_dir, "tls", get_context_id(name), endpoint)
return os.path.join(context_dir, "tls")
def get_context_host(path=None, tls=False):
host = utils.parse_host(path, IS_WINDOWS_PLATFORM, tls)
if host == DEFAULT_UNIX_SOCKET:
# remove http+ from default docker socket url
if host.startswith("http+"):
host = host[5:]
return host

249
docker/context/context.py Normal file
View File

@ -0,0 +1,249 @@
import json
import os
from shutil import copyfile, rmtree
from docker.errors import ContextException
from docker.tls import TLSConfig
from .config import (
get_context_host,
get_meta_dir,
get_meta_file,
get_tls_dir,
)
class Context:
"""A context."""
def __init__(self, name, orchestrator=None, host=None, endpoints=None,
tls=False):
if not name:
raise Exception("Name not provided")
self.name = name
self.context_type = None
self.orchestrator = orchestrator
self.endpoints = {}
self.tls_cfg = {}
self.meta_path = "IN MEMORY"
self.tls_path = "IN MEMORY"
if not endpoints:
# set default docker endpoint if no endpoint is set
default_endpoint = "docker" if (
not orchestrator or orchestrator == "swarm"
) else orchestrator
self.endpoints = {
default_endpoint: {
"Host": get_context_host(host, tls),
"SkipTLSVerify": not tls
}
}
return
# check docker endpoints
for k, v in endpoints.items():
if not isinstance(v, dict):
# unknown format
raise ContextException(
f"Unknown endpoint format for context {name}: {v}",
)
self.endpoints[k] = v
if k != "docker":
continue
self.endpoints[k]["Host"] = v.get("Host", get_context_host(
host, tls))
self.endpoints[k]["SkipTLSVerify"] = bool(v.get(
"SkipTLSVerify", not tls))
def set_endpoint(
self, name="docker", host=None, tls_cfg=None,
skip_tls_verify=False, def_namespace=None):
self.endpoints[name] = {
"Host": get_context_host(host, not skip_tls_verify),
"SkipTLSVerify": skip_tls_verify
}
if def_namespace:
self.endpoints[name]["DefaultNamespace"] = def_namespace
if tls_cfg:
self.tls_cfg[name] = tls_cfg
def inspect(self):
return self.__call__()
@classmethod
def load_context(cls, name):
meta = Context._load_meta(name)
if meta:
instance = cls(
meta["Name"],
orchestrator=meta["Metadata"].get("StackOrchestrator", None),
endpoints=meta.get("Endpoints", None))
instance.context_type = meta["Metadata"].get("Type", None)
instance._load_certs()
instance.meta_path = get_meta_dir(name)
return instance
return None
@classmethod
def _load_meta(cls, name):
meta_file = get_meta_file(name)
if not os.path.isfile(meta_file):
return None
metadata = {}
try:
with open(meta_file) as f:
metadata = json.load(f)
except (OSError, KeyError, ValueError) as e:
# unknown format
raise Exception(
f"Detected corrupted meta file for context {name} : {e}"
) from e
# for docker endpoints, set defaults for
# Host and SkipTLSVerify fields
for k, v in metadata["Endpoints"].items():
if k != "docker":
continue
metadata["Endpoints"][k]["Host"] = v.get(
"Host", get_context_host(None, False))
metadata["Endpoints"][k]["SkipTLSVerify"] = bool(
v.get("SkipTLSVerify", True))
return metadata
def _load_certs(self):
certs = {}
tls_dir = get_tls_dir(self.name)
for endpoint in self.endpoints.keys():
if not os.path.isdir(os.path.join(tls_dir, endpoint)):
continue
ca_cert = None
cert = None
key = None
for filename in os.listdir(os.path.join(tls_dir, endpoint)):
if filename.startswith("ca"):
ca_cert = os.path.join(tls_dir, endpoint, filename)
elif filename.startswith("cert"):
cert = os.path.join(tls_dir, endpoint, filename)
elif filename.startswith("key"):
key = os.path.join(tls_dir, endpoint, filename)
if all([ca_cert, cert, key]):
verify = None
if endpoint == "docker" and not self.endpoints["docker"].get(
"SkipTLSVerify", False):
verify = True
certs[endpoint] = TLSConfig(
client_cert=(cert, key), ca_cert=ca_cert, verify=verify)
self.tls_cfg = certs
self.tls_path = tls_dir
def save(self):
meta_dir = get_meta_dir(self.name)
if not os.path.isdir(meta_dir):
os.makedirs(meta_dir)
with open(get_meta_file(self.name), "w") as f:
f.write(json.dumps(self.Metadata))
tls_dir = get_tls_dir(self.name)
for endpoint, tls in self.tls_cfg.items():
if not os.path.isdir(os.path.join(tls_dir, endpoint)):
os.makedirs(os.path.join(tls_dir, endpoint))
ca_file = tls.ca_cert
if ca_file:
copyfile(ca_file, os.path.join(
tls_dir, endpoint, os.path.basename(ca_file)))
if tls.cert:
cert_file, key_file = tls.cert
copyfile(cert_file, os.path.join(
tls_dir, endpoint, os.path.basename(cert_file)))
copyfile(key_file, os.path.join(
tls_dir, endpoint, os.path.basename(key_file)))
self.meta_path = get_meta_dir(self.name)
self.tls_path = get_tls_dir(self.name)
def remove(self):
if os.path.isdir(self.meta_path):
rmtree(self.meta_path)
if os.path.isdir(self.tls_path):
rmtree(self.tls_path)
def __repr__(self):
return f"<{self.__class__.__name__}: '{self.name}'>"
def __str__(self):
return json.dumps(self.__call__(), indent=2)
def __call__(self):
result = self.Metadata
result.update(self.TLSMaterial)
result.update(self.Storage)
return result
def is_docker_host(self):
return self.context_type is None
@property
def Name(self):
return self.name
@property
def Host(self):
if not self.orchestrator or self.orchestrator == "swarm":
endpoint = self.endpoints.get("docker", None)
if endpoint:
return endpoint.get("Host", None)
return None
return self.endpoints[self.orchestrator].get("Host", None)
@property
def Orchestrator(self):
return self.orchestrator
@property
def Metadata(self):
meta = {}
if self.orchestrator:
meta = {"StackOrchestrator": self.orchestrator}
return {
"Name": self.name,
"Metadata": meta,
"Endpoints": self.endpoints
}
@property
def TLSConfig(self):
key = self.orchestrator
if not key or key == "swarm":
key = "docker"
if key in self.tls_cfg.keys():
return self.tls_cfg[key]
return None
@property
def TLSMaterial(self):
certs = {}
for endpoint, tls in self.tls_cfg.items():
cert, key = tls.cert
certs[endpoint] = list(
map(os.path.basename, [tls.ca_cert, cert, key]))
return {
"TLSMaterial": certs
}
@property
def Storage(self):
return {
"Storage": {
"MetadataPath": self.meta_path,
"TLSPath": self.tls_path
}}

View File

@ -0,0 +1,8 @@
from .constants import (
DEFAULT_LINUX_STORE,
DEFAULT_OSX_STORE,
DEFAULT_WIN32_STORE,
PROGRAM_PREFIX,
)
from .errors import CredentialsNotFound, StoreError
from .store import Store

View File

@ -0,0 +1,4 @@
PROGRAM_PREFIX = 'docker-credential-'
DEFAULT_LINUX_STORE = 'secretservice'
DEFAULT_OSX_STORE = 'osxkeychain'
DEFAULT_WIN32_STORE = 'wincred'

View File

@ -0,0 +1,17 @@
class StoreError(RuntimeError):
pass
class CredentialsNotFound(StoreError):
pass
class InitializationError(StoreError):
pass
def process_store_error(cpe, program):
message = cpe.output.decode('utf-8')
if 'credentials not found in native keychain' in message:
return CredentialsNotFound(f'No matching credentials in {program}')
return StoreError(f'Credentials store {program} exited with "{message}".')

View File

@ -0,0 +1,93 @@
import errno
import json
import shutil
import subprocess
import warnings
from . import constants, errors
from .utils import create_environment_dict
class Store:
def __init__(self, program, environment=None):
""" Create a store object that acts as an interface to
perform the basic operations for storing, retrieving
and erasing credentials using `program`.
"""
self.program = constants.PROGRAM_PREFIX + program
self.exe = shutil.which(self.program)
self.environment = environment
if self.exe is None:
warnings.warn(
f'{self.program} not installed or not available in PATH',
stacklevel=1,
)
def get(self, server):
""" Retrieve credentials for `server`. If no credentials are found,
a `StoreError` will be raised.
"""
if not isinstance(server, bytes):
server = server.encode('utf-8')
data = self._execute('get', server)
result = json.loads(data.decode('utf-8'))
# docker-credential-pass will return an object for inexistent servers
# whereas other helpers will exit with returncode != 0. For
# consistency, if no significant data is returned,
# raise CredentialsNotFound
if result['Username'] == '' and result['Secret'] == '':
raise errors.CredentialsNotFound(
f'No matching credentials in {self.program}'
)
return result
def store(self, server, username, secret):
""" Store credentials for `server`. Raises a `StoreError` if an error
occurs.
"""
data_input = json.dumps({
'ServerURL': server,
'Username': username,
'Secret': secret
}).encode('utf-8')
return self._execute('store', data_input)
def erase(self, server):
""" Erase credentials for `server`. Raises a `StoreError` if an error
occurs.
"""
if not isinstance(server, bytes):
server = server.encode('utf-8')
self._execute('erase', server)
def list(self):
""" List stored credentials. Requires v0.4.0+ of the helper.
"""
data = self._execute('list', None)
return json.loads(data.decode('utf-8'))
def _execute(self, subcmd, data_input):
if self.exe is None:
raise errors.StoreError(
f'{self.program} not installed or not available in PATH'
)
output = None
env = create_environment_dict(self.environment)
try:
output = subprocess.check_output(
[self.exe, subcmd], input=data_input, env=env,
)
except subprocess.CalledProcessError as e:
raise errors.process_store_error(e, self.program) from e
except OSError as e:
if e.errno == errno.ENOENT:
raise errors.StoreError(
f'{self.program} not installed or not available in PATH'
) from e
else:
raise errors.StoreError(
f'Unexpected OS error "{e.strerror}", errno={e.errno}'
) from e
return output

View File

@ -0,0 +1,10 @@
import os
def create_environment_dict(overrides):
"""
Create and return a copy of os.environ with the specified overrides
"""
result = os.environ.copy()
result.update(overrides or {})
return result

View File

@ -1,62 +1,102 @@
# Copyright 2014 dotCloud inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import requests
class APIError(requests.exceptions.HTTPError):
def __init__(self, message, response, explanation=None):
# requests 1.2 supports response as a keyword argument, but
# requests 1.1 doesn't
super(APIError, self).__init__(message)
self.response = response
self.explanation = explanation
if self.explanation is None and response.content:
self.explanation = response.content.strip()
def __str__(self):
message = super(APIError, self).__str__()
if self.is_client_error():
message = '{0} Client Error: {1}'.format(
self.response.status_code, self.response.reason)
elif self.is_server_error():
message = '{0} Server Error: {1}'.format(
self.response.status_code, self.response.reason)
if self.explanation:
message = '{0} ("{1}")'.format(message, self.explanation)
return message
def is_client_error(self):
return 400 <= self.response.status_code < 500
def is_server_error(self):
return 500 <= self.response.status_code < 600
_image_not_found_explanation_fragments = frozenset(
fragment.lower() for fragment in [
'no such image',
'not found: does not exist or no pull access',
'repository does not exist',
'was found but does not match the specified platform',
]
)
class DockerException(Exception):
pass
"""
A base class from which all other exceptions inherit.
If you want to catch all errors that the Docker SDK might raise,
catch this base exception.
"""
def create_api_error_from_http_exception(e):
"""
Create a suitable APIError from requests.exceptions.HTTPError.
"""
response = e.response
try:
explanation = response.json()['message']
except ValueError:
explanation = (response.text or '').strip()
cls = APIError
if response.status_code == 404:
explanation_msg = (explanation or '').lower()
if any(fragment in explanation_msg
for fragment in _image_not_found_explanation_fragments):
cls = ImageNotFound
else:
cls = NotFound
raise cls(e, response=response, explanation=explanation) from e
class APIError(requests.exceptions.HTTPError, DockerException):
"""
An HTTP error from the API.
"""
def __init__(self, message, response=None, explanation=None):
# requests 1.2 supports response as a keyword argument, but
# requests 1.1 doesn't
super().__init__(message)
self.response = response
self.explanation = explanation
def __str__(self):
message = super().__str__()
if self.is_client_error():
message = (
f'{self.response.status_code} Client Error for '
f'{self.response.url}: {self.response.reason}'
)
elif self.is_server_error():
message = (
f'{self.response.status_code} Server Error for '
f'{self.response.url}: {self.response.reason}'
)
if self.explanation:
message = f'{message} ("{self.explanation}")'
return message
@property
def status_code(self):
if self.response is not None:
return self.response.status_code
def is_error(self):
return self.is_client_error() or self.is_server_error()
def is_client_error(self):
if self.status_code is None:
return False
return 400 <= self.status_code < 500
def is_server_error(self):
if self.status_code is None:
return False
return 500 <= self.status_code < 600
class NotFound(APIError):
pass
class ImageNotFound(NotFound):
pass
class InvalidVersion(DockerException):
pass
@ -69,6 +109,10 @@ class InvalidConfigFile(DockerException):
pass
class InvalidArgument(DockerException):
pass
class DeprecatedMethod(DockerException):
pass
@ -86,3 +130,80 @@ class TLSParameterError(DockerException):
class NullResource(DockerException, ValueError):
pass
class ContainerError(DockerException):
"""
Represents a container that has exited with a non-zero exit code.
"""
def __init__(self, container, exit_status, command, image, stderr):
self.container = container
self.exit_status = exit_status
self.command = command
self.image = image
self.stderr = stderr
err = f": {stderr}" if stderr is not None else ""
super().__init__(
f"Command '{command}' in image '{image}' "
f"returned non-zero exit status {exit_status}{err}"
)
class StreamParseError(RuntimeError):
def __init__(self, reason):
self.msg = reason
class BuildError(DockerException):
def __init__(self, reason, build_log):
super().__init__(reason)
self.msg = reason
self.build_log = build_log
class ImageLoadError(DockerException):
pass
def create_unexpected_kwargs_error(name, kwargs):
quoted_kwargs = [f"'{k}'" for k in sorted(kwargs)]
text = [f"{name}() "]
if len(quoted_kwargs) == 1:
text.append("got an unexpected keyword argument ")
else:
text.append("got unexpected keyword arguments ")
text.append(', '.join(quoted_kwargs))
return TypeError(''.join(text))
class MissingContextParameter(DockerException):
def __init__(self, param):
self.param = param
def __str__(self):
return (f"missing parameter: {self.param}")
class ContextAlreadyExists(DockerException):
def __init__(self, name):
self.name = name
def __str__(self):
return (f"context {self.name} already exists")
class ContextException(DockerException):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return (self.msg)
class ContextNotFound(DockerException):
def __init__(self, name):
self.name = name
def __str__(self):
return (f"context '{self.name}' not found")

View File

70
docker/models/configs.py Normal file
View File

@ -0,0 +1,70 @@
from ..api import APIClient
from .resource import Collection, Model
class Config(Model):
"""A config."""
id_attribute = 'ID'
def __repr__(self):
return f"<{self.__class__.__name__}: '{self.name}'>"
@property
def name(self):
return self.attrs['Spec']['Name']
def remove(self):
"""
Remove this config.
Raises:
:py:class:`docker.errors.APIError`
If config failed to remove.
"""
return self.client.api.remove_config(self.id)
class ConfigCollection(Collection):
"""Configs on the Docker server."""
model = Config
def create(self, **kwargs):
obj = self.client.api.create_config(**kwargs)
obj.setdefault("Spec", {})["Name"] = kwargs.get("name")
return self.prepare_model(obj)
create.__doc__ = APIClient.create_config.__doc__
def get(self, config_id):
"""
Get a config.
Args:
config_id (str): Config ID.
Returns:
(:py:class:`Config`): The config.
Raises:
:py:class:`docker.errors.NotFound`
If the config does not exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(self.client.api.inspect_config(config_id))
def list(self, **kwargs):
"""
List configs. Similar to the ``docker config ls`` command.
Args:
filters (dict): Server-side list filtering options.
Returns:
(list of :py:class:`Config`): The configs.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
resp = self.client.api.configs(**kwargs)
return [self.prepare_model(obj) for obj in resp]

1198
docker/models/containers.py Normal file

File diff suppressed because it is too large Load Diff

505
docker/models/images.py Normal file
View File

@ -0,0 +1,505 @@
import itertools
import re
import warnings
from ..api import APIClient
from ..constants import DEFAULT_DATA_CHUNK_SIZE
from ..errors import BuildError, ImageLoadError, InvalidArgument
from ..utils import parse_repository_tag
from ..utils.json_stream import json_stream
from .resource import Collection, Model
class Image(Model):
"""
An image on the server.
"""
def __repr__(self):
tag_str = "', '".join(self.tags)
return f"<{self.__class__.__name__}: '{tag_str}'>"
@property
def labels(self):
"""
The labels of an image as dictionary.
"""
result = self.attrs['Config'].get('Labels')
return result or {}
@property
def short_id(self):
"""
The ID of the image truncated to 12 characters, plus the ``sha256:``
prefix.
"""
if self.id.startswith('sha256:'):
return self.id[:19]
return self.id[:12]
@property
def tags(self):
"""
The image's tags.
"""
tags = self.attrs.get('RepoTags')
if tags is None:
tags = []
return [tag for tag in tags if tag != '<none>:<none>']
def history(self):
"""
Show the history of an image.
Returns:
(list): The history of the image.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.history(self.id)
def remove(self, force=False, noprune=False):
"""
Remove this image.
Args:
force (bool): Force removal of the image
noprune (bool): Do not delete untagged parents
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.remove_image(
self.id,
force=force,
noprune=noprune,
)
def save(self, chunk_size=DEFAULT_DATA_CHUNK_SIZE, named=False):
"""
Get a tarball of an image. Similar to the ``docker save`` command.
Args:
chunk_size (int): The generator will return up to that much data
per iteration, but may return less. If ``None``, data will be
streamed as it is received. Default: 2 MB
named (str or bool): If ``False`` (default), the tarball will not
retain repository and tag information for this image. If set
to ``True``, the first tag in the :py:attr:`~tags` list will
be used to identify the image. Alternatively, any element of
the :py:attr:`~tags` list can be used as an argument to use
that specific tag as the saved identifier.
Returns:
(generator): A stream of raw archive data.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> image = cli.images.get("busybox:latest")
>>> f = open('/tmp/busybox-latest.tar', 'wb')
>>> for chunk in image.save():
>>> f.write(chunk)
>>> f.close()
"""
img = self.id
if named:
img = self.tags[0] if self.tags else img
if isinstance(named, str):
if named not in self.tags:
raise InvalidArgument(
f"{named} is not a valid tag for this image"
)
img = named
return self.client.api.get_image(img, chunk_size)
def tag(self, repository, tag=None, **kwargs):
"""
Tag this image into a repository. Similar to the ``docker tag``
command.
Args:
repository (str): The repository to set for the tag
tag (str): The tag name
force (bool): Force
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Returns:
(bool): ``True`` if successful
"""
return self.client.api.tag(self.id, repository, tag=tag, **kwargs)
class RegistryData(Model):
"""
Image metadata stored on the registry, including available platforms.
"""
def __init__(self, image_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.image_name = image_name
@property
def id(self):
"""
The ID of the object.
"""
return self.attrs['Descriptor']['digest']
@property
def short_id(self):
"""
The ID of the image truncated to 12 characters, plus the ``sha256:``
prefix.
"""
return self.id[:19]
def pull(self, platform=None):
"""
Pull the image digest.
Args:
platform (str): The platform to pull the image for.
Default: ``None``
Returns:
(:py:class:`Image`): A reference to the pulled image.
"""
repository, _ = parse_repository_tag(self.image_name)
return self.collection.pull(repository, tag=self.id, platform=platform)
def has_platform(self, platform):
"""
Check whether the given platform identifier is available for this
digest.
Args:
platform (str or dict): A string using the ``os[/arch[/variant]]``
format, or a platform dictionary.
Returns:
(bool): ``True`` if the platform is recognized as available,
``False`` otherwise.
Raises:
:py:class:`docker.errors.InvalidArgument`
If the platform argument is not a valid descriptor.
"""
if platform and not isinstance(platform, dict):
parts = platform.split('/')
if len(parts) > 3 or len(parts) < 1:
raise InvalidArgument(
f'"{platform}" is not a valid platform descriptor'
)
platform = {'os': parts[0]}
if len(parts) > 2:
platform['variant'] = parts[2]
if len(parts) > 1:
platform['architecture'] = parts[1]
return normalize_platform(
platform, self.client.version()
) in self.attrs['Platforms']
def reload(self):
self.attrs = self.client.api.inspect_distribution(self.image_name)
reload.__doc__ = Model.reload.__doc__
class ImageCollection(Collection):
model = Image
def build(self, **kwargs):
"""
Build an image and return it. Similar to the ``docker build``
command. Either ``path`` or ``fileobj`` must be set.
If you already have a tar file for the Docker build context (including
a Dockerfile), pass a readable file-like object to ``fileobj``
and also pass ``custom_context=True``. If the stream is also
compressed, set ``encoding`` to the correct value (e.g ``gzip``).
If you want to get the raw output of the build, use the
:py:meth:`~docker.api.build.BuildApiMixin.build` method in the
low-level API.
Args:
path (str): Path to the directory containing the Dockerfile
fileobj: A file object to use as the Dockerfile. (Or a file-like
object)
tag (str): A tag to add to the final image
quiet (bool): Whether to return the status
nocache (bool): Don't use the cache when set to ``True``
rm (bool): Remove intermediate containers. The ``docker build``
command now defaults to ``--rm=true``, but we have kept the old
default of `False` to preserve backward compatibility
timeout (int): HTTP timeout
custom_context (bool): Optional if using ``fileobj``
encoding (str): The encoding for a stream. Set to ``gzip`` for
compressing
pull (bool): Downloads any updates to the FROM image in Dockerfiles
forcerm (bool): Always remove intermediate containers, even after
unsuccessful builds
dockerfile (str): path within the build context to the Dockerfile
buildargs (dict): A dictionary of build arguments
container_limits (dict): A dictionary of limits applied to each
container created by the build process. Valid keys:
- memory (int): set memory limit for build
- memswap (int): Total memory (memory + swap), -1 to disable
swap
- cpushares (int): CPU shares (relative weight)
- cpusetcpus (str): CPUs in which to allow execution, e.g.,
``"0-3"``, ``"0,1"``
shmsize (int): Size of `/dev/shm` in bytes. The size must be
greater than 0. If omitted the system uses 64MB
labels (dict): A dictionary of labels to set on the image
cache_from (list): A list of images used for build cache
resolution
target (str): Name of the build-stage to build in a multi-stage
Dockerfile
network_mode (str): networking mode for the run commands during
build
squash (bool): Squash the resulting images layers into a
single layer.
extra_hosts (dict): Extra hosts to add to /etc/hosts in building
containers, as a mapping of hostname to IP address.
platform (str): Platform in the format ``os[/arch[/variant]]``.
isolation (str): Isolation technology used during build.
Default: `None`.
use_config_proxy (bool): If ``True``, and if the docker client
configuration file (``~/.docker/config.json`` by default)
contains a proxy configuration, the corresponding environment
variables will be set in the container being built.
Returns:
(tuple): The first item is the :py:class:`Image` object for the
image that was built. The second item is a generator of the
build logs as JSON-decoded objects.
Raises:
:py:class:`docker.errors.BuildError`
If there is an error during the build.
:py:class:`docker.errors.APIError`
If the server returns any other error.
``TypeError``
If neither ``path`` nor ``fileobj`` is specified.
"""
resp = self.client.api.build(**kwargs)
if isinstance(resp, str):
return self.get(resp)
last_event = None
image_id = None
result_stream, internal_stream = itertools.tee(json_stream(resp))
for chunk in internal_stream:
if 'error' in chunk:
raise BuildError(chunk['error'], result_stream)
if 'stream' in chunk:
match = re.search(
r'(^Successfully built |sha256:)([0-9a-f]+)$',
chunk['stream']
)
if match:
image_id = match.group(2)
last_event = chunk
if image_id:
return (self.get(image_id), result_stream)
raise BuildError(last_event or 'Unknown', result_stream)
def get(self, name):
"""
Gets an image.
Args:
name (str): The name of the image.
Returns:
(:py:class:`Image`): The image.
Raises:
:py:class:`docker.errors.ImageNotFound`
If the image does not exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(self.client.api.inspect_image(name))
def get_registry_data(self, name, auth_config=None):
"""
Gets the registry data for an image.
Args:
name (str): The name of the image.
auth_config (dict): Override the credentials that are found in the
config for this request. ``auth_config`` should contain the
``username`` and ``password`` keys to be valid.
Returns:
(:py:class:`RegistryData`): The data object.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return RegistryData(
image_name=name,
attrs=self.client.api.inspect_distribution(name, auth_config),
client=self.client,
collection=self,
)
def list(self, name=None, all=False, filters=None):
"""
List images on the server.
Args:
name (str): Only show images belonging to the repository ``name``
all (bool): Show intermediate image layers. By default, these are
filtered out.
filters (dict): Filters to be processed on the image list.
Available filters:
- ``dangling`` (bool)
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
Returns:
(list of :py:class:`Image`): The images.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
resp = self.client.api.images(name=name, all=all, filters=filters)
return [self.get(r["Id"]) for r in resp]
def load(self, data):
"""
Load an image that was previously saved using
:py:meth:`~docker.models.images.Image.save` (or ``docker save``).
Similar to ``docker load``.
Args:
data (binary): Image data to be loaded.
Returns:
(list of :py:class:`Image`): The images.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
resp = self.client.api.load_image(data)
images = []
for chunk in resp:
if 'stream' in chunk:
match = re.search(
r'(^Loaded image ID: |^Loaded image: )(.+)$',
chunk['stream']
)
if match:
image_id = match.group(2)
images.append(image_id)
if 'errorDetail' in chunk:
raise ImageLoadError(chunk['errorDetail']['message'])
return [self.get(i) for i in images]
def pull(self, repository, tag=None, all_tags=False, **kwargs):
"""
Pull an image of the given name and return it. Similar to the
``docker pull`` command.
If ``tag`` is ``None`` or empty, it is set to ``latest``.
If ``all_tags`` is set, the ``tag`` parameter is ignored and all image
tags will be pulled.
If you want to get the raw pull output, use the
:py:meth:`~docker.api.image.ImageApiMixin.pull` method in the
low-level API.
Args:
repository (str): The repository to pull
tag (str): The tag to pull
auth_config (dict): Override the credentials that are found in the
config for this request. ``auth_config`` should contain the
``username`` and ``password`` keys to be valid.
platform (str): Platform in the format ``os[/arch[/variant]]``
all_tags (bool): Pull all image tags
Returns:
(:py:class:`Image` or list): The image that has been pulled.
If ``all_tags`` is True, the method will return a list
of :py:class:`Image` objects belonging to this repository.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> # Pull the image tagged `latest` in the busybox repo
>>> image = client.images.pull('busybox')
>>> # Pull all tags in the busybox repo
>>> images = client.images.pull('busybox', all_tags=True)
"""
repository, image_tag = parse_repository_tag(repository)
tag = tag or image_tag or 'latest'
if 'stream' in kwargs:
warnings.warn(
'`stream` is not a valid parameter for this method'
' and will be overridden',
stacklevel=1,
)
del kwargs['stream']
pull_log = self.client.api.pull(
repository, tag=tag, stream=True, all_tags=all_tags, **kwargs
)
for _ in pull_log:
# We don't do anything with the logs, but we need
# to keep the connection alive and wait for the image
# to be pulled.
pass
if not all_tags:
sep = '@' if tag.startswith('sha256:') else ':'
return self.get(f'{repository}{sep}{tag}')
return self.list(repository)
def push(self, repository, tag=None, **kwargs):
return self.client.api.push(repository, tag=tag, **kwargs)
push.__doc__ = APIClient.push.__doc__
def remove(self, *args, **kwargs):
self.client.api.remove_image(*args, **kwargs)
remove.__doc__ = APIClient.remove_image.__doc__
def search(self, *args, **kwargs):
return self.client.api.search(*args, **kwargs)
search.__doc__ = APIClient.search.__doc__
def prune(self, filters=None):
return self.client.api.prune_images(filters=filters)
prune.__doc__ = APIClient.prune_images.__doc__
def prune_builds(self, *args, **kwargs):
return self.client.api.prune_builds(*args, **kwargs)
prune_builds.__doc__ = APIClient.prune_builds.__doc__
def normalize_platform(platform, engine_info):
if platform is None:
platform = {}
if 'os' not in platform:
platform['os'] = engine_info['Os']
if 'architecture' not in platform:
platform['architecture'] = engine_info['Arch']
return platform

218
docker/models/networks.py Normal file
View File

@ -0,0 +1,218 @@
from ..api import APIClient
from ..utils import version_gte
from .containers import Container
from .resource import Collection, Model
class Network(Model):
"""
A Docker network.
"""
@property
def name(self):
"""
The name of the network.
"""
return self.attrs.get('Name')
@property
def containers(self):
"""
The containers that are connected to the network, as a list of
:py:class:`~docker.models.containers.Container` objects.
"""
return [
self.client.containers.get(cid) for cid in
(self.attrs.get('Containers') or {}).keys()
]
def connect(self, container, *args, **kwargs):
"""
Connect a container to this network.
Args:
container (str): Container to connect to this network, as either
an ID, name, or :py:class:`~docker.models.containers.Container`
object.
aliases (:py:class:`list`): A list of aliases for this endpoint.
Names in that list can be used within the network to reach the
container. Defaults to ``None``.
links (:py:class:`list`): A list of links for this endpoint.
Containers declared in this list will be linkedto this
container. Defaults to ``None``.
ipv4_address (str): The IP address of this container on the
network, using the IPv4 protocol. Defaults to ``None``.
ipv6_address (str): The IP address of this container on the
network, using the IPv6 protocol. Defaults to ``None``.
link_local_ips (:py:class:`list`): A list of link-local (IPv4/IPv6)
addresses.
driver_opt (dict): A dictionary of options to provide to the
network driver. Defaults to ``None``.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if isinstance(container, Container):
container = container.id
return self.client.api.connect_container_to_network(
container, self.id, *args, **kwargs
)
def disconnect(self, container, *args, **kwargs):
"""
Disconnect a container from this network.
Args:
container (str): Container to disconnect from this network, as
either an ID, name, or
:py:class:`~docker.models.containers.Container` object.
force (bool): Force the container to disconnect from a network.
Default: ``False``
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if isinstance(container, Container):
container = container.id
return self.client.api.disconnect_container_from_network(
container, self.id, *args, **kwargs
)
def remove(self):
"""
Remove this network.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.remove_network(self.id)
class NetworkCollection(Collection):
"""
Networks on the Docker server.
"""
model = Network
def create(self, name, *args, **kwargs):
"""
Create a network. Similar to the ``docker network create``.
Args:
name (str): Name of the network
driver (str): Name of the driver used to create the network
options (dict): Driver options as a key-value dictionary
ipam (IPAMConfig): Optional custom IP scheme for the network.
check_duplicate (bool): Request daemon to check for networks with
same name. Default: ``None``.
internal (bool): Restrict external access to the network. Default
``False``.
labels (dict): Map of labels to set on the network. Default
``None``.
enable_ipv6 (bool): Enable IPv6 on the network. Default ``False``.
attachable (bool): If enabled, and the network is in the global
scope, non-service containers on worker nodes will be able to
connect to the network.
scope (str): Specify the network's scope (``local``, ``global`` or
``swarm``)
ingress (bool): If set, create an ingress network which provides
the routing-mesh in swarm mode.
Returns:
(:py:class:`Network`): The network that was created.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
A network using the bridge driver:
>>> client.networks.create("network1", driver="bridge")
You can also create more advanced networks with custom IPAM
configurations. For example, setting the subnet to
``192.168.52.0/24`` and gateway address to ``192.168.52.254``.
.. code-block:: python
>>> ipam_pool = docker.types.IPAMPool(
subnet='192.168.52.0/24',
gateway='192.168.52.254'
)
>>> ipam_config = docker.types.IPAMConfig(
pool_configs=[ipam_pool]
)
>>> client.networks.create(
"network1",
driver="bridge",
ipam=ipam_config
)
"""
resp = self.client.api.create_network(name, *args, **kwargs)
return self.get(resp['Id'])
def get(self, network_id, *args, **kwargs):
"""
Get a network by its ID.
Args:
network_id (str): The ID of the network.
verbose (bool): Retrieve the service details across the cluster in
swarm mode.
scope (str): Filter the network by scope (``swarm``, ``global``
or ``local``).
Returns:
(:py:class:`Network`) The network.
Raises:
:py:class:`docker.errors.NotFound`
If the network does not exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(
self.client.api.inspect_network(network_id, *args, **kwargs)
)
def list(self, *args, **kwargs):
"""
List networks. Similar to the ``docker network ls`` command.
Args:
names (:py:class:`list`): List of names to filter by.
ids (:py:class:`list`): List of ids to filter by.
filters (dict): Filters to be processed on the network list.
Available filters:
- ``driver=[<driver-name>]`` Matches a network's driver.
- `label` (str|list): format either ``"key"``, ``"key=value"``
or a list of such.
- ``type=["custom"|"builtin"]`` Filters networks by type.
greedy (bool): Fetch more details for each network individually.
You might want this to get the containers attached to them.
Returns:
(list of :py:class:`Network`) The networks on the server.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
greedy = kwargs.pop('greedy', False)
resp = self.client.api.networks(*args, **kwargs)
networks = [self.prepare_model(item) for item in resp]
if greedy and version_gte(self.client.api._version, '1.28'):
for net in networks:
net.reload()
return networks
def prune(self, filters=None):
return self.client.api.prune_networks(filters=filters)
prune.__doc__ = APIClient.prune_networks.__doc__

107
docker/models/nodes.py Normal file
View File

@ -0,0 +1,107 @@
from .resource import Collection, Model
class Node(Model):
"""A node in a swarm."""
id_attribute = 'ID'
@property
def version(self):
"""
The version number of the service. If this is not the same as the
server, the :py:meth:`update` function will not work and you will
need to call :py:meth:`reload` before calling it again.
"""
return self.attrs.get('Version').get('Index')
def update(self, node_spec):
"""
Update the node's configuration.
Args:
node_spec (dict): Configuration settings to update. Any values
not provided will be removed. Default: ``None``
Returns:
`True` if the request went through.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> node_spec = {'Availability': 'active',
'Name': 'node-name',
'Role': 'manager',
'Labels': {'foo': 'bar'}
}
>>> node.update(node_spec)
"""
return self.client.api.update_node(self.id, self.version, node_spec)
def remove(self, force=False):
"""
Remove this node from the swarm.
Args:
force (bool): Force remove an active node. Default: `False`
Returns:
`True` if the request was successful.
Raises:
:py:class:`docker.errors.NotFound`
If the node doesn't exist in the swarm.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.remove_node(self.id, force=force)
class NodeCollection(Collection):
"""Nodes on the Docker server."""
model = Node
def get(self, node_id):
"""
Get a node.
Args:
node_id (string): ID of the node to be inspected.
Returns:
A :py:class:`Node` object.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(self.client.api.inspect_node(node_id))
def list(self, *args, **kwargs):
"""
List swarm nodes.
Args:
filters (dict): Filters to process on the nodes list. Valid
filters: ``id``, ``name``, ``membership`` and ``role``.
Default: ``None``
Returns:
A list of :py:class:`Node` objects.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> client.nodes.list(filters={'role': 'manager'})
"""
return [
self.prepare_model(n)
for n in self.client.api.nodes(*args, **kwargs)
]

206
docker/models/plugins.py Normal file
View File

@ -0,0 +1,206 @@
from .. import errors
from .resource import Collection, Model
class Plugin(Model):
"""
A plugin on the server.
"""
def __repr__(self):
return f"<{self.__class__.__name__}: '{self.name}'>"
@property
def name(self):
"""
The plugin's name.
"""
return self.attrs.get('Name')
@property
def enabled(self):
"""
Whether the plugin is enabled.
"""
return self.attrs.get('Enabled')
@property
def settings(self):
"""
A dictionary representing the plugin's configuration.
"""
return self.attrs.get('Settings')
def configure(self, options):
"""
Update the plugin's settings.
Args:
options (dict): A key-value mapping of options.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
self.client.api.configure_plugin(self.name, options)
self.reload()
def disable(self, force=False):
"""
Disable the plugin.
Args:
force (bool): Force disable. Default: False
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
self.client.api.disable_plugin(self.name, force)
self.reload()
def enable(self, timeout=0):
"""
Enable the plugin.
Args:
timeout (int): Timeout in seconds. Default: 0
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
self.client.api.enable_plugin(self.name, timeout)
self.reload()
def push(self):
"""
Push the plugin to a remote registry.
Returns:
A dict iterator streaming the status of the upload.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.push_plugin(self.name)
def remove(self, force=False):
"""
Remove the plugin from the server.
Args:
force (bool): Remove even if the plugin is enabled.
Default: False
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.remove_plugin(self.name, force=force)
def upgrade(self, remote=None):
"""
Upgrade the plugin.
Args:
remote (string): Remote reference to upgrade to. The
``:latest`` tag is optional and is the default if omitted.
Default: this plugin's name.
Returns:
A generator streaming the decoded API logs
"""
if self.enabled:
raise errors.DockerError(
'Plugin must be disabled before upgrading.'
)
if remote is None:
remote = self.name
privileges = self.client.api.plugin_privileges(remote)
yield from self.client.api.upgrade_plugin(
self.name,
remote,
privileges,
)
self.reload()
class PluginCollection(Collection):
model = Plugin
def create(self, name, plugin_data_dir, gzip=False):
"""
Create a new plugin.
Args:
name (string): The name of the plugin. The ``:latest`` tag is
optional, and is the default if omitted.
plugin_data_dir (string): Path to the plugin data directory.
Plugin data directory must contain the ``config.json``
manifest file and the ``rootfs`` directory.
gzip (bool): Compress the context using gzip. Default: False
Returns:
(:py:class:`Plugin`): The newly created plugin.
"""
self.client.api.create_plugin(name, plugin_data_dir, gzip)
return self.get(name)
def get(self, name):
"""
Gets a plugin.
Args:
name (str): The name of the plugin.
Returns:
(:py:class:`Plugin`): The plugin.
Raises:
:py:class:`docker.errors.NotFound` If the plugin does not
exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(self.client.api.inspect_plugin(name))
def install(self, remote_name, local_name=None):
"""
Pull and install a plugin.
Args:
remote_name (string): Remote reference for the plugin to
install. The ``:latest`` tag is optional, and is the
default if omitted.
local_name (string): Local name for the pulled plugin.
The ``:latest`` tag is optional, and is the default if
omitted. Optional.
Returns:
(:py:class:`Plugin`): The installed plugin
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
privileges = self.client.api.plugin_privileges(remote_name)
it = self.client.api.pull_plugin(remote_name, privileges, local_name)
for _data in it:
pass
return self.get(local_name or remote_name)
def list(self):
"""
List plugins installed on the server.
Returns:
(list of :py:class:`Plugin`): The plugins.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
resp = self.client.api.plugins()
return [self.prepare_model(r) for r in resp]

92
docker/models/resource.py Normal file
View File

@ -0,0 +1,92 @@
class Model:
"""
A base class for representing a single object on the server.
"""
id_attribute = 'Id'
def __init__(self, attrs=None, client=None, collection=None):
#: A client pointing at the server that this object is on.
self.client = client
#: The collection that this model is part of.
self.collection = collection
#: The raw representation of this object from the API
self.attrs = attrs
if self.attrs is None:
self.attrs = {}
def __repr__(self):
return f"<{self.__class__.__name__}: {self.short_id}>"
def __eq__(self, other):
return isinstance(other, self.__class__) and self.id == other.id
def __hash__(self):
return hash(f"{self.__class__.__name__}:{self.id}")
@property
def id(self):
"""
The ID of the object.
"""
return self.attrs.get(self.id_attribute)
@property
def short_id(self):
"""
The ID of the object, truncated to 12 characters.
"""
return self.id[:12]
def reload(self):
"""
Load this object from the server again and update ``attrs`` with the
new data.
"""
new_model = self.collection.get(self.id)
self.attrs = new_model.attrs
class Collection:
"""
A base class for representing all objects of a particular type on the
server.
"""
#: The type of object this collection represents, set by subclasses
model = None
def __init__(self, client=None):
#: The client pointing at the server that this collection of objects
#: is on.
self.client = client
def __call__(self, *args, **kwargs):
raise TypeError(
f"'{self.__class__.__name__}' object is not callable. "
"You might be trying to use the old (pre-2.0) API - "
"use docker.APIClient if so."
)
def list(self):
raise NotImplementedError
def get(self, key):
raise NotImplementedError
def create(self, attrs=None):
raise NotImplementedError
def prepare_model(self, attrs):
"""
Create a model from a set of attributes.
"""
if isinstance(attrs, Model):
attrs.client = self.client
attrs.collection = self
return attrs
elif isinstance(attrs, dict):
return self.model(attrs=attrs, client=self.client, collection=self)
else:
raise Exception(f"Can't create {self.model.__name__} from {attrs}")

70
docker/models/secrets.py Normal file
View File

@ -0,0 +1,70 @@
from ..api import APIClient
from .resource import Collection, Model
class Secret(Model):
"""A secret."""
id_attribute = 'ID'
def __repr__(self):
return f"<{self.__class__.__name__}: '{self.name}'>"
@property
def name(self):
return self.attrs['Spec']['Name']
def remove(self):
"""
Remove this secret.
Raises:
:py:class:`docker.errors.APIError`
If secret failed to remove.
"""
return self.client.api.remove_secret(self.id)
class SecretCollection(Collection):
"""Secrets on the Docker server."""
model = Secret
def create(self, **kwargs):
obj = self.client.api.create_secret(**kwargs)
obj.setdefault("Spec", {})["Name"] = kwargs.get("name")
return self.prepare_model(obj)
create.__doc__ = APIClient.create_secret.__doc__
def get(self, secret_id):
"""
Get a secret.
Args:
secret_id (str): Secret ID.
Returns:
(:py:class:`Secret`): The secret.
Raises:
:py:class:`docker.errors.NotFound`
If the secret does not exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(self.client.api.inspect_secret(secret_id))
def list(self, **kwargs):
"""
List secrets. Similar to the ``docker secret ls`` command.
Args:
filters (dict): Server-side list filtering options.
Returns:
(list of :py:class:`Secret`): The secrets.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
resp = self.client.api.secrets(**kwargs)
return [self.prepare_model(obj) for obj in resp]

390
docker/models/services.py Normal file
View File

@ -0,0 +1,390 @@
import copy
from docker.errors import InvalidArgument, create_unexpected_kwargs_error
from docker.types import ContainerSpec, Placement, ServiceMode, TaskTemplate
from .resource import Collection, Model
class Service(Model):
"""A service."""
id_attribute = 'ID'
@property
def name(self):
"""The service's name."""
return self.attrs['Spec']['Name']
@property
def version(self):
"""
The version number of the service. If this is not the same as the
server, the :py:meth:`update` function will not work and you will
need to call :py:meth:`reload` before calling it again.
"""
return self.attrs.get('Version').get('Index')
def remove(self):
"""
Stop and remove the service.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.client.api.remove_service(self.id)
def tasks(self, filters=None):
"""
List the tasks in this service.
Args:
filters (dict): A map of filters to process on the tasks list.
Valid filters: ``id``, ``name``, ``node``,
``label``, and ``desired-state``.
Returns:
:py:class:`list`: List of task dictionaries.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
if filters is None:
filters = {}
filters['service'] = self.id
return self.client.api.tasks(filters=filters)
def update(self, **kwargs):
"""
Update a service's configuration. Similar to the ``docker service
update`` command.
Takes the same parameters as :py:meth:`~ServiceCollection.create`.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
# Image is required, so if it hasn't been set, use current image
if 'image' not in kwargs:
spec = self.attrs['Spec']['TaskTemplate']['ContainerSpec']
kwargs['image'] = spec['Image']
if kwargs.get('force_update') is True:
task_template = self.attrs['Spec']['TaskTemplate']
current_value = int(task_template.get('ForceUpdate', 0))
kwargs['force_update'] = current_value + 1
create_kwargs = _get_create_service_kwargs('update', kwargs)
return self.client.api.update_service(
self.id,
self.version,
**create_kwargs
)
def logs(self, **kwargs):
"""
Get log stream for the service.
Note: This method works only for services with the ``json-file``
or ``journald`` logging drivers.
Args:
details (bool): Show extra details provided to logs.
Default: ``False``
follow (bool): Keep connection open to read logs as they are
sent by the Engine. Default: ``False``
stdout (bool): Return logs from ``stdout``. Default: ``False``
stderr (bool): Return logs from ``stderr``. Default: ``False``
since (int): UNIX timestamp for the logs staring point.
Default: 0
timestamps (bool): Add timestamps to every log line.
tail (string or int): Number of log lines to be returned,
counting from the current end of the logs. Specify an
integer or ``'all'`` to output all log lines.
Default: ``all``
Returns:
generator: Logs for the service.
"""
is_tty = self.attrs['Spec']['TaskTemplate']['ContainerSpec'].get(
'TTY', False
)
return self.client.api.service_logs(self.id, is_tty=is_tty, **kwargs)
def scale(self, replicas):
"""
Scale service container.
Args:
replicas (int): The number of containers that should be running.
Returns:
bool: ``True`` if successful.
"""
if 'Global' in self.attrs['Spec']['Mode'].keys():
raise InvalidArgument('Cannot scale a global container')
service_mode = ServiceMode('replicated', replicas)
return self.client.api.update_service(self.id, self.version,
mode=service_mode,
fetch_current_spec=True)
def force_update(self):
"""
Force update the service even if no changes require it.
Returns:
bool: ``True`` if successful.
"""
return self.update(force_update=True, fetch_current_spec=True)
class ServiceCollection(Collection):
"""Services on the Docker server."""
model = Service
def create(self, image, command=None, **kwargs):
"""
Create a service. Similar to the ``docker service create`` command.
Args:
image (str): The image name to use for the containers.
command (list of str or str): Command to run.
args (list of str): Arguments to the command.
constraints (list of str): :py:class:`~docker.types.Placement`
constraints.
preferences (list of tuple): :py:class:`~docker.types.Placement`
preferences.
maxreplicas (int): :py:class:`~docker.types.Placement` maxreplicas
or (int) representing maximum number of replicas per node.
platforms (list of tuple): A list of platform constraints
expressed as ``(arch, os)`` tuples.
container_labels (dict): Labels to apply to the container.
endpoint_spec (EndpointSpec): Properties that can be configured to
access and load balance a service. Default: ``None``.
env (list of str): Environment variables, in the form
``KEY=val``.
hostname (string): Hostname to set on the container.
init (boolean): Run an init inside the container that forwards
signals and reaps processes
isolation (string): Isolation technology used by the service's
containers. Only used for Windows containers.
labels (dict): Labels to apply to the service.
log_driver (str): Log driver to use for containers.
log_driver_options (dict): Log driver options.
mode (ServiceMode): Scheduling mode for the service.
Default:``None``
mounts (list of str): Mounts for the containers, in the form
``source:target:options``, where options is either
``ro`` or ``rw``.
name (str): Name to give to the service.
networks (:py:class:`list`): List of network names or IDs or
:py:class:`~docker.types.NetworkAttachmentConfig` to attach the
service to. Default: ``None``.
resources (Resources): Resource limits and reservations.
restart_policy (RestartPolicy): Restart policy for containers.
secrets (list of :py:class:`~docker.types.SecretReference`): List
of secrets accessible to containers for this service.
stop_grace_period (int): Amount of time to wait for
containers to terminate before forcefully killing them.
update_config (UpdateConfig): Specification for the update strategy
of the service. Default: ``None``
rollback_config (RollbackConfig): Specification for the rollback
strategy of the service. Default: ``None``
user (str): User to run commands as.
workdir (str): Working directory for commands to run.
tty (boolean): Whether a pseudo-TTY should be allocated.
groups (:py:class:`list`): A list of additional groups that the
container process will run as.
open_stdin (boolean): Open ``stdin``
read_only (boolean): Mount the container's root filesystem as read
only.
stop_signal (string): Set signal to stop the service's containers
healthcheck (Healthcheck): Healthcheck
configuration for this service.
hosts (:py:class:`dict`): A set of host to IP mappings to add to
the container's `hosts` file.
dns_config (DNSConfig): Specification for DNS
related configurations in resolver configuration file.
configs (:py:class:`list`): List of
:py:class:`~docker.types.ConfigReference` that will be exposed
to the service.
privileges (Privileges): Security options for the service's
containers.
cap_add (:py:class:`list`): A list of kernel capabilities to add to
the default set for the container.
cap_drop (:py:class:`list`): A list of kernel capabilities to drop
from the default set for the container.
sysctls (:py:class:`dict`): A dict of sysctl values to add to the
container
Returns:
:py:class:`Service`: The created service.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
kwargs['image'] = image
kwargs['command'] = command
create_kwargs = _get_create_service_kwargs('create', kwargs)
service_id = self.client.api.create_service(**create_kwargs)
return self.get(service_id)
def get(self, service_id, insert_defaults=None):
"""
Get a service.
Args:
service_id (str): The ID of the service.
insert_defaults (boolean): If true, default values will be merged
into the output.
Returns:
:py:class:`Service`: The service.
Raises:
:py:class:`docker.errors.NotFound`
If the service does not exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
:py:class:`docker.errors.InvalidVersion`
If one of the arguments is not supported with the current
API version.
"""
return self.prepare_model(
self.client.api.inspect_service(service_id, insert_defaults)
)
def list(self, **kwargs):
"""
List services.
Args:
filters (dict): Filters to process on the nodes list. Valid
filters: ``id``, ``name`` , ``label`` and ``mode``.
Default: ``None``.
status (bool): Include the service task count of running and
desired tasks. Default: ``None``.
Returns:
list of :py:class:`Service`: The services.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return [
self.prepare_model(s)
for s in self.client.api.services(**kwargs)
]
# kwargs to copy straight over to ContainerSpec
CONTAINER_SPEC_KWARGS = [
'args',
'cap_add',
'cap_drop',
'command',
'configs',
'dns_config',
'env',
'groups',
'healthcheck',
'hostname',
'hosts',
'image',
'init',
'isolation',
'labels',
'mounts',
'open_stdin',
'privileges',
'read_only',
'secrets',
'stop_grace_period',
'stop_signal',
'tty',
'user',
'workdir',
'sysctls',
]
# kwargs to copy straight over to TaskTemplate
TASK_TEMPLATE_KWARGS = [
'networks',
'resources',
'restart_policy',
]
# kwargs to copy straight over to create_service
CREATE_SERVICE_KWARGS = [
'name',
'labels',
'mode',
'update_config',
'rollback_config',
'endpoint_spec',
]
PLACEMENT_KWARGS = [
'constraints',
'preferences',
'platforms',
'maxreplicas',
]
def _get_create_service_kwargs(func_name, kwargs):
# Copy over things which can be copied directly
create_kwargs = {}
for key in copy.copy(kwargs):
if key in CREATE_SERVICE_KWARGS:
create_kwargs[key] = kwargs.pop(key)
container_spec_kwargs = {}
for key in copy.copy(kwargs):
if key in CONTAINER_SPEC_KWARGS:
container_spec_kwargs[key] = kwargs.pop(key)
task_template_kwargs = {}
for key in copy.copy(kwargs):
if key in TASK_TEMPLATE_KWARGS:
task_template_kwargs[key] = kwargs.pop(key)
if 'container_labels' in kwargs:
container_spec_kwargs['labels'] = kwargs.pop('container_labels')
placement = {}
for key in copy.copy(kwargs):
if key in PLACEMENT_KWARGS:
placement[key] = kwargs.pop(key)
placement = Placement(**placement)
task_template_kwargs['placement'] = placement
if 'log_driver' in kwargs:
task_template_kwargs['log_driver'] = {
'Name': kwargs.pop('log_driver'),
'Options': kwargs.pop('log_driver_options', {})
}
if func_name == 'update':
if 'force_update' in kwargs:
task_template_kwargs['force_update'] = kwargs.pop('force_update')
# fetch the current spec by default if updating the service
# through the model
fetch_current_spec = kwargs.pop('fetch_current_spec', True)
create_kwargs['fetch_current_spec'] = fetch_current_spec
# All kwargs should have been consumed by this point, so raise
# error if any are left
if kwargs:
raise create_unexpected_kwargs_error(func_name, kwargs)
container_spec = ContainerSpec(**container_spec_kwargs)
task_template_kwargs['container_spec'] = container_spec
create_kwargs['task_template'] = TaskTemplate(**task_template_kwargs)
return create_kwargs

190
docker/models/swarm.py Normal file
View File

@ -0,0 +1,190 @@
from docker.api import APIClient
from docker.errors import APIError
from .resource import Model
class Swarm(Model):
"""
The server's Swarm state. This a singleton that must be reloaded to get
the current state of the Swarm.
"""
id_attribute = 'ID'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.client:
try:
self.reload()
except APIError as e:
# FIXME: https://github.com/docker/docker/issues/29192
if e.response.status_code not in (406, 503):
raise
@property
def version(self):
"""
The version number of the swarm. If this is not the same as the
server, the :py:meth:`update` function will not work and you will
need to call :py:meth:`reload` before calling it again.
"""
return self.attrs.get('Version').get('Index')
def get_unlock_key(self):
return self.client.api.get_unlock_key()
get_unlock_key.__doc__ = APIClient.get_unlock_key.__doc__
def init(self, advertise_addr=None, listen_addr='0.0.0.0:2377',
force_new_cluster=False, default_addr_pool=None,
subnet_size=None, data_path_addr=None, data_path_port=None,
**kwargs):
"""
Initialize a new swarm on this Engine.
Args:
advertise_addr (str): Externally reachable address advertised to
other nodes. This can either be an address/port combination in
the form ``192.168.1.1:4567``, or an interface followed by a
port number, like ``eth0:4567``. If the port number is omitted,
the port number from the listen address is used.
If not specified, it will be automatically detected when
possible.
listen_addr (str): Listen address used for inter-manager
communication, as well as determining the networking interface
used for the VXLAN Tunnel Endpoint (VTEP). This can either be
an address/port combination in the form ``192.168.1.1:4567``,
or an interface followed by a port number, like ``eth0:4567``.
If the port number is omitted, the default swarm listening port
is used. Default: ``0.0.0.0:2377``
force_new_cluster (bool): Force creating a new Swarm, even if
already part of one. Default: False
default_addr_pool (list of str): Default Address Pool specifies
default subnet pools for global scope networks. Each pool
should be specified as a CIDR block, like '10.0.0.0/8'.
Default: None
subnet_size (int): SubnetSize specifies the subnet size of the
networks created from the default subnet pool. Default: None
data_path_addr (string): Address or interface to use for data path
traffic. For example, 192.168.1.1, or an interface, like eth0.
data_path_port (int): Port number to use for data path traffic.
Acceptable port range is 1024 to 49151. If set to ``None`` or
0, the default port 4789 will be used. Default: None
task_history_retention_limit (int): Maximum number of tasks
history stored.
snapshot_interval (int): Number of logs entries between snapshot.
keep_old_snapshots (int): Number of snapshots to keep beyond the
current snapshot.
log_entries_for_slow_followers (int): Number of log entries to
keep around to sync up slow followers after a snapshot is
created.
heartbeat_tick (int): Amount of ticks (in seconds) between each
heartbeat.
election_tick (int): Amount of ticks (in seconds) needed without a
leader to trigger a new election.
dispatcher_heartbeat_period (int): The delay for an agent to send
a heartbeat to the dispatcher.
node_cert_expiry (int): Automatic expiry for nodes certificates.
external_ca (dict): Configuration for forwarding signing requests
to an external certificate authority. Use
``docker.types.SwarmExternalCA``.
name (string): Swarm's name
labels (dict): User-defined key/value metadata.
signing_ca_cert (str): The desired signing CA certificate for all
swarm node TLS leaf certificates, in PEM format.
signing_ca_key (str): The desired signing CA key for all swarm
node TLS leaf certificates, in PEM format.
ca_force_rotate (int): An integer whose purpose is to force swarm
to generate a new signing CA certificate and key, if none have
been specified.
autolock_managers (boolean): If set, generate a key and use it to
lock data stored on the managers.
log_driver (DriverConfig): The default log driver to use for tasks
created in the orchestrator.
Returns:
(str): The ID of the created node.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> client.swarm.init(
advertise_addr='eth0', listen_addr='0.0.0.0:5000',
force_new_cluster=False, default_addr_pool=['10.20.0.0/16],
subnet_size=24, snapshot_interval=5000,
log_entries_for_slow_followers=1200
)
"""
init_kwargs = {
'advertise_addr': advertise_addr,
'listen_addr': listen_addr,
'force_new_cluster': force_new_cluster,
'default_addr_pool': default_addr_pool,
'subnet_size': subnet_size,
'data_path_addr': data_path_addr,
'data_path_port': data_path_port,
}
init_kwargs['swarm_spec'] = self.client.api.create_swarm_spec(**kwargs)
node_id = self.client.api.init_swarm(**init_kwargs)
self.reload()
return node_id
def join(self, *args, **kwargs):
return self.client.api.join_swarm(*args, **kwargs)
join.__doc__ = APIClient.join_swarm.__doc__
def leave(self, *args, **kwargs):
return self.client.api.leave_swarm(*args, **kwargs)
leave.__doc__ = APIClient.leave_swarm.__doc__
def reload(self):
"""
Inspect the swarm on the server and store the response in
:py:attr:`attrs`.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
self.attrs = self.client.api.inspect_swarm()
def unlock(self, key):
return self.client.api.unlock_swarm(key)
unlock.__doc__ = APIClient.unlock_swarm.__doc__
def update(self, rotate_worker_token=False, rotate_manager_token=False,
rotate_manager_unlock_key=False, **kwargs):
"""
Update the swarm's configuration.
It takes the same arguments as :py:meth:`init`, except
``advertise_addr``, ``listen_addr``, and ``force_new_cluster``. In
addition, it takes these arguments:
Args:
rotate_worker_token (bool): Rotate the worker join token. Default:
``False``.
rotate_manager_token (bool): Rotate the manager join token.
Default: ``False``.
rotate_manager_unlock_key (bool): Rotate the manager unlock key.
Default: ``False``.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
# this seems to have to be set
if kwargs.get('node_cert_expiry') is None:
kwargs['node_cert_expiry'] = 7776000000000000
return self.client.api.update_swarm(
version=self.version,
swarm_spec=self.client.api.create_swarm_spec(**kwargs),
rotate_worker_token=rotate_worker_token,
rotate_manager_token=rotate_manager_token,
rotate_manager_unlock_key=rotate_manager_unlock_key
)

99
docker/models/volumes.py Normal file
View File

@ -0,0 +1,99 @@
from ..api import APIClient
from .resource import Collection, Model
class Volume(Model):
"""A volume."""
id_attribute = 'Name'
@property
def name(self):
"""The name of the volume."""
return self.attrs['Name']
def remove(self, force=False):
"""
Remove this volume.
Args:
force (bool): Force removal of volumes that were already removed
out of band by the volume driver plugin.
Raises:
:py:class:`docker.errors.APIError`
If volume failed to remove.
"""
return self.client.api.remove_volume(self.id, force=force)
class VolumeCollection(Collection):
"""Volumes on the Docker server."""
model = Volume
def create(self, name=None, **kwargs):
"""
Create a volume.
Args:
name (str): Name of the volume. If not specified, the engine
generates a name.
driver (str): Name of the driver used to create the volume
driver_opts (dict): Driver options as a key-value dictionary
labels (dict): Labels to set on the volume
Returns:
(:py:class:`Volume`): The volume created.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
Example:
>>> volume = client.volumes.create(name='foobar', driver='local',
driver_opts={'foo': 'bar', 'baz': 'false'},
labels={"key": "value"})
"""
obj = self.client.api.create_volume(name, **kwargs)
return self.prepare_model(obj)
def get(self, volume_id):
"""
Get a volume.
Args:
volume_id (str): Volume name.
Returns:
(:py:class:`Volume`): The volume.
Raises:
:py:class:`docker.errors.NotFound`
If the volume does not exist.
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
return self.prepare_model(self.client.api.inspect_volume(volume_id))
def list(self, **kwargs):
"""
List volumes. Similar to the ``docker volume ls`` command.
Args:
filters (dict): Server-side list filtering options.
Returns:
(list of :py:class:`Volume`): The volumes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
resp = self.client.api.volumes(**kwargs)
if not resp.get('Volumes'):
return []
return [self.prepare_model(obj) for obj in resp['Volumes']]
def prune(self, filters=None):
return self.client.api.prune_volumes(filters=filters)
prune.__doc__ = APIClient.prune_volumes.__doc__

View File

@ -1 +0,0 @@
from .ssladapter import SSLAdapter # flake8: noqa

View File

@ -1,57 +0,0 @@
""" Resolves OpenSSL issues in some servers:
https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/
https://github.com/kennethreitz/requests/pull/799
"""
from distutils.version import StrictVersion
from requests.adapters import HTTPAdapter
try:
import requests.packages.urllib3 as urllib3
except ImportError:
import urllib3
PoolManager = urllib3.poolmanager.PoolManager
class SSLAdapter(HTTPAdapter):
'''An HTTPS Transport Adapter that uses an arbitrary SSL version.'''
def __init__(self, ssl_version=None, assert_hostname=None,
assert_fingerprint=None, **kwargs):
self.ssl_version = ssl_version
self.assert_hostname = assert_hostname
self.assert_fingerprint = assert_fingerprint
super(SSLAdapter, self).__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
kwargs = {
'num_pools': connections,
'maxsize': maxsize,
'block': block,
'assert_hostname': self.assert_hostname,
'assert_fingerprint': self.assert_fingerprint,
}
if self.ssl_version and self.can_override_ssl_version():
kwargs['ssl_version'] = self.ssl_version
self.poolmanager = PoolManager(**kwargs)
def get_connection(self, *args, **kwargs):
"""
Ensure assert_hostname is set correctly on our pool
We already take care of a normal poolmanager via init_poolmanager
But we still need to take care of when there is a proxy poolmanager
"""
conn = super(SSLAdapter, self).get_connection(*args, **kwargs)
if conn.assert_hostname != self.assert_hostname:
conn.assert_hostname = self.assert_hostname
return conn
def can_override_ssl_version(self):
urllib_ver = urllib3.__version__.split('-')[0]
if urllib_ver is None:
return False
if urllib_ver == 'dev':
return True
return StrictVersion(urllib_ver) > StrictVersion('1.5')

View File

@ -1,35 +1,32 @@
import os
import ssl
from . import errors
from .ssladapter import ssladapter
class TLSConfig(object):
class TLSConfig:
"""
TLS configuration.
Args:
client_cert (tuple of str): Path to client cert, path to client key.
ca_cert (str): Path to CA cert file.
verify (bool or str): This can be a bool or a path to a CA cert
file to verify against. If ``True``, verify using ca_cert;
if ``False`` or not specified, do not verify.
"""
cert = None
ca_cert = None
verify = None
ssl_version = None
def __init__(self, client_cert=None, ca_cert=None, verify=None,
ssl_version=None, assert_hostname=None,
assert_fingerprint=None):
def __init__(self, client_cert=None, ca_cert=None, verify=None):
# Argument compatibility/mapping with
# https://docs.docker.com/engine/articles/https/
# This diverges from the Docker CLI in that users can specify 'tls'
# here, but also disable any public/default CA pool verification by
# leaving tls_verify=False
# leaving verify=False
self.assert_hostname = assert_hostname
self.assert_fingerprint = assert_fingerprint
# TLS v1.0 seems to be the safest default; SSLv23 fails in mysterious
# ways: https://github.com/docker/docker-py/issues/963
self.ssl_version = ssl_version or ssl.PROTOCOL_TLSv1
# "tls" and "tls_verify" must have both or neither cert/key files
# In either case, Alert the user when both are expected, but any are
# "client_cert" must have both or neither cert/key files. In
# either case, Alert the user when both are expected, but any are
# missing.
if client_cert:
@ -37,15 +34,15 @@ class TLSConfig(object):
tls_cert, tls_key = client_cert
except ValueError:
raise errors.TLSParameterError(
'client_config must be a tuple of'
'client_cert must be a tuple of'
' (client certificate, key file)'
)
) from None
if not (tls_cert and tls_key) or (not os.path.isfile(tls_cert) or
not os.path.isfile(tls_key)):
not os.path.isfile(tls_key)):
raise errors.TLSParameterError(
'Path to a certificate and key files must be provided'
' through the client_config param'
' through the client_cert param'
)
self.cert = (tls_cert, tls_key)
@ -54,12 +51,13 @@ class TLSConfig(object):
self.ca_cert = ca_cert
if self.verify and self.ca_cert and not os.path.isfile(self.ca_cert):
raise errors.TLSParameterError(
'Invalid CA certificate provided for `tls_ca_cert`.'
'Invalid CA certificate provided for `ca_cert`.'
)
def configure_client(self, client):
client.ssl_version = self.ssl_version
"""
Configure a client with these TLS options.
"""
if self.verify and self.ca_cert:
client.verify = self.ca_cert
else:
@ -67,9 +65,3 @@ class TLSConfig(object):
if self.cert:
client.cert = self.cert
client.mount('https://', ssladapter.SSLAdapter(
ssl_version=self.ssl_version,
assert_hostname=self.assert_hostname,
assert_fingerprint=self.assert_fingerprint,
))

View File

@ -0,0 +1,12 @@
from .unixconn import UnixHTTPAdapter
try:
from .npipeconn import NpipeHTTPAdapter
from .npipesocket import NpipeSocket
except ImportError:
pass
try:
from .sshconn import SSHHTTPAdapter
except ImportError:
pass

View File

@ -0,0 +1,13 @@
import requests.adapters
class BaseHTTPAdapter(requests.adapters.HTTPAdapter):
def close(self):
super().close()
if hasattr(self, 'pools'):
self.pools.clear()
# Fix for requests 2.32.2+:
# https://github.com/psf/requests/commit/c98e4d133ef29c46a9b68cd783087218a8075e05
def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None):
return self.get_connection(request.url, proxies)

View File

@ -0,0 +1,102 @@
import queue
import requests.adapters
import urllib3
import urllib3.connection
from .. import constants
from .basehttpadapter import BaseHTTPAdapter
from .npipesocket import NpipeSocket
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class NpipeHTTPConnection(urllib3.connection.HTTPConnection):
def __init__(self, npipe_path, timeout=60):
super().__init__(
'localhost', timeout=timeout
)
self.npipe_path = npipe_path
self.timeout = timeout
def connect(self):
sock = NpipeSocket()
sock.settimeout(self.timeout)
sock.connect(self.npipe_path)
self.sock = sock
class NpipeHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
def __init__(self, npipe_path, timeout=60, maxsize=10):
super().__init__(
'localhost', timeout=timeout, maxsize=maxsize
)
self.npipe_path = npipe_path
self.timeout = timeout
def _new_conn(self):
return NpipeHTTPConnection(
self.npipe_path, self.timeout
)
# When re-using connections, urllib3 tries to call select() on our
# NpipeSocket instance, causing a crash. To circumvent this, we override
# _get_conn, where that check happens.
def _get_conn(self, timeout):
conn = None
try:
conn = self.pool.get(block=self.block, timeout=timeout)
except AttributeError as ae: # self.pool is None
raise urllib3.exceptions.ClosedPoolError(self, "Pool is closed.") from ae
except queue.Empty:
if self.block:
raise urllib3.exceptions.EmptyPoolError(
self,
"Pool reached maximum size and no more "
"connections are allowed."
) from None
# Oh well, we'll create a new connection then
return conn or self._new_conn()
class NpipeHTTPAdapter(BaseHTTPAdapter):
__attrs__ = requests.adapters.HTTPAdapter.__attrs__ + ['npipe_path',
'pools',
'timeout',
'max_pool_size']
def __init__(self, base_url, timeout=60,
pool_connections=constants.DEFAULT_NUM_POOLS,
max_pool_size=constants.DEFAULT_MAX_POOL_SIZE):
self.npipe_path = base_url.replace('npipe://', '')
self.timeout = timeout
self.max_pool_size = max_pool_size
self.pools = RecentlyUsedContainer(
pool_connections, dispose_func=lambda p: p.close()
)
super().__init__()
def get_connection(self, url, proxies=None):
with self.pools.lock:
pool = self.pools.get(url)
if pool:
return pool
pool = NpipeHTTPConnectionPool(
self.npipe_path, self.timeout,
maxsize=self.max_pool_size
)
self.pools[url] = pool
return pool
def request_url(self, request, proxies):
# The select_proxy utility in requests errors out when the provided URL
# doesn't have a hostname, like is the case when using a UNIX socket.
# Since proxies are an irrelevant notion in the case of UNIX sockets
# anyway, we simply return the path URL directly.
# See also: https://github.com/docker/docker-sdk-python/issues/811
return request.path_url

View File

@ -0,0 +1,230 @@
import functools
import io
import time
import pywintypes
import win32api
import win32event
import win32file
import win32pipe
cERROR_PIPE_BUSY = 0xe7
cSECURITY_SQOS_PRESENT = 0x100000
cSECURITY_ANONYMOUS = 0
MAXIMUM_RETRY_COUNT = 10
def check_closed(f):
@functools.wraps(f)
def wrapped(self, *args, **kwargs):
if self._closed:
raise RuntimeError(
'Can not reuse socket after connection was closed.'
)
return f(self, *args, **kwargs)
return wrapped
class NpipeSocket:
""" Partial implementation of the socket API over windows named pipes.
This implementation is only designed to be used as a client socket,
and server-specific methods (bind, listen, accept...) are not
implemented.
"""
def __init__(self, handle=None):
self._timeout = win32pipe.NMPWAIT_USE_DEFAULT_WAIT
self._handle = handle
self._closed = False
def accept(self):
raise NotImplementedError()
def bind(self, address):
raise NotImplementedError()
def close(self):
self._handle.Close()
self._closed = True
@check_closed
def connect(self, address, retry_count=0):
try:
handle = win32file.CreateFile(
address,
win32file.GENERIC_READ | win32file.GENERIC_WRITE,
0,
None,
win32file.OPEN_EXISTING,
(cSECURITY_ANONYMOUS
| cSECURITY_SQOS_PRESENT
| win32file.FILE_FLAG_OVERLAPPED),
0
)
except win32pipe.error as e:
# See Remarks:
# https://msdn.microsoft.com/en-us/library/aa365800.aspx
if e.winerror == cERROR_PIPE_BUSY:
# Another program or thread has grabbed our pipe instance
# before we got to it. Wait for availability and attempt to
# connect again.
retry_count = retry_count + 1
if (retry_count < MAXIMUM_RETRY_COUNT):
time.sleep(1)
return self.connect(address, retry_count)
raise e
self.flags = win32pipe.GetNamedPipeInfo(handle)[0]
self._handle = handle
self._address = address
@check_closed
def connect_ex(self, address):
return self.connect(address)
@check_closed
def detach(self):
self._closed = True
return self._handle
@check_closed
def dup(self):
return NpipeSocket(self._handle)
def getpeername(self):
return self._address
def getsockname(self):
return self._address
def getsockopt(self, level, optname, buflen=None):
raise NotImplementedError()
def ioctl(self, control, option):
raise NotImplementedError()
def listen(self, backlog):
raise NotImplementedError()
def makefile(self, mode=None, bufsize=None):
if mode.strip('b') != 'r':
raise NotImplementedError()
rawio = NpipeFileIOBase(self)
if bufsize is None or bufsize <= 0:
bufsize = io.DEFAULT_BUFFER_SIZE
return io.BufferedReader(rawio, buffer_size=bufsize)
@check_closed
def recv(self, bufsize, flags=0):
err, data = win32file.ReadFile(self._handle, bufsize)
return data
@check_closed
def recvfrom(self, bufsize, flags=0):
data = self.recv(bufsize, flags)
return (data, self._address)
@check_closed
def recvfrom_into(self, buf, nbytes=0, flags=0):
return self.recv_into(buf, nbytes, flags), self._address
@check_closed
def recv_into(self, buf, nbytes=0):
readbuf = buf
if not isinstance(buf, memoryview):
readbuf = memoryview(buf)
event = win32event.CreateEvent(None, True, True, None)
try:
overlapped = pywintypes.OVERLAPPED()
overlapped.hEvent = event
err, data = win32file.ReadFile(
self._handle,
readbuf[:nbytes] if nbytes else readbuf,
overlapped
)
wait_result = win32event.WaitForSingleObject(event, self._timeout)
if wait_result == win32event.WAIT_TIMEOUT:
win32file.CancelIo(self._handle)
raise TimeoutError
return win32file.GetOverlappedResult(self._handle, overlapped, 0)
finally:
win32api.CloseHandle(event)
@check_closed
def send(self, string, flags=0):
event = win32event.CreateEvent(None, True, True, None)
try:
overlapped = pywintypes.OVERLAPPED()
overlapped.hEvent = event
win32file.WriteFile(self._handle, string, overlapped)
wait_result = win32event.WaitForSingleObject(event, self._timeout)
if wait_result == win32event.WAIT_TIMEOUT:
win32file.CancelIo(self._handle)
raise TimeoutError
return win32file.GetOverlappedResult(self._handle, overlapped, 0)
finally:
win32api.CloseHandle(event)
@check_closed
def sendall(self, string, flags=0):
return self.send(string, flags)
@check_closed
def sendto(self, string, address):
self.connect(address)
return self.send(string)
def setblocking(self, flag):
if flag:
return self.settimeout(None)
return self.settimeout(0)
def settimeout(self, value):
if value is None:
# Blocking mode
self._timeout = win32event.INFINITE
elif not isinstance(value, (float, int)) or value < 0:
raise ValueError('Timeout value out of range')
else:
# Timeout mode - Value converted to milliseconds
self._timeout = int(value * 1000)
def gettimeout(self):
return self._timeout
def setsockopt(self, level, optname, value):
raise NotImplementedError()
@check_closed
def shutdown(self, how):
return self.close()
class NpipeFileIOBase(io.RawIOBase):
def __init__(self, npipe_socket):
self.sock = npipe_socket
def close(self):
super().close()
self.sock = None
def fileno(self):
return self.sock.fileno()
def isatty(self):
return False
def readable(self):
return True
def readinto(self, buf):
return self.sock.recv_into(buf)
def seekable(self):
return False
def writable(self):
return False

250
docker/transport/sshconn.py Normal file
View File

@ -0,0 +1,250 @@
import logging
import os
import queue
import signal
import socket
import subprocess
import urllib.parse
import paramiko
import requests.adapters
import urllib3
import urllib3.connection
from .. import constants
from .basehttpadapter import BaseHTTPAdapter
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class SSHSocket(socket.socket):
def __init__(self, host):
super().__init__(
socket.AF_INET, socket.SOCK_STREAM)
self.host = host
self.port = None
self.user = None
if ':' in self.host:
self.host, self.port = self.host.split(':')
if '@' in self.host:
self.user, self.host = self.host.split('@')
self.proc = None
def connect(self, **kwargs):
args = ['ssh']
if self.user:
args = args + ['-l', self.user]
if self.port:
args = args + ['-p', self.port]
args = args + ['--', self.host, 'docker system dial-stdio']
preexec_func = None
if not constants.IS_WINDOWS_PLATFORM:
def f():
signal.signal(signal.SIGINT, signal.SIG_IGN)
preexec_func = f
env = dict(os.environ)
# drop LD_LIBRARY_PATH and SSL_CERT_FILE
env.pop('LD_LIBRARY_PATH', None)
env.pop('SSL_CERT_FILE', None)
self.proc = subprocess.Popen(
args,
env=env,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
preexec_fn=preexec_func)
def _write(self, data):
if not self.proc or self.proc.stdin.closed:
raise Exception('SSH subprocess not initiated.'
'connect() must be called first.')
written = self.proc.stdin.write(data)
self.proc.stdin.flush()
return written
def sendall(self, data):
self._write(data)
def send(self, data):
return self._write(data)
def recv(self, n):
if not self.proc:
raise Exception('SSH subprocess not initiated.'
'connect() must be called first.')
return self.proc.stdout.read(n)
def makefile(self, mode):
if not self.proc:
self.connect()
self.proc.stdout.channel = self
return self.proc.stdout
def close(self):
if not self.proc or self.proc.stdin.closed:
return
self.proc.stdin.write(b'\n\n')
self.proc.stdin.flush()
self.proc.terminate()
class SSHConnection(urllib3.connection.HTTPConnection):
def __init__(self, ssh_transport=None, timeout=60, host=None):
super().__init__(
'localhost', timeout=timeout
)
self.ssh_transport = ssh_transport
self.timeout = timeout
self.ssh_host = host
def connect(self):
if self.ssh_transport:
sock = self.ssh_transport.open_session()
sock.settimeout(self.timeout)
sock.exec_command('docker system dial-stdio')
else:
sock = SSHSocket(self.ssh_host)
sock.settimeout(self.timeout)
sock.connect()
self.sock = sock
class SSHConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
scheme = 'ssh'
def __init__(self, ssh_client=None, timeout=60, maxsize=10, host=None):
super().__init__(
'localhost', timeout=timeout, maxsize=maxsize
)
self.ssh_transport = None
self.timeout = timeout
if ssh_client:
self.ssh_transport = ssh_client.get_transport()
self.ssh_host = host
def _new_conn(self):
return SSHConnection(self.ssh_transport, self.timeout, self.ssh_host)
# When re-using connections, urllib3 calls fileno() on our
# SSH channel instance, quickly overloading our fd limit. To avoid this,
# we override _get_conn
def _get_conn(self, timeout):
conn = None
try:
conn = self.pool.get(block=self.block, timeout=timeout)
except AttributeError as ae: # self.pool is None
raise urllib3.exceptions.ClosedPoolError(self, "Pool is closed.") from ae
except queue.Empty:
if self.block:
raise urllib3.exceptions.EmptyPoolError(
self,
"Pool reached maximum size and no more "
"connections are allowed."
) from None
# Oh well, we'll create a new connection then
return conn or self._new_conn()
class SSHHTTPAdapter(BaseHTTPAdapter):
__attrs__ = requests.adapters.HTTPAdapter.__attrs__ + [
'pools', 'timeout', 'ssh_client', 'ssh_params', 'max_pool_size'
]
def __init__(self, base_url, timeout=60,
pool_connections=constants.DEFAULT_NUM_POOLS,
max_pool_size=constants.DEFAULT_MAX_POOL_SIZE,
shell_out=False):
self.ssh_client = None
if not shell_out:
self._create_paramiko_client(base_url)
self._connect()
self.ssh_host = base_url
if base_url.startswith('ssh://'):
self.ssh_host = base_url[len('ssh://'):]
self.timeout = timeout
self.max_pool_size = max_pool_size
self.pools = RecentlyUsedContainer(
pool_connections, dispose_func=lambda p: p.close()
)
super().__init__()
def _create_paramiko_client(self, base_url):
logging.getLogger("paramiko").setLevel(logging.WARNING)
self.ssh_client = paramiko.SSHClient()
base_url = urllib.parse.urlparse(base_url)
self.ssh_params = {
"hostname": base_url.hostname,
"port": base_url.port,
"username": base_url.username
}
ssh_config_file = os.path.expanduser("~/.ssh/config")
if os.path.exists(ssh_config_file):
conf = paramiko.SSHConfig()
with open(ssh_config_file) as f:
conf.parse(f)
host_config = conf.lookup(base_url.hostname)
if 'proxycommand' in host_config:
self.ssh_params["sock"] = paramiko.ProxyCommand(
host_config['proxycommand']
)
if 'hostname' in host_config:
self.ssh_params['hostname'] = host_config['hostname']
if base_url.port is None and 'port' in host_config:
self.ssh_params['port'] = host_config['port']
if base_url.username is None and 'user' in host_config:
self.ssh_params['username'] = host_config['user']
if 'identityfile' in host_config:
self.ssh_params['key_filename'] = host_config['identityfile']
self.ssh_client.load_system_host_keys()
self.ssh_client.set_missing_host_key_policy(paramiko.RejectPolicy())
def _connect(self):
if self.ssh_client:
self.ssh_client.connect(**self.ssh_params)
def get_connection(self, url, proxies=None):
if not self.ssh_client:
return SSHConnectionPool(
ssh_client=self.ssh_client,
timeout=self.timeout,
maxsize=self.max_pool_size,
host=self.ssh_host
)
with self.pools.lock:
pool = self.pools.get(url)
if pool:
return pool
# Connection is closed try a reconnect
if self.ssh_client and not self.ssh_client.get_transport():
self._connect()
pool = SSHConnectionPool(
ssh_client=self.ssh_client,
timeout=self.timeout,
maxsize=self.max_pool_size,
host=self.ssh_host
)
self.pools[url] = pool
return pool
def close(self):
super().close()
if self.ssh_client:
self.ssh_client.close()

View File

@ -0,0 +1,86 @@
import socket
import requests.adapters
import urllib3
import urllib3.connection
from .. import constants
from .basehttpadapter import BaseHTTPAdapter
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class UnixHTTPConnection(urllib3.connection.HTTPConnection):
def __init__(self, base_url, unix_socket, timeout=60):
super().__init__(
'localhost', timeout=timeout
)
self.base_url = base_url
self.unix_socket = unix_socket
self.timeout = timeout
def connect(self):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
sock.connect(self.unix_socket)
self.sock = sock
class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
def __init__(self, base_url, socket_path, timeout=60, maxsize=10):
super().__init__(
'localhost', timeout=timeout, maxsize=maxsize
)
self.base_url = base_url
self.socket_path = socket_path
self.timeout = timeout
def _new_conn(self):
return UnixHTTPConnection(
self.base_url, self.socket_path, self.timeout
)
class UnixHTTPAdapter(BaseHTTPAdapter):
__attrs__ = requests.adapters.HTTPAdapter.__attrs__ + ['pools',
'socket_path',
'timeout',
'max_pool_size']
def __init__(self, socket_url, timeout=60,
pool_connections=constants.DEFAULT_NUM_POOLS,
max_pool_size=constants.DEFAULT_MAX_POOL_SIZE):
socket_path = socket_url.replace('http+unix://', '')
if not socket_path.startswith('/'):
socket_path = f"/{socket_path}"
self.socket_path = socket_path
self.timeout = timeout
self.max_pool_size = max_pool_size
self.pools = RecentlyUsedContainer(
pool_connections, dispose_func=lambda p: p.close()
)
super().__init__()
def get_connection(self, url, proxies=None):
with self.pools.lock:
pool = self.pools.get(url)
if pool:
return pool
pool = UnixHTTPConnectionPool(
url, self.socket_path, self.timeout,
maxsize=self.max_pool_size
)
self.pools[url] = pool
return pool
def request_url(self, request, proxies):
# The select_proxy utility in requests errors out when the provided URL
# doesn't have a hostname, like is the case when using a UNIX socket.
# Since proxies are an irrelevant notion in the case of UNIX sockets
# anyway, we simply return the path URL directly.
# See also: https://github.com/docker/docker-py/issues/811
return request.path_url

24
docker/types/__init__.py Normal file
View File

@ -0,0 +1,24 @@
from .containers import ContainerConfig, DeviceRequest, HostConfig, LogConfig, Ulimit
from .daemon import CancellableStream
from .healthcheck import Healthcheck
from .networks import EndpointConfig, IPAMConfig, IPAMPool, NetworkingConfig
from .services import (
ConfigReference,
ContainerSpec,
DNSConfig,
DriverConfig,
EndpointSpec,
Mount,
NetworkAttachmentConfig,
Placement,
PlacementPreference,
Privileges,
Resources,
RestartPolicy,
RollbackConfig,
SecretReference,
ServiceMode,
TaskTemplate,
UpdateConfig,
)
from .swarm import SwarmExternalCA, SwarmSpec

4
docker/types/base.py Normal file
View File

@ -0,0 +1,4 @@
class DictType(dict):
def __init__(self, init):
for k, v in init.items():
self[k] = v

790
docker/types/containers.py Normal file
View File

@ -0,0 +1,790 @@
from .. import errors
from ..utils.utils import (
convert_port_bindings,
convert_tmpfs_mounts,
convert_volume_binds,
format_environment,
format_extra_hosts,
normalize_links,
parse_bytes,
parse_devices,
split_command,
version_gte,
version_lt,
)
from .base import DictType
from .healthcheck import Healthcheck
class LogConfigTypesEnum:
_values = (
'json-file',
'syslog',
'journald',
'gelf',
'fluentd',
'none'
)
JSON, SYSLOG, JOURNALD, GELF, FLUENTD, NONE = _values
class LogConfig(DictType):
"""
Configure logging for a container, when provided as an argument to
:py:meth:`~docker.api.container.ContainerApiMixin.create_host_config`.
You may refer to the
`official logging driver documentation <https://docs.docker.com/config/containers/logging/configure/>`_
for more information.
Args:
type (str): Indicate which log driver to use. A set of valid drivers
is provided as part of the :py:attr:`LogConfig.types`
enum. Other values may be accepted depending on the engine version
and available logging plugins.
config (dict): A driver-dependent configuration dictionary. Please
refer to the driver's documentation for a list of valid config
keys.
Example:
>>> from docker.types import LogConfig
>>> lc = LogConfig(type=LogConfig.types.JSON, config={
... 'max-size': '1g',
... 'labels': 'production_status,geo'
... })
>>> hc = client.create_host_config(log_config=lc)
>>> container = client.create_container('busybox', 'true',
... host_config=hc)
>>> client.inspect_container(container)['HostConfig']['LogConfig']
{
'Type': 'json-file',
'Config': {'labels': 'production_status,geo', 'max-size': '1g'}
}
"""
types = LogConfigTypesEnum
def __init__(self, **kwargs):
log_driver_type = kwargs.get('type', kwargs.get('Type'))
config = kwargs.get('config', kwargs.get('Config')) or {}
if config and not isinstance(config, dict):
raise ValueError("LogConfig.config must be a dictionary")
super().__init__({
'Type': log_driver_type,
'Config': config
})
@property
def type(self):
return self['Type']
@type.setter
def type(self, value):
self['Type'] = value
@property
def config(self):
return self['Config']
def set_config_value(self, key, value):
""" Set a the value for ``key`` to ``value`` inside the ``config``
dict.
"""
self.config[key] = value
def unset_config(self, key):
""" Remove the ``key`` property from the ``config`` dict. """
if key in self.config:
del self.config[key]
class Ulimit(DictType):
"""
Create a ulimit declaration to be used with
:py:meth:`~docker.api.container.ContainerApiMixin.create_host_config`.
Args:
name (str): Which ulimit will this apply to. The valid names can be
found in '/etc/security/limits.conf' on a gnu/linux system.
soft (int): The soft limit for this ulimit. Optional.
hard (int): The hard limit for this ulimit. Optional.
Example:
>>> nproc_limit = docker.types.Ulimit(name='nproc', soft=1024)
>>> hc = client.create_host_config(ulimits=[nproc_limit])
>>> container = client.create_container(
'busybox', 'true', host_config=hc
)
>>> client.inspect_container(container)['HostConfig']['Ulimits']
[{'Name': 'nproc', 'Hard': 0, 'Soft': 1024}]
"""
def __init__(self, **kwargs):
name = kwargs.get('name', kwargs.get('Name'))
soft = kwargs.get('soft', kwargs.get('Soft'))
hard = kwargs.get('hard', kwargs.get('Hard'))
if not isinstance(name, str):
raise ValueError("Ulimit.name must be a string")
if soft and not isinstance(soft, int):
raise ValueError("Ulimit.soft must be an integer")
if hard and not isinstance(hard, int):
raise ValueError("Ulimit.hard must be an integer")
super().__init__({
'Name': name,
'Soft': soft,
'Hard': hard
})
@property
def name(self):
return self['Name']
@name.setter
def name(self, value):
self['Name'] = value
@property
def soft(self):
return self.get('Soft')
@soft.setter
def soft(self, value):
self['Soft'] = value
@property
def hard(self):
return self.get('Hard')
@hard.setter
def hard(self, value):
self['Hard'] = value
class DeviceRequest(DictType):
"""
Create a device request to be used with
:py:meth:`~docker.api.container.ContainerApiMixin.create_host_config`.
Args:
driver (str): Which driver to use for this device. Optional.
count (int): Number or devices to request. Optional.
Set to -1 to request all available devices.
device_ids (list): List of strings for device IDs. Optional.
Set either ``count`` or ``device_ids``.
capabilities (list): List of lists of strings to request
capabilities. Optional. The global list acts like an OR,
and the sub-lists are AND. The driver will try to satisfy
one of the sub-lists.
Available capabilities for the ``nvidia`` driver can be found
`here <https://github.com/NVIDIA/nvidia-container-runtime>`_.
options (dict): Driver-specific options. Optional.
"""
def __init__(self, **kwargs):
driver = kwargs.get('driver', kwargs.get('Driver'))
count = kwargs.get('count', kwargs.get('Count'))
device_ids = kwargs.get('device_ids', kwargs.get('DeviceIDs'))
capabilities = kwargs.get('capabilities', kwargs.get('Capabilities'))
options = kwargs.get('options', kwargs.get('Options'))
if driver is None:
driver = ''
elif not isinstance(driver, str):
raise ValueError('DeviceRequest.driver must be a string')
if count is None:
count = 0
elif not isinstance(count, int):
raise ValueError('DeviceRequest.count must be an integer')
if device_ids is None:
device_ids = []
elif not isinstance(device_ids, list):
raise ValueError('DeviceRequest.device_ids must be a list')
if capabilities is None:
capabilities = []
elif not isinstance(capabilities, list):
raise ValueError('DeviceRequest.capabilities must be a list')
if options is None:
options = {}
elif not isinstance(options, dict):
raise ValueError('DeviceRequest.options must be a dict')
super().__init__({
'Driver': driver,
'Count': count,
'DeviceIDs': device_ids,
'Capabilities': capabilities,
'Options': options
})
@property
def driver(self):
return self['Driver']
@driver.setter
def driver(self, value):
self['Driver'] = value
@property
def count(self):
return self['Count']
@count.setter
def count(self, value):
self['Count'] = value
@property
def device_ids(self):
return self['DeviceIDs']
@device_ids.setter
def device_ids(self, value):
self['DeviceIDs'] = value
@property
def capabilities(self):
return self['Capabilities']
@capabilities.setter
def capabilities(self, value):
self['Capabilities'] = value
@property
def options(self):
return self['Options']
@options.setter
def options(self, value):
self['Options'] = value
class HostConfig(dict):
def __init__(self, version, binds=None, port_bindings=None,
lxc_conf=None, publish_all_ports=False, links=None,
privileged=False, dns=None, dns_search=None,
volumes_from=None, network_mode=None, restart_policy=None,
cap_add=None, cap_drop=None, devices=None, extra_hosts=None,
read_only=None, pid_mode=None, ipc_mode=None,
security_opt=None, ulimits=None, log_config=None,
mem_limit=None, memswap_limit=None, mem_reservation=None,
kernel_memory=None, mem_swappiness=None, cgroup_parent=None,
group_add=None, cpu_quota=None, cpu_period=None,
blkio_weight=None, blkio_weight_device=None,
device_read_bps=None, device_write_bps=None,
device_read_iops=None, device_write_iops=None,
oom_kill_disable=False, shm_size=None, sysctls=None,
tmpfs=None, oom_score_adj=None, dns_opt=None, cpu_shares=None,
cpuset_cpus=None, userns_mode=None, uts_mode=None,
pids_limit=None, isolation=None, auto_remove=False,
storage_opt=None, init=None, init_path=None,
volume_driver=None, cpu_count=None, cpu_percent=None,
nano_cpus=None, cpuset_mems=None, runtime=None, mounts=None,
cpu_rt_period=None, cpu_rt_runtime=None,
device_cgroup_rules=None, device_requests=None,
cgroupns=None):
if mem_limit is not None:
self['Memory'] = parse_bytes(mem_limit)
if memswap_limit is not None:
self['MemorySwap'] = parse_bytes(memswap_limit)
if mem_reservation:
self['MemoryReservation'] = parse_bytes(mem_reservation)
if kernel_memory:
self['KernelMemory'] = parse_bytes(kernel_memory)
if mem_swappiness is not None:
if not isinstance(mem_swappiness, int):
raise host_config_type_error(
'mem_swappiness', mem_swappiness, 'int'
)
self['MemorySwappiness'] = mem_swappiness
if shm_size is not None:
if isinstance(shm_size, str):
shm_size = parse_bytes(shm_size)
self['ShmSize'] = shm_size
if pid_mode:
if version_lt(version, '1.24') and pid_mode != 'host':
raise host_config_value_error('pid_mode', pid_mode)
self['PidMode'] = pid_mode
if ipc_mode:
self['IpcMode'] = ipc_mode
if privileged:
self['Privileged'] = privileged
if oom_kill_disable:
self['OomKillDisable'] = oom_kill_disable
if oom_score_adj:
if version_lt(version, '1.22'):
raise host_config_version_error('oom_score_adj', '1.22')
if not isinstance(oom_score_adj, int):
raise host_config_type_error(
'oom_score_adj', oom_score_adj, 'int'
)
self['OomScoreAdj'] = oom_score_adj
if publish_all_ports:
self['PublishAllPorts'] = publish_all_ports
if read_only is not None:
self['ReadonlyRootfs'] = read_only
if dns_search:
self['DnsSearch'] = dns_search
if network_mode == 'host' and port_bindings:
raise host_config_incompatible_error(
'network_mode', 'host', 'port_bindings'
)
self['NetworkMode'] = network_mode or 'default'
if restart_policy:
if not isinstance(restart_policy, dict):
raise host_config_type_error(
'restart_policy', restart_policy, 'dict'
)
self['RestartPolicy'] = restart_policy
if cap_add:
self['CapAdd'] = cap_add
if cap_drop:
self['CapDrop'] = cap_drop
if devices:
self['Devices'] = parse_devices(devices)
if group_add:
self['GroupAdd'] = [str(grp) for grp in group_add]
if dns is not None:
self['Dns'] = dns
if dns_opt is not None:
self['DnsOptions'] = dns_opt
if security_opt is not None:
if not isinstance(security_opt, list):
raise host_config_type_error(
'security_opt', security_opt, 'list'
)
self['SecurityOpt'] = security_opt
if sysctls:
if not isinstance(sysctls, dict):
raise host_config_type_error('sysctls', sysctls, 'dict')
self['Sysctls'] = {}
for k, v in sysctls.items():
self['Sysctls'][k] = str(v)
if volumes_from is not None:
if isinstance(volumes_from, str):
volumes_from = volumes_from.split(',')
self['VolumesFrom'] = volumes_from
if binds is not None:
self['Binds'] = convert_volume_binds(binds)
if port_bindings is not None:
self['PortBindings'] = convert_port_bindings(port_bindings)
if extra_hosts is not None:
if isinstance(extra_hosts, dict):
extra_hosts = format_extra_hosts(extra_hosts)
self['ExtraHosts'] = extra_hosts
if links is not None:
self['Links'] = normalize_links(links)
if isinstance(lxc_conf, dict):
formatted = []
for k, v in lxc_conf.items():
formatted.append({'Key': k, 'Value': str(v)})
lxc_conf = formatted
if lxc_conf is not None:
self['LxcConf'] = lxc_conf
if cgroup_parent is not None:
self['CgroupParent'] = cgroup_parent
if ulimits is not None:
if not isinstance(ulimits, list):
raise host_config_type_error('ulimits', ulimits, 'list')
self['Ulimits'] = []
for lmt in ulimits:
if not isinstance(lmt, Ulimit):
lmt = Ulimit(**lmt)
self['Ulimits'].append(lmt)
if log_config is not None:
if not isinstance(log_config, LogConfig):
if not isinstance(log_config, dict):
raise host_config_type_error(
'log_config', log_config, 'LogConfig'
)
log_config = LogConfig(**log_config)
self['LogConfig'] = log_config
if cpu_quota:
if not isinstance(cpu_quota, int):
raise host_config_type_error('cpu_quota', cpu_quota, 'int')
self['CpuQuota'] = cpu_quota
if cpu_period:
if not isinstance(cpu_period, int):
raise host_config_type_error('cpu_period', cpu_period, 'int')
self['CpuPeriod'] = cpu_period
if cpu_shares:
if not isinstance(cpu_shares, int):
raise host_config_type_error('cpu_shares', cpu_shares, 'int')
self['CpuShares'] = cpu_shares
if cpuset_cpus:
self['CpusetCpus'] = cpuset_cpus
if cpuset_mems:
if not isinstance(cpuset_mems, str):
raise host_config_type_error(
'cpuset_mems', cpuset_mems, 'str'
)
self['CpusetMems'] = cpuset_mems
if cpu_rt_period:
if version_lt(version, '1.25'):
raise host_config_version_error('cpu_rt_period', '1.25')
if not isinstance(cpu_rt_period, int):
raise host_config_type_error(
'cpu_rt_period', cpu_rt_period, 'int'
)
self['CPURealtimePeriod'] = cpu_rt_period
if cpu_rt_runtime:
if version_lt(version, '1.25'):
raise host_config_version_error('cpu_rt_runtime', '1.25')
if not isinstance(cpu_rt_runtime, int):
raise host_config_type_error(
'cpu_rt_runtime', cpu_rt_runtime, 'int'
)
self['CPURealtimeRuntime'] = cpu_rt_runtime
if blkio_weight:
if not isinstance(blkio_weight, int):
raise host_config_type_error(
'blkio_weight', blkio_weight, 'int'
)
if version_lt(version, '1.22'):
raise host_config_version_error('blkio_weight', '1.22')
self["BlkioWeight"] = blkio_weight
if blkio_weight_device:
if not isinstance(blkio_weight_device, list):
raise host_config_type_error(
'blkio_weight_device', blkio_weight_device, 'list'
)
if version_lt(version, '1.22'):
raise host_config_version_error('blkio_weight_device', '1.22')
self["BlkioWeightDevice"] = blkio_weight_device
if device_read_bps:
if not isinstance(device_read_bps, list):
raise host_config_type_error(
'device_read_bps', device_read_bps, 'list'
)
if version_lt(version, '1.22'):
raise host_config_version_error('device_read_bps', '1.22')
self["BlkioDeviceReadBps"] = device_read_bps
if device_write_bps:
if not isinstance(device_write_bps, list):
raise host_config_type_error(
'device_write_bps', device_write_bps, 'list'
)
if version_lt(version, '1.22'):
raise host_config_version_error('device_write_bps', '1.22')
self["BlkioDeviceWriteBps"] = device_write_bps
if device_read_iops:
if not isinstance(device_read_iops, list):
raise host_config_type_error(
'device_read_iops', device_read_iops, 'list'
)
if version_lt(version, '1.22'):
raise host_config_version_error('device_read_iops', '1.22')
self["BlkioDeviceReadIOps"] = device_read_iops
if device_write_iops:
if not isinstance(device_write_iops, list):
raise host_config_type_error(
'device_write_iops', device_write_iops, 'list'
)
if version_lt(version, '1.22'):
raise host_config_version_error('device_write_iops', '1.22')
self["BlkioDeviceWriteIOps"] = device_write_iops
if tmpfs:
if version_lt(version, '1.22'):
raise host_config_version_error('tmpfs', '1.22')
self["Tmpfs"] = convert_tmpfs_mounts(tmpfs)
if userns_mode:
if version_lt(version, '1.23'):
raise host_config_version_error('userns_mode', '1.23')
if userns_mode != "host":
raise host_config_value_error("userns_mode", userns_mode)
self['UsernsMode'] = userns_mode
if uts_mode:
if uts_mode != "host":
raise host_config_value_error("uts_mode", uts_mode)
self['UTSMode'] = uts_mode
if pids_limit:
if not isinstance(pids_limit, int):
raise host_config_type_error('pids_limit', pids_limit, 'int')
if version_lt(version, '1.23'):
raise host_config_version_error('pids_limit', '1.23')
self["PidsLimit"] = pids_limit
if isolation:
if not isinstance(isolation, str):
raise host_config_type_error('isolation', isolation, 'string')
if version_lt(version, '1.24'):
raise host_config_version_error('isolation', '1.24')
self['Isolation'] = isolation
if auto_remove:
if version_lt(version, '1.25'):
raise host_config_version_error('auto_remove', '1.25')
self['AutoRemove'] = auto_remove
if storage_opt is not None:
if version_lt(version, '1.24'):
raise host_config_version_error('storage_opt', '1.24')
self['StorageOpt'] = storage_opt
if init is not None:
if version_lt(version, '1.25'):
raise host_config_version_error('init', '1.25')
self['Init'] = init
if init_path is not None:
if version_lt(version, '1.25'):
raise host_config_version_error('init_path', '1.25')
if version_gte(version, '1.29'):
# https://github.com/moby/moby/pull/32470
raise host_config_version_error('init_path', '1.29', False)
self['InitPath'] = init_path
if volume_driver is not None:
self['VolumeDriver'] = volume_driver
if cpu_count:
if not isinstance(cpu_count, int):
raise host_config_type_error('cpu_count', cpu_count, 'int')
if version_lt(version, '1.25'):
raise host_config_version_error('cpu_count', '1.25')
self['CpuCount'] = cpu_count
if cpu_percent:
if not isinstance(cpu_percent, int):
raise host_config_type_error('cpu_percent', cpu_percent, 'int')
if version_lt(version, '1.25'):
raise host_config_version_error('cpu_percent', '1.25')
self['CpuPercent'] = cpu_percent
if nano_cpus:
if not isinstance(nano_cpus, int):
raise host_config_type_error('nano_cpus', nano_cpus, 'int')
if version_lt(version, '1.25'):
raise host_config_version_error('nano_cpus', '1.25')
self['NanoCpus'] = nano_cpus
if runtime:
if version_lt(version, '1.25'):
raise host_config_version_error('runtime', '1.25')
self['Runtime'] = runtime
if mounts is not None:
if version_lt(version, '1.30'):
raise host_config_version_error('mounts', '1.30')
self['Mounts'] = mounts
if device_cgroup_rules is not None:
if version_lt(version, '1.28'):
raise host_config_version_error('device_cgroup_rules', '1.28')
if not isinstance(device_cgroup_rules, list):
raise host_config_type_error(
'device_cgroup_rules', device_cgroup_rules, 'list'
)
self['DeviceCgroupRules'] = device_cgroup_rules
if device_requests is not None:
if version_lt(version, '1.40'):
raise host_config_version_error('device_requests', '1.40')
if not isinstance(device_requests, list):
raise host_config_type_error(
'device_requests', device_requests, 'list'
)
self['DeviceRequests'] = []
for req in device_requests:
if not isinstance(req, DeviceRequest):
req = DeviceRequest(**req)
self['DeviceRequests'].append(req)
if cgroupns:
self['CgroupnsMode'] = cgroupns
def host_config_type_error(param, param_value, expected):
return TypeError(
f'Invalid type for {param} param: expected {expected} '
f'but found {type(param_value)}'
)
def host_config_version_error(param, version, less_than=True):
operator = '<' if less_than else '>'
return errors.InvalidVersion(
f'{param} param is not supported in API versions {operator} {version}',
)
def host_config_value_error(param, param_value):
return ValueError(f'Invalid value for {param} param: {param_value}')
def host_config_incompatible_error(param, param_value, incompatible_param):
return errors.InvalidArgument(
f'\"{param_value}\" {param} is incompatible with {incompatible_param}'
)
class ContainerConfig(dict):
def __init__(
self, version, image, command, hostname=None, user=None, detach=False,
stdin_open=False, tty=False, ports=None, environment=None,
volumes=None, network_disabled=False, entrypoint=None,
working_dir=None, domainname=None, host_config=None, mac_address=None,
labels=None, stop_signal=None, networking_config=None,
healthcheck=None, stop_timeout=None, runtime=None
):
if stop_timeout is not None and version_lt(version, '1.25'):
raise errors.InvalidVersion(
'stop_timeout was only introduced in API version 1.25'
)
if healthcheck is not None:
if version_lt(version, '1.24'):
raise errors.InvalidVersion(
'Health options were only introduced in API version 1.24'
)
if version_lt(version, '1.29') and 'StartPeriod' in healthcheck:
raise errors.InvalidVersion(
'healthcheck start period was introduced in API '
'version 1.29'
)
if isinstance(command, str):
command = split_command(command)
if isinstance(entrypoint, str):
entrypoint = split_command(entrypoint)
if isinstance(environment, dict):
environment = format_environment(environment)
if isinstance(labels, list):
labels = {lbl: '' for lbl in labels}
if isinstance(ports, list):
exposed_ports = {}
for port_definition in ports:
port = port_definition
proto = 'tcp'
if isinstance(port_definition, tuple):
if len(port_definition) == 2:
proto = port_definition[1]
port = port_definition[0]
exposed_ports[f'{port}/{proto}'] = {}
ports = exposed_ports
if isinstance(volumes, str):
volumes = [volumes, ]
if isinstance(volumes, list):
volumes_dict = {}
for vol in volumes:
volumes_dict[vol] = {}
volumes = volumes_dict
if healthcheck and isinstance(healthcheck, dict):
healthcheck = Healthcheck(**healthcheck)
attach_stdin = False
attach_stdout = False
attach_stderr = False
stdin_once = False
if not detach:
attach_stdout = True
attach_stderr = True
if stdin_open:
attach_stdin = True
stdin_once = True
self.update({
'Hostname': hostname,
'Domainname': domainname,
'ExposedPorts': ports,
'User': str(user) if user is not None else None,
'Tty': tty,
'OpenStdin': stdin_open,
'StdinOnce': stdin_once,
'AttachStdin': attach_stdin,
'AttachStdout': attach_stdout,
'AttachStderr': attach_stderr,
'Env': environment,
'Cmd': command,
'Image': image,
'Volumes': volumes,
'NetworkDisabled': network_disabled,
'Entrypoint': entrypoint,
'WorkingDir': working_dir,
'HostConfig': host_config,
'NetworkingConfig': networking_config,
'MacAddress': mac_address,
'Labels': labels,
'StopSignal': stop_signal,
'Healthcheck': healthcheck,
'StopTimeout': stop_timeout,
'Runtime': runtime
})

71
docker/types/daemon.py Normal file
View File

@ -0,0 +1,71 @@
import socket
import urllib3
from ..errors import DockerException
class CancellableStream:
"""
Stream wrapper for real-time events, logs, etc. from the server.
Example:
>>> events = client.events()
>>> for event in events:
... print(event)
>>> # and cancel from another thread
>>> events.close()
"""
def __init__(self, stream, response):
self._stream = stream
self._response = response
def __iter__(self):
return self
def __next__(self):
try:
return next(self._stream)
except urllib3.exceptions.ProtocolError:
raise StopIteration from None
except OSError:
raise StopIteration from None
next = __next__
def close(self):
"""
Closes the event streaming.
"""
if not self._response.raw.closed:
# find the underlying socket object
# based on api.client._get_raw_response_socket
sock_fp = self._response.raw._fp.fp
if hasattr(sock_fp, 'raw'):
sock_raw = sock_fp.raw
if hasattr(sock_raw, 'sock'):
sock = sock_raw.sock
elif hasattr(sock_raw, '_sock'):
sock = sock_raw._sock
elif hasattr(sock_fp, 'channel'):
# We're working with a paramiko (SSH) channel, which doesn't
# support cancelable streams with the current implementation
raise DockerException(
'Cancellable streams not supported for the SSH protocol'
)
else:
sock = sock_fp._sock
if hasattr(urllib3.contrib, 'pyopenssl') and isinstance(
sock, urllib3.contrib.pyopenssl.WrappedSocket):
sock = sock.socket
sock.shutdown(socket.SHUT_RDWR)
sock.close()

View File

@ -0,0 +1,88 @@
from .base import DictType
class Healthcheck(DictType):
"""
Defines a healthcheck configuration for a container or service.
Args:
test (:py:class:`list` or str): Test to perform to determine
container health. Possible values:
- Empty list: Inherit healthcheck from parent image
- ``["NONE"]``: Disable healthcheck
- ``["CMD", args...]``: exec arguments directly.
- ``["CMD-SHELL", command]``: Run command in the system's
default shell.
If a string is provided, it will be used as a ``CMD-SHELL``
command.
interval (int): The time to wait between checks in nanoseconds. It
should be 0 or at least 1000000 (1 ms).
timeout (int): The time to wait before considering the check to
have hung. It should be 0 or at least 1000000 (1 ms).
retries (int): The number of consecutive failures needed to
consider a container as unhealthy.
start_period (int): Start period for the container to
initialize before starting health-retries countdown in
nanoseconds. It should be 0 or at least 1000000 (1 ms).
"""
def __init__(self, **kwargs):
test = kwargs.get('test', kwargs.get('Test'))
if isinstance(test, str):
test = ["CMD-SHELL", test]
interval = kwargs.get('interval', kwargs.get('Interval'))
timeout = kwargs.get('timeout', kwargs.get('Timeout'))
retries = kwargs.get('retries', kwargs.get('Retries'))
start_period = kwargs.get('start_period', kwargs.get('StartPeriod'))
super().__init__({
'Test': test,
'Interval': interval,
'Timeout': timeout,
'Retries': retries,
'StartPeriod': start_period
})
@property
def test(self):
return self['Test']
@test.setter
def test(self, value):
if isinstance(value, str):
value = ["CMD-SHELL", value]
self['Test'] = value
@property
def interval(self):
return self['Interval']
@interval.setter
def interval(self, value):
self['Interval'] = value
@property
def timeout(self):
return self['Timeout']
@timeout.setter
def timeout(self, value):
self['Timeout'] = value
@property
def retries(self):
return self['Retries']
@retries.setter
def retries(self, value):
self['Retries'] = value
@property
def start_period(self):
return self['StartPeriod']
@start_period.setter
def start_period(self, value):
self['StartPeriod'] = value

128
docker/types/networks.py Normal file
View File

@ -0,0 +1,128 @@
from .. import errors
from ..utils import normalize_links, version_lt
class EndpointConfig(dict):
def __init__(self, version, aliases=None, links=None, ipv4_address=None,
ipv6_address=None, link_local_ips=None, driver_opt=None,
mac_address=None):
if version_lt(version, '1.22'):
raise errors.InvalidVersion(
'Endpoint config is not supported for API version < 1.22'
)
if aliases:
self["Aliases"] = aliases
if links:
self["Links"] = normalize_links(links)
ipam_config = {}
if ipv4_address:
ipam_config['IPv4Address'] = ipv4_address
if ipv6_address:
ipam_config['IPv6Address'] = ipv6_address
if mac_address:
if version_lt(version, '1.25'):
raise errors.InvalidVersion(
'mac_address is not supported for API version < 1.25'
)
self['MacAddress'] = mac_address
if link_local_ips is not None:
if version_lt(version, '1.24'):
raise errors.InvalidVersion(
'link_local_ips is not supported for API version < 1.24'
)
ipam_config['LinkLocalIPs'] = link_local_ips
if ipam_config:
self['IPAMConfig'] = ipam_config
if driver_opt:
if version_lt(version, '1.32'):
raise errors.InvalidVersion(
'DriverOpts is not supported for API version < 1.32'
)
if not isinstance(driver_opt, dict):
raise TypeError('driver_opt must be a dictionary')
self['DriverOpts'] = driver_opt
class NetworkingConfig(dict):
def __init__(self, endpoints_config=None):
if endpoints_config:
self["EndpointsConfig"] = endpoints_config
class IPAMConfig(dict):
"""
Create an IPAM (IP Address Management) config dictionary to be used with
:py:meth:`~docker.api.network.NetworkApiMixin.create_network`.
Args:
driver (str): The IPAM driver to use. Defaults to ``default``.
pool_configs (:py:class:`list`): A list of pool configurations
(:py:class:`~docker.types.IPAMPool`). Defaults to empty list.
options (dict): Driver options as a key-value dictionary.
Defaults to `None`.
Example:
>>> ipam_config = docker.types.IPAMConfig(driver='default')
>>> network = client.create_network('network1', ipam=ipam_config)
"""
def __init__(self, driver='default', pool_configs=None, options=None):
self.update({
'Driver': driver,
'Config': pool_configs or []
})
if options:
if not isinstance(options, dict):
raise TypeError('IPAMConfig options must be a dictionary')
self['Options'] = options
class IPAMPool(dict):
"""
Create an IPAM pool config dictionary to be added to the
``pool_configs`` parameter of
:py:class:`~docker.types.IPAMConfig`.
Args:
subnet (str): Custom subnet for this IPAM pool using the CIDR
notation. Defaults to ``None``.
iprange (str): Custom IP range for endpoints in this IPAM pool using
the CIDR notation. Defaults to ``None``.
gateway (str): Custom IP address for the pool's gateway.
aux_addresses (dict): A dictionary of ``key -> ip_address``
relationships specifying auxiliary addresses that need to be
allocated by the IPAM driver.
Example:
>>> ipam_pool = docker.types.IPAMPool(
subnet='124.42.0.0/16',
iprange='124.42.0.0/24',
gateway='124.42.0.254',
aux_addresses={
'reserved1': '124.42.1.1'
}
)
>>> ipam_config = docker.types.IPAMConfig(
pool_configs=[ipam_pool])
"""
def __init__(self, subnet=None, iprange=None, gateway=None,
aux_addresses=None):
self.update({
'Subnet': subnet,
'IPRange': iprange,
'Gateway': gateway,
'AuxiliaryAddresses': aux_addresses
})

870
docker/types/services.py Normal file
View File

@ -0,0 +1,870 @@
from .. import errors
from ..constants import IS_WINDOWS_PLATFORM
from ..utils import (
check_resource,
convert_service_networks,
format_environment,
format_extra_hosts,
parse_bytes,
split_command,
)
class TaskTemplate(dict):
"""
Describe the task specification to be used when creating or updating a
service.
Args:
container_spec (ContainerSpec): Container settings for containers
started as part of this task.
log_driver (DriverConfig): Log configuration for containers created as
part of the service.
resources (Resources): Resource requirements which apply to each
individual container created as part of the service.
restart_policy (RestartPolicy): Specification for the restart policy
which applies to containers created as part of this service.
placement (Placement): Placement instructions for the scheduler.
If a list is passed instead, it is assumed to be a list of
constraints as part of a :py:class:`Placement` object.
networks (:py:class:`list`): List of network names or IDs or
:py:class:`NetworkAttachmentConfig` to attach the service to.
force_update (int): A counter that triggers an update even if no
relevant parameters have been changed.
"""
def __init__(self, container_spec, resources=None, restart_policy=None,
placement=None, log_driver=None, networks=None,
force_update=None):
self['ContainerSpec'] = container_spec
if resources:
self['Resources'] = resources
if restart_policy:
self['RestartPolicy'] = restart_policy
if placement:
if isinstance(placement, list):
placement = Placement(constraints=placement)
self['Placement'] = placement
if log_driver:
self['LogDriver'] = log_driver
if networks:
self['Networks'] = convert_service_networks(networks)
if force_update is not None:
if not isinstance(force_update, int):
raise TypeError('force_update must be an integer')
self['ForceUpdate'] = force_update
@property
def container_spec(self):
return self.get('ContainerSpec')
@property
def resources(self):
return self.get('Resources')
@property
def restart_policy(self):
return self.get('RestartPolicy')
@property
def placement(self):
return self.get('Placement')
class ContainerSpec(dict):
"""
Describes the behavior of containers that are part of a task, and is used
when declaring a :py:class:`~docker.types.TaskTemplate`.
Args:
image (string): The image name to use for the container.
command (string or list): The command to be run in the image.
args (:py:class:`list`): Arguments to the command.
hostname (string): The hostname to set on the container.
env (dict): Environment variables.
workdir (string): The working directory for commands to run in.
user (string): The user inside the container.
labels (dict): A map of labels to associate with the service.
mounts (:py:class:`list`): A list of specifications for mounts to be
added to containers created as part of the service. See the
:py:class:`~docker.types.Mount` class for details.
stop_grace_period (int): Amount of time to wait for the container to
terminate before forcefully killing it.
secrets (:py:class:`list`): List of :py:class:`SecretReference` to be
made available inside the containers.
tty (boolean): Whether a pseudo-TTY should be allocated.
groups (:py:class:`list`): A list of additional groups that the
container process will run as.
open_stdin (boolean): Open ``stdin``
read_only (boolean): Mount the container's root filesystem as read
only.
stop_signal (string): Set signal to stop the service's containers
healthcheck (Healthcheck): Healthcheck
configuration for this service.
hosts (:py:class:`dict`): A set of host to IP mappings to add to
the container's ``hosts`` file.
dns_config (DNSConfig): Specification for DNS
related configurations in resolver configuration file.
configs (:py:class:`list`): List of :py:class:`ConfigReference` that
will be exposed to the service.
privileges (Privileges): Security options for the service's containers.
isolation (string): Isolation technology used by the service's
containers. Only used for Windows containers.
init (boolean): Run an init inside the container that forwards signals
and reaps processes.
cap_add (:py:class:`list`): A list of kernel capabilities to add to the
default set for the container.
cap_drop (:py:class:`list`): A list of kernel capabilities to drop from
the default set for the container.
sysctls (:py:class:`dict`): A dict of sysctl values to add to
the container
"""
def __init__(self, image, command=None, args=None, hostname=None, env=None,
workdir=None, user=None, labels=None, mounts=None,
stop_grace_period=None, secrets=None, tty=None, groups=None,
open_stdin=None, read_only=None, stop_signal=None,
healthcheck=None, hosts=None, dns_config=None, configs=None,
privileges=None, isolation=None, init=None, cap_add=None,
cap_drop=None, sysctls=None):
self['Image'] = image
if isinstance(command, str):
command = split_command(command)
self['Command'] = command
self['Args'] = args
if hostname is not None:
self['Hostname'] = hostname
if env is not None:
if isinstance(env, dict):
self['Env'] = format_environment(env)
else:
self['Env'] = env
if workdir is not None:
self['Dir'] = workdir
if user is not None:
self['User'] = user
if groups is not None:
self['Groups'] = groups
if stop_signal is not None:
self['StopSignal'] = stop_signal
if stop_grace_period is not None:
self['StopGracePeriod'] = stop_grace_period
if labels is not None:
self['Labels'] = labels
if hosts is not None:
self['Hosts'] = format_extra_hosts(hosts, task=True)
if mounts is not None:
parsed_mounts = []
for mount in mounts:
if isinstance(mount, str):
parsed_mounts.append(Mount.parse_mount_string(mount))
else:
# If mount already parsed
parsed_mounts.append(mount)
self['Mounts'] = parsed_mounts
if secrets is not None:
if not isinstance(secrets, list):
raise TypeError('secrets must be a list')
self['Secrets'] = secrets
if configs is not None:
if not isinstance(configs, list):
raise TypeError('configs must be a list')
self['Configs'] = configs
if dns_config is not None:
self['DNSConfig'] = dns_config
if privileges is not None:
self['Privileges'] = privileges
if healthcheck is not None:
self['Healthcheck'] = healthcheck
if tty is not None:
self['TTY'] = tty
if open_stdin is not None:
self['OpenStdin'] = open_stdin
if read_only is not None:
self['ReadOnly'] = read_only
if isolation is not None:
self['Isolation'] = isolation
if init is not None:
self['Init'] = init
if cap_add is not None:
if not isinstance(cap_add, list):
raise TypeError('cap_add must be a list')
self['CapabilityAdd'] = cap_add
if cap_drop is not None:
if not isinstance(cap_drop, list):
raise TypeError('cap_drop must be a list')
self['CapabilityDrop'] = cap_drop
if sysctls is not None:
if not isinstance(sysctls, dict):
raise TypeError('sysctls must be a dict')
self['Sysctls'] = sysctls
class Mount(dict):
"""
Describes a mounted folder's configuration inside a container. A list of
:py:class:`Mount` would be used as part of a
:py:class:`~docker.types.ContainerSpec`.
Args:
target (string): Container path.
source (string): Mount source (e.g. a volume name or a host path).
type (string): The mount type (``bind`` / ``volume`` / ``tmpfs`` /
``npipe``). Default: ``volume``.
read_only (bool): Whether the mount should be read-only.
consistency (string): The consistency requirement for the mount. One of
``default```, ``consistent``, ``cached``, ``delegated``.
propagation (string): A propagation mode with the value ``[r]private``,
``[r]shared``, or ``[r]slave``. Only valid for the ``bind`` type.
no_copy (bool): False if the volume should be populated with the data
from the target. Default: ``False``. Only valid for the ``volume``
type.
labels (dict): User-defined name and labels for the volume. Only valid
for the ``volume`` type.
driver_config (DriverConfig): Volume driver configuration. Only valid
for the ``volume`` type.
subpath (str): Path inside a volume to mount instead of the volume root.
tmpfs_size (int or string): The size for the tmpfs mount in bytes.
tmpfs_mode (int): The permission mode for the tmpfs mount.
"""
def __init__(self, target, source, type='volume', read_only=False,
consistency=None, propagation=None, no_copy=False,
labels=None, driver_config=None, tmpfs_size=None,
tmpfs_mode=None, subpath=None):
self['Target'] = target
self['Source'] = source
if type not in ('bind', 'volume', 'tmpfs', 'npipe'):
raise errors.InvalidArgument(
f'Unsupported mount type: "{type}"'
)
self['Type'] = type
self['ReadOnly'] = read_only
if consistency:
self['Consistency'] = consistency
if type == 'bind':
if propagation is not None:
self['BindOptions'] = {
'Propagation': propagation
}
if any([labels, driver_config, no_copy, tmpfs_size, tmpfs_mode, subpath]):
raise errors.InvalidArgument(
'Incompatible options have been provided for the bind '
'type mount.'
)
elif type == 'volume':
volume_opts = {}
if no_copy:
volume_opts['NoCopy'] = True
if labels:
volume_opts['Labels'] = labels
if driver_config:
volume_opts['DriverConfig'] = driver_config
if subpath:
volume_opts['Subpath'] = subpath
if volume_opts:
self['VolumeOptions'] = volume_opts
if any([propagation, tmpfs_size, tmpfs_mode]):
raise errors.InvalidArgument(
'Incompatible options have been provided for the volume '
'type mount.'
)
elif type == 'tmpfs':
tmpfs_opts = {}
if tmpfs_mode:
if not isinstance(tmpfs_mode, int):
raise errors.InvalidArgument(
'tmpfs_mode must be an integer'
)
tmpfs_opts['Mode'] = tmpfs_mode
if tmpfs_size:
tmpfs_opts['SizeBytes'] = parse_bytes(tmpfs_size)
if tmpfs_opts:
self['TmpfsOptions'] = tmpfs_opts
if any([propagation, labels, driver_config, no_copy]):
raise errors.InvalidArgument(
'Incompatible options have been provided for the tmpfs '
'type mount.'
)
@classmethod
def parse_mount_string(cls, string):
parts = string.split(':')
if len(parts) > 3:
raise errors.InvalidArgument(
f'Invalid mount format "{string}"'
)
if len(parts) == 1:
return cls(target=parts[0], source=None)
else:
target = parts[1]
source = parts[0]
mount_type = 'volume'
if source.startswith('/') or (
IS_WINDOWS_PLATFORM and source[0].isalpha() and
source[1] == ':'
):
# FIXME: That windows condition will fail earlier since we
# split on ':'. We should look into doing a smarter split
# if we detect we are on Windows.
mount_type = 'bind'
read_only = not (len(parts) == 2 or parts[2] == 'rw')
return cls(target, source, read_only=read_only, type=mount_type)
class Resources(dict):
"""
Configures resource allocation for containers when made part of a
:py:class:`~docker.types.ContainerSpec`.
Args:
cpu_limit (int): CPU limit in units of 10^9 CPU shares.
mem_limit (int): Memory limit in Bytes.
cpu_reservation (int): CPU reservation in units of 10^9 CPU shares.
mem_reservation (int): Memory reservation in Bytes.
generic_resources (dict or :py:class:`list`): Node level generic
resources, for example a GPU, using the following format:
``{ resource_name: resource_value }``. Alternatively, a list of
of resource specifications as defined by the Engine API.
"""
def __init__(self, cpu_limit=None, mem_limit=None, cpu_reservation=None,
mem_reservation=None, generic_resources=None):
limits = {}
reservation = {}
if cpu_limit is not None:
limits['NanoCPUs'] = cpu_limit
if mem_limit is not None:
limits['MemoryBytes'] = mem_limit
if cpu_reservation is not None:
reservation['NanoCPUs'] = cpu_reservation
if mem_reservation is not None:
reservation['MemoryBytes'] = mem_reservation
if generic_resources is not None:
reservation['GenericResources'] = (
_convert_generic_resources_dict(generic_resources)
)
if limits:
self['Limits'] = limits
if reservation:
self['Reservations'] = reservation
def _convert_generic_resources_dict(generic_resources):
if isinstance(generic_resources, list):
return generic_resources
if not isinstance(generic_resources, dict):
raise errors.InvalidArgument(
'generic_resources must be a dict or a list '
f'(found {type(generic_resources)})'
)
resources = []
for kind, value in generic_resources.items():
resource_type = None
if isinstance(value, int):
resource_type = 'DiscreteResourceSpec'
elif isinstance(value, str):
resource_type = 'NamedResourceSpec'
else:
kv = {kind: value}
raise errors.InvalidArgument(
f'Unsupported generic resource reservation type: {kv}'
)
resources.append({
resource_type: {'Kind': kind, 'Value': value}
})
return resources
class UpdateConfig(dict):
"""
Used to specify the way container updates should be performed by a service.
Args:
parallelism (int): Maximum number of tasks to be updated in one
iteration (0 means unlimited parallelism). Default: 0.
delay (int): Amount of time between updates, in nanoseconds.
failure_action (string): Action to take if an updated task fails to
run, or stops running during the update. Acceptable values are
``continue``, ``pause``, as well as ``rollback`` since API v1.28.
Default: ``continue``
monitor (int): Amount of time to monitor each updated task for
failures, in nanoseconds.
max_failure_ratio (float): The fraction of tasks that may fail during
an update before the failure action is invoked, specified as a
floating point number between 0 and 1. Default: 0
order (string): Specifies the order of operations when rolling out an
updated task. Either ``start-first`` or ``stop-first`` are accepted.
"""
def __init__(self, parallelism=0, delay=None, failure_action='continue',
monitor=None, max_failure_ratio=None, order=None):
self['Parallelism'] = parallelism
if delay is not None:
self['Delay'] = delay
if failure_action not in ('pause', 'continue', 'rollback'):
raise errors.InvalidArgument(
'failure_action must be one of `pause`, `continue`, `rollback`'
)
self['FailureAction'] = failure_action
if monitor is not None:
if not isinstance(monitor, int):
raise TypeError('monitor must be an integer')
self['Monitor'] = monitor
if max_failure_ratio is not None:
if not isinstance(max_failure_ratio, (float, int)):
raise TypeError('max_failure_ratio must be a float')
if max_failure_ratio > 1 or max_failure_ratio < 0:
raise errors.InvalidArgument(
'max_failure_ratio must be a number between 0 and 1'
)
self['MaxFailureRatio'] = max_failure_ratio
if order is not None:
if order not in ('start-first', 'stop-first'):
raise errors.InvalidArgument(
'order must be either `start-first` or `stop-first`'
)
self['Order'] = order
class RollbackConfig(UpdateConfig):
"""
Used to specify the way container rollbacks should be performed by a
service
Args:
parallelism (int): Maximum number of tasks to be rolled back in one
iteration (0 means unlimited parallelism). Default: 0
delay (int): Amount of time between rollbacks, in nanoseconds.
failure_action (string): Action to take if a rolled back task fails to
run, or stops running during the rollback. Acceptable values are
``continue``, ``pause`` or ``rollback``.
Default: ``continue``
monitor (int): Amount of time to monitor each rolled back task for
failures, in nanoseconds.
max_failure_ratio (float): The fraction of tasks that may fail during
a rollback before the failure action is invoked, specified as a
floating point number between 0 and 1. Default: 0
order (string): Specifies the order of operations when rolling out a
rolled back task. Either ``start-first`` or ``stop-first`` are
accepted.
"""
pass
class RestartConditionTypesEnum:
_values = (
'none',
'on-failure',
'any',
)
NONE, ON_FAILURE, ANY = _values
class RestartPolicy(dict):
"""
Used when creating a :py:class:`~docker.types.ContainerSpec`,
dictates whether a container should restart after stopping or failing.
Args:
condition (string): Condition for restart (``none``, ``on-failure``,
or ``any``). Default: `none`.
delay (int): Delay between restart attempts. Default: 0
max_attempts (int): Maximum attempts to restart a given container
before giving up. Default value is 0, which is ignored.
window (int): Time window used to evaluate the restart policy. Default
value is 0, which is unbounded.
"""
condition_types = RestartConditionTypesEnum
def __init__(self, condition=RestartConditionTypesEnum.NONE, delay=0,
max_attempts=0, window=0):
if condition not in self.condition_types._values:
raise TypeError(
f'Invalid RestartPolicy condition {condition}'
)
self['Condition'] = condition
self['Delay'] = delay
self['MaxAttempts'] = max_attempts
self['Window'] = window
class DriverConfig(dict):
"""
Indicates which driver to use, as well as its configuration. Can be used
as ``log_driver`` in a :py:class:`~docker.types.ContainerSpec`,
for the `driver_config` in a volume :py:class:`~docker.types.Mount`, or
as the driver object in
:py:meth:`create_secret`.
Args:
name (string): Name of the driver to use.
options (dict): Driver-specific options. Default: ``None``.
"""
def __init__(self, name, options=None):
self['Name'] = name
if options:
self['Options'] = options
class EndpointSpec(dict):
"""
Describes properties to access and load-balance a service.
Args:
mode (string): The mode of resolution to use for internal load
balancing between tasks (``'vip'`` or ``'dnsrr'``). Defaults to
``'vip'`` if not provided.
ports (dict): Exposed ports that this service is accessible on from the
outside, in the form of ``{ published_port: target_port }`` or
``{ published_port: <port_config_tuple> }``. Port config tuple format
is ``(target_port [, protocol [, publish_mode]])``.
Ports can only be provided if the ``vip`` resolution mode is used.
"""
def __init__(self, mode=None, ports=None):
if ports:
self['Ports'] = convert_service_ports(ports)
if mode:
self['Mode'] = mode
def convert_service_ports(ports):
if isinstance(ports, list):
return ports
if not isinstance(ports, dict):
raise TypeError(
'Invalid type for ports, expected dict or list'
)
result = []
for k, v in ports.items():
port_spec = {
'Protocol': 'tcp',
'PublishedPort': k
}
if isinstance(v, tuple):
port_spec['TargetPort'] = v[0]
if len(v) >= 2 and v[1] is not None:
port_spec['Protocol'] = v[1]
if len(v) == 3:
port_spec['PublishMode'] = v[2]
if len(v) > 3:
raise ValueError(
'Service port configuration can have at most 3 elements: '
'(target_port, protocol, mode)'
)
else:
port_spec['TargetPort'] = v
result.append(port_spec)
return result
class ServiceMode(dict):
"""
Indicate whether a service or a job should be deployed as a replicated
or global service, and associated parameters
Args:
mode (string): Can be either ``replicated``, ``global``,
``replicated-job`` or ``global-job``
replicas (int): Number of replicas. For replicated services only.
concurrency (int): Number of concurrent jobs. For replicated job
services only.
"""
def __init__(self, mode, replicas=None, concurrency=None):
replicated_modes = ('replicated', 'replicated-job')
supported_modes = replicated_modes + ('global', 'global-job')
if mode not in supported_modes:
raise errors.InvalidArgument(
'mode must be either "replicated", "global", "replicated-job"'
' or "global-job"'
)
if mode not in replicated_modes:
if replicas is not None:
raise errors.InvalidArgument(
'replicas can only be used for "replicated" or'
' "replicated-job" mode'
)
if concurrency is not None:
raise errors.InvalidArgument(
'concurrency can only be used for "replicated-job" mode'
)
service_mode = self._convert_mode(mode)
self.mode = service_mode
self[service_mode] = {}
if replicas is not None:
if mode == 'replicated':
self[service_mode]['Replicas'] = replicas
if mode == 'replicated-job':
self[service_mode]['MaxConcurrent'] = concurrency or 1
self[service_mode]['TotalCompletions'] = replicas
@staticmethod
def _convert_mode(original_mode):
if original_mode == 'global-job':
return 'GlobalJob'
if original_mode == 'replicated-job':
return 'ReplicatedJob'
return original_mode
@property
def replicas(self):
if 'replicated' in self:
return self['replicated'].get('Replicas')
if 'ReplicatedJob' in self:
return self['ReplicatedJob'].get('TotalCompletions')
return None
class SecretReference(dict):
"""
Secret reference to be used as part of a :py:class:`ContainerSpec`.
Describes how a secret is made accessible inside the service's
containers.
Args:
secret_id (string): Secret's ID
secret_name (string): Secret's name as defined at its creation.
filename (string): Name of the file containing the secret. Defaults
to the secret's name if not specified.
uid (string): UID of the secret file's owner. Default: 0
gid (string): GID of the secret file's group. Default: 0
mode (int): File access mode inside the container. Default: 0o444
"""
@check_resource('secret_id')
def __init__(self, secret_id, secret_name, filename=None, uid=None,
gid=None, mode=0o444):
self['SecretName'] = secret_name
self['SecretID'] = secret_id
self['File'] = {
'Name': filename or secret_name,
'UID': uid or '0',
'GID': gid or '0',
'Mode': mode
}
class ConfigReference(dict):
"""
Config reference to be used as part of a :py:class:`ContainerSpec`.
Describes how a config is made accessible inside the service's
containers.
Args:
config_id (string): Config's ID
config_name (string): Config's name as defined at its creation.
filename (string): Name of the file containing the config. Defaults
to the config's name if not specified.
uid (string): UID of the config file's owner. Default: 0
gid (string): GID of the config file's group. Default: 0
mode (int): File access mode inside the container. Default: 0o444
"""
@check_resource('config_id')
def __init__(self, config_id, config_name, filename=None, uid=None,
gid=None, mode=0o444):
self['ConfigName'] = config_name
self['ConfigID'] = config_id
self['File'] = {
'Name': filename or config_name,
'UID': uid or '0',
'GID': gid or '0',
'Mode': mode
}
class Placement(dict):
"""
Placement constraints to be used as part of a :py:class:`TaskTemplate`
Args:
constraints (:py:class:`list` of str): A list of constraints
preferences (:py:class:`list` of tuple): Preferences provide a way
to make the scheduler aware of factors such as topology. They
are provided in order from highest to lowest precedence and
are expressed as ``(strategy, descriptor)`` tuples. See
:py:class:`PlacementPreference` for details.
maxreplicas (int): Maximum number of replicas per node
platforms (:py:class:`list` of tuple): A list of platforms
expressed as ``(arch, os)`` tuples
"""
def __init__(self, constraints=None, preferences=None, platforms=None,
maxreplicas=None):
if constraints is not None:
self['Constraints'] = constraints
if preferences is not None:
self['Preferences'] = []
for pref in preferences:
if isinstance(pref, tuple):
pref = PlacementPreference(*pref)
self['Preferences'].append(pref)
if maxreplicas is not None:
self['MaxReplicas'] = maxreplicas
if platforms:
self['Platforms'] = []
for plat in platforms:
self['Platforms'].append({
'Architecture': plat[0], 'OS': plat[1]
})
class PlacementPreference(dict):
"""
Placement preference to be used as an element in the list of
preferences for :py:class:`Placement` objects.
Args:
strategy (string): The placement strategy to implement. Currently,
the only supported strategy is ``spread``.
descriptor (string): A label descriptor. For the spread strategy,
the scheduler will try to spread tasks evenly over groups of
nodes identified by this label.
"""
def __init__(self, strategy, descriptor):
if strategy != 'spread':
raise errors.InvalidArgument(
f'PlacementPreference strategy value is invalid ({strategy}): '
'must be "spread".'
)
self['Spread'] = {'SpreadDescriptor': descriptor}
class DNSConfig(dict):
"""
Specification for DNS related configurations in resolver configuration
file (``resolv.conf``). Part of a :py:class:`ContainerSpec` definition.
Args:
nameservers (:py:class:`list`): The IP addresses of the name
servers.
search (:py:class:`list`): A search list for host-name lookup.
options (:py:class:`list`): A list of internal resolver variables
to be modified (e.g., ``debug``, ``ndots:3``, etc.).
"""
def __init__(self, nameservers=None, search=None, options=None):
self['Nameservers'] = nameservers
self['Search'] = search
self['Options'] = options
class Privileges(dict):
r"""
Security options for a service's containers.
Part of a :py:class:`ContainerSpec` definition.
Args:
credentialspec_file (str): Load credential spec from this file.
The file is read by the daemon, and must be present in the
CredentialSpecs subdirectory in the docker data directory,
which defaults to ``C:\ProgramData\Docker\`` on Windows.
Can not be combined with credentialspec_registry.
credentialspec_registry (str): Load credential spec from this value
in the Windows registry. The specified registry value must be
located in: ``HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
\Virtualization\Containers\CredentialSpecs``.
Can not be combined with credentialspec_file.
selinux_disable (boolean): Disable SELinux
selinux_user (string): SELinux user label
selinux_role (string): SELinux role label
selinux_type (string): SELinux type label
selinux_level (string): SELinux level label
"""
def __init__(self, credentialspec_file=None, credentialspec_registry=None,
selinux_disable=None, selinux_user=None, selinux_role=None,
selinux_type=None, selinux_level=None):
credential_spec = {}
if credentialspec_registry is not None:
credential_spec['Registry'] = credentialspec_registry
if credentialspec_file is not None:
credential_spec['File'] = credentialspec_file
if len(credential_spec) > 1:
raise errors.InvalidArgument(
'credentialspec_file and credentialspec_registry are mutually'
' exclusive'
)
selinux_context = {
'Disable': selinux_disable,
'User': selinux_user,
'Role': selinux_role,
'Type': selinux_type,
'Level': selinux_level,
}
if len(credential_spec) > 0:
self['CredentialSpec'] = credential_spec
if len(selinux_context) > 0:
self['SELinuxContext'] = selinux_context
class NetworkAttachmentConfig(dict):
"""
Network attachment options for a service.
Args:
target (str): The target network for attachment.
Can be a network name or ID.
aliases (:py:class:`list`): A list of discoverable alternate names
for the service.
options (:py:class:`dict`): Driver attachment options for the
network target.
"""
def __init__(self, target, aliases=None, options=None):
self['Target'] = target
self['Aliases'] = aliases
self['DriverOpts'] = options

119
docker/types/swarm.py Normal file
View File

@ -0,0 +1,119 @@
from ..errors import InvalidVersion
from ..utils import version_lt
class SwarmSpec(dict):
"""
Describe a Swarm's configuration and options. Use
:py:meth:`~docker.api.swarm.SwarmApiMixin.create_swarm_spec`
to instantiate.
"""
def __init__(self, version, task_history_retention_limit=None,
snapshot_interval=None, keep_old_snapshots=None,
log_entries_for_slow_followers=None, heartbeat_tick=None,
election_tick=None, dispatcher_heartbeat_period=None,
node_cert_expiry=None, external_cas=None, name=None,
labels=None, signing_ca_cert=None, signing_ca_key=None,
ca_force_rotate=None, autolock_managers=None,
log_driver=None):
if task_history_retention_limit is not None:
self['Orchestration'] = {
'TaskHistoryRetentionLimit': task_history_retention_limit
}
if any([snapshot_interval,
keep_old_snapshots,
log_entries_for_slow_followers,
heartbeat_tick,
election_tick]):
self['Raft'] = {
'SnapshotInterval': snapshot_interval,
'KeepOldSnapshots': keep_old_snapshots,
'LogEntriesForSlowFollowers': log_entries_for_slow_followers,
'HeartbeatTick': heartbeat_tick,
'ElectionTick': election_tick
}
if dispatcher_heartbeat_period:
self['Dispatcher'] = {
'HeartbeatPeriod': dispatcher_heartbeat_period
}
ca_config = {}
if node_cert_expiry is not None:
ca_config['NodeCertExpiry'] = node_cert_expiry
if external_cas:
if version_lt(version, '1.25'):
if len(external_cas) > 1:
raise InvalidVersion(
'Support for multiple external CAs is not available '
'for API version < 1.25'
)
ca_config['ExternalCA'] = external_cas[0]
else:
ca_config['ExternalCAs'] = external_cas
if signing_ca_key:
if version_lt(version, '1.30'):
raise InvalidVersion(
'signing_ca_key is not supported in API version < 1.30'
)
ca_config['SigningCAKey'] = signing_ca_key
if signing_ca_cert:
if version_lt(version, '1.30'):
raise InvalidVersion(
'signing_ca_cert is not supported in API version < 1.30'
)
ca_config['SigningCACert'] = signing_ca_cert
if ca_force_rotate is not None:
if version_lt(version, '1.30'):
raise InvalidVersion(
'force_rotate is not supported in API version < 1.30'
)
ca_config['ForceRotate'] = ca_force_rotate
if ca_config:
self['CAConfig'] = ca_config
if autolock_managers is not None:
if version_lt(version, '1.25'):
raise InvalidVersion(
'autolock_managers is not supported in API version < 1.25'
)
self['EncryptionConfig'] = {'AutoLockManagers': autolock_managers}
if log_driver is not None:
if version_lt(version, '1.25'):
raise InvalidVersion(
'log_driver is not supported in API version < 1.25'
)
self['TaskDefaults'] = {'LogDriver': log_driver}
if name is not None:
self['Name'] = name
if labels is not None:
self['Labels'] = labels
class SwarmExternalCA(dict):
"""
Configuration for forwarding signing requests to an external
certificate authority.
Args:
url (string): URL where certificate signing requests should be
sent.
protocol (string): Protocol for communication with the external CA.
options (dict): An object with key/value pairs that are interpreted
as protocol-specific options for the external CA driver.
ca_cert (string): The root CA certificate (in PEM format) this
external CA uses to issue TLS certificates (assumed to be to
the current swarm root CA certificate if not provided).
"""
def __init__(self, url, protocol=None, options=None, ca_cert=None):
self['URL'] = url
self['Protocol'] = protocol
self['Options'] = options
self['CACert'] = ca_cert

View File

@ -1 +0,0 @@
from .unixconn import UnixAdapter # flake8: noqa

View File

@ -1,92 +0,0 @@
# Copyright 2013 dotCloud inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import six
import requests.adapters
import socket
if six.PY3:
import http.client as httplib
else:
import httplib
try:
import requests.packages.urllib3 as urllib3
except ImportError:
import urllib3
RecentlyUsedContainer = urllib3._collections.RecentlyUsedContainer
class UnixHTTPConnection(httplib.HTTPConnection, object):
def __init__(self, base_url, unix_socket, timeout=60):
super(UnixHTTPConnection, self).__init__(
'localhost', timeout=timeout)
self.base_url = base_url
self.unix_socket = unix_socket
self.timeout = timeout
def connect(self):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
sock.connect(self.unix_socket)
self.sock = sock
class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
def __init__(self, base_url, socket_path, timeout=60):
super(UnixHTTPConnectionPool, self).__init__(
'localhost', timeout=timeout)
self.base_url = base_url
self.socket_path = socket_path
self.timeout = timeout
def _new_conn(self):
return UnixHTTPConnection(self.base_url, self.socket_path,
self.timeout)
class UnixAdapter(requests.adapters.HTTPAdapter):
def __init__(self, socket_url, timeout=60):
socket_path = socket_url.replace('http+unix://', '')
if not socket_path.startswith('/'):
socket_path = '/' + socket_path
self.socket_path = socket_path
self.timeout = timeout
self.pools = RecentlyUsedContainer(10,
dispose_func=lambda p: p.close())
super(UnixAdapter, self).__init__()
def get_connection(self, url, proxies=None):
with self.pools.lock:
pool = self.pools.get(url)
if pool:
return pool
pool = UnixHTTPConnectionPool(
url, self.socket_path, self.timeout
)
self.pools[url] = pool
return pool
def request_url(self, request, proxies):
# The select_proxy utility in requests errors out when the provided URL
# doesn't have a hostname, like is the case when using a UNIX socket.
# Since proxies are an irrelevant notion in the case of UNIX sockets
# anyway, we simply return the path URL directly.
# See also: https://github.com/docker/docker-py/issues/811
return request.path_url
def close(self):
self.pools.clear()

View File

@ -1,11 +1,28 @@
from .utils import (
compare_version, convert_port_bindings, convert_volume_binds,
mkbuildcontext, tar, exclude_paths, parse_repository_tag, parse_host,
kwargs_from_env, convert_filters, datetime_to_timestamp, create_host_config,
create_container_config, parse_bytes, ping_registry, parse_env_file,
version_lt, version_gte, decode_json_header, split_command,
create_ipam_config, create_ipam_pool, parse_devices, normalize_links,
) # flake8: noqa
from .types import Ulimit, LogConfig # flake8: noqa
from .decorators import check_resource, minimum_version, update_headers #flake8: noqa
from .build import create_archive, exclude_paths, match_tag, mkbuildcontext, tar
from .decorators import check_resource, minimum_version, update_headers
from .utils import (
compare_version,
convert_filters,
convert_port_bindings,
convert_service_networks,
convert_volume_binds,
create_host_config,
create_ipam_config,
create_ipam_pool,
datetime_to_timestamp,
decode_json_header,
format_environment,
format_extra_hosts,
kwargs_from_env,
normalize_links,
parse_bytes,
parse_devices,
parse_env_file,
parse_host,
parse_repository_tag,
split_command,
version_gte,
version_lt,
)

260
docker/utils/build.py Normal file
View File

@ -0,0 +1,260 @@
import io
import os
import re
import tarfile
import tempfile
from ..constants import IS_WINDOWS_PLATFORM
from .fnmatch import fnmatch
_SEP = re.compile('/|\\\\') if IS_WINDOWS_PLATFORM else re.compile('/')
_TAG = re.compile(
r"^[a-z0-9]+((\.|_|__|-+)[a-z0-9]+)*"
r"(?::[0-9]+)?(/[a-z0-9]+((\.|_|__|-+)[a-z0-9]+)*)*"
r"(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127})?$"
)
def match_tag(tag: str) -> bool:
return bool(_TAG.match(tag))
def tar(path, exclude=None, dockerfile=None, fileobj=None, gzip=False):
root = os.path.abspath(path)
exclude = exclude or []
dockerfile = dockerfile or (None, None)
extra_files = []
if dockerfile[1] is not None:
dockerignore_contents = '\n'.join(
(exclude or ['.dockerignore']) + [dockerfile[0]]
)
extra_files = [
('.dockerignore', dockerignore_contents),
dockerfile,
]
return create_archive(
files=sorted(exclude_paths(root, exclude, dockerfile=dockerfile[0])),
root=root, fileobj=fileobj, gzip=gzip, extra_files=extra_files
)
def exclude_paths(root, patterns, dockerfile=None):
"""
Given a root directory path and a list of .dockerignore patterns, return
an iterator of all paths (both regular files and directories) in the root
directory that do *not* match any of the patterns.
All paths returned are relative to the root.
"""
if dockerfile is None:
dockerfile = 'Dockerfile'
patterns.append(f"!{dockerfile}")
pm = PatternMatcher(patterns)
return set(pm.walk(root))
def build_file_list(root):
files = []
for dirname, dirnames, fnames in os.walk(root):
for filename in fnames + dirnames:
longpath = os.path.join(dirname, filename)
files.append(
longpath.replace(root, '', 1).lstrip('/')
)
return files
def create_archive(root, files=None, fileobj=None, gzip=False,
extra_files=None):
extra_files = extra_files or []
if not fileobj:
fileobj = tempfile.NamedTemporaryFile()
t = tarfile.open(mode='w:gz' if gzip else 'w', fileobj=fileobj)
if files is None:
files = build_file_list(root)
extra_names = {e[0] for e in extra_files}
for path in files:
if path in extra_names:
# Extra files override context files with the same name
continue
full_path = os.path.join(root, path)
i = t.gettarinfo(full_path, arcname=path)
if i is None:
# This happens when we encounter a socket file. We can safely
# ignore it and proceed.
continue
# Workaround https://bugs.python.org/issue32713
if i.mtime < 0 or i.mtime > 8**11 - 1:
i.mtime = int(i.mtime)
if IS_WINDOWS_PLATFORM:
# Windows doesn't keep track of the execute bit, so we make files
# and directories executable by default.
i.mode = i.mode & 0o755 | 0o111
if i.isfile():
try:
with open(full_path, 'rb') as f:
t.addfile(i, f)
except OSError as oe:
raise OSError(
f'Can not read file in context: {full_path}'
) from oe
else:
# Directories, FIFOs, symlinks... don't need to be read.
t.addfile(i, None)
for name, contents in extra_files:
info = tarfile.TarInfo(name)
contents_encoded = contents.encode('utf-8')
info.size = len(contents_encoded)
t.addfile(info, io.BytesIO(contents_encoded))
t.close()
fileobj.seek(0)
return fileobj
def mkbuildcontext(dockerfile):
f = tempfile.NamedTemporaryFile()
t = tarfile.open(mode='w', fileobj=f)
if isinstance(dockerfile, io.StringIO):
dfinfo = tarfile.TarInfo('Dockerfile')
raise TypeError('Please use io.BytesIO to create in-memory '
'Dockerfiles with Python 3')
elif isinstance(dockerfile, io.BytesIO):
dfinfo = tarfile.TarInfo('Dockerfile')
dfinfo.size = len(dockerfile.getvalue())
dockerfile.seek(0)
else:
dfinfo = t.gettarinfo(fileobj=dockerfile, arcname='Dockerfile')
t.addfile(dfinfo, dockerfile)
t.close()
f.seek(0)
return f
def split_path(p):
return [pt for pt in re.split(_SEP, p) if pt and pt != '.']
def normalize_slashes(p):
if IS_WINDOWS_PLATFORM:
return '/'.join(split_path(p))
return p
def walk(root, patterns, default=True):
pm = PatternMatcher(patterns)
return pm.walk(root)
# Heavily based on
# https://github.com/moby/moby/blob/master/pkg/fileutils/fileutils.go
class PatternMatcher:
def __init__(self, patterns):
self.patterns = list(filter(
lambda p: p.dirs, [Pattern(p) for p in patterns]
))
self.patterns.append(Pattern('!.dockerignore'))
def matches(self, filepath):
matched = False
parent_path = os.path.dirname(filepath)
parent_path_dirs = split_path(parent_path)
for pattern in self.patterns:
negative = pattern.exclusion
match = pattern.match(filepath)
if not match and parent_path != '':
if len(pattern.dirs) <= len(parent_path_dirs):
match = pattern.match(
os.path.sep.join(parent_path_dirs[:len(pattern.dirs)])
)
if match:
matched = not negative
return matched
def walk(self, root):
def rec_walk(current_dir):
for f in os.listdir(current_dir):
fpath = os.path.join(
os.path.relpath(current_dir, root), f
)
if fpath.startswith(f".{os.path.sep}"):
fpath = fpath[2:]
match = self.matches(fpath)
if not match:
yield fpath
cur = os.path.join(root, fpath)
if not os.path.isdir(cur) or os.path.islink(cur):
continue
if match:
# If we want to skip this file and it's a directory
# then we should first check to see if there's an
# excludes pattern (e.g. !dir/file) that starts with this
# dir. If so then we can't skip this dir.
skip = True
for pat in self.patterns:
if not pat.exclusion:
continue
if pat.cleaned_pattern.startswith(
normalize_slashes(fpath)):
skip = False
break
if skip:
continue
yield from rec_walk(cur)
return rec_walk(root)
class Pattern:
def __init__(self, pattern_str):
self.exclusion = False
if pattern_str.startswith('!'):
self.exclusion = True
pattern_str = pattern_str[1:]
self.dirs = self.normalize(pattern_str)
self.cleaned_pattern = '/'.join(self.dirs)
@classmethod
def normalize(cls, p):
# Remove trailing spaces
p = p.strip()
# Leading and trailing slashes are not relevant. Yes,
# "foo.py/" must exclude the "foo.py" regular file. "."
# components are not relevant either, even if the whole
# pattern is only ".", as the Docker reference states: "For
# historical reasons, the pattern . is ignored."
# ".." component must be cleared with the potential previous
# component, regardless of whether it exists: "A preprocessing
# step [...] eliminates . and .. elements using Go's
# filepath.".
i = 0
split = split_path(p)
while i < len(split):
if split[i] == '..':
del split[i]
if i > 0:
del split[i - 1]
i -= 1
else:
i += 1
return split
def match(self, filepath):
return fnmatch(normalize_slashes(filepath), self.cleaned_pattern)

66
docker/utils/config.py Normal file
View File

@ -0,0 +1,66 @@
import json
import logging
import os
from ..constants import IS_WINDOWS_PLATFORM
DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')
LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'
log = logging.getLogger(__name__)
def find_config_file(config_path=None):
paths = list(filter(None, [
config_path, # 1
config_path_from_environment(), # 2
os.path.join(home_dir(), DOCKER_CONFIG_FILENAME), # 3
os.path.join(home_dir(), LEGACY_DOCKER_CONFIG_FILENAME), # 4
]))
log.debug(f"Trying paths: {repr(paths)}")
for path in paths:
if os.path.exists(path):
log.debug(f"Found file at path: {path}")
return path
log.debug("No config file found")
return None
def config_path_from_environment():
config_dir = os.environ.get('DOCKER_CONFIG')
if not config_dir:
return None
return os.path.join(config_dir, os.path.basename(DOCKER_CONFIG_FILENAME))
def home_dir():
"""
Get the user's home directory, using the same logic as the Docker Engine
client - use %USERPROFILE% on Windows, $HOME/getuid on POSIX.
"""
if IS_WINDOWS_PLATFORM:
return os.environ.get('USERPROFILE', '')
else:
return os.path.expanduser('~')
def load_general_config(config_path=None):
config_file = find_config_file(config_path)
if not config_file:
return {}
try:
with open(config_file) as f:
return json.load(f)
except (OSError, ValueError) as e:
# In the case of a legacy `.dockercfg` file, we won't
# be able to load any JSON data.
log.debug(e)
log.debug("All parsing attempts failed - returning empty config")
return {}

View File

@ -4,22 +4,21 @@ from .. import errors
from . import utils
def check_resource(f):
@functools.wraps(f)
def wrapped(self, resource_id=None, *args, **kwargs):
if resource_id is None:
if kwargs.get('container'):
resource_id = kwargs.pop('container')
elif kwargs.get('image'):
resource_id = kwargs.pop('image')
if isinstance(resource_id, dict):
resource_id = resource_id.get('Id')
if not resource_id:
raise errors.NullResource(
'image or container param is undefined'
)
return f(self, resource_id, *args, **kwargs)
return wrapped
def check_resource(resource_name):
def decorator(f):
@functools.wraps(f)
def wrapped(self, resource_id=None, *args, **kwargs):
if resource_id is None and kwargs.get(resource_name):
resource_id = kwargs.pop(resource_name)
if isinstance(resource_id, dict):
resource_id = resource_id.get('Id', resource_id.get('ID'))
if not resource_id:
raise errors.NullResource(
'Resource ID was not provided'
)
return f(self, resource_id, *args, **kwargs)
return wrapped
return decorator
def minimum_version(version):
@ -28,9 +27,7 @@ def minimum_version(version):
def wrapper(self, *args, **kwargs):
if utils.version_lt(self._version, version):
raise errors.InvalidVersion(
'{0} is not available for version < {1}'.format(
f.__name__, version
)
f'{f.__name__} is not available for version < {version}',
)
return f(self, *args, **kwargs)
return wrapper
@ -39,10 +36,10 @@ def minimum_version(version):
def update_headers(f):
def inner(self, *args, **kwargs):
if 'HttpHeaders' in self._auth_configs:
if 'headers' not in kwargs:
kwargs['headers'] = self._auth_configs['HttpHeaders']
if 'HttpHeaders' in self._general_configs:
if not kwargs.get('headers'):
kwargs['headers'] = self._general_configs['HttpHeaders']
else:
kwargs['headers'].update(self._auth_configs['HttpHeaders'])
kwargs['headers'].update(self._general_configs['HttpHeaders'])
return f(self, *args, **kwargs)
return inner

115
docker/utils/fnmatch.py Normal file
View File

@ -0,0 +1,115 @@
"""Filename matching with shell patterns.
fnmatch(FILENAME, PATTERN) matches according to the local convention.
fnmatchcase(FILENAME, PATTERN) always takes case in account.
The functions operate by translating the pattern into a regular
expression. They cache the compiled regular expressions for speed.
The function translate(PATTERN) returns a regular expression
corresponding to PATTERN. (It does not compile it.)
"""
import re
__all__ = ["fnmatch", "fnmatchcase", "translate"]
_cache = {}
_MAXCACHE = 100
def _purge():
"""Clear the pattern cache"""
_cache.clear()
def fnmatch(name, pat):
"""Test whether FILENAME matches PATTERN.
Patterns are Unix shell style:
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any char not in seq
An initial period in FILENAME is not special.
Both FILENAME and PATTERN are first case-normalized
if the operating system requires it.
If you don't want this, use fnmatchcase(FILENAME, PATTERN).
"""
name = name.lower()
pat = pat.lower()
return fnmatchcase(name, pat)
def fnmatchcase(name, pat):
"""Test whether FILENAME matches PATTERN, including case.
This is a version of fnmatch() which doesn't case-normalize
its arguments.
"""
try:
re_pat = _cache[pat]
except KeyError:
res = translate(pat)
if len(_cache) >= _MAXCACHE:
_cache.clear()
_cache[pat] = re_pat = re.compile(res)
return re_pat.match(name) is not None
def translate(pat):
"""Translate a shell PATTERN to a regular expression.
There is no way to quote meta-characters.
"""
i, n = 0, len(pat)
res = '^'
while i < n:
c = pat[i]
i = i + 1
if c == '*':
if i < n and pat[i] == '*':
# is some flavor of "**"
i = i + 1
# Treat **/ as ** so eat the "/"
if i < n and pat[i] == '/':
i = i + 1
if i >= n:
# is "**EOF" - to align with .gitignore just accept all
res = f"{res}.*"
else:
# is "**"
# Note that this allows for any # of /'s (even 0) because
# the .* will eat everything, even /'s
res = f"{res}(.*/)?"
else:
# is "*" so map it to anything but "/"
res = f"{res}[^/]*"
elif c == '?':
# "?" is any char except "/"
res = f"{res}[^/]"
elif c == '[':
j = i
if j < n and pat[j] == '!':
j = j + 1
if j < n and pat[j] == ']':
j = j + 1
while j < n and pat[j] != ']':
j = j + 1
if j >= n:
res = f"{res}\\["
else:
stuff = pat[i:j].replace('\\', '\\\\')
i = j + 1
if stuff[0] == '!':
stuff = f"^{stuff[1:]}"
elif stuff[0] == '^':
stuff = f"\\{stuff}"
res = f'{res}[{stuff}]'
else:
res = res + re.escape(c)
return f"{res}$"

View File

@ -0,0 +1,74 @@
import json
import json.decoder
from ..errors import StreamParseError
json_decoder = json.JSONDecoder()
def stream_as_text(stream):
"""
Given a stream of bytes or text, if any of the items in the stream
are bytes convert them to text.
This function can be removed once we return text streams
instead of byte streams.
"""
for data in stream:
if not isinstance(data, str):
data = data.decode('utf-8', 'replace')
yield data
def json_splitter(buffer):
"""Attempt to parse a json object from a buffer. If there is at least one
object, return it and the rest of the buffer, otherwise return None.
"""
buffer = buffer.strip()
try:
obj, index = json_decoder.raw_decode(buffer)
rest = buffer[json.decoder.WHITESPACE.match(buffer, index).end():]
return obj, rest
except ValueError:
return None
def json_stream(stream):
"""Given a stream of text, return a stream of json objects.
This handles streams which are inconsistently buffered (some entries may
be newline delimited, and others are not).
"""
return split_buffer(stream, json_splitter, json_decoder.decode)
def line_splitter(buffer, separator='\n'):
index = buffer.find(str(separator))
if index == -1:
return None
return buffer[:index + 1], buffer[index + 1:]
def split_buffer(stream, splitter=None, decoder=lambda a: a):
"""Given a generator which yields strings and a splitter function,
joins all input, splits on the separator and yields each chunk.
Unlike string.split(), each chunk includes the trailing
separator, except for the last one if none was found on the end
of the input.
"""
splitter = splitter or line_splitter
buffered = ''
for data in stream_as_text(stream):
buffered += data
while True:
buffer_split = splitter(buffered)
if buffer_split is None:
break
item, buffered = buffer_split
yield item
if buffered:
try:
yield decoder(buffered)
except Exception as e:
raise StreamParseError(e) from e

83
docker/utils/ports.py Normal file
View File

@ -0,0 +1,83 @@
import re
PORT_SPEC = re.compile(
"^" # Match full string
"(" # External part
r"(\[?(?P<host>[a-fA-F\d.:]+)\]?:)?" # Address
r"(?P<ext>[\d]*)(-(?P<ext_end>[\d]+))?:" # External range
")?"
r"(?P<int>[\d]+)(-(?P<int_end>[\d]+))?" # Internal range
"(?P<proto>/(udp|tcp|sctp))?" # Protocol
"$" # Match full string
)
def add_port_mapping(port_bindings, internal_port, external):
if internal_port in port_bindings:
port_bindings[internal_port].append(external)
else:
port_bindings[internal_port] = [external]
def add_port(port_bindings, internal_port_range, external_range):
if external_range is None:
for internal_port in internal_port_range:
add_port_mapping(port_bindings, internal_port, None)
else:
ports = zip(internal_port_range, external_range)
for internal_port, external_port in ports:
add_port_mapping(port_bindings, internal_port, external_port)
def build_port_bindings(ports):
port_bindings = {}
for port in ports:
internal_port_range, external_range = split_port(port)
add_port(port_bindings, internal_port_range, external_range)
return port_bindings
def _raise_invalid_port(port):
raise ValueError('Invalid port "%s", should be '
'[[remote_ip:]remote_port[-remote_port]:]'
'port[/protocol]' % port)
def port_range(start, end, proto, randomly_available_port=False):
if not start:
return start
if not end:
return [start + proto]
if randomly_available_port:
return [f"{start}-{end}{proto}"]
return [str(port) + proto for port in range(int(start), int(end) + 1)]
def split_port(port):
if hasattr(port, 'legacy_repr'):
# This is the worst hack, but it prevents a bug in Compose 1.14.0
# https://github.com/docker/docker-py/issues/1668
# TODO: remove once fixed in Compose stable
port = port.legacy_repr()
port = str(port)
match = PORT_SPEC.match(port)
if match is None:
_raise_invalid_port(port)
parts = match.groupdict()
host = parts['host']
proto = parts['proto'] or ''
internal = port_range(parts['int'], parts['int_end'], proto)
external = port_range(
parts['ext'], parts['ext_end'], '', len(internal) == 1)
if host is None:
if external is not None and len(internal) != len(external):
raise ValueError('Port ranges don\'t match in length')
return internal, external
else:
if not external:
external = [None] * len(internal)
elif len(internal) != len(external):
raise ValueError('Port ranges don\'t match in length')
return internal, [(host, ext_port) for ext_port in external]

View File

@ -1,4 +0,0 @@
from .ports import (
split_port,
build_port_bindings
) # flake8: noqa

View File

@ -1,92 +0,0 @@
def add_port_mapping(port_bindings, internal_port, external):
if internal_port in port_bindings:
port_bindings[internal_port].append(external)
else:
port_bindings[internal_port] = [external]
def add_port(port_bindings, internal_port_range, external_range):
if external_range is None:
for internal_port in internal_port_range:
add_port_mapping(port_bindings, internal_port, None)
else:
ports = zip(internal_port_range, external_range)
for internal_port, external_port in ports:
add_port_mapping(port_bindings, internal_port, external_port)
def build_port_bindings(ports):
port_bindings = {}
for port in ports:
internal_port_range, external_range = split_port(port)
add_port(port_bindings, internal_port_range, external_range)
return port_bindings
def to_port_range(port):
if not port:
return None
protocol = ""
if "/" in port:
parts = port.split("/")
if len(parts) != 2:
_raise_invalid_port(port)
port, protocol = parts
protocol = "/" + protocol
parts = str(port).split('-')
if len(parts) == 1:
return ["%s%s" % (port, protocol)]
if len(parts) == 2:
full_port_range = range(int(parts[0]), int(parts[1]) + 1)
return ["%s%s" % (p, protocol) for p in full_port_range]
raise ValueError('Invalid port range "%s", should be '
'port or startport-endport' % port)
def _raise_invalid_port(port):
raise ValueError('Invalid port "%s", should be '
'[[remote_ip:]remote_port[-remote_port]:]'
'port[/protocol]' % port)
def split_port(port):
parts = str(port).split(':')
if not 1 <= len(parts) <= 3:
_raise_invalid_port(port)
if len(parts) == 1:
internal_port, = parts
return to_port_range(internal_port), None
if len(parts) == 2:
external_port, internal_port = parts
internal_range = to_port_range(internal_port)
external_range = to_port_range(external_port)
if internal_range is None or external_range is None:
_raise_invalid_port(port)
if len(internal_range) != len(external_range):
raise ValueError('Port ranges don\'t match in length')
return internal_range, external_range
external_ip, external_port, internal_port = parts
internal_range = to_port_range(internal_port)
external_range = to_port_range(external_port)
if not external_range:
external_range = [None] * len(internal_range)
if len(internal_range) != len(external_range):
raise ValueError('Port ranges don\'t match in length')
return internal_range, [(external_ip, ex_port or None)
for ex_port in external_range]

77
docker/utils/proxy.py Normal file
View File

@ -0,0 +1,77 @@
from .utils import format_environment
class ProxyConfig(dict):
'''
Hold the client's proxy configuration
'''
@property
def http(self):
return self.get('http')
@property
def https(self):
return self.get('https')
@property
def ftp(self):
return self.get('ftp')
@property
def no_proxy(self):
return self.get('no_proxy')
@staticmethod
def from_dict(config):
'''
Instantiate a new ProxyConfig from a dictionary that represents a
client configuration, as described in `the documentation`_.
.. _the documentation:
https://docs.docker.com/network/proxy/#configure-the-docker-client
'''
return ProxyConfig(
http=config.get('httpProxy'),
https=config.get('httpsProxy'),
ftp=config.get('ftpProxy'),
no_proxy=config.get('noProxy'),
)
def get_environment(self):
'''
Return a dictionary representing the environment variables used to
set the proxy settings.
'''
env = {}
if self.http:
env['http_proxy'] = env['HTTP_PROXY'] = self.http
if self.https:
env['https_proxy'] = env['HTTPS_PROXY'] = self.https
if self.ftp:
env['ftp_proxy'] = env['FTP_PROXY'] = self.ftp
if self.no_proxy:
env['no_proxy'] = env['NO_PROXY'] = self.no_proxy
return env
def inject_proxy_environment(self, environment):
'''
Given a list of strings representing environment variables, prepend the
environment variables corresponding to the proxy settings.
'''
if not self:
return environment
proxy_env = format_environment(self.get_environment())
if not environment:
return proxy_env
# It is important to prepend our variables, because we want the
# variables defined in "environment" to take precedence.
return proxy_env + environment
def __str__(self):
return (
'ProxyConfig('
f'http={self.http}, https={self.https}, '
f'ftp={self.ftp}, no_proxy={self.no_proxy}'
')'
)

187
docker/utils/socket.py Normal file
View File

@ -0,0 +1,187 @@
import errno
import os
import select
import socket as pysocket
import struct
try:
from ..transport import NpipeSocket
except ImportError:
NpipeSocket = type(None)
STDOUT = 1
STDERR = 2
class SocketError(Exception):
pass
# NpipeSockets have their own error types
# pywintypes.error: (109, 'ReadFile', 'The pipe has been ended.')
NPIPE_ENDED = 109
def read(socket, n=4096):
"""
Reads at most n bytes from socket
"""
recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)
if not isinstance(socket, NpipeSocket):
if not hasattr(select, "poll"):
# Limited to 1024
select.select([socket], [], [])
else:
poll = select.poll()
poll.register(socket, select.POLLIN | select.POLLPRI)
poll.poll()
try:
if hasattr(socket, 'recv'):
return socket.recv(n)
if isinstance(socket, pysocket.SocketIO):
return socket.read(n)
return os.read(socket.fileno(), n)
except OSError as e:
if e.errno not in recoverable_errors:
raise
except Exception as e:
is_pipe_ended = (isinstance(socket, NpipeSocket) and
len(e.args) > 0 and
e.args[0] == NPIPE_ENDED)
if is_pipe_ended:
# npipes don't support duplex sockets, so we interpret
# a PIPE_ENDED error as a close operation (0-length read).
return ''
raise
def read_exactly(socket, n):
"""
Reads exactly n bytes from socket
Raises SocketError if there isn't enough data
"""
data = b""
while len(data) < n:
next_data = read(socket, n - len(data))
if not next_data:
raise SocketError("Unexpected EOF")
data += next_data
return data
def next_frame_header(socket):
"""
Returns the stream and size of the next frame of data waiting to be read
from socket, according to the protocol defined here:
https://docs.docker.com/engine/api/v1.24/#attach-to-a-container
"""
try:
data = read_exactly(socket, 8)
except SocketError:
return (-1, -1)
stream, actual = struct.unpack('>BxxxL', data)
return (stream, actual)
def frames_iter(socket, tty):
"""
Return a generator of frames read from socket. A frame is a tuple where
the first item is the stream number and the second item is a chunk of data.
If the tty setting is enabled, the streams are multiplexed into the stdout
stream.
"""
if tty:
return ((STDOUT, frame) for frame in frames_iter_tty(socket))
else:
return frames_iter_no_tty(socket)
def frames_iter_no_tty(socket):
"""
Returns a generator of data read from the socket when the tty setting is
not enabled.
"""
while True:
(stream, n) = next_frame_header(socket)
if n < 0:
break
while n > 0:
result = read(socket, n)
if result is None:
continue
data_length = len(result)
if data_length == 0:
# We have reached EOF
return
n -= data_length
yield (stream, result)
def frames_iter_tty(socket):
"""
Return a generator of data read from the socket when the tty setting is
enabled.
"""
while True:
result = read(socket)
if len(result) == 0:
# We have reached EOF
return
yield result
def consume_socket_output(frames, demux=False):
"""
Iterate through frames read from the socket and return the result.
Args:
demux (bool):
If False, stdout and stderr are multiplexed, and the result is the
concatenation of all the frames. If True, the streams are
demultiplexed, and the result is a 2-tuple where each item is the
concatenation of frames belonging to the same stream.
"""
if demux is False:
# If the streams are multiplexed, the generator returns strings, that
# we just need to concatenate.
return b"".join(frames)
# If the streams are demultiplexed, the generator yields tuples
# (stdout, stderr)
out = [None, None]
for frame in frames:
# It is guaranteed that for each frame, one and only one stream
# is not None.
assert frame != (None, None)
if frame[0] is not None:
if out[0] is None:
out[0] = frame[0]
else:
out[0] += frame[0]
else:
if out[1] is None:
out[1] = frame[1]
else:
out[1] += frame[1]
return tuple(out)
def demux_adaptor(stream_id, data):
"""
Utility to demultiplex stdout and stderr when reading frames from the
socket.
"""
if stream_id == STDOUT:
return (data, None)
elif stream_id == STDERR:
return (None, data)
else:
raise ValueError(f'{stream_id} is not a valid stream')

View File

@ -1,96 +0,0 @@
import six
class LogConfigTypesEnum(object):
_values = (
'json-file',
'syslog',
'journald',
'gelf',
'fluentd',
'none'
)
JSON, SYSLOG, JOURNALD, GELF, FLUENTD, NONE = _values
class DictType(dict):
def __init__(self, init):
for k, v in six.iteritems(init):
self[k] = v
class LogConfig(DictType):
types = LogConfigTypesEnum
def __init__(self, **kwargs):
log_driver_type = kwargs.get('type', kwargs.get('Type'))
config = kwargs.get('config', kwargs.get('Config')) or {}
if config and not isinstance(config, dict):
raise ValueError("LogConfig.config must be a dictionary")
super(LogConfig, self).__init__({
'Type': log_driver_type,
'Config': config
})
@property
def type(self):
return self['Type']
@type.setter
def type(self, value):
self['Type'] = value
@property
def config(self):
return self['Config']
def set_config_value(self, key, value):
self.config[key] = value
def unset_config(self, key):
if key in self.config:
del self.config[key]
class Ulimit(DictType):
def __init__(self, **kwargs):
name = kwargs.get('name', kwargs.get('Name'))
soft = kwargs.get('soft', kwargs.get('Soft'))
hard = kwargs.get('hard', kwargs.get('Hard'))
if not isinstance(name, six.string_types):
raise ValueError("Ulimit.name must be a string")
if soft and not isinstance(soft, int):
raise ValueError("Ulimit.soft must be an integer")
if hard and not isinstance(hard, int):
raise ValueError("Ulimit.hard must be an integer")
super(Ulimit, self).__init__({
'Name': name,
'Soft': soft,
'Hard': hard
})
@property
def name(self):
return self['Name']
@name.setter
def name(self, value):
self['Name'] = value
@property
def soft(self):
return self.get('Soft')
@soft.setter
def soft(self, value):
self['Soft'] = value
@property
def hard(self):
return self.get('Hard')
@hard.setter
def hard(self, value):
self['Hard'] = value

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +1,8 @@
version = "1.8.0-rc2"
version_info = tuple([int(d) for d in version.split("-")[0].split(".")])
try:
from ._version import __version__
except ImportError:
from importlib.metadata import PackageNotFoundError, version
try:
__version__ = version('docker')
except PackageNotFoundError:
__version__ = '0.0.0'

View File

@ -1 +0,0 @@
mkdocs==0.9

12
docs/_static/custom.css vendored Normal file
View File

@ -0,0 +1,12 @@
dl.hide-signature > dt {
display: none;
}
dl.field-list > dt {
/* prevent code blocks from forcing wrapping on the "Parameters" header */
word-break: initial;
}
code.literal{
hyphens: none;
}

2
docs/_templates/page.html vendored Normal file
View File

@ -0,0 +1,2 @@
{% extends "!page.html" %}
{% set css_files = css_files + ["_static/custom.css"] %}

File diff suppressed because it is too large Load Diff

158
docs/api.rst Normal file
View File

@ -0,0 +1,158 @@
Low-level API
=============
The main object-orientated API is built on top of :py:class:`APIClient`. Each method on :py:class:`APIClient` maps one-to-one with a REST API endpoint, and returns the response that the API responds with.
It's possible to use :py:class:`APIClient` directly. Some basic things (e.g. running a container) consist of several API calls and are complex to do with the low-level API, but it's useful if you need extra flexibility and power.
.. py:module:: docker.api
.. autoclass:: docker.api.client.APIClient
Configs
-------
.. py:module:: docker.api.config
.. rst-class:: hide-signature
.. autoclass:: ConfigApiMixin
:members:
:undoc-members:
Containers
----------
.. py:module:: docker.api.container
.. rst-class:: hide-signature
.. autoclass:: ContainerApiMixin
:members:
:undoc-members:
Images
------
.. py:module:: docker.api.image
.. rst-class:: hide-signature
.. autoclass:: ImageApiMixin
:members:
:undoc-members:
Building images
---------------
.. py:module:: docker.api.build
.. rst-class:: hide-signature
.. autoclass:: BuildApiMixin
:members:
:undoc-members:
Networks
--------
.. rst-class:: hide-signature
.. autoclass:: docker.api.network.NetworkApiMixin
:members:
:undoc-members:
Volumes
-------
.. py:module:: docker.api.volume
.. rst-class:: hide-signature
.. autoclass:: VolumeApiMixin
:members:
:undoc-members:
Executing commands in containers
--------------------------------
.. py:module:: docker.api.exec_api
.. rst-class:: hide-signature
.. autoclass:: ExecApiMixin
:members:
:undoc-members:
Swarms
------
.. py:module:: docker.api.swarm
.. rst-class:: hide-signature
.. autoclass:: SwarmApiMixin
:members:
:undoc-members:
Services
--------
.. py:module:: docker.api.service
.. rst-class:: hide-signature
.. autoclass:: ServiceApiMixin
:members:
:undoc-members:
Plugins
-------
.. py:module:: docker.api.plugin
.. rst-class:: hide-signature
.. autoclass:: PluginApiMixin
:members:
:undoc-members:
Secrets
-------
.. py:module:: docker.api.secret
.. rst-class:: hide-signature
.. autoclass:: SecretApiMixin
:members:
:undoc-members:
The Docker daemon
-----------------
.. py:module:: docker.api.daemon
.. rst-class:: hide-signature
.. autoclass:: DaemonApiMixin
:members:
:undoc-members:
Configuration types
-------------------
.. py:module:: docker.types
.. autoclass:: ConfigReference
.. autoclass:: ContainerSpec
.. autoclass:: DNSConfig
.. autoclass:: DriverConfig
.. autoclass:: EndpointSpec
.. autoclass:: Healthcheck
.. autoclass:: IPAMConfig
.. autoclass:: IPAMPool
.. autoclass:: LogConfig
.. autoclass:: Mount
.. autoclass:: NetworkAttachmentConfig
.. autoclass:: Placement
.. autoclass:: PlacementPreference
.. autoclass:: Privileges
.. autoclass:: Resources
.. autoclass:: RestartPolicy
.. autoclass:: RollbackConfig
.. autoclass:: SecretReference
.. autoclass:: ServiceMode
.. autoclass:: SwarmExternalCA
.. autoclass:: SwarmSpec(*args, **kwargs)
.. autoclass:: TaskTemplate
.. autoclass:: Ulimit
.. autoclass:: UpdateConfig

2242
docs/change-log.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,899 +0,0 @@
Change Log
==========
1.8.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.8.0+is%3Aclosed)
### Features
* Added `Client.update_container` method (Update resource configs of a
container)
* Added support for gzipped context in `Client.build`
* Added ability to specify IP address when connecting a container to a
network
* Added `tmpfs` support to `Client.create_host_config`
* Added support for the `changes` param in `Client.commit`
* Added support for the `follow` param in `Client.logs`
* Added support for the `check_duplicate` param in `Client.create_network`
* Added support for the `decode` param in `Client.push` and `Client.pull`
* Added `docker.from_env` shortcut function. Instantiates a client with
`kwargs_from_env`
* `kwargs_from_env` now supports an optional `environment` parameter.
If present, values will be fetched from this dictionary instead of
`os.environ`
### Bugfixes
* Fixed a bug where some environment variables specified through
`create_container` would be improperly formatted
* Fixed an issue where the default TLS version in TLSConfig would
break in some environments. `docker-py` now uses TLSv1 by default
This setting can be overridden using the `ssl_version` param in
`kwargs_from_env` or the `TLSConfig` constructor
* Fixed a bug where using the unix socket connection would raise
an error in some edge-case situations
* Fixed a bug where `tcp` hosts would fail to connect to TLS-enabled
endpoints.
### Miscellaneous
* Default API version is now 1.22 (introduced in Docker 1.10.0)
1.7.2
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.7.2+is%3Aclosed)
### Bugfixes
* Fixed a bug where TLS verification was improperly executed when providing
a custom CA certificate.
1.7.1
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.7.1+is%3Aclosed)
### Features
* Added support for `shm_size` in `Client.create_host_config`
### Bugfixes
* Fixed a bug where Dockerfile would sometimes be excluded from the build
context.
* Fixed a bug where a docker config file containing unknown keys would raise
an exception.
* Fixed an issue with SSL connections behaving improperly when pyOpenSSL
was installed in the same environment.
* Several TLS configuration improvements
1.7.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.7.0+is%3Aclosed)
### Features
* Added support for cusom IPAM configuration in `Client.create_network`
* Added input support to `Client.exec_create`
* Added support for `stop_signal` in `Client.create_host_config`
* Added support for custom HTTP headers in Docker config file.
* Added support for unspecified transfer protocol in `base_url` when TLS is
enabled.
### Bugfixes
* Fixed a bug where the `filters` parameter in `Client.volumes` would not be
applied properly.
* Fixed a bug where memory limits would parse to incorrect values.
* Fixed a bug where the `devices` parameter in `Client.create_host_config`
would sometimes be misinterpreted.
* Fixed a bug where instantiating a `Client` object would sometimes crash if
`base_url` was unspecified.
* Fixed a bug where an error message related to TLS configuration would link
to a non-existent (outdated) docs page.
### Miscellaneous
* Processing of `.dockerignore` has been made significantly faster.
* Dropped explicit support for Python 3.2
1.6.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.6.0+is%3Aclosed)
### Features
* Added support for the `since` param in `Client.logs` (introduced in API
version 1.19)
* Added support for the `DOCKER_CONFIG` environment variable when looking up
auth config
* Added support for the `stream` param in `Client.stats` (when set to `False`,
allows user to retrieve a single snapshot instead of a constant data stream)
* Added support for the `mem_swappiness`, `oom_kill_disable` params
in `Client.create_host_config`
* Added support for build arguments in `Client.build` through the `buildargs`
param.
### Bugfixes
* Fixed a bug where streaming data over HTTPS would sometimes behave
incorrectly with Python 3.x
* Fixed a bug where commands containing unicode characters would be incorrectly
handled by `Client.create_container`.
* Fixed a bug where auth config credentials containing unicode characters would
cause failures when pushing / pulling images.
* Setting `tail=0` in `Client.logs` no longer shows past logs.
* Fixed a bug where `Client.pull` and `Client.push` couldn't handle image names
containing a dot.
### Miscellaneous
* Default API version is now 1.21 (introduced in Docker 1.9.0)
* Several test improvements and cleanup that should make the suite easier to
expand and maintain moving forward.
1.5.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.5.0+is%3Aclosed)
### Features
* Added support for the networking API introduced in Docker 1.9.0
(`Client.networks`, `Client.create_network`, `Client.remove_network`,
`Client.inspect_network`, `Client.connect_container_to_network`,
`Client.disconnect_container_from_network`).
* Added support for the volumes API introduced in Docker 1.9.0
(`Client.volumes`, `Client.create_volume`, `Client.inspect_volume`,
`Client.remove_volume`).
* Added support for the `group_add` parameter in `create_host_config`.
* Added support for the CPU CFS (`cpu_quota` and `cpu_period`) parameteres
in `create_host_config`.
* Added support for the archive API endpoint (`Client.get_archive`,
`Client.put_archive`).
* Added support for `ps_args` parameter in `Client.top`.
### Bugfixes
* Fixed a bug where specifying volume binds with unicode characters would
fail.
* Fixed a bug where providing an explicit protocol in `Client.port` would fail
to yield the expected result.
* Fixed a bug where the priority protocol returned by `Client.port` would be UDP
instead of the expected TCP.
### Miscellaneous
* Broke up Client code into several files to facilitate maintenance and
contribution.
* Added contributing guidelines to the repository.
1.4.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.4.0+is%3Aclosed)
### Deprecation warning
* `docker.utils.create_host_config` is deprecated in favor of
`Client.create_host_config`.
### Features
* Added `utils.parse_env_file` to support env-files.
See [docs](http://docker-py.readthedocs.org/en/latest/api/#create_container)
for usage.
* Added support for arbitrary log drivers
* Added support for URL paths in the docker host URL (`base_url`)
* Drastically improved support for .dockerignore syntax
### Bugfixes
* Fixed a bug where exec_inspect would allow invocation when the API version
was too low.
* Fixed a bug where `docker.utils.ports.split_port` would break if an open
range was provided.
* Fixed a bug where invalid image IDs / container IDs could be provided to
bypass or reroute request URLs
* Default `base_url` now adapts depending on the OS (better Windows support)
* Fixed a bug where using an integer as the user param in
`Client.create_container` would result in a failure.
### Miscellaneous
* Docs fixes
* Integration tests are now run as part of our continuous integration.
* Updated dependency on `six` library
1.3.1
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.3.1+is%3Aclosed)
### Bugfixes
* Fixed a bug where empty chunks in streams was misinterpreted as EOF.
* `datetime` arguments passed to `Client.events` parameters `since` and
`until` are now always considered to be UTC.
* Fixed a bug with Docker 1.7.x where the wrong auth headers were being passed
in `Client.build`, failing builds that depended on private images.
* `Client.exec_create` can now retrieve the `Id` key from a dictionary for its
container param.
### Miscellaneous
* 404 API status now raises `docker.errors.NotFound`. This exception inherits
`APIError` which was used previously.
* Docs fixes
* Test fixes
1.3.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.3.0+is%3Aclosed)
### Deprecation warning
* As announced in the 1.2.0 release, `Client.execute` has been removed in favor
of `Client.exec_create` and `Client.exec_start`.
### Features
* `extra_hosts` parameter in host config can now also be provided as a list.
* Added support for `memory_limit` and `memswap_limit` in host config to
comply with recent deprecations.
* Added support for `volume_driver` in `Client.create_container`
* Added support for advanced modes in volume binds (using the `mode` key)
* Added support for `decode` in `Client.build` (decodes JSON stream on the fly)
* docker-py will now look for login configuration under the new config path,
and fall back to the old `~/.dockercfg` path if not present.
### Bugfixes
* Configuration file lookup now also work on platforms that don't define a
`$HOME` environment variable.
* Fixed an issue where pinging a v2 private registry wasn't working properly,
preventing users from pushing and pulling.
* `pull` parameter in `Client.build` now defaults to `False`. Fixes a bug where
the default options would try to force a pull of non-remote images.
* Fixed a bug where getting logs from tty-enabled containers wasn't working
properly with more recent versions of Docker
* `Client.push` and `Client.pull` will now raise exceptions if the HTTP
status indicates an error.
* Fixed a bug with adapter lookup when using the Unix socket adapter
(this affected some weird edge cases, see issue #647 for details)
* Fixed a bug where providing `timeout=None` to `Client.stop` would result
in an exception despite the usecase being valid.
* Added `git@` to the list of valid prefixes for remote build paths.
### Dependencies
* The websocket-client dependency has been updated to a more recent version.
This new version also supports Python 3.x, making `attach_socket` available
on those versions as well.
### Documentation
* Various fixes
1.2.3
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.2.3+is%3Aclosed)
### Deprecation warning
* Passing host config in the `Client.start` method is now deprecated. Please
use the `host_config` in `Client.create_container` instead.
### Features
* Added support for `privileged` param in `Client.exec_create`
(only available in API >= 1.19)
* Volume binds can now also be specified as a list of strings.
### Bugfixes
* Fixed a bug where the `read_only` param in host_config wasn't handled
properly.
* Fixed a bug in `Client.execute` (this method is still deprecated).
* The `cpuset` param in `Client.create_container` is also passed as
the `CpusetCpus` param (`Cpuset` deprecated in recent versions of the API)
* Fixed an issue with integration tests being run inside a container
(`make integration-test`)
* Fixed a bug where an empty string would be considered a valid container ID
or image ID.
* Fixed a bug in `Client.insert`
### Documentation
* Various fixes
1.2.2
-----
### Bugfixes
* Fixed a bug where parameters passed to `Client.exec_resize` would be ignored (#576)
* Fixed a bug where auth config wouldn't be resolved properly in `Client.pull` (#577)
1.2.1
-----
### Bugfixes
* Fixed a bug where the check_resource decorator would break with some
argument-passing methods. (#573)
1.2.0
-----
[List of PRs / issues for this release](https://github.com/docker/docker-py/issues?q=milestone%3A1.2.0+is%3Aclosed)
### Deprecation warning
* `Client.execute` is being deprecated in favor of the more dev-friendly
`Client.exec_start` and `Client.exec_create`. **It will be removed in 1.3.0**
### Features
* Added `exec_create`, `exec_start`, `exec_inspect` and `exec_resize` to
client, accurately mirroring the
[Exec API](https://docs.docker.com/reference/api/docker_remote_api_v1.18/#exec-create)
* Added `auth_config` param to `Client.pull` (allows to use one-off credentials
for this pull request)
* Added support for `ipc_mode` in host config.
* Added support for the `log_config` param in host config.
* Added support for the `ulimit` param in host config.
* Added support for container resource limits in `Client.build`.
* When a resource identifier (image or container ID) is passed to a Client
method, we now check for `None` values to avoid crashing
(now raises `docker.errors.NullResource`)
* Added tools to parse port ranges inside the new `docker.utils.ports` package.
* Added a `version_info` attribute to the `docker` package.
### Bugfixes
* Fixed a bug in `Client.port` where absence of a certain key in the
container's JSON would raise an error (now just returns `None`)
* Fixed a bug with the `trunc` parameter in `Client.containers` having no
effect (moved functionality to the client)
* Several improvements have been made to the `Client.import_image` method.
* Fixed pushing / pulling to
[v2 registries](https://github.com/docker/distribution)
* Fixed a bug where passing a container dictionary to `Client.commit`
would fail
### Miscellaneous
* Default API version has been bumped to 1.18 (Docker Engine 1.6.0)
* Several testing coverage improvements
* Docs fixes and improvements
1.1.0
-----
### Features
* Added `dockerfile` param support to `Client.build` (mirrors
`docker build -f` behavior)
* Added the ability to specify `'auto'` as `version` in `Client.__init__`,
allowing the constructor to autodetect the daemon's API version.
### Bugfixes
* Fixed a bug where decoding a result stream using the `decode` parameter
would break when using Python 3.x
* Fixed a bug where some files in `.dockerignore` weren't being handled
properly
* Fixed `resolve_authconfig` issues by bringing it closer to Docker Engine's
behavior. This should fix all issues encountered with private registry auth
* Fixed an issue where passwords containing a colon weren't being handled
properly.
* Bumped `requests` version requirement, which should fix most of the SSL
issues encountered recently.
### Miscellaneous
* Several integration test improvements.
* Fixed some unclosed resources in unit tests.
* Several docs improvements.
1.0.0
-----
### Features
* Added new `Client.rename` method (`docker rename`)
* Added now `Client.stats` method (`docker stats`)
* Added `read_only` param support to `utils.create_host_config` and
`Client.start` (`docker run --read-only`)
* Added `pid_mode` param support to `utils.create_host_config` and
`Client.start` (`docker run --pid='host'`)
* Added `since`, `until` and `filters` params to `Client.events`.
* Added `decode` parameter to `Client.stats` and `Client.events` to decode
JSON objects on the fly (False by default).
### Bugfixes
* Fixed a bug that caused `Client.build` to crash when the provided source was
a remote source.
### Miscellaneous
* Default API version has been bumped to 1.17 (Docker Engine 1.5.0)
* `Client.timeout` is now a public attribute, and users are encouraged to use it
when request timeouts need to be changed at runtime.
* Added `Client.api_version` as a read-only property.
* The `memswap_limit` argument in `Client.create_container` now accepts string
type values similar to `mem_limit` ('6g', '120000k', etc.)
* Improved documentation
0.7.2
-----
### Features
* Added support for `mac_address` in `Client.create_container`
### Bugfixes
* Fixed a bug where streaming responses (`pull`, `push`, `logs`, etc.) were
unreliable (#300)
* Fixed a bug where resolve_authconfig wouldn't properly resolve configuration
for private repositories (#468)
* Fixed a bug where some errors wouldn't be properly constructed in
`client.py`, leading to unhelpful exceptions bubbling up (#466)
* Fixed a bug where `Client.build` would try to close context when externally
provided (`custom_context == True`) (#458)
* Fixed an issue in `create_host_config` where empty sequences wouldn't be
interpreted properly (#462)
### Miscellaneous
* Added `resolve_authconfig` tests.
0.7.1
-----
### Bugfixes
* `setup.py` now indicates a maximum version of requests to work around the
boot2docker / `assert_hostname` bug.
* Removed invalid exception when using the Registry Hub's FQDN when pulling.
* Fixed an issue where early HTTP errors weren't handled properly in streaming
responses.
* Fixed a bug where sockets would close unexpectedly using Python 3.x
* Various fixes for integration tests.
### Miscellaneous
* Small doc fixes
0.7.0
-----
### Breaking changes
* Passing `dns` or `volumes_from` in `Client.start` with API version < 1.10
will now raise an exception (previously only triggered a warning)
### Features
* Added support for `host_config` in `Client.create_container`
* Added utility method `docker.utils.create_host_config` to help build a
proper `HostConfig` dictionary.
* Added support for the `pull` parameter in `Client.build`
* Added support for the `forcerm` parameter in `Client.build`
* Added support for `extra_hosts` in `Client.start`
* Added support for a custom `timeout` in `Client.wait`
* Added support for custom `.dockercfg` loading in `Client.login`
(`dockercfg_path` argument)
### Bugfixes
* Fixed a bug where some output wouldn't be streamed properly in streaming
chunked responses
* Fixed a bug where the `devices` param didn't recognize the proper delimiter
* `Client.login` now properly expands the `registry` URL if provided.
* Fixed a bug where unicode characters in passed for `environment` in
`create_container` would break.
### Miscellaneous
* Several unit tests and integration tests improvements.
* `Client` constructor now enforces passing the `version` parameter as a
string.
* Build context files are now ordered by filename when creating the archive
(for consistency with docker mainline behavior)
0.6.0
-----
* **This version introduces breaking changes!**
### Breaking changes
* The default SSL protocol is now the highest TLS v1.x (was SSL v2.3 before)
(Poodle fix)
* The `history` command now returns a dict instead of a raw JSON string.
### Features
* Added the `execute` command.
* Added `pause` and `unpause` commands.
* Added support fo the `cpuset` param in `create_container`
* Added support for host devices (`devices` param in `start`)
* Added support for the `tail` param in `logs`.
* Added support for the `filters` param in `images` and `containers`
* The `kwargs_from_env` method is now available in the `docker.utils`
module. This should make it easier for boot2docker user to connect
to their daemon.
### Bugfixes
* Fixed a bug where empty directories weren't correctly included when
providing a context to `Client.build`.
* Fixed a bug where UNIX socket connections weren't properly cleaned up,
causing `ResourceWarning`s to appear in some cases.
* Fixed a bug where docker-py would crash if the docker daemon was stopped
while reading a streaming response
* Fixed a bug with streaming responses in Python 3
* `remove_image` now supports a dict containing an `Id` key as its `id`
parameter (similar to other methods requiring a resource ID)
### Documentation
* Added new MkDocs documentation. Currently hosted on
[ReadTheDocs](http://docker-py.readthedocs.org/en/latest/)
### Miscellaneous
* Added tests to sdist
* Added a Makefile for running tests in Docker
* Updated Dockerfile
0.5.3
-----
* Fixed attaching when connecting to the daemon over a UNIX socket.
0.5.2
-----
* Fixed a bug where sockets were closed immediately when attaching over
TLS.
0.5.1
-----
* Added a `assert_hostname` option to `TLSConfig` which can be used to
disable verification of hostnames.
* Fixed SSL not working due to an incorrect version comparison
* Fixed streams not working on Windows
0.5.0
-----
* **This version introduces breaking changes!**
* Added `insecure_registry` parameter in `Client.push` and `Client.pull`.
*It defaults to False and code pushing to non-HTTPS private registries
might break as a result.*
* Added support for adding and dropping capabilities
* Added support for restart policy
* Added support for string values in `Client.create_container`'s `mem_limit`
* Added support for `.dockerignore` file in `Client.build`
### Bugfixes
* Fixed timeout behavior in `Client.stop`
### Miscellaneous
* `Client.create_container` provides better validation of the `volumes`
parameter
* Improved integration tests
0.4.0
-----
* **This version introduces breaking changes!**
* The `base_url` parameter in the `Client` constructor should now allow most
of the `DOCKER_HOST` environment values (except for the fd:// protocol)
* As a result, URLs that don't specify a port are now invalid (similar
to the official client's behavior)
* Added TLS support (see [documentation](https://github.com/dotcloud/docker-py#connection-to-daemon-using-https))
### Bugfixes
* Fixed an issue with `Client.build` streamed logs in Python 3
### Miscellaneous
* Added unit tests coverage
* Various integration tests fixes
0.3.2
-----
* Default API version is now 1.12 (support for docker 1.0)
* Added new methods `Client.get_image` and `Client.load_image`
(`docker save` and `docker load`)
* Added new method `Client.ping`
* Added new method `Client.resize`
* `Client.build` can now be provided with a custom context using the
`custom_context` parameter.
* Added support for `memswap_limit` parameter in `create_container`
* Added support for `force` parameter in `remove_container`
* Added support for `force` and `noprune` parameters in `remove_image`
* Added support for `timestamps` parameter in `logs`
* Added support for `dns_search` parameter in `start`
* Added support for `network_mode` parameter in `start`
* Added support for `size` parameter in `containers`
* Added support for `volumes_from` and `dns` parameters in `start`. As of
API version >= 1.10, these parameters no longer belong to `create_container`
* `Client.logs` now uses the logs endpoint when API version is sufficient
### Bugfixes
* Fixed a bug in pull where the `repo:tag` notation wasn't interpreted
properly
* Fixed a bug in streaming methods with python 3 (unicode, bytes/str related)
* Fixed a bug in `Client.start` where legacy notation for volumes wasn't
supported anymore.
### Miscellaneous
* The client now raises `DockerException`s when appropriate. You can import
`DockerException` (and its subclasses) from the `docker.errors` module to
catch them if needed.
* `docker.APIError` has been moved to the new `docker.errors` module as well.
* `Client.insert` is deprecated in API version > 1.11
* Improved integration tests should now run much faster.
* There is now a single source of truth for the docker-py version number.
0.3.1
-----
* Default API version is now 1.9
* Streaming responses no longer yield blank lines.
* `Client.create_container` now supports the `domainname` parameter.
* `volumes_from` parameter in `Client.create_container` now supports
iterables.
* Auth credentials are provided to the docker daemon when using `Client.build`
(new feature in API version 1.9)
### Bugfixes
* Various fixes for response streams (`logs`, `pull`, etc.).
* Fixed a bug with `Client.push` when using API version < 1.5
* Fixed a bug with API version checks.
### Miscellaneous
* `mock` has been removed from the runtime requirements.
* Added installation instructions in the README.
0.3.0
-----
* **This version introduces breaking changes!**
* Support for API version 1.7 through 1.9 (Docker 0.8.0+)
* Default API version is now 1.8
* The client has been updated to support Requests 2.x. `requests==2.2.1`
is now the recommended version.
* Links can now be specified as tuples in `Client.start` (see docs for
more information)
* Added support for various options in `Client.create_container`
(`network_disabled`, `cpu_shares`, `working_dir` and `entrypoint`)
* `Client.attach` has been reworked to work similarly to `Client.logs`
minus the historical data.
* Logs can now be streamed using the `stream` parameter.
* Added support for `tcp://` URLs as client `base_url`.
* Various auth improvements.
* Added support for custom `Client.build` timeout.
### Bugfixes
* Fixed a bug where determining the protocol of a private registry
would sometimes yield the wrong result.
* Fixed a bug where `Client.copy` wouldn't accept a dict as argument.
* Fixed several streaming bugs.
* Removed unused parameter in `Client.import_image`.
* The client's `base_url` now tolerates trailing slashes.
#### Miscellaneous
* Updated integration tests
* Small doc fixes
0.2.3
-----
* Support for API version 1.6
* Added support for links
* Added support for global request timeout
* Added `signal` parameter in `Client.kill`
* Added support for `publish_all_ports` in `Client.start`
* `Client.pull`, `Client.push` and `Client.build` can be streamed now
* Added support for websockets in `Client.attach`
* Fixed ports for Docker 0.6.5+
* Added `Client.events` method (access to the `/events` endpoint)
* Changed the way the ports and volumes are provided in `Client.start` and
`Client.create_container̀` to make them simpler and more intuitive.
### Bugfixes
* Fixed a bug where private registries on HTTPS weren't handled properly
* Fixed a bug where auth would break with Python 3
### Miscellaneous
* Test improvements
* Slight doc improvements
0.2.2
-----
* Added support for the `rm` parameter in `Client.build`
* Added support for tarball imports in `Client.import_image` through `data`
parameter.
* The `command` parameter in `Client.create_container` is now optional (for
containers that include a default run command)
### Bugfixes
* Fixed Python 3 support
* Fixed a bug where anonymous push/pull would break when no authconfig is
present
* Fixed a bug where the `quiet` parameter wouldn't be taken into account in
`Client.containers`
* Fixed a bug where `Client.push` would break when pushing to private
registries.
* Removed unused `registry` parameter in `Client.pull`.
* Removed obsolete custom error message in `Client.create_container`.
### Miscellaneous
* docker-py is now unit-tested, and Travis-CI has been enabled on the
source repository.
0.2.1
-----
* Improvements to the `tox.ini` file
### Bugfixes
* Fixed a bug where the package would fail with an `ImportError` if requests
was installed using `apt-get`
* Fixed a bug where `Client.build` would fail if given a `path` parameter.
* Fixed several bugs in `Client.login`. It should now work with API versions
1.4, 1.5.
* Please note that `Client.login` currently doesn't write auth to the
`.dockercfg` file, thus **auth is not persistent when using this method.**
0.2.0
-----
* **This version introduces breaking changes!**
* `Client.kill`, `Client.remove_container`, `Client.remove_image`,
`Client.restart`, `Client.start`, `Client.stop` and `Client.wait` don't support
varargs anymore.
* Added commands `Client.top` and `Client.copy`
* Added `lxc_conf` parameter to `Client.start`
* Added support for authentication in `Client.pull` (API version >=1.5)
* Added support for privileged containers.
* Error management overhaul. The new version should be more consistent and
* All methods that expected a container ID as argument now also support a dict
containing an `Id` key.
* Added license header to python files.
* Several `README.md` updates.
### Bugfixes
* Fixed several bugs with auth config parsing.
* Fixed a bug in `Client.push` where it would raise an exception if
the auth config wasn't loaded.
* Fixed a bug in `Client.pull` where private registry images wouldn't be parsed
properly if it contained port information.
0.1.5
-----
* `Client.build` now uses tempfiles to store build context instead of storing
it in memory
* Added `nocache` option to `Client.build`
* `Client.remove_container` now raises an exception when trying to remove a
running container
* `Client.create_container` now accepts dicts for the `environment` parameter
### Bugfixes
* Fixed a bug in `Client.create_container` on Python 2.6 where unicode
commands would fail to be parsed
* Fixed a bug in `Client.build` where the `tag` parameter would not be taken
into account
0.1.4
-----
* Added support for API connection through UNIX socket (default for docker 0.5.2+)
0.1.3
-----
* The client now tries to load the auth config from `~/.dockercfg`. This is necessary to use the push command if API version is >1.0
0.1.2
-----
* Added a `quiet parameter` to `Client.build` (mirrors the `q` parameter in the API)
0.1.1
-----
* Fixed a bug where the build command would list tar contents before sending the request
* Fixed a bug in `Client.port`
0.1.0
-----
* **This version introduces breaking changes!**
* Switched to server side build system
* Removed the BuilderClient
* Added support for contextual builds
* Added support for remote URL builds
* Added python 3 support
* Added bind mounts support
* Added API version support
* Fixed a bug where `Client.port` would fail if provided with a port of type number
* Fixed a bug where `Client._post_json` wouldn't set the Content-Type header to `application/json`
0.0.6
-----
* Added support for custom loggers in `Client.build`
* Added `Client.attach` command
* Added support for `ADD` command in builder
* Fixed a bug in `Client.logs`
* Improved unit tests
0.0.5
-----
* Added tag support for the builder
* Use `shlex` to parse plain string commands when creating a container
* Fixed several bugs in the builder
* Fixed the `quiet` option in `Client.images`
* Unit tests
0.0.4
-----
* Improved error reporting
0.0.3
-----
* Fixed a bug in `Client.tag`
* Fixed a bug where generated images would be removed after a successful build
0.0.2
-----
* Implemented first version of the builder client

35
docs/client.rst Normal file
View File

@ -0,0 +1,35 @@
Client
======
.. py:module:: docker.client
Creating a client
-----------------
To communicate with the Docker daemon, you first need to instantiate a client. The easiest way to do that is by calling the function :py:func:`~docker.client.from_env`. It can also be configured manually by instantiating a :py:class:`~docker.client.DockerClient` class.
.. autofunction:: from_env()
Client reference
----------------
.. autoclass:: DockerClient()
.. autoattribute:: configs
.. autoattribute:: containers
.. autoattribute:: images
.. autoattribute:: networks
.. autoattribute:: nodes
.. autoattribute:: plugins
.. autoattribute:: secrets
.. autoattribute:: services
.. autoattribute:: swarm
.. autoattribute:: volumes
.. automethod:: close()
.. automethod:: df()
.. automethod:: events()
.. automethod:: info()
.. automethod:: login()
.. automethod:: ping()
.. automethod:: version()

361
docs/conf.py Normal file
View File

@ -0,0 +1,361 @@
#
# docker-sdk-python documentation build configuration file, created by
# sphinx-quickstart on Wed Sep 14 15:48:58 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import datetime
import os
import sys
from importlib.metadata import version
sys.path.insert(0, os.path.abspath('..'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'myst_parser'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
source_suffix = {
'.rst': 'restructuredtext',
'.txt': 'markdown',
'.md': 'markdown',
}
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Docker SDK for Python'
year = datetime.datetime.now().year
copyright = f'{year} Docker Inc'
author = 'Docker Inc'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# see https://github.com/pypa/setuptools_scm#usage-from-sphinx
release = version('docker')
# for example take major/minor
version = '.'.join(release.split('.')[:2])
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#
# today = ''
#
# Else, today_fmt is used as the format for a strftime call.
#
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
'description': 'A Python library for the Docker Engine API',
'fixed_sidebar': True,
}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'docker-sdk-python v2.0'
# A shorter title for the navigation bar. Default is the same as html_title.
#
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
html_sidebars = {
'**': [
'about.html',
'navigation.html',
'searchbox.html',
]
}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#
# html_additional_pages = {}
# If false, no module index is generated.
#
# html_domain_indices = True
# If false, no index is generated.
#
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'docker-sdk-pythondoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'docker-sdk-python.tex', 'docker-sdk-python Documentation',
'Docker Inc.', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#
# latex_use_parts = False
# If true, show page references after internal links.
#
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#
# latex_appendices = []
# It false, will not define \strong, \code, itleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated.
#
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'docker-sdk-python', 'docker-sdk-python Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'docker-sdk-python', 'docker-sdk-python Documentation',
author, 'docker-sdk-python', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#
# texinfo_appendices = []
# If false, no module index is generated.
#
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#
# texinfo_no_detailmenu = False
# Napoleon settings
napoleon_google_docstring = True
napoleon_numpy_docstring = False

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