pybuilder-docker-too 47__tar.gz → 48__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/PKG-INFO +1 -1
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too/__init__.py +161 -33
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/PKG-INFO +1 -1
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/setup.py +1 -1
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/SOURCES.txt +0 -0
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/dependency_links.txt +0 -0
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/namespace_packages.txt +0 -0
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/top_level.txt +0 -0
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/zip-safe +0 -0
- {pybuilder_docker_too-47 → pybuilder_docker_too-48}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pybuilder-docker-too
|
|
3
|
-
Version:
|
|
3
|
+
Version: 48
|
|
4
4
|
Summary: A pybuilder plugin that stages a python package into a docker container and optionally publishes it to a registry.
|
|
5
5
|
Home-page: https://github.com/rspitler/pybuilder-docker
|
|
6
6
|
Author:
|
|
@@ -41,10 +41,15 @@ RUN ${package_cmd}
|
|
|
41
41
|
""")
|
|
42
42
|
|
|
43
43
|
DEFAULT_DOCKER_COMPOSE_READY_TIMEOUT_SECONDS = 180
|
|
44
|
-
DEFAULT_DOCKER_COMPOSE_READY_POLL_INTERVAL_SECONDS =
|
|
44
|
+
DEFAULT_DOCKER_COMPOSE_READY_POLL_INTERVAL_SECONDS = 1
|
|
45
|
+
DEFAULT_DOCKER_COMPOSE_DOWN_TIMEOUT_SECONDS = 1
|
|
45
46
|
COMPOSE_DIAGNOSTIC_LOG_TAIL = 200
|
|
46
47
|
COMPOSE_DIAGNOSTIC_MAX_BYTES = 1024 * 1024
|
|
47
48
|
_DEFAULT_SERVICES = object()
|
|
49
|
+
_PRESTARTED_COMPOSE_SERVICES_PROPERTY = (
|
|
50
|
+
"_pybuilder_docker_prestarted_compose_services")
|
|
51
|
+
_INFERRED_PRETEST_SERVICES_PROPERTY = (
|
|
52
|
+
"_pybuilder_docker_inferred_pretest_services")
|
|
48
53
|
|
|
49
54
|
|
|
50
55
|
@init
|
|
@@ -56,6 +61,12 @@ def init_plugin(project: Project, logger: Logger, reactor: Reactor):
|
|
|
56
61
|
project.set_property_if_unset(
|
|
57
62
|
'docker_compose_ready_poll_interval',
|
|
58
63
|
DEFAULT_DOCKER_COMPOSE_READY_POLL_INTERVAL_SECONDS)
|
|
64
|
+
project.set_property_if_unset(
|
|
65
|
+
'docker_compose_down_timeout',
|
|
66
|
+
DEFAULT_DOCKER_COMPOSE_DOWN_TIMEOUT_SECONDS)
|
|
67
|
+
project.set_property_if_unset(
|
|
68
|
+
'docker_compose_prestart_during_package',
|
|
69
|
+
False)
|
|
59
70
|
|
|
60
71
|
|
|
61
72
|
@task(description="Package artifact into a docker container with the tag "
|
|
@@ -109,6 +120,7 @@ def do_docker_package(project, logger, reactor):
|
|
|
109
120
|
if ecr_login_before_build:
|
|
110
121
|
registry = project.get_mandatory_property("docker_push_registry")
|
|
111
122
|
_ecr_login(project, registry, logger, reactor)
|
|
123
|
+
_prestart_compose_services_during_package(project, logger)
|
|
112
124
|
dist_dir = prepare_dist_directory(project)
|
|
113
125
|
reactor.pybuilder_venv.verify_can_execute(["docker", "--version"], prerequisite="docker", caller="docker_package")
|
|
114
126
|
# is true if user set verbose in build.py or from command line
|
|
@@ -661,6 +673,62 @@ def _run_compose_command(
|
|
|
661
673
|
return output
|
|
662
674
|
|
|
663
675
|
|
|
676
|
+
def _prestart_compose_services_during_package(project, logger):
|
|
677
|
+
if not project.get_property(
|
|
678
|
+
"docker_compose_prestart_during_package", False):
|
|
679
|
+
return []
|
|
680
|
+
if not project.get_property("run_docker_compose_on_verify", False):
|
|
681
|
+
return []
|
|
682
|
+
if not (
|
|
683
|
+
project.get_property("run_pretest_executable", False)
|
|
684
|
+
and project.get_property("pretest_executable", None)):
|
|
685
|
+
return []
|
|
686
|
+
if _normalize_required_services(
|
|
687
|
+
project.get_property("docker_compose_pretest_services", None)):
|
|
688
|
+
logger.debug(
|
|
689
|
+
"Skipping early Compose prestart because pretest services "
|
|
690
|
+
"are explicitly configured")
|
|
691
|
+
return []
|
|
692
|
+
|
|
693
|
+
compose_file = _get_docker_compose_file(project)
|
|
694
|
+
if not compose_file:
|
|
695
|
+
logger.debug(
|
|
696
|
+
"Skipping early Compose prestart because the Compose file "
|
|
697
|
+
"is not prepared yet")
|
|
698
|
+
return []
|
|
699
|
+
|
|
700
|
+
timeout_seconds = _to_number(
|
|
701
|
+
project.get_property(
|
|
702
|
+
"docker_compose_ready_timeout",
|
|
703
|
+
DEFAULT_DOCKER_COMPOSE_READY_TIMEOUT_SECONDS),
|
|
704
|
+
DEFAULT_DOCKER_COMPOSE_READY_TIMEOUT_SECONDS)
|
|
705
|
+
if not math.isfinite(timeout_seconds) or timeout_seconds < 0:
|
|
706
|
+
raise ValueError(
|
|
707
|
+
"docker_compose_ready_timeout must be finite and >= 0")
|
|
708
|
+
deadline = time.monotonic() + timeout_seconds
|
|
709
|
+
compose_env = _compose_environment(project)
|
|
710
|
+
inferred_services = _list_compose_healthy_dependencies(
|
|
711
|
+
compose_file, compose_env, deadline)
|
|
712
|
+
if not inferred_services:
|
|
713
|
+
return []
|
|
714
|
+
|
|
715
|
+
logger.info(
|
|
716
|
+
"Starting Compose infrastructure during image packaging ({})".format(
|
|
717
|
+
", ".join(inferred_services)))
|
|
718
|
+
_run_compose_command(
|
|
719
|
+
compose_file,
|
|
720
|
+
["up", "--detach", "--no-deps"] + inferred_services,
|
|
721
|
+
compose_env,
|
|
722
|
+
_remaining_timeout(deadline, time.monotonic))
|
|
723
|
+
project.set_property(
|
|
724
|
+
_PRESTARTED_COMPOSE_SERVICES_PROPERTY,
|
|
725
|
+
list(inferred_services))
|
|
726
|
+
project.set_property(
|
|
727
|
+
_INFERRED_PRETEST_SERVICES_PROPERTY,
|
|
728
|
+
list(inferred_services))
|
|
729
|
+
return inferred_services
|
|
730
|
+
|
|
731
|
+
|
|
664
732
|
def _capture_compose_service_logs(
|
|
665
733
|
compose_file,
|
|
666
734
|
pending,
|
|
@@ -830,6 +898,8 @@ def _wait_for_compose_services(
|
|
|
830
898
|
last_services = []
|
|
831
899
|
last_inspect_error = None
|
|
832
900
|
last_service_logs = ""
|
|
901
|
+
logs_captured = False
|
|
902
|
+
last_log_capture_pending = None
|
|
833
903
|
while True:
|
|
834
904
|
if compose_process is not None:
|
|
835
905
|
exit_code = compose_process.poll()
|
|
@@ -860,24 +930,33 @@ def _wait_for_compose_services(
|
|
|
860
930
|
logger.info("Required compose services are ready")
|
|
861
931
|
return last_services
|
|
862
932
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
933
|
+
remaining_before_logs = deadline - time_fn()
|
|
934
|
+
pending_key = tuple(sorted(last_pending))
|
|
935
|
+
should_capture_logs = (
|
|
936
|
+
not logs_captured
|
|
937
|
+
or pending_key != last_log_capture_pending
|
|
938
|
+
or 0 < remaining_before_logs <= poll_interval)
|
|
939
|
+
if should_capture_logs:
|
|
940
|
+
try:
|
|
941
|
+
captured_service_logs = logs_fn(
|
|
942
|
+
compose_file,
|
|
943
|
+
last_pending,
|
|
944
|
+
compose_env,
|
|
945
|
+
deadline,
|
|
946
|
+
time_fn)
|
|
947
|
+
if (
|
|
948
|
+
captured_service_logs
|
|
949
|
+
and not captured_service_logs.startswith(
|
|
950
|
+
"<unable to collect service logs:")):
|
|
951
|
+
last_service_logs = captured_service_logs
|
|
952
|
+
elif not last_service_logs:
|
|
953
|
+
last_service_logs = captured_service_logs
|
|
954
|
+
except Exception as exc:
|
|
955
|
+
if not last_service_logs:
|
|
956
|
+
last_service_logs = (
|
|
957
|
+
"<unable to collect service logs: {}>".format(exc))
|
|
958
|
+
logs_captured = True
|
|
959
|
+
last_log_capture_pending = pending_key
|
|
881
960
|
|
|
882
961
|
remaining = deadline - time_fn()
|
|
883
962
|
if remaining <= 0:
|
|
@@ -951,10 +1030,12 @@ def _run_docker_compose(project, logger, reactor: Reactor):
|
|
|
951
1030
|
"up"]
|
|
952
1031
|
|
|
953
1032
|
expected_services = None
|
|
1033
|
+
application_services = None
|
|
954
1034
|
pretest_enabled = (
|
|
955
1035
|
project.get_property("run_pretest_executable", False)
|
|
956
1036
|
and project.get_property("pretest_executable", None))
|
|
957
1037
|
if pretest_enabled:
|
|
1038
|
+
pretest_services_started_at = time.monotonic()
|
|
958
1039
|
timeout_seconds = _to_number(
|
|
959
1040
|
project.get_property(
|
|
960
1041
|
"docker_compose_ready_timeout",
|
|
@@ -966,10 +1047,15 @@ def _run_docker_compose(project, logger, reactor: Reactor):
|
|
|
966
1047
|
setup_deadline = time.monotonic() + timeout_seconds
|
|
967
1048
|
expected_services = _list_compose_services(
|
|
968
1049
|
compose_file, compose_env, setup_deadline)
|
|
969
|
-
inferred_pretest_services =
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1050
|
+
inferred_pretest_services = _normalize_required_services(
|
|
1051
|
+
project.get_property(
|
|
1052
|
+
_INFERRED_PRETEST_SERVICES_PROPERTY, None))
|
|
1053
|
+
configured_pretest_services = _normalize_required_services(
|
|
1054
|
+
project.get_property(
|
|
1055
|
+
"docker_compose_pretest_services", None))
|
|
1056
|
+
if (
|
|
1057
|
+
not configured_pretest_services
|
|
1058
|
+
and not inferred_pretest_services):
|
|
973
1059
|
inferred_pretest_services = (
|
|
974
1060
|
_list_compose_healthy_dependencies(
|
|
975
1061
|
compose_file, compose_env, setup_deadline))
|
|
@@ -987,14 +1073,27 @@ def _run_docker_compose(project, logger, reactor: Reactor):
|
|
|
987
1073
|
project,
|
|
988
1074
|
created_services,
|
|
989
1075
|
inferred_services=inferred_pretest_services)
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1076
|
+
pretest_service_names = set(pretest_services)
|
|
1077
|
+
application_services = [
|
|
1078
|
+
service for service in expected_services
|
|
1079
|
+
if service not in pretest_service_names]
|
|
1080
|
+
prestarted_services = set(
|
|
1081
|
+
_normalize_required_services(
|
|
1082
|
+
project.get_property(
|
|
1083
|
+
_PRESTARTED_COMPOSE_SERVICES_PROPERTY, None))
|
|
1084
|
+
or [])
|
|
1085
|
+
services_to_start = [
|
|
1086
|
+
service for service in pretest_services
|
|
1087
|
+
if service not in prestarted_services]
|
|
1088
|
+
if services_to_start:
|
|
1089
|
+
start_output = _run_compose_command(
|
|
1090
|
+
compose_file,
|
|
1091
|
+
["up", "--detach", "--no-deps"] + services_to_start,
|
|
1092
|
+
compose_env,
|
|
1093
|
+
_remaining_timeout(setup_deadline, time.monotonic))
|
|
1094
|
+
if start_output:
|
|
1095
|
+
fp.write(start_output)
|
|
1096
|
+
fp.flush()
|
|
998
1097
|
_wait_for_compose_services(
|
|
999
1098
|
project,
|
|
1000
1099
|
logger,
|
|
@@ -1002,8 +1101,19 @@ def _run_docker_compose(project, logger, reactor: Reactor):
|
|
|
1002
1101
|
compose_env=compose_env,
|
|
1003
1102
|
required_services_override=pretest_services,
|
|
1004
1103
|
deadline_override=setup_deadline)
|
|
1104
|
+
logger.info(
|
|
1105
|
+
"Pretest compose services ready after {:.1f}s".format(
|
|
1106
|
+
time.monotonic() - pretest_services_started_at))
|
|
1107
|
+
pretest_started_at = time.monotonic()
|
|
1005
1108
|
_run_pretest_executable(project, logger, reactor)
|
|
1006
|
-
|
|
1109
|
+
logger.info(
|
|
1110
|
+
"Pretest executable completed after {:.1f}s".format(
|
|
1111
|
+
time.monotonic() - pretest_started_at))
|
|
1112
|
+
|
|
1113
|
+
if application_services:
|
|
1114
|
+
args += (
|
|
1115
|
+
["--no-deps", "--no-recreate"]
|
|
1116
|
+
+ application_services)
|
|
1007
1117
|
logger.debug(f"Running docker compose with {args}")
|
|
1008
1118
|
application_timeout = _to_number(
|
|
1009
1119
|
project.get_property(
|
|
@@ -1014,6 +1124,7 @@ def _run_docker_compose(project, logger, reactor: Reactor):
|
|
|
1014
1124
|
raise ValueError(
|
|
1015
1125
|
"docker_compose_ready_timeout must be finite and >= 0")
|
|
1016
1126
|
application_deadline = time.monotonic() + application_timeout
|
|
1127
|
+
application_started_at = time.monotonic()
|
|
1017
1128
|
compose_process = subprocess.Popen(
|
|
1018
1129
|
args, stderr=fp_err, stdout=fp, env=compose_env)
|
|
1019
1130
|
running_services = _wait_for_compose_services(
|
|
@@ -1024,10 +1135,17 @@ def _run_docker_compose(project, logger, reactor: Reactor):
|
|
|
1024
1135
|
compose_env=compose_env,
|
|
1025
1136
|
expected_services_override=expected_services,
|
|
1026
1137
|
deadline_override=application_deadline)
|
|
1138
|
+
logger.info(
|
|
1139
|
+
"Compose application services ready after {:.1f}s".format(
|
|
1140
|
+
time.monotonic() - application_started_at))
|
|
1141
|
+
target_started_at = time.monotonic()
|
|
1027
1142
|
_wait_for_target_url(
|
|
1028
1143
|
project,
|
|
1029
1144
|
logger,
|
|
1030
1145
|
compose_services=running_services)
|
|
1146
|
+
logger.info(
|
|
1147
|
+
"Integration target ready after {:.1f}s".format(
|
|
1148
|
+
time.monotonic() - target_started_at))
|
|
1031
1149
|
if not pretest_enabled:
|
|
1032
1150
|
_run_pretest_executable(project, logger, reactor)
|
|
1033
1151
|
|
|
@@ -1063,12 +1181,22 @@ def _docker_compose_down(project, logger, reactor: Reactor):
|
|
|
1063
1181
|
compose_file = _get_docker_compose_file(project)
|
|
1064
1182
|
if compose_file:
|
|
1065
1183
|
logger.info(f"Docker Compose Down: {compose_file}")
|
|
1184
|
+
timeout_seconds = _to_number(
|
|
1185
|
+
project.get_property(
|
|
1186
|
+
"docker_compose_down_timeout",
|
|
1187
|
+
DEFAULT_DOCKER_COMPOSE_DOWN_TIMEOUT_SECONDS),
|
|
1188
|
+
DEFAULT_DOCKER_COMPOSE_DOWN_TIMEOUT_SECONDS)
|
|
1189
|
+
if not math.isfinite(timeout_seconds) or timeout_seconds < 0:
|
|
1190
|
+
raise ValueError(
|
|
1191
|
+
"docker_compose_down_timeout must be finite and >= 0")
|
|
1066
1192
|
# clean up our test run
|
|
1067
1193
|
exec_command("docker", [
|
|
1068
1194
|
"compose",
|
|
1069
1195
|
"-f",
|
|
1070
1196
|
compose_file,
|
|
1071
|
-
"down"
|
|
1197
|
+
"down",
|
|
1198
|
+
"--timeout",
|
|
1199
|
+
str(int(math.ceil(timeout_seconds)))
|
|
1072
1200
|
], output_file_name="docker_compose_run", project=project, logger=logger,
|
|
1073
1201
|
reactor=reactor, env=_compose_environment(project))
|
|
1074
1202
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pybuilder-docker-too
|
|
3
|
-
Version:
|
|
3
|
+
Version: 48
|
|
4
4
|
Summary: A pybuilder plugin that stages a python package into a docker container and optionally publishes it to a registry.
|
|
5
5
|
Home-page: https://github.com/rspitler/pybuilder-docker
|
|
6
6
|
Author:
|
|
@@ -21,7 +21,7 @@ class install(_install):
|
|
|
21
21
|
if __name__ == '__main__':
|
|
22
22
|
setup(
|
|
23
23
|
name = 'pybuilder-docker-too',
|
|
24
|
-
version = '
|
|
24
|
+
version = '48',
|
|
25
25
|
description = 'A pybuilder plugin that stages a python package into a docker container and optionally publishes it to a registry.',
|
|
26
26
|
long_description = 'A pybuilder plugin that stages a python package into a docker container and optionally publishes it to a registry.',
|
|
27
27
|
long_description_content_type = None,
|
{pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pybuilder_docker_too-47 → pybuilder_docker_too-48}/pybuilder_docker_too.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|