From 629453ab5b8ba6d14521788a12afe559565133fd Mon Sep 17 00:00:00 2001
From: Daniil Fedotov <dfedotov@pivotal.io>
Date: Mon, 3 Apr 2017 14:46:26 +0100
Subject: [PATCH 1/2] Make it possible to specify erlang cookie from command
 line

Add new flag `--erlang-cookie` and environment variable `RABBITMQ_ERLANG_COOKIE`
to configure a cookie for CLI to connect to RabbitMQ node.
---
 DESIGN.md                             | 22 ++++++------
 lib/rabbitmq/cli/core/config.ex       |  8 ++++-
 lib/rabbitmq/cli/core/distribution.ex | 19 ++++++++---
 lib/rabbitmq/cli/core/parser.ex       |  3 +-
 test/distribution_test.exs            | 48 +++++++++++++++++++++++++++
 test/rabbitmqctl_test.exs             |  2 --
 6 files changed, 84 insertions(+), 18 deletions(-)
 create mode 100644 test/distribution_test.exs

diff --git a/DESIGN.md b/DESIGN.md
index 073e1243..4d2b19ee 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -231,13 +231,14 @@ be shown in usage and available for execution.
 
 #### Environment Arguments
 
- * script_name: atom, configurable tool name (`rabbitmq-plugins`, `rabbitmqctl`) to select command scope (see [Command scopes](#command-scopes))
- * rabbitmq_home: string, broker install directory
- * mnesia_dir: string, broker mnesia data directory
- * plugins_dir: string, broker plugins directory
- * enabled_plugins_file: string, broker enabled plugins file
+ * script-name: atom, configurable tool name (`rabbitmq-plugins`, `rabbitmqctl`) to select command scope (see [Command scopes](#command-scopes))
+ * rabbitmq-home: string, broker install directory
+ * mnesia-dir: string, broker mnesia data directory
+ * plugins-dir: string, broker plugins directory
+ * enabled-plugins-file: string, broker enabled plugins file
  * longnames (l): boolean, use longnames to communicate with broker erlang node. Should be set to `true` only if broker is started with longnames.
  * aliases-file: string, a file name to load aliases from
+ * erlang-cookie: atom, an [erlang distribution cookie](http://erlang.org/doc/reference_manual/distributed.html)
 
 Environment argument defaults are loaded from rabbitmq environment variables (see [Environment configuration](#environment-configuration)).
 
@@ -469,11 +470,12 @@ By default it will be loaded from environment variables, same as used in rabbitm
 
 | Argument name        | Environment variable          |
 |----------------------|-------------------------------|
-| rabbitmq_home        | RABBITMQ_HOME                 |
-| mnesia_dir           | RABBITMQ_MNESIA_DIR           |
-| plugins_dir          | RABBITMQ_PLUGINS_DIR          |
-| enabled_plugins_file | RABBITMQ_ENABLED_PLUGINS_FILE |
+| rabbitmq-home        | RABBITMQ_HOME                 |
+| mnesia-dir           | RABBITMQ_MNESIA_DIR           |
+| plugins-dir          | RABBITMQ_PLUGINS_DIR          |
+| enabled-plugins-file | RABBITMQ_ENABLED_PLUGINS_FILE |
 | longnames            | RABBITMQ_USE_LONGNAME         |
 | node                 | RABBITMQ_NODENAME             |
-| aliases_file         | RABBITMQ_CLI_ALIASES_FILE     |
+| aliases-file         | RABBITMQ_CLI_ALIASES_FILE     |
+| erlang-cookie        | RABBITMQ_ERLANG_COOKIE        |
 
diff --git a/lib/rabbitmq/cli/core/config.ex b/lib/rabbitmq/cli/core/config.ex
index 82dd3a19..5a1928e2 100644
--- a/lib/rabbitmq/cli/core/config.ex
+++ b/lib/rabbitmq/cli/core/config.ex
@@ -22,9 +22,14 @@ defmodule RabbitMQ.CLI.Core.Config do
     normalize(name, raw_option)
   end
 
+  def normalize(:node, nil), do: nil
   def normalize(:node, node) when not is_atom(node) do
     Rabbitmq.Atom.Coerce.to_atom(node)
   end
+  def normalize(:erlang_cookie, nil), do: nil
+  def normalize(:erlang_cookie, c) when not is_atom(c) do
+    Rabbitmq.Atom.Coerce.to_atom(c)
+  end
   def normalize(:longnames, true),   do: :longnames
   def normalize(:longnames, "true"), do: :longnames
   def normalize(:longnames, 'true'), do: :longnames
@@ -44,7 +49,8 @@ defmodule RabbitMQ.CLI.Core.Config do
       :plugins_dir          -> "RABBITMQ_PLUGINS_DIR";
       :enabled_plugins_file -> "RABBITMQ_ENABLED_PLUGINS_FILE";
       :node                 -> "RABBITMQ_NODENAME";
-      :aliases_file         -> "RABBITMQ_CLI_ALIASES_FILE"
+      :aliases_file         -> "RABBITMQ_CLI_ALIASES_FILE";
+      :erlang_cookie        -> "RABBITMQ_ERLANG_COOKIE";
       _ -> ""
     end
     System.get_env(system_env_option)
diff --git a/lib/rabbitmq/cli/core/distribution.ex b/lib/rabbitmq/cli/core/distribution.ex
index 23b24f92..293feda6 100644
--- a/lib/rabbitmq/cli/core/distribution.ex
+++ b/lib/rabbitmq/cli/core/distribution.ex
@@ -27,13 +27,24 @@ defmodule RabbitMQ.CLI.Core.Distribution do
   def start(options) do
     node_name_type = Config.get_option(:longnames, options)
     :rabbit_nodes.ensure_epmd()
-    start(node_name_type, 10, :undefined)
+    distribution = start(node_name_type, 10, :undefined)
+    ensure_cookie(options)
+    distribution
   end
 
-  def start_as(node_name, opts) do
+  def start_as(node_name, options) do
     :rabbit_nodes.ensure_epmd()
-    node_name_type = Config.get_option(:longnames, opts)
-    :net_kernel.start([node_name, node_name_type])
+    node_name_type = Config.get_option(:longnames, options)
+    distribution = :net_kernel.start([node_name, node_name_type])
+    ensure_cookie(options)
+    distribution
+  end
+
+  def ensure_cookie(options) do
+    case Config.get_option(:erlang_cookie, options) do
+      nil    -> :ok;
+      cookie -> Node.set_cookie(cookie)
+    end
   end
 
   #
diff --git a/lib/rabbitmq/cli/core/parser.ex b/lib/rabbitmq/cli/core/parser.ex
index ef53a469..6eafb74e 100644
--- a/lib/rabbitmq/cli/core/parser.ex
+++ b/lib/rabbitmq/cli/core/parser.ex
@@ -170,7 +170,8 @@ defmodule RabbitMQ.CLI.Core.Parser do
      mnesia_dir: :string,
      plugins_dir: :string,
      enabled_plugins_file: :string,
-     aliases_file: :string
+     aliases_file: :string,
+     erlang_cookie: :atom
     ]
   end
 
diff --git a/test/distribution_test.exs b/test/distribution_test.exs
new file mode 100644
index 00000000..20d470e3
--- /dev/null
+++ b/test/distribution_test.exs
@@ -0,0 +1,48 @@
+## 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-2017 Pivotal Software, Inc.  All rights reserved.
+
+alias RabbitMQ.CLI.Core.Distribution, as: Distribution
+
+defmodule DostributionTest do
+  use ExUnit.Case, async: false
+  import TestHelper
+
+  setup_all do
+    :net_kernel.stop()
+    :ok
+  end
+
+  test "set cookie via environment variable" do
+    on_exit(fn ->
+      :net_kernel.stop()
+      System.delete_env("RABBITMQ_ERLANG_COOKIE")
+    end)
+    :nocookie = Node.get_cookie()
+    System.put_env("RABBITMQ_ERLANG_COOKIE", "mycookie")
+    opts = %{}
+    Distribution.start(opts)
+    :mycookie = Node.get_cookie()
+  end
+
+  test "set cookie via argument" do
+    on_exit(fn ->
+      :net_kernel.stop()
+    end)
+    :nocookie = Node.get_cookie()
+    opts = %{erlang_cookie: :mycookie}
+    Distribution.start(opts)
+    :mycookie = Node.get_cookie()
+  end
+end
\ No newline at end of file
diff --git a/test/rabbitmqctl_test.exs b/test/rabbitmqctl_test.exs
index a4937af0..0bd1bb1c 100644
--- a/test/rabbitmqctl_test.exs
+++ b/test/rabbitmqctl_test.exs
@@ -27,9 +27,7 @@ defmodule RabbitMQCtlTest do
     set_scope(:all)
     on_exit([], fn ->
       :erlang.disconnect_node(get_rabbit_hostname())
-
     end)
-
     :ok
   end
 

From 15659d88abd606bdfe4854faac58704850a9c3a0 Mon Sep 17 00:00:00 2001
From: Michael Klishin <mklishin@pivotal.io>
Date: Tue, 4 Apr 2017 15:11:41 +0300
Subject: [PATCH 2/2] Naming; make sure ensure_cookie/1 always returns :ok

erlang:set_cookie/2 returns true, not ok.
---
 lib/rabbitmq/cli/core/distribution.ex | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/rabbitmq/cli/core/distribution.ex b/lib/rabbitmq/cli/core/distribution.ex
index 293feda6..0f246e77 100644
--- a/lib/rabbitmq/cli/core/distribution.ex
+++ b/lib/rabbitmq/cli/core/distribution.ex
@@ -27,23 +27,24 @@ defmodule RabbitMQ.CLI.Core.Distribution do
   def start(options) do
     node_name_type = Config.get_option(:longnames, options)
     :rabbit_nodes.ensure_epmd()
-    distribution = start(node_name_type, 10, :undefined)
+    result = start(node_name_type, 10, :undefined)
     ensure_cookie(options)
-    distribution
+    result
   end
 
   def start_as(node_name, options) do
     :rabbit_nodes.ensure_epmd()
     node_name_type = Config.get_option(:longnames, options)
-    distribution = :net_kernel.start([node_name, node_name_type])
+    result = :net_kernel.start([node_name, node_name_type])
     ensure_cookie(options)
-    distribution
+    result
   end
 
   def ensure_cookie(options) do
     case Config.get_option(:erlang_cookie, options) do
       nil    -> :ok;
       cookie -> Node.set_cookie(cookie)
+                :ok
     end
   end