From c195289e5ec49d52ea93e258facfb2f9bc070e05 Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Fri, 22 Mar 2013 17:39:43 +0100
Subject: [PATCH] redis-trib: All output wrapped by a specific function.

This is needed in order to colorize it as next step.
We use conventions in output messages such as

>>> This is an action
*** This is a warning
[ERR] This is an error
[OK] That's fine

And so forth, so that a color will be associated checking the first
three chars.
---
 src/redis-trib.rb | 91 +++++++++++++++++++++++------------------------
 1 file changed, 45 insertions(+), 46 deletions(-)

diff --git a/src/redis-trib.rb b/src/redis-trib.rb
index d5d166e63..22e2c96ce 100755
--- a/src/redis-trib.rb
+++ b/src/redis-trib.rb
@@ -27,8 +27,7 @@ require 'redis'
 ClusterHashSlots = 16384
 
 def xputs(s)
-    printf s
-    STDOUT.flush
+    puts s
 end
 
 class ClusterNode
@@ -67,23 +66,23 @@ class ClusterNode
 
     def connect(o={})
         return if @r
-        xputs "Connecting to node #{self}: "
+        print "Connecting to node #{self}: "
+        STDOUT.flush
         begin
             @r = Redis.new(:host => @info[:host], :port => @info[:port])
             @r.ping
         rescue
-            puts "ERROR"
-            puts "Sorry, can't connect to node #{self}"
+            xputs "[ERR] Sorry, can't connect to node #{self}"
             exit 1 if o[:abort]
             @r = nil
         end
-        puts "OK"
+        xputs "OK"
     end
 
     def assert_cluster
         info = @r.info
         if !info["cluster_enabled"] || info["cluster_enabled"].to_i == 0
-            puts "Error: Node #{self} is not configured as a cluster node."
+            xputs "[ERR] Node #{self} is not configured as a cluster node."
             exit 1
         end
     end
@@ -91,7 +90,7 @@ class ClusterNode
     def assert_empty
         if !(@r.cluster("info").split("\r\n").index("cluster_known_nodes:1")) ||
             (@r.info['db0'])
-            puts "Error: Node #{self} is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0."
+            xputs "[ERR] Node #{self} is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0."
             exit 1
         end
     end
@@ -241,7 +240,7 @@ class RedisTrib
     def check_arity(req_args, num_args)
         if ((req_args > 0 and num_args != req_args) ||
            (req_args < 0 and num_args < req_args.abs))
-           puts "Wrong number of arguments for specified sub command"
+           xputs "[ERR] Wrong number of arguments for specified sub command"
            exit 1
         end
     end
@@ -252,7 +251,7 @@ class RedisTrib
 
     def cluster_error(msg)
         @errors << msg
-        puts msg
+        xputs msg
     end
 
     def get_node_by_name(name)
@@ -263,7 +262,7 @@ class RedisTrib
     end
 
     def check_cluster
-        puts ">>> Performing Cluster Check (using node #{@nodes[0]})"
+        xputs ">>> Performing Cluster Check (using node #{@nodes[0]})"
         show_nodes
         check_config_consistency
         check_open_slots
@@ -281,10 +280,10 @@ class RedisTrib
     end
 
     def check_slots_coverage
-        puts ">>> Check slots coverage..."
+        xputs ">>> Check slots coverage..."
         slots = covered_slots
         if slots.length == ClusterHashSlots
-            puts "[OK] All #{ClusterHashSlots} slots covered."
+            xputs "[OK] All #{ClusterHashSlots} slots covered."
         else
             cluster_error \
                 "[ERR] Not all #{ClusterHashSlots} slots are covered by nodes."
@@ -293,7 +292,7 @@ class RedisTrib
     end
 
     def check_open_slots
-        puts ">>> Check for open slots..."
+        xputs ">>> Check for open slots..."
         open_slots = []
         @nodes.each{|n|
             if n.info[:migrating].size > 0
@@ -308,7 +307,7 @@ class RedisTrib
         }
         open_slots.uniq!
         if open_slots.length > 0
