diff --git a/deps/rabbitmq_cli/lib/set_parameter_command.ex b/deps/rabbitmq_cli/lib/set_parameter_command.ex new file mode 100644 index 0000000000..f89dcba2bf --- /dev/null +++ b/deps/rabbitmq_cli/lib/set_parameter_command.ex @@ -0,0 +1,45 @@ +## 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. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + +defmodule SetParameterCommand do + + def set_parameter([], _) do + HelpCommand.help + {:bad_argument, []} + end + + def set_parameter([_|_] = args, _) when length(args) != 3 do + HelpCommand.help + {:bad_argument, args} + end + + def set_parameter([component_name, name, value], %{node: node_name, param: vhost}) do + node_name + |> Helpers.parse_node + |> :rabbit_misc.rpc_call( + :rabbit_runtime_parameters, + :parse_set, + [vhost, component_name, name, value, :none] + ) + end + + def set_parameter([_, _, _] = args, %{node: _} = opts) do + default_opts = Map.merge(opts, %{param: "/"}) + set_parameter(args, default_opts) + end + + def usage, do: "set_parameter [-p ] " +end diff --git a/deps/rabbitmq_cli/test/set_parameter_command_test.exs b/deps/rabbitmq_cli/test/set_parameter_command_test.exs new file mode 100644 index 0000000000..fa05ae99c2 --- /dev/null +++ b/deps/rabbitmq_cli/test/set_parameter_command_test.exs @@ -0,0 +1,167 @@ +## 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. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + +defmodule SetParameterCommandTest do + use ExUnit.Case, async: false + import TestHelper + import ExUnit.CaptureIO + + @vhost "test1" + @user "guest" + @root "/" + @component_name "federation-upstream" + @key "reconnect-delay" + @value "{\"uri\":\"amqp://\"}" + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + add_vhost @vhost + + on_exit([], fn -> + delete_vhost @vhost + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + + on_exit(context, fn -> + clear_parameter context[:vhost], context[:component_name], context[:key] + end) + + { + :ok, + opts: %{ + node: get_rabbit_hostname + } + } + end + + test "wrong number of arguments leads to usage and bad_arg" do + assert capture_io(fn -> + SetParameterCommand.set_parameter([], %{}) + end) =~ ~r/Usage:\n/ + + capture_io(fn -> + assert SetParameterCommand.set_parameter([], %{}) == {:bad_argument, []} + end) + + assert capture_io(fn -> + SetParameterCommand.set_parameter(["insufficient"], %{}) + end) =~ ~r/Usage:\n/ + + capture_io(fn -> + assert SetParameterCommand.set_parameter(["insufficient"], %{}) == {:bad_argument, ["insufficient"]} + end) + + assert capture_io(fn -> + SetParameterCommand.set_parameter(["not", "enough"], %{}) + end) =~ ~r/Usage:\n/ + + capture_io(fn -> + assert SetParameterCommand.set_parameter(["not", "enough"], %{}) == {:bad_argument, ["not", "enough"]} + end) + + assert capture_io(fn -> + SetParameterCommand.set_parameter(["this", "is", "way", "too", "many"], %{}) + end) =~ ~r/Usage:\n/ + + capture_io(fn -> + assert SetParameterCommand.set_parameter(["this", "is", "way", "too", "many"], %{}) == {:bad_argument, ["this", "is", "way", "too", "many"],} + end) + end + + @tag component_name: @component_name, key: @key, value: @value, vhost: @vhost + test "a well-formed, host-specific command returns okay", context do + vhost_opts = Map.merge(context[:opts], %{param: context[:vhost]}) + assert SetParameterCommand.set_parameter( + [context[:component_name], context[:key], context[:value]], + vhost_opts + ) == :ok + + parameters = List.first(list_parameters(context[:vhost])) + assert parameters[:value] == context[:value] + assert parameters[:vhost] == context[:vhost] + assert parameters[:component] == context[:component_name] + assert parameters[:name] == context[:key] + end + + test "An invalid rabbitmq node throws a badrpc" do + target = :jake@thedog + :net_kernel.connect_node(target) + opts = %{node: target} + + assert SetParameterCommand.set_parameter([@component_name, @key, @value], opts) == {:badrpc, :nodedown} + end + + @tag component_name: @component_name, key: @key, value: @value, vhost: @root + test "a well-formed command with no vhost runs against the default", context do + assert SetParameterCommand.set_parameter( + [context[:component_name], context[:key], context[:value]], + context[:opts] + ) == :ok + + parameters = List.first(list_parameters(context[:vhost])) + assert parameters[:value] == context[:value] + assert parameters[:vhost] == context[:vhost] + assert parameters[:component] == context[:component_name] + assert parameters[:name] == context[:key] + end + + @tag component_name: "bad-component-name", key: @key, value: @value, vhost: @root + test "an invalid component_name returns a validation failed error", context do + assert SetParameterCommand.set_parameter( + [context[:component_name], context[:key], context[:value]], + context[:opts] + ) == {:error_string, 'Validation failed\n\ncomponent #{context[:component_name]} not found\n'} + + assert list_parameters(context[:vhost]) == [] + end + + @tag component_name: @component_name, key: @key, value: @value, vhost: "bad-vhost" + test "an invalid vhost returns a no-such-vhost error", context do + vhost_opts = Map.merge(context[:opts], %{param: context[:vhost]}) + assert SetParameterCommand.set_parameter( + [context[:component_name], context[:key], context[:value]], + vhost_opts + ) == {:error, {:no_such_vhost, context[:vhost]}} + end + + @tag component_name: @component_name, key: @key, value: "bad-value", vhost: @root + test "an invalid value returns a JSON decoding error", context do + assert SetParameterCommand.set_parameter( + [context[:component_name], context[:key], context[:value]], + context[:opts] + ) == {:error_string, 'JSON decoding error'} + + assert list_parameters(context[:vhost]) == [] + end + + @tag component_name: @component_name, key: @key, value: "{}", vhost: @root + test "an empty JSON object value returns a key \"uri\" not found error", context do + assert SetParameterCommand.set_parameter( + [context[:component_name], context[:key], context[:value]], + context[:opts] + ) == {:error_string, 'Validation failed\n\nKey "uri" not found in reconnect-delay\n'} + + assert list_parameters(context[:vhost]) == [] + end +end diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 8afa068e6f..7f799e4275 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -65,6 +65,14 @@ defmodule TestHelper do :rpc.call(get_rabbit_hostname, :rabbit_access_control,:check_user_pass_login, [name, password]) end + def clear_parameter(vhost, component_name, key) do + :rpc.call(get_rabbit_hostname, :rabbit_runtime_parameters, :clear, [vhost, component_name, key]) + end + + def list_parameters(vhost) do + :rpc.call(get_rabbit_hostname, :rabbit_runtime_parameters, :list_formatted, [vhost]) + end + def set_permissions(user, vhost, [conf, write, read]) do :rpc.call(get_rabbit_hostname, :rabbit_auth_backend_internal, :set_permissions, [user, vhost, conf, write, read]) end