diff --git a/Makefile b/Makefile index 559dee5f..bd7cca9a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ PROJECT = rabbitmq_cli +dep_observer_cli = git https://github.com/zhongwencool/observer_cli 1.4.4 + BUILD_DEPS = rabbit_common DEPS = observer_cli TEST_DEPS = amqp_client rabbit diff --git a/lib/rabbitmq/cli/diagnostics/commands/observer_command.ex b/lib/rabbitmq/cli/diagnostics/commands/observer_command.ex new file mode 100644 index 00000000..2b750a50 --- /dev/null +++ b/lib/rabbitmq/cli/diagnostics/commands/observer_command.ex @@ -0,0 +1,58 @@ +## 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 https://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. +## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved. + +defmodule RabbitMQ.CLI.Diagnostics.Commands.ObserverCommand do + @behaviour RabbitMQ.CLI.CommandBehaviour + use RabbitMQ.CLI.DefaultOutput + + def switches(), do: [interval: :integer] + def aliases(), do: [i: :interval] + + def merge_defaults(args, opts) do + {args, Map.merge(%{interval: 5}, opts)} + end + + + use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments + use RabbitMQ.CLI.Core.RequiresRabbitAppRunning + + def run([], %{node: node_name, interval: interval}) do + case :observer_cli.start(node_name, [{:interval, interval * 1000}]) do + # See zhongwencool/observer_cli#54 + {:badrpc, _} = err -> err + {:error, _} = err -> err + {:error, _, _} = err -> err + :ok -> {:ok, "Disconnected from #{node_name}."} + :quit -> {:ok, "Disconnected from #{node_name}."} + other -> other + end + end + + def help_section(), do: :observability_and_health_checks + + def description(), do: "Starts a CLI observer interface on the target node" + + def usage, do: "observer [--interval ]" + + def usage_additional() do + [ + ["--interval ", "Update interval to use, in seconds"] + ] + end + + def banner(_, %{node: node_name}) do + "Starting a CLI observer interface on node #{node_name}..." + end +end diff --git a/mix.exs b/mix.exs index 910a310b..a94ee4cc 100644 --- a/mix.exs +++ b/mix.exs @@ -89,10 +89,11 @@ defmodule RabbitMQCtl.MixfileBase do {:json, "~> 1.2.0"}, {:csv, "~> 2.0.0"}, {:stdout_formatter, "~> 0.2.3"}, + {:observer_cli, "~> 1.4.4"}, {:amqp, "~> 1.2.0", only: :test}, {:dialyxir, "~> 0.5", only: :test, runtime: false}, - {:temp, "~> 0.4", only: :test}, + {:temp, "~> 0.4", only: :test} ] rabbitmq_deps = case System.get_env("DEPS_DIR") do @@ -100,7 +101,7 @@ defmodule RabbitMQCtl.MixfileBase do # rabbitmq_cli is built as a standalone Elixir application. [ {:rabbit_common, "~> 3.7.0"}, - {:amqp_client, "~> 3.7.0", only: :test}, + {:amqp_client, "~> 3.7.0", only: :test} ] deps_dir -> # rabbitmq_cli is built as part of RabbitMQ. diff --git a/test/diagnostics/observer_command_test.exs b/test/diagnostics/observer_command_test.exs new file mode 100644 index 00000000..948a2adf --- /dev/null +++ b/test/diagnostics/observer_command_test.exs @@ -0,0 +1,53 @@ +## 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 https://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. +## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved. + + +defmodule ObserverCommandTest do + use ExUnit.Case + import TestHelper + + @command RabbitMQ.CLI.Diagnostics.Commands.ObserverCommand + + setup_all do + RabbitMQ.CLI.Core.Distribution.start() + + :ok + end + + setup context do + {:ok, opts: %{ + node: get_rabbit_hostname(), + interval: 5, + timeout: context[:test_timeout] || 15000 + }} + end + + test "merge_defaults: injects a default interval of 5s" do + assert @command.merge_defaults([], %{}) == {[], %{interval: 5}} + end + + test "validate: treats positional arguments as a failure" do + assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} + end + + test "validate: treats empty positional arguments and default switches as a success" do + assert @command.validate([], %{}) == :ok + end + + @tag test_timeout: 3000 + test "run: targeting an unreachable node throws a badrpc", context do + assert match?({:badrpc, _}, @command.run([], %{node: :jake@thedog, interval: 5})) + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs index 17a563fc..ad72f232 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -14,6 +14,7 @@ ## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved. +ExUnit.configure(exclude: [disabled: true]) ExUnit.start() defmodule TestHelper do