mirror of
				https://github.com/docker/compose.git
				synced 2025-10-30 18:53:51 +01:00 
			
		
		
		
	Merge branch 'TheClimateCorporation-forward-exit'
This commit is contained in:
		
						commit
						31b2d9176b
					
				| @ -858,8 +858,11 @@ class TopLevelCommand(object): | |||||||
|                                        running. (default: 10) |                                        running. (default: 10) | ||||||
|             --remove-orphans           Remove containers for services not |             --remove-orphans           Remove containers for services not | ||||||
|                                        defined in the Compose file |                                        defined in the Compose file | ||||||
|  |             --exit-code-from SERVICE   Return the exit code of the selected service container. | ||||||
|  |                                        Requires --abort-on-container-exit. | ||||||
|         """ |         """ | ||||||
|         start_deps = not options['--no-deps'] |         start_deps = not options['--no-deps'] | ||||||
|  |         exit_value_from = exitval_from_opts(options, self.project) | ||||||
|         cascade_stop = options['--abort-on-container-exit'] |         cascade_stop = options['--abort-on-container-exit'] | ||||||
|         service_names = options['SERVICE'] |         service_names = options['SERVICE'] | ||||||
|         timeout = timeout_from_opts(options) |         timeout = timeout_from_opts(options) | ||||||
| @ -882,9 +885,11 @@ class TopLevelCommand(object): | |||||||
|             if detached: |             if detached: | ||||||
|                 return |                 return | ||||||
| 
 | 
 | ||||||
|  |             attached_containers = filter_containers_to_service_names(to_attach, service_names) | ||||||
|  | 
 | ||||||
|             log_printer = log_printer_from_project( |             log_printer = log_printer_from_project( | ||||||
|                 self.project, |                 self.project, | ||||||
|                 filter_containers_to_service_names(to_attach, service_names), |                 attached_containers, | ||||||
|                 options['--no-color'], |                 options['--no-color'], | ||||||
|                 {'follow': True}, |                 {'follow': True}, | ||||||
|                 cascade_stop, |                 cascade_stop, | ||||||
| @ -894,12 +899,34 @@ class TopLevelCommand(object): | |||||||
| 
 | 
 | ||||||
|             if cascade_stop: |             if cascade_stop: | ||||||
|                 print("Aborting on container exit...") |                 print("Aborting on container exit...") | ||||||
|  | 
 | ||||||
|                 exit_code = 0 |                 exit_code = 0 | ||||||
|  |                 if exit_value_from: | ||||||
|  |                     candidates = filter( | ||||||
|  |                         lambda c: c.service == exit_value_from, | ||||||
|  |                         attached_containers) | ||||||
|  |                     if not candidates: | ||||||
|  |                         log.error( | ||||||
|  |                             'No containers matching the spec "{0}" ' | ||||||
|  |                             'were run.'.format(exit_value_from) | ||||||
|  |                         ) | ||||||
|  |                         exit_code = 2 | ||||||
|  |                     elif len(candidates) > 1: | ||||||
|  |                         exit_values = filter( | ||||||
|  |                             lambda e: e != 0, | ||||||
|  |                             [c.inspect()['State']['ExitCode'] for c in candidates] | ||||||
|  |                         ) | ||||||
|  | 
 | ||||||
|  |                         exit_code = exit_values[0] | ||||||
|  |                     else: | ||||||
|  |                         exit_code = candidates[0].inspect()['State']['ExitCode'] | ||||||
|  |                 else: | ||||||
|                     for e in self.project.containers(service_names=options['SERVICE'], stopped=True): |                     for e in self.project.containers(service_names=options['SERVICE'], stopped=True): | ||||||
|                         if (not e.is_running and cascade_starter == e.name): |                         if (not e.is_running and cascade_starter == e.name): | ||||||
|                             if not e.exit_code == 0: |                             if not e.exit_code == 0: | ||||||
|                                 exit_code = e.exit_code |                                 exit_code = e.exit_code | ||||||
|                                 break |                                 break | ||||||
|  | 
 | ||||||
|                 self.project.stop(service_names=service_names, timeout=timeout) |                 self.project.stop(service_names=service_names, timeout=timeout) | ||||||
|                 sys.exit(exit_code) |                 sys.exit(exit_code) | ||||||
| 
 | 
 | ||||||
| @ -939,6 +966,19 @@ def timeout_from_opts(options): | |||||||
|     return None if timeout is None else int(timeout) |     return None if timeout is None else int(timeout) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def exitval_from_opts(options, project): | ||||||
|  |     exit_value_from = options.get('--exit-code-from') | ||||||
|  |     if exit_value_from: | ||||||
|  |         if not options.get('--abort-on-container-exit'): | ||||||
|  |             log.warn('using --exit-code-from implies --abort-on-container-exit') | ||||||
|  |             options['--abort-on-container-exit'] = True | ||||||
|  |         if exit_value_from not in [s.name for s in project.get_services()]: | ||||||
|  |             log.error('No service named "%s" was found in your compose file.', | ||||||
|  |                       exit_value_from) | ||||||
|  |             sys.exit(2) | ||||||
|  |     return exit_value_from | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def image_type_from_opt(flag, value): | def image_type_from_opt(flag, value): | ||||||
|     if not value: |     if not value: | ||||||
|         return ImageType.none |         return ImageType.none | ||||||
|  | |||||||
| @ -467,7 +467,7 @@ _docker_compose_up() { | |||||||
| 
 | 
 | ||||||
| 	case "$cur" in | 	case "$cur" in | ||||||
| 		-*) | 		-*) | ||||||
| 			COMPREPLY=( $( compgen -W "--abort-on-container-exit --build -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t --remove-orphans" -- "$cur" ) ) | 			COMPREPLY=( $( compgen -W "--exit-code-from --abort-on-container-exit --build -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t --remove-orphans" -- "$cur" ) ) | ||||||
| 			;; | 			;; | ||||||
| 		*) | 		*) | ||||||
| 			__docker_compose_services_all | 			__docker_compose_services_all | ||||||
|  | |||||||
| @ -1976,3 +1976,13 @@ class CLITestCase(DockerClientTestCase): | |||||||
|         self.dispatch(['up', '-d']) |         self.dispatch(['up', '-d']) | ||||||
|         result = self.dispatch(['top']) |         result = self.dispatch(['top']) | ||||||
|         assert result.stdout.count("top") == 4 |         assert result.stdout.count("top") == 4 | ||||||
|  | 
 | ||||||
|  |     def test_forward_exitval(self): | ||||||
|  |         self.base_dir = 'tests/fixtures/exit-code-from' | ||||||
|  |         proc = start_process( | ||||||
|  |             self.base_dir, | ||||||
|  |             ['up', '--abort-on-container-exit', '--exit-code-from', 'another']) | ||||||
|  | 
 | ||||||
|  |         result = wait_on_process(proc, returncode=1) | ||||||
|  | 
 | ||||||
|  |         assert 'exitcodefrom_another_1 exited with code 1' in result.stdout | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								tests/fixtures/exit-code-from/docker-compose.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/fixtures/exit-code-from/docker-compose.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | simple: | ||||||
|  |   image: busybox:latest | ||||||
|  |   command: sh -c "echo hello && tail -f /dev/null" | ||||||
|  | another: | ||||||
|  |   image: busybox:latest | ||||||
|  |   command: /bin/false | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user