Skip to content

Commit b1f7d18

Browse files
committed
[gantry] Do not change replicas after updating.
1 parent 2c13597 commit b1f7d18

8 files changed

Lines changed: 202 additions & 27 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ You can configure the most behaviors of *Gantry* via environment variables.
9292
| GANTRY_ROLLBACK_OPTIONS | | [Options](https://docs.docker.com/engine/reference/commandline/service_update/#options) added to the `docker service update --rollback` command for all services. You can apply a different value to a particular service via [labels](#labels). |
9393
| GANTRY_UPDATE_JOBS | false | Set to `true` to update `replicated-job` or `global-job`. Set to `false` to disable updating jobs. *Gantry* adds additional options to `docker service update` when there is [no running tasks](docs/faq.md#how-to-update-services-with-no-running-tasks). You can apply a different value to a particular service via [labels](#labels). |
9494
| GANTRY_UPDATE_NUM_WORKERS | 1 | The maximum number of updates that can run in parallel. |
95-
| GANTRY_UPDATE_OPTIONS | | [Options](https://docs.docker.com/engine/reference/commandline/service_update/#options) added to the `docker service update` command for all services. You can apply a different value to a particular service via [labels](#labels). |
95+
| GANTRY_UPDATE_OPTIONS | | [Options](https://docs.docker.com/engine/reference/commandline/service_update/#options) added to the `docker service update` command for all services. This also overrides any automatically added options. You can apply a different value to a particular service via [labels](#labels). |
9696
| GANTRY_UPDATE_TIMEOUT_SECONDS | 0 | Error out if updating of a single service takes longer than the given time. Set to `0` to disable timeout. You can apply a different value to a particular service via [labels](#labels). |
9797

9898
### After updating

docs/faq.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ You can start *Gantry* as a docker swarm service and use [`swarm-cronjob`](https
2626

2727
## How to update services with no running tasks?
2828

29-
As discussed in [docker/cli/issues/627](https://github.com/docker/cli/issues/627), the CLI will hang when running `docker service update` on a service with no running tasks. We must add `--detach=true` option to the `docker service update`.
29+
As discussed in [docker/cli/issues/627](https://github.com/docker/cli/issues/627), the Docker CLI hangs when `docker service update` is running on a service with no running tasks, requiring the option `--detach=true` to be added.
3030

31-
*Gantry* will check whether there are running tasks in a service. If there is no running task, *Gantry* automatically adds the option `--detach=true`. In addition to the detach option, *Gantry* also adds `--replicas=0` for services in replicated mode. You don't need to add these options manually.
31+
*Gantry* checks whether a service has running tasks. When none are found, it automatically adds the option `--detach=true`.
32+
33+
If you want to keep replicas at zero post-update, which prevents tasks from starting, you should add the [label](../README.md#labels) `gantry.update.options=--replicas=0` to the service. See the [example](../examples/cronjob).
3234

3335
## Which `GANTRY_MANIFEST_CMD` to use?
3436

examples/cronjob/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ Use [*swarm-cronjob*](https://github.com/crazy-max/swarm-cronjob) to launch [*Ga
55
In this example, we only want to run *Gantry* at the specific time, therefore we set `replicas` to `0` on the *Gantry* service to avoid running it as soon as the service is deployed. We also need to set `restart_policy.condition` to `none` to prevent *Gantry* from restarting automatically after a cronjob.
66

77
Refer to the [*swarm-cronjob* document](https://crazymax.dev/swarm-cronjob/) for more information.
8+
9+
*service_to_be_updated* is another service managed by the *swarm-cronjob* and updated by *Gantry*. The label `gantry.update.options=--replicas=0` is set on the service so that only *swarm-cronjob* starts it. Updating the image does not start the service.

examples/cronjob/docker-compose.yml

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ services:
1616
restart_policy:
1717
condition: none
1818
labels:
19-
- swarm.cronjob.enable=true
20-
- swarm.cronjob.schedule=45 23 0 * * *
21-
- swarm.cronjob.skip-running=true
19+
- "swarm.cronjob.enable=true"
20+
- "swarm.cronjob.schedule=45 23 0 * * *"
21+
- "swarm.cronjob.skip-running=true"
2222

2323
cronjob:
2424
image: crazymax/swarm-cronjob:latest
@@ -28,3 +28,25 @@ services:
2828
placement:
2929
constraints:
3030
- node.role==manager
31+
32+
# Another service to be updated.
33+
service_to_be_updated:
34+
image: docker
35+
command: ["docker", "system", "prune", "-f"]
36+
volumes:
37+
- "/var/run/docker.sock:/var/run/docker.sock"
38+
deploy:
39+
replicas: 0
40+
placement:
41+
constraints:
42+
- node.role==manager
43+
restart_policy:
44+
condition: none
45+
labels:
46+
- "swarm.cronjob.enable=true"
47+
- "swarm.cronjob.schedule=0 */5 * * * *"
48+
- "swarm.cronjob.skip-running=false"
49+
# Add "gantry.update.options=--replicas=0" to prevent tasks from starting after the update.
50+
# Only start the tasks via cronjob.
51+
# "--replicas=0" only works in replicated mode, you cannot add it to services in global mode.
52+
- "gantry.update.options=--replicas=0"

src/lib-gantry.sh

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,22 +1013,20 @@ _get_service_update_additional_options() {
10131013
local SERVICE_NAME="${1}"
10141014
local IMAGE_UPDATE_TO="${2}"
10151015
local AUTH_CONFIG="${3}"
1016-
local NUM_RUNS=
1017-
NUM_RUNS=$(_get_number_of_running_tasks "${SERVICE_NAME}")
1018-
! is_number "${NUM_RUNS}" && log WARN "NUM_RUNS \"${NUM_RUNS}\" is not a number." && return 1
1016+
local RETURN_VALUE=0
10191017
local OPTIONS=
10201018
local SPACE=
1021-
if [ "${NUM_RUNS}" = "0" ]; then
1022-
# Add "--detach=true" when there is no running tasks.
1023-
# https://github.com/docker/cli/issues/627
1024-
OPTIONS="${OPTIONS}${SPACE}--detach=true"
1025-
SPACE=" "
1026-
local MODE=
1027-
# Do not start a new task. Only works for replicated, not global.
1028-
if MODE=$(_service_is_replicated "${SERVICE_NAME}"); then
1029-
OPTIONS="${OPTIONS}${SPACE}--replicas=0"
1019+
local NUM_RUNS=
1020+
NUM_RUNS=$(_get_number_of_running_tasks "${SERVICE_NAME}")
1021+
if is_number "${NUM_RUNS}"; then
1022+
if [ "${NUM_RUNS}" = "0" ]; then
1023+
# Add "--detach=true" when there is no running tasks.
1024+
# https://github.com/docker/cli/issues/627
1025+
OPTIONS="${OPTIONS}${SPACE}--detach=true"
10301026
SPACE=" "
10311027
fi
1028+
else
1029+
log WARN "NUM_RUNS \"${NUM_RUNS}\" is not a number." && RETURN_VALUE=1
10321030
fi
10331031
# Add `--with-registry-auth` if needed.
10341032
local WITH_REGISTRY_AUTH=
@@ -1048,6 +1046,31 @@ _get_service_update_additional_options() {
10481046
SPACE=" "
10491047
fi
10501048
echo "${OPTIONS}"
1049+
return "${RETURN_VALUE}"
1050+
}
1051+
1052+
_warning_no_running_task() {
1053+
local SERVICE_NAME="${1}"
1054+
local OPTIONS="${2}"
1055+
local NUM_RUNS=
1056+
NUM_RUNS=$(_get_number_of_running_tasks "${SERVICE_NAME}")
1057+
! is_number "${NUM_RUNS}" && log WARN "NUM_RUNS \"${NUM_RUNS}\" is not a number." && return 1
1058+
if [ "${NUM_RUNS}" != "0" ]; then
1059+
return 0
1060+
fi
1061+
# Warning for replicated, not global, as "--replicas" only works on replicated, not global.
1062+
local MODE=
1063+
if MODE=$(! _service_is_replicated "${SERVICE_NAME}"); then
1064+
return 0
1065+
fi
1066+
# Now, the number of running task is 0, the mode is replicated.
1067+
# If "--replicas=" is already part of the option, no warning.
1068+
if [ -n "${OPTIONS}" ] && echo "${OPTIONS}" | grep_q "--replicas="; then
1069+
return 0
1070+
fi
1071+
local MSG="Service ${SERVICE_NAME} is in ${MODE} mode and has no running task before updating."
1072+
MSG="${MSG} Adding label \"gantry.update.options=--replicas=0\" to the service to prevent tasks from starting after the update."
1073+
log WARN "${MSG}"
10511074
}
10521075

10531076
_get_service_rollback_additional_options() {
@@ -1132,6 +1155,7 @@ _update_single_service() {
11321155
[ -n "${AUTH_CONFIG}" ] && log INFO "Adding options \"${AUTH_CONFIG}\" to the command ${CMD_STRING} for ${SERVICE_NAME}."
11331156
[ -n "${AUTOMATIC_OPTIONS}" ] && log INFO "Adding options \"${AUTOMATIC_OPTIONS}\" automatically to the command ${CMD_STRING} for ${SERVICE_NAME}."
11341157
[ -n "${UPDATE_OPTIONS}" ] && log INFO "Adding options \"${UPDATE_OPTIONS}\" specified by user to the command ${CMD_STRING} for ${SERVICE_NAME}."
1158+
_warning_no_running_task "${SERVICE_NAME}" "${AUTOMATIC_OPTIONS} ${UPDATE_OPTIONS}"
11351159
local TIMEOUT_COMMAND=
11361160
TIMEOUT_COMMAND=$(_get_timeout_command "${SERVICE_NAME}") || return 1
11371161
local SPACE_T=

tests/gantry_login_spec.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ Describe 'login'
7979
The stderr should satisfy spec_expect_message "${NUM_SERVICES_UPDATING}"
8080
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--config ${AUTH_CONFIG}.*${SERVICE_NAME}"
8181
# 2 "--with-registry-auth" for SERVICE_NAME. One is automatically added. The other is from user.
82-
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS_WITH_REGISTRY_AUTH}.*automatically.*${SERVICE_NAME}"
83-
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS_WITH_REGISTRY_AUTH}.*specified by user.*${SERVICE_NAME}"
82+
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS_WITH_REGISTRY_AUTH}.*${AUTOMATICALLY}.*${SERVICE_NAME}"
83+
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS_WITH_REGISTRY_AUTH}.*${SPECIFIED_BY_USER}.*${SERVICE_NAME}"
8484
The stderr should satisfy spec_expect_no_message "${FROM_DOCKER_IMAGE_DIGEST_WARNING}.*${SERVICE_NAME}"
8585
The stderr should satisfy spec_expect_no_message "${DOES_NOT_HAVE_A_DIGEST}"
8686
The stderr should satisfy spec_expect_message "${UPDATED}.*${SERVICE_NAME}"

tests/gantry_service_no_running_tasks_spec.sh

Lines changed: 129 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@
1515
# along with this program. If not, see <https://www.gnu.org/licenses/>.
1616
#
1717

18+
docker_service_replicas() {
19+
local SERVICE_NAME="${1}"
20+
local REPLICAS=
21+
if ! REPLICAS=$(run_cmd docker service ls --filter "name=${SERVICE_NAME}" --format '{{.Replicas}} {{.Name}}'); then
22+
echo "docker service ls failed. ${REPLICAS}"
23+
return 1
24+
fi
25+
# For `docker service ls --filter`, the name filter matches on all or the prefix of a service's name
26+
# See https://docs.docker.com/engine/reference/commandline/service_ls/#name
27+
# It does not do the exact match of the name. See https://github.com/moby/moby/issues/32985
28+
# We do an extra step to to perform the exact match.
29+
echo "${REPLICAS}" | sed -n -E "s/(.*) ${SERVICE_NAME}$/\1/p"
30+
}
31+
1832
Describe "service-no-running-tasks"
1933
SUITE_NAME="service-no-running-tasks"
2034
BeforeAll "initialize_all_tests ${SUITE_NAME}"
@@ -46,8 +60,17 @@ Describe "service-no-running-tasks"
4660
test_no_running_tasks_replicated() {
4761
local TEST_NAME="${1}"
4862
local SERVICE_NAME="${2}"
63+
local REPLICAS_BEFORE=
64+
REPLICAS_BEFORE=$(docker_service_replicas "${SERVICE_NAME}")
65+
echo "Before updating: REPLICAS_BEFORE=${REPLICAS_BEFORE}"
4966
reset_gantry_env "${SUITE_NAME}" "${SERVICE_NAME}"
67+
local RETURN_VALUE=
5068
run_gantry "${SUITE_NAME}" "${TEST_NAME}"
69+
RETURN_VALUE="${?}"
70+
local REPLICAS_AFTER=
71+
REPLICAS_AFTER=$(docker_service_replicas "${SERVICE_NAME}")
72+
echo "After updating: REPLICAS_AFTER=${REPLICAS_AFTER}"
73+
return "${RETURN_VALUE}"
5174
}
5275
test_end() {
5376
local TEST_NAME="${1}"
@@ -65,15 +88,113 @@ Describe "service-no-running-tasks"
6588
When run test_no_running_tasks_replicated "${TEST_NAME}" "${SERVICE_NAME}"
6689
The status should be success
6790
The stdout should satisfy display_output
68-
The stdout should satisfy spec_expect_no_message ".+"
91+
The stdout should satisfy spec_expect_message "Before updating: REPLICAS_BEFORE=0/0"
92+
The stdout should satisfy spec_expect_message "After updating: REPLICAS_AFTER=0/0"
93+
The stderr should satisfy display_output
94+
The stderr should satisfy spec_expect_no_message "${START_WITHOUT_A_SQUARE_BRACKET}"
95+
# Add "--detach=true" when there is no running tasks.
96+
# https://github.com/docker/cli/issues/627
97+
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--detach=true.*${AUTOMATICALLY}.*${SERVICE_NAME}\."
98+
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--replicas=.*${SERVICE_NAME}\."
99+
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--detach.*${SERVICE_NAME_SUFFIX}"
100+
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--replicas.*${SERVICE_NAME_SUFFIX}"
101+
The stderr should satisfy spec_expect_message "${SERVICE_NAME}.*${REPLICATED_MODE_NO_RUNNING_TASK}"
102+
The stderr should satisfy spec_expect_no_message "${SKIP_UPDATING}.*${SERVICE_NAME}"
103+
The stderr should satisfy spec_expect_message "${PERFORM_UPDATING}.*${SERVICE_NAME}.*${PERFORM_REASON_HAS_NEWER_IMAGE}"
104+
The stderr should satisfy spec_expect_no_message "${SKIP_UPDATING}.*${SERVICE_NAME_SUFFIX}"
105+
The stderr should satisfy spec_expect_message "${PERFORM_UPDATING}.*${SERVICE_NAME_SUFFIX}.*${PERFORM_REASON_KNOWN_NEWER_IMAGE}"
106+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_SKIP_JOBS}"
107+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_INSPECT_FAILURE}"
108+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_NO_NEW_IMAGES}"
109+
The stderr should satisfy spec_expect_message "${NUM_SERVICES_UPDATING}"
110+
The stderr should satisfy spec_expect_message "${UPDATED}.*${SERVICE_NAME}"
111+
The stderr should satisfy spec_expect_no_message "${NO_UPDATES}.*${SERVICE_NAME}"
112+
The stderr should satisfy spec_expect_no_message "${ROLLING_BACK}.*${SERVICE_NAME}"
113+
The stderr should satisfy spec_expect_no_message "${FAILED_TO_ROLLBACK}.*${SERVICE_NAME}"
114+
The stderr should satisfy spec_expect_no_message "${ROLLED_BACK}.*${SERVICE_NAME}"
115+
The stderr should satisfy spec_expect_no_message "${NO_SERVICES_UPDATED}"
116+
The stderr should satisfy spec_expect_message "2 ${SERVICES_UPDATED}"
117+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_UPDATE_FAILED}"
118+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_INSPECT_FAILED}"
119+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_ROLLBACK_FAILED}"
120+
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_ERRORS}"
121+
The stderr should satisfy spec_expect_no_message "${NO_IMAGES_TO_REMOVE}"
122+
The stderr should satisfy spec_expect_message "${REMOVING_NUM_IMAGES}"
123+
The stderr should satisfy spec_expect_no_message "${SKIP_REMOVING_IMAGES}"
124+
The stderr should satisfy spec_expect_message "${REMOVED_IMAGE}.*${IMAGE_WITH_TAG}"
125+
The stderr should satisfy spec_expect_no_message "${FAILED_TO_REMOVE_IMAGE}.*${IMAGE_WITH_TAG}"
126+
The stderr should satisfy spec_expect_message "${DONE_REMOVING_IMAGES}"
127+
End
128+
End
129+
Describe "test_no_running_tasks_replicated_user_replicas"
130+
# For `docker service ls --filter`, the name filter matches on all or the prefix of a service's name
131+
# See https://docs.docker.com/engine/reference/commandline/service_ls/#name
132+
# It does not do the exact match of the name. See https://github.com/moby/moby/issues/32985
133+
# This test also checks whether we do an extra step to to perform the exact match.
134+
TEST_NAME="test_no_running_tasks_replicated_user_replicas"
135+
IMAGE_WITH_TAG=$(get_image_with_tag "${SUITE_NAME}")
136+
SERVICE_NAME=$(get_test_service_name "${TEST_NAME}")
137+
SERVICE_NAME_SUFFIX="${SERVICE_NAME}-suffix"
138+
test_start() {
139+
local TEST_NAME="${1}"
140+
local IMAGE_WITH_TAG="${2}"
141+
local SERVICE_NAME="${3}"
142+
local SERVICE_NAME_SUFFIX="${SERVICE_NAME}-suffix"
143+
initialize_test "${TEST_NAME}"
144+
build_and_push_test_image "${IMAGE_WITH_TAG}"
145+
start_replicated_service "${SERVICE_NAME}" "${IMAGE_WITH_TAG}"
146+
start_replicated_service "${SERVICE_NAME_SUFFIX}" "${IMAGE_WITH_TAG}"
147+
build_and_push_test_image "${IMAGE_WITH_TAG}"
148+
# Set running tasks to 0 for SERVICE_NAME.
149+
# But keep tasks running for SERVICE_NAME_SUFFIX.
150+
docker_service_update --replicas=0 "${SERVICE_NAME}"
151+
wait_zero_running_tasks "${SERVICE_NAME}"
152+
}
153+
test_no_running_tasks_replicated_user_replicas() {
154+
local TEST_NAME="${1}"
155+
local SERVICE_NAME="${2}"
156+
local REPLICAS_BEFORE=
157+
REPLICAS_BEFORE=$(docker_service_replicas "${SERVICE_NAME}")
158+
echo "Before updating: REPLICAS_BEFORE=${REPLICAS_BEFORE}"
159+
reset_gantry_env "${SUITE_NAME}" "${SERVICE_NAME}"
160+
# Test that user could override the replicas.
161+
local LABEL_AND_VALUE="gantry.update.options=--replicas=1"
162+
docker_service_update --label-add "${LABEL_AND_VALUE}" "${SERVICE_NAME}"
163+
local RETURN_VALUE=
164+
run_gantry "${SUITE_NAME}" "${TEST_NAME}"
165+
RETURN_VALUE="${?}"
166+
local REPLICAS_AFTER=
167+
REPLICAS_AFTER=$(docker_service_replicas "${SERVICE_NAME}")
168+
echo "After updating: REPLICAS_AFTER=${REPLICAS_AFTER}"
169+
return "${RETURN_VALUE}"
170+
}
171+
test_end() {
172+
local TEST_NAME="${1}"
173+
local IMAGE_WITH_TAG="${2}"
174+
local SERVICE_NAME="${3}"
175+
local SERVICE_NAME_SUFFIX="${SERVICE_NAME}-suffix"
176+
stop_service "${SERVICE_NAME}"
177+
stop_service "${SERVICE_NAME_SUFFIX}"
178+
prune_local_test_image "${IMAGE_WITH_TAG}"
179+
finalize_test "${TEST_NAME}"
180+
}
181+
BeforeEach "test_start ${TEST_NAME} ${IMAGE_WITH_TAG} ${SERVICE_NAME}"
182+
AfterEach "test_end ${TEST_NAME} ${IMAGE_WITH_TAG} ${SERVICE_NAME}"
183+
It 'run_test'
184+
When run test_no_running_tasks_replicated_user_replicas "${TEST_NAME}" "${SERVICE_NAME}"
185+
The status should be success
186+
The stdout should satisfy display_output
187+
The stdout should satisfy spec_expect_message "Before updating: REPLICAS_BEFORE=0/0"
188+
The stdout should satisfy spec_expect_message "After updating: REPLICAS_AFTER=1/1"
69189
The stderr should satisfy display_output
70190
The stderr should satisfy spec_expect_no_message "${START_WITHOUT_A_SQUARE_BRACKET}"
71191
# Add "--detach=true" when there is no running tasks.
72192
# https://github.com/docker/cli/issues/627
73-
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--detach=true.*${SERVICE_NAME}\."
74-
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--replicas=0.*${SERVICE_NAME}\."
75-
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--detach=true.*${SERVICE_NAME_SUFFIX}"
76-
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--replicas=0.*${SERVICE_NAME_SUFFIX}"
193+
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--detach=true.*${AUTOMATICALLY}.*${SERVICE_NAME}\."
194+
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--replicas=1.*${SPECIFIED_BY_USER}.*${SERVICE_NAME}\."
195+
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--detach.*${SERVICE_NAME_SUFFIX}"
196+
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--replicas.*${SERVICE_NAME_SUFFIX}"
197+
The stderr should satisfy spec_expect_no_message "${SERVICE_NAME}.*${REPLICATED_MODE_NO_RUNNING_TASK}"
77198
The stderr should satisfy spec_expect_no_message "${SKIP_UPDATING}.*${SERVICE_NAME}"
78199
The stderr should satisfy spec_expect_message "${PERFORM_UPDATING}.*${SERVICE_NAME}.*${PERFORM_REASON_HAS_NEWER_IMAGE}"
79200
The stderr should satisfy spec_expect_no_message "${SKIP_UPDATING}.*${SERVICE_NAME_SUFFIX}"
@@ -136,9 +257,10 @@ Describe "service-no-running-tasks"
136257
The stderr should satisfy spec_expect_no_message "${START_WITHOUT_A_SQUARE_BRACKET}"
137258
# Add "--detach=true" when there is no running tasks.
138259
# https://github.com/docker/cli/issues/627
139-
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--detach=true.*${SERVICE_NAME}"
260+
The stderr should satisfy spec_expect_message "${ADDING_OPTIONS}.*--detach=true.*${AUTOMATICALLY}.*${SERVICE_NAME}"
140261
# Cannot add "--replicas" to global mode
141-
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--replicas=0"
262+
The stderr should satisfy spec_expect_no_message "${ADDING_OPTIONS}.*--replicas"
263+
The stderr should satisfy spec_expect_no_message "${SERVICE_NAME}.*${REPLICATED_MODE_NO_RUNNING_TASK}"
142264
The stderr should satisfy spec_expect_no_message "${SKIP_UPDATING}.*${SERVICE_NAME}"
143265
The stderr should satisfy spec_expect_message "${PERFORM_UPDATING}.*${SERVICE_NAME}.*${PERFORM_REASON_HAS_NEWER_IMAGE}"
144266
The stderr should satisfy spec_expect_no_message "${NUM_SERVICES_SKIP_JOBS}"

0 commit comments

Comments
 (0)