-            puts "[WARNING] The following slots are open: #{open_slots.join(",")}"
+            xputs "[WARNING] The following slots are open: #{open_slots.join(",")}"
         end
         if @fix
             open_slots.each{|slot| fix_open_slot slot}
@@ -325,8 +324,8 @@ class RedisTrib
 
     def fix_slots_coverage
         not_covered = (0...ClusterHashSlots).to_a - covered_slots.keys
-        puts "\nFixing slots coverage..."
-        puts "List of not covered slots: " + not_covered.join(",")
+        xputs ">>> Fixing slots coverage..."
+        xputs "List of not covered slots: " + not_covered.join(",")
 
         # For every slot, take action depending on the actual condition:
         # 1) No node has keys for this slot.
@@ -336,7 +335,7 @@ class RedisTrib
         not_covered.each{|slot|
             nodes = nodes_with_keys_in_slot(slot)
             slots[slot] = nodes
-            puts "Slot #{slot} has keys in #{nodes.length} nodes: #{nodes.join}"
+            xputs "Slot #{slot} has keys in #{nodes.length} nodes: #{nodes.join}"
         }
 
         none = slots.select {|k,v| v.length == 0}
@@ -345,34 +344,34 @@ class RedisTrib
 
         # Handle case "1": keys in no node.
         if none.length > 0
-            puts "The folowing uncovered slots have no keys across the cluster:"
-            puts none.keys.join(",")
+            xputs "The folowing uncovered slots have no keys across the cluster:"
+            xputs none.keys.join(",")
             yes_or_die "Fix these slots by covering with a random node?"
             none.each{|slot,nodes|
                 node = @nodes.sample
-                puts "Covering slot #{slot} with #{node}"
+                xputs ">>> Covering slot #{slot} with #{node}"
                 node.r.cluster("addslots",slot)
             }
         end
 
         # Handle case "2": keys only in one node.
         if single.length > 0
-            puts "The folowing uncovered slots have keys in just one node:"
+            xputs "The folowing uncovered slots have keys in just one node:"
             puts single.keys.join(",")
             yes_or_die "Fix these slots by covering with those nodes?"
             single.each{|slot,nodes|
-                puts "Covering slot #{slot} with #{nodes[0]}"
+                xputs ">>> Covering slot #{slot} with #{nodes[0]}"
                 nodes[0].r.cluster("addslots",slot)
             }
         end
 
         # Handle case "3": keys in multiple nodes.
         if multi.length > 0
-            puts "The folowing uncovered slots have keys in multiple nodes:"
-            puts multi.keys.join(",")
+            xputs "The folowing uncovered slots have keys in multiple nodes:"
+            xputs multi.keys.join(",")
             yes_or_die "Fix these slots by moving keys into a single node?"
             multi.each{|slot,nodes|
-                puts "Covering slot #{slot} moving keys to #{nodes[0]}"
+                xputs ">>> Covering slot #{slot} moving keys to #{nodes[0]}"
                 # TODO
                 # 1) Set all nodes as "MIGRATING" for this slot, so that we
                 # can access keys in the hash slot using ASKING.
@@ -397,10 +396,10 @@ class RedisTrib
             elsif n.info[:importing][slot]
                 importing << n
             elsif n.r.cluster("countkeysinslot",slot) > 0
-                puts "Found keys about slot #{slot} in node #{n}!"
+                xputs "*** Found keys about slot #{slot} in node #{n}!"
             end
         }
-        puts "Fixing open slot 0:"
+        puts ">>> Fixing open slot #{slot}"
         puts "Set as migrating in: #{migrating.join(",")}"
         puts "Set as importing in: #{importing.join(",")}"
 
@@ -409,7 +408,7 @@ class RedisTrib
         if migrating.length == 1 && importing.length == 1
             move_slot(migrating[0],importing[0],slot,:verbose=>true)
         else
-            puts "Sorry, Redis-trib can't fix this slot yet (work in progress)"
+            xputs "[ERR] Sorry, Redis-trib can't fix this slot yet (work in progress)"
         end
     end
 
@@ -420,9 +419,9 @@ class RedisTrib
             signatures << n.get_config_signature
         }
         if signatures.uniq.length != 1
