| 
									
										
										
										
											2016-02-03 23:01:32 +08:00
										 |  |  | ## The contents of this file are subject to the Mozilla Public License | 
					
						
							|  |  |  | ## Version 1.1 (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.mozilla.org/MPL/ | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Software distributed under the License is distributed on an "AS IS" | 
					
						
							|  |  |  | ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | 
					
						
							|  |  |  | ## the License for the specific language governing rights and | 
					
						
							|  |  |  | ## limitations under the License. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## The Original Code is RabbitMQ. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## The Initial Developer of the Original Code is GoPivotal, Inc. | 
					
						
							| 
									
										
										
										
											2017-01-10 22:42:40 +08:00
										 |  |  | ## Copyright (c) 2007-2017 Pivotal Software, Inc.  All rights reserved. | 
					
						
							| 
									
										
										
										
											2016-02-03 23:01:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 22:42:45 +08:00
										 |  |  | defmodule RabbitMQCtl do | 
					
						
							| 
									
										
										
										
											2016-11-15 01:52:08 +08:00
										 |  |  |   alias RabbitMQ.CLI.Core.Distribution,  as: Distribution | 
					
						
							| 
									
										
										
										
											2016-06-09 08:34:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-10 07:54:22 +08:00
										 |  |  |   alias RabbitMQ.CLI.Ctl.Commands.HelpCommand, as: HelpCommand | 
					
						
							| 
									
										
										
										
											2016-11-15 01:52:08 +08:00
										 |  |  |   alias RabbitMQ.CLI.Core.Output, as: Output | 
					
						
							|  |  |  |   alias RabbitMQ.CLI.Core.ExitCodes, as: ExitCodes | 
					
						
							| 
									
										
										
										
											2016-06-10 07:54:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 01:52:08 +08:00
										 |  |  |   import RabbitMQ.CLI.Core.Helpers | 
					
						
							| 
									
										
										
										
											2016-11-22 19:07:58 +08:00
										 |  |  |   import  RabbitMQ.CLI.Core.Parser | 
					
						
							| 
									
										
										
										
											2016-08-22 19:58:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 22:49:56 +08:00
										 |  |  |   @type options() :: Map.t | 
					
						
							|  |  |  |   @type command_result() :: {:error, ExitCodes.exit_code, term()} | term() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 22:40:31 +08:00
										 |  |  |   def main(["--auto-complete" | []]) do | 
					
						
							|  |  |  |     handle_shutdown(:ok) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   def main(["--auto-complete", script_name | args]) do | 
					
						
							|  |  |  |     script_basename = Path.basename(script_name) | 
					
						
							|  |  |  |     auto_complete(script_basename, args) | 
					
						
							| 
									
										
										
										
											2016-07-29 00:46:37 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-05-09 18:07:46 +08:00
										 |  |  |   def main(unparsed_command) do | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |     unparsed_command | 
					
						
							|  |  |  |     |> exec_command(fn(command, output, options) -> | 
					
						
							|  |  |  |         formatter = get_formatter(command, options) | 
					
						
							|  |  |  |         printer = get_printer(options) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         output | 
					
						
							|  |  |  |         |> Output.format_output(formatter, options) | 
					
						
							|  |  |  |         |> Output.print_output(printer, options) | 
					
						
							|  |  |  |       end) | 
					
						
							|  |  |  |     |> handle_shutdown | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def exec_command(unparsed_command, output_fun) do | 
					
						
							| 
									
										
										
										
											2016-11-23 01:40:45 +08:00
										 |  |  |     {command, command_name, arguments, parsed_options, invalid} = parse(unparsed_command) | 
					
						
							|  |  |  |     case {command, invalid} do | 
					
						
							|  |  |  |       {:no_command, _} -> | 
					
						
							| 
									
										
										
										
											2017-01-25 23:24:47 +08:00
										 |  |  |         command_not_found_string = case command_name do | 
					
						
							|  |  |  |           "" -> "" | 
					
						
							|  |  |  |           _  -> "\nCommand '#{command_name}' not found. \n" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         usage_string = command_not_found_string <> | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |                        HelpCommand.all_usage(parsed_options) | 
					
						
							| 
									
										
										
										
											2016-11-22 19:07:58 +08:00
										 |  |  |         {:error, ExitCodes.exit_usage, usage_string}; | 
					
						
							| 
									
										
										
										
											2016-12-06 02:59:58 +08:00
										 |  |  |       {{:suggest, suggested}, _} -> | 
					
						
							| 
									
										
										
										
											2016-12-06 20:19:25 +08:00
										 |  |  |         suggest_message = "\nCommand '#{command_name}' not found. \n"<> | 
					
						
							|  |  |  |                           "Did you mean '#{suggested}'? \n" | 
					
						
							| 
									
										
										
										
											2016-12-06 02:59:58 +08:00
										 |  |  |         {:error, ExitCodes.exit_usage, suggest_message}; | 
					
						
							| 
									
										
										
										
											2016-11-23 01:40:45 +08:00
										 |  |  |       {_, [_|_]} -> | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         validation_error({:bad_option, invalid}, command, | 
					
						
							|  |  |  |                          unparsed_command, parsed_options); | 
					
						
							| 
									
										
										
										
											2016-11-23 01:40:45 +08:00
										 |  |  |       _ -> | 
					
						
							|  |  |  |         options = parsed_options |> merge_all_defaults |> normalize_options | 
					
						
							| 
									
										
										
										
											2016-12-06 00:23:20 +08:00
										 |  |  |         with_distribution(options, fn() -> | 
					
						
							| 
									
										
										
										
											2016-12-05 22:49:56 +08:00
										 |  |  |           case execute_command(options, command, arguments) do | 
					
						
							|  |  |  |             {:error, _, _} = err -> | 
					
						
							|  |  |  |               err; | 
					
						
							|  |  |  |             {:validation_failure, err} -> | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |               validation_error(err, command, unparsed_command, options); | 
					
						
							| 
									
										
										
										
											2016-12-05 22:49:56 +08:00
										 |  |  |             output  -> | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |               output_fun.(command, output, options) | 
					
						
							| 
									
										
										
										
											2016-12-05 22:49:56 +08:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2016-12-06 00:23:20 +08:00
										 |  |  |         end) | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-06-08 22:19:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |   def handle_shutdown({:error, exit_code, output}) do | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |     output_device = case exit_code == ExitCodes.exit_ok do | 
					
						
							| 
									
										
										
										
											2016-11-04 19:12:14 +08:00
										 |  |  |       true  -> :stdio; | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |       false -> :stderr | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     for line <- List.flatten([output]) do | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |       IO.puts(output_device, line) | 
					
						
							| 
									
										
										
										
											2016-03-05 05:35:54 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     exit_program(exit_code) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   def handle_shutdown(_) do | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |     exit_program(ExitCodes.exit_ok) | 
					
						
							| 
									
										
										
										
											2016-02-03 05:32:35 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 22:40:31 +08:00
										 |  |  |   def auto_complete(script_name, args) do | 
					
						
							|  |  |  |     Rabbitmq.CLI.AutoComplete.complete(script_name, args) | 
					
						
							| 
									
										
										
										
											2016-07-29 00:46:37 +08:00
										 |  |  |     |> Stream.map(&IO.puts/1) |> Stream.run | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |     exit_program(ExitCodes.exit_ok) | 
					
						
							| 
									
										
										
										
											2016-07-29 00:46:37 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-09 02:43:09 +08:00
										 |  |  |   def merge_all_defaults(%{} = options) do | 
					
						
							| 
									
										
										
										
											2016-03-08 03:08:38 +08:00
										 |  |  |     options | 
					
						
							| 
									
										
										
										
											2016-05-24 19:33:11 +08:00
										 |  |  |     |> merge_defaults_node | 
					
						
							|  |  |  |     |> merge_defaults_timeout | 
					
						
							| 
									
										
										
										
											2016-06-08 22:19:37 +08:00
										 |  |  |     |> merge_defaults_longnames | 
					
						
							| 
									
										
										
										
											2016-03-08 03:08:38 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 17:59:00 +08:00
										 |  |  |   defp merge_defaults_node(%{} = opts), do: Map.merge(%{node: get_rabbit_hostname()}, opts) | 
					
						
							| 
									
										
										
										
											2016-03-08 06:45:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-24 19:33:11 +08:00
										 |  |  |   defp merge_defaults_timeout(%{} = opts), do: Map.merge(%{timeout: :infinity}, opts) | 
					
						
							| 
									
										
										
										
											2016-03-08 06:45:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 22:19:37 +08:00
										 |  |  |   defp merge_defaults_longnames(%{} = opts), do: Map.merge(%{longnames: false}, opts) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 01:40:43 +08:00
										 |  |  |   defp normalize_options(opts) do | 
					
						
							|  |  |  |     opts | 
					
						
							|  |  |  |     |> normalize_node | 
					
						
							|  |  |  |     |> normalize_timeout | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-10 05:55:59 +08:00
										 |  |  |   defp normalize_node(%{node: node} = opts) do | 
					
						
							|  |  |  |     Map.merge(opts, %{node: parse_node(node)}) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 01:40:43 +08:00
										 |  |  |   defp normalize_timeout(%{timeout: timeout} = opts) | 
					
						
							|  |  |  |   when is_integer(timeout) do | 
					
						
							|  |  |  |     Map.put(opts, :timeout, timeout * 1000) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   defp normalize_timeout(opts) do | 
					
						
							|  |  |  |     opts | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |   defp maybe_connect_to_rabbitmq(HelpCommand, _), do: nil | 
					
						
							| 
									
										
										
										
											2016-05-31 16:40:48 +08:00
										 |  |  |   defp maybe_connect_to_rabbitmq(_, node) do | 
					
						
							| 
									
										
										
										
											2016-06-09 08:34:56 +08:00
										 |  |  |     connect_to_rabbitmq(node) | 
					
						
							| 
									
										
										
										
											2016-05-31 16:40:48 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 19:07:58 +08:00
										 |  |  |   defp execute_command(options, command, arguments) do | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |     {arguments, options} = command.merge_defaults(arguments, options) | 
					
						
							|  |  |  |     case command.validate(arguments, options) do | 
					
						
							|  |  |  |       :ok -> | 
					
						
							| 
									
										
										
										
											2016-10-26 23:25:39 +08:00
										 |  |  |         maybe_print_banner(command, arguments, options) | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |         maybe_connect_to_rabbitmq(command, options[:node]) | 
					
						
							| 
									
										
										
										
											2016-11-18 22:12:53 +08:00
										 |  |  |         maybe_run_command(command, arguments, options) | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |       {:validation_failure, _} = err -> err | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-02-03 02:54:36 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-02-26 05:16:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-18 22:12:53 +08:00
										 |  |  |   defp maybe_run_command(_, _, %{dry_run: true}) do | 
					
						
							|  |  |  |     :ok | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   defp maybe_run_command(command, arguments, options) do | 
					
						
							|  |  |  |     try do | 
					
						
							|  |  |  |       command.run(arguments, options) |> command.output(options) | 
					
						
							|  |  |  |     catch _error_type, error -> | 
					
						
							|  |  |  |       {:error, ExitCodes.exit_software, | 
					
						
							|  |  |  |        to_string(:io_lib.format("Error: ~n~p~n Stacktrace ~p~n", | 
					
						
							|  |  |  |                                 [error, System.stacktrace()]))} | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |   defp get_formatter(command, %{formatter: formatter}) do | 
					
						
							| 
									
										
										
										
											2016-11-16 00:14:22 +08:00
										 |  |  |     module_name = Module.safe_concat("RabbitMQ.CLI.Formatters", Macro.camelize(formatter)) | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     case Code.ensure_loaded(module_name) do | 
					
						
							|  |  |  |       {:module, _}      -> module_name; | 
					
						
							|  |  |  |       {:error, :nofile} -> default_formatter(command) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |   defp get_formatter(command, _) do | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     default_formatter(command) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def get_printer(%{printer: printer}) do | 
					
						
							| 
									
										
										
										
											2016-11-16 00:14:22 +08:00
										 |  |  |     module_name = String.to_atom("RabbitMQ.CLI.Printers." <> Macro.camelize(printer)) | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     case Code.ensure_loaded(module_name) do | 
					
						
							|  |  |  |       {:module, _}      -> module_name; | 
					
						
							| 
									
										
										
										
											2017-01-24 17:59:00 +08:00
										 |  |  |       {:error, :nofile} -> default_printer() | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   def get_printer(_) do | 
					
						
							| 
									
										
										
										
											2017-01-24 17:59:00 +08:00
										 |  |  |     default_printer() | 
					
						
							| 
									
										
										
										
											2016-11-04 02:10:18 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def default_printer() do | 
					
						
							|  |  |  |     RabbitMQ.CLI.Printers.StdIO | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def default_formatter(command) do | 
					
						
							|  |  |  |     case function_exported?(command, :formatter, 0) do | 
					
						
							|  |  |  |       true  -> command.formatter; | 
					
						
							|  |  |  |       false -> RabbitMQ.CLI.Formatters.Inspect | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-05-05 06:31:11 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-04-27 02:38:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 23:25:39 +08:00
										 |  |  |   ## Suppress banner if --quiet option is provided | 
					
						
							|  |  |  |   defp maybe_print_banner(_, _, %{quiet: true}) do | 
					
						
							|  |  |  |     nil | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   defp maybe_print_banner(command, args, opts) do | 
					
						
							| 
									
										
										
										
											2016-05-31 16:40:48 +08:00
										 |  |  |     case command.banner(args, opts) do | 
					
						
							| 
									
										
										
										
											2016-10-26 23:25:39 +08:00
										 |  |  |       nil -> nil | 
					
						
							|  |  |  |       banner -> | 
					
						
							|  |  |  |         case banner do | 
					
						
							|  |  |  |           list when is_list(list) -> | 
					
						
							|  |  |  |             for line <- list, do: IO.puts(line); | 
					
						
							|  |  |  |           binary when is_binary(binary) -> | 
					
						
							|  |  |  |             IO.puts(binary) | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-05-31 16:40:48 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2016-05-24 19:33:11 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |   defp validation_error(err_detail, command, unparsed_command, options) do | 
					
						
							|  |  |  |     err = format_validation_error(err_detail) # TODO format the error better | 
					
						
							| 
									
										
										
										
											2016-08-22 19:58:37 +08:00
										 |  |  |     base_error = "Error: #{err}\nGiven:\n\t#{unparsed_command |> Enum.join(" ")}" | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |     usage = HelpCommand.base_usage(command, options) | 
					
						
							| 
									
										
										
										
											2016-11-04 19:11:03 +08:00
										 |  |  |     message = base_error <> "\n" <> usage | 
					
						
							|  |  |  |     {:error, ExitCodes.exit_code_for({:validation_failure, err_detail}), message} | 
					
						
							| 
									
										
										
										
											2016-04-02 01:58:47 +08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |   defp format_validation_error(:not_enough_args), do: "not enough arguments." | 
					
						
							|  |  |  |   defp format_validation_error({:not_enough_args, detail}), do: "not enough arguments. #{detail}" | 
					
						
							|  |  |  |   defp format_validation_error(:too_many_args), do: "too many arguments." | 
					
						
							|  |  |  |   defp format_validation_error({:too_many_args, detail}), do: "too many arguments. #{detail}" | 
					
						
							|  |  |  |   defp format_validation_error(:bad_argument), do: "Bad argument." | 
					
						
							|  |  |  |   defp format_validation_error({:bad_argument, detail}), do: "Bad argument. #{detail}" | 
					
						
							|  |  |  |   defp format_validation_error({:bad_option, opts}) do | 
					
						
							|  |  |  |     header = "Invalid options for this command:" | 
					
						
							| 
									
										
										
										
											2016-08-19 00:38:49 +08:00
										 |  |  |     Enum.join([header | for {key, val} <- opts do "#{key} : #{val}" end], "\n") | 
					
						
							| 
									
										
										
										
											2016-08-18 21:56:21 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-12-23 20:12:33 +08:00
										 |  |  |   defp format_validation_error(err), do: inspect err | 
					
						
							| 
									
										
										
										
											2016-03-23 00:21:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   defp exit_program(code) do | 
					
						
							|  |  |  |     :net_kernel.stop | 
					
						
							| 
									
										
										
										
											2016-04-02 00:13:01 +08:00
										 |  |  |     exit({:shutdown, code}) | 
					
						
							| 
									
										
										
										
											2016-03-23 00:21:12 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-12-05 22:49:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @spec with_distribution(options(), (() -> command_result())) :: command_result() | 
					
						
							|  |  |  |   defp with_distribution(options, code) do | 
					
						
							|  |  |  |     # Tries to start net_kernel distribution, and calls `code` | 
					
						
							|  |  |  |     # function on success. Otherswise returns error suitable for | 
					
						
							|  |  |  |     # handle_shutdown/0. | 
					
						
							|  |  |  |     case Distribution.start(options) do | 
					
						
							| 
									
										
										
										
											2016-12-06 00:23:20 +08:00
										 |  |  |       :ok      -> | 
					
						
							|  |  |  |         code.() | 
					
						
							|  |  |  |       {:ok, _} -> | 
					
						
							| 
									
										
										
										
											2016-12-05 22:49:56 +08:00
										 |  |  |         code.() | 
					
						
							|  |  |  |       {:error, reason} -> | 
					
						
							|  |  |  |         {:error, ExitCodes.exit_config, "Distribution failed: #{inspect reason}"} | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-03 02:54:36 +08:00
										 |  |  | end |