anchor.diff:  %%==============================================================================
   %% @author Gavin M. Roy <gavinr@aweber.com>
  -%% @copyright 2015 AWeber Communications
  +%% @copyright 2015-2016 AWeber Communications
   %% @end
   %%==============================================================================
   -module(autocluster).
  
positive.code: ensure_registered(etcd) ->
    ensure_registered(etcd, autocluster_etcd);
  ensure_registered(Backend) ->
    autocluster_log:error("Unsupported backend: ~s", [Backend]),
    error.
  
  
  %% @private
  %% @spec ensure_registered(Name, Module) -> ok|error
  %% @where Name = atom()
  %%        Module = module()
  %% @doc Invoke the backend module to ensure the node is registered
  %% @end
  %%
  ensure_registered(Name, Module) ->
    case Module:nodelist() of
      {ok, Nodes} ->
        case lists:member(node(), Nodes) of
          true  -> {ok, Nodes};
          false ->
            autocluster_log:info("Registering node with ~p", [Name]),
            case Module:register() of
              ok ->
                autocluster_log:debug("Registered node"),
                {ok, Nodes};
              {error, Reason} ->
                autocluster_log:error("Error registering node with ~p: ~p", [Name, Reason]),
                error
            end
        end;
      {error, Reason} ->
        autocluster_log:error("Could not fetch node list from ~p: ~p", [Module, Reason]),
        error
    end.
  
  
  %% @private
  %% @spec filter_dead_nodes([node()]) -> ok
  %% @doc Take the list of nodes specified by the backend and ensure they're pingable
  %% @end
  %%
  filter_dead_nodes(Nodes) ->
    lists:filter(fun(N) -> net_adm:ping(N) =:= pong end, Nodes).
  
  
  %% @private
  %% @spec join_cluster([node()]) -> ok
  %% @doc Have the current node join a cluster using the specified discovery node
  %% @end
  %%
  join_cluster(Nodes) ->
    case filter_dead_nodes(Nodes) of
      [] ->
        autocluster_log:warning("Can not communicate with cluster nodes: ~p",
          [Nodes]),
        case autocluster_config:get(cluster_formation_failure_mode) of
          "stop" -> error;
          "ignore" -> ok
        end;
      Alive ->
        autocluster_log:debug("Joining existing cluster: ~p", [Alive]),
        application:stop(rabbit),
        mnesia:stop(),
        rabbit_mnesia:reset(),
        rabbit_mnesia:join_cluster(lists:nth(1, Alive),
                                   autocluster_config:get(node_type)),
        mnesia:start(),
        rabbit:start(),
        autocluster_log:debug("Cluster joined"),
        ok
    end.
  
negative.code:                     {enables,     pre_boot}]}).
  
  
  -spec init() -> ok | error.
  %% @doc Register the node with Consul and then check to see if there are other
  %%      nodes available that this node can cluster with. If so, stop the rabbit
  %%      and mnesia applications, reset the mnesia database, join the cluster,
  %%      and then start the mnesia and rabbit applications back up again.
  %% @end
  %%
  init() ->
    autocluster_log:maybe_set_default_log_level(),
    application:ensure_started(inets),
    maybe_delay_startup(),
    Registered = node_is_registered(),
    maybe_cluster_node(Registered).
  
  
  %% Clustering Logic
  
  -spec node_is_registered() -> ok | error.
  %% @private
  %% @doc Step 1: get the backend type from config and pass it to step two.
  %% @end
  %%
  node_is_registered() ->
    ensure_registered(autocluster_config:get(backend)).
  
  
  -spec ensure_registered(atom()) -> ok | error.
  %% @private
  %% @doc Step 2: get the module for the backend type and pass it to step three.
  %% @end
  %%
  ensure_registered(consul) ->
  