-            puts "[ERR] Nodes don't agree about configuration!"
+            cluster_error "[ERR] Nodes don't agree about configuration!"
         else
-            puts "[OK] All nodes agree about slots configuration."
+            xputs "[OK] All nodes agree about slots configuration."
         end
     end
 
@@ -446,7 +445,7 @@ class RedisTrib
 
     def show_nodes
         @nodes.each{|n|
-            puts n.info_string
+            xputs n.info_string
         }
     end
 
@@ -467,7 +466,7 @@ class RedisTrib
         print "#{msg} (type 'yes' to accept): "
         STDOUT.flush
         if !(STDIN.gets.chomp.downcase == "yes")
-            puts "Aborting..."
+            xputs "*** Aborting..."
             exit 1
         end
     end
@@ -571,7 +570,7 @@ class RedisTrib
         load_cluster_info_from_node(ARGV[1])
         check_cluster
         if @errors.length != 0
-            puts "\n--- Please fix your cluster problems before resharding ---"
+            puts "*** Please fix your cluster problems before resharding"
             exit 1
         end
         numslots = 0
@@ -584,14 +583,14 @@ class RedisTrib
             print "What is the receiving node ID? "
             target = get_node_by_name(STDIN.gets.chop)
             if !target || target.has_flag?("slave")
-                puts "The specified node is not known or not a master, please retry."
+                xputs "*** The specified node is not known or not a master, please retry."
                 target = nil
             end
         end
         sources = []
-        puts "Please enter all the source node IDs."
-        puts "  Type 'all' to use all the nodes as source nodes for the hash slots."
-        puts "  Type 'done' once you entered all the source nodes IDs."
+        xputs "Please enter all the source node IDs."
+        xputs "  Type 'all' to use all the nodes as source nodes for the hash slots."
+        xputs "  Type 'done' once you entered all the source nodes IDs."
         while true
             print "Source node ##{sources.length+1}:"
             line = STDIN.gets.chop
@@ -611,9 +610,9 @@ class RedisTrib
                 }
                 break
             elsif !src || src.has_flag?("slave")
-                puts "The specified node is not known or is not a master, please retry."
+                xputs "*** The specified node is not known or is not a master, please retry."
             elsif src.info[:name] == target.info[:name]
-                puts "It is not possible to use the target node as source node."
+                xputs "*** It is not possible to use the target node as source node."
             else
                 sources << src
             end
@@ -635,7 +634,7 @@ class RedisTrib
     end
 
     def create_cluster_cmd
-        puts "Creating cluster"
+        xputs ">>> Creating cluster"
         ARGV[1..-1].each{|n|
             node = ClusterNode.new(n)
             node.connect(:abort => true)
@@ -644,19 +643,19 @@ class RedisTrib
             node.assert_empty
             add_node(node)
         }
-        puts "Performing hash slots allocation on #{@nodes.length} nodes..."
+        xputs ">>> Performing hash slots allocation on #{@nodes.length} nodes..."
         alloc_slots
         show_nodes
         yes_or_die "Can I set the above configuration?"
         flush_nodes_config
-        puts "** Nodes configuration updated"
-        puts "** Sending CLUSTER MEET messages to join the cluster"
+        xputs ">>> Nodes configuration updated"
+        xputs ">>> Sending CLUSTER MEET messages to join the cluster"
         join_cluster
         check_cluster
     end
 
     def addnode_cluster_cmd
-        puts "Adding node #{ARGV[1]} to cluster #{ARGV[2]}"
+        xputs ">>> Adding node #{ARGV[1]} to cluster #{ARGV[2]}"
 
         # Check the existing cluster
         load_cluster_info_from_node(ARGV[2])
@@ -671,7 +670,7 @@ class RedisTrib
         first = @nodes.first.info
 
         # Send CLUSTER MEET command to the new node
-        puts "Send CLUSTER MEET to node #{new} to make it join the cluster."
+        xputs ">>> Send CLUSTER MEET to node #{new} to make it join the cluster."
         new.r.cluster("meet",first[:host],first[:port])
     end