kafkat 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZjAwMzc4N2FlYjVhYmYzZTRkOGRlYWIxZWRkZWY1ZjM4NjlkMWE0Mw==
4
+ MTY0MTdhYjQ3YjAzNWExNWJjMzMyYThmOTY5ZWQ5NmQyOTcyMGM4Yw==
5
5
  data.tar.gz: !binary |-
6
- Mzk4ZjIxNzhmZWZjN2QzZjZiODk4ODA3NmZmYWY5N2Y0Yzg2MmNiNQ==
6
+ MTkzM2UzODgxNTIzMmJiYTAwNDQ2NmI5ZmVjYWZkYTdiYjNkZDk4Ng==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YTMwNzhiNTliZTU1ZmY0OWYxYTY2NGIzZWEwZGI4ZDQ3ODQyNDU4Njg1ZTgw
10
- ZmM4NGZiYjNlMWFkYjIxMDIwNjFhZWIwN2ZjYWRhNGE0MWE1NmU1NDI2Njhl
11
- NWIwNjE0YTQ5YWRhNTNmZjFlM2ZjMDk5N2FhNDM2MWY4Nzc3YTE=
9
+ N2U0ZTMyMjQ4MmI3M2QzMDkyNTM4ZWFjOWJmMTNhNmIxNjlkM2NjMzBkYTli
10
+ YmY3N2Y1ZTk5OWIwZjZlZjZhMzNjOGE2MmE4NDg2ZTc4NzFjYTYzZmZlZWNi
11
+ YzFmNzFjZGU5N2Y5Y2UyMGY5NDhiNmEyZWU5NjdiNzViMjVlNjU=
12
12
  data.tar.gz: !binary |-
13
- NzZiZmZjNjlmNmRjMzBhYjRhZDVmOTdmZDU5MTE1YWFlOTZmODNmZDY5YmU2
14
- ZTFkNmM2YjVhMGNkM2FjMWI4ZmY4MTNlYjZiMDlkY2UyNzU2ZWQwMTY4MmVk
15
- ZGNhNGM2OGQxMWVmNGQ5YzMwOWU3MGYyMzc1MmE4ZDdjYWRiNzc=
13
+ YjRiMzllYmZjNDBiMmYxNjRiNzExMzlkZGM2ZWQwOTA0NmFiMGRkZTQzZjMz
14
+ ZmRlMGM5OTczMTcwYzI4MmJiYmE1ZGYwMDZlNzhhMTI3ZmQ2YThkN2E4OTdj
15
+ ZmUzN2QyZDMxNDk5ODE1ZWIwNTdjZmMyNWFkMTYzYWRjOWJmZWY=
data/Gemfile.lock CHANGED
@@ -1,12 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kafkat (0.0.7)
4
+ kafkat (0.0.10)
5
5
  colored (~> 1.2)
6
- highline (~> 1.6.21)
7
- retryable (~> 1.3.5)
6
+ highline (~> 1.6, >= 1.6.21)
7
+ retryable (~> 1.3, >= 1.3.5)
8
8
  trollop (~> 2.0)
9
- zk (~> 1.9.4)
9
+ zk (~> 1.9, >= 1.9.4)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
@@ -23,7 +23,7 @@ GEM
23
23
  zk (1.9.4)
24
24
  logging (~> 1.8.2)
25
25
  zookeeper (~> 1.4.0)
26
- zookeeper (1.4.8)
26
+ zookeeper (1.4.9)
27
27
 
28
28
  PLATFORMS
29
29
  ruby
data/README.md CHANGED
@@ -34,23 +34,24 @@ Kafkat searches for this file in two places, `~/.kafkatcfg` and `/etc/kafkatcfg`
34
34
 
35
35
  ```
36
36
  $ kafkat
37
- kafkat 0.0.1: Simplified command-line administration for Kafka brokers
37
+ kafkat 0.0.10: Simplified command-line administration for Kafka brokers
38
38
  usage: kafkat [command] [options]
39
39
 
40
40
  Here's a list of supported commands:
41
41
 
42
- brokers Print available brokers from Zookeeper.
43
- clean-indexes Delete untruncated Kafka log indexes from the filesystem.
44
- controller Print the current controller.
45
- elect-leaders [topic] Begin election of the preferred leaders.
46
- partitions [topic] Print partitions by topic.
47
- partitions [topic] --under-replicated Print partitions by topic (only under-replicated).
48
- partitions [topic] --unavailable Print partitions by topic (only unavailable).
49
- reassign [topic] [--brokers <ids>] [--replicas <n>] Begin reassignment of partitions.
50
- resign-rewrite <broker id> Forcibly rewrite leaderships to exclude a broker.
51
- resign-rewrite <broker id> --force Same as above but proceed if there are no available ISRs.
52
- shutdown <broker id> Gracefully remove leaderships from a broker (requires JMX).
53
- topics Print all topics.
42
+ brokers Print available brokers from Zookeeper.
43
+ clean-indexes Delete untruncated Kafka log indexes from the filesystem.
44
+ controller Print the current controller.
45
+ elect-leaders [topic] Begin election of the preferred leaders.
46
+ partitions [topic] Print partitions by topic.
47
+ partitions [topic] --under-replicated Print partitions by topic (only under-replicated).
48
+ partitions [topic] --unavailable Print partitions by topic (only unavailable).
49
+ reassign [topic] [--brokers <ids>] [--replicas <n>] Begin reassignment of partitions.
50
+ resign-rewrite <broker id> Forcibly rewrite leaderships to exclude a broker.
51
+ resign-rewrite <broker id> --force Same as above but proceed if there are no available ISRs.
52
+ set-replication-factor [topic] [--newrf <n>] [--brokers id[,id]] Set the replication factor of
53
+ shutdown <broker id> Gracefully remove leaderships from a broker (requires JMX).
54
+ topics Print all topics.
54
55
 
55
56
  ```
56
57
 
data/kafkat.gemspec CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |s|
18
18
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
19
  s.require_path = 'lib'
20
20
 
21
- s.add_runtime_dependency 'zk', '~> 1.9.4'
21
+ s.add_runtime_dependency 'zk', '~> 1.9', '>= 1.9.4'
22
22
  s.add_runtime_dependency 'trollop', '~> 2.0'
23
- s.add_runtime_dependency 'highline', '~> 1.6.21'
24
- s.add_runtime_dependency 'retryable', '~> 1.3.5'
23
+ s.add_runtime_dependency 'highline', '~> 1.6', '>= 1.6.21'
24
+ s.add_runtime_dependency 'retryable', '~> 1.3', '>= 1.3.5'
25
25
  s.add_runtime_dependency 'colored', '~> 1.2'
26
26
  end
data/lib/kafkat/cli.rb CHANGED
@@ -44,8 +44,8 @@ module Kafkat
44
44
  Command.all.values.sort_by(&:command_name).each do |klass|
45
45
  klass.usages.each do |usage|
46
46
  format, description = usage[0], usage[1]
47
- padding_length = 52 - format.length
48
- padding = " " * padding_length
47
+ padding_length = 68 - format.length
48
+ padding = " " * padding_length unless padding_length < 0
49
49
  print " #{format}#{padding}#{description}\n"
50
50
  end
51
51
  end
@@ -22,7 +22,7 @@ module Kafkat
22
22
  print "\nBeginning.\n"
23
23
  result = admin.elect_leaders!(partitions)
24
24
  print "Started.\n"
25
- rescue Admin::ExecutionFailedError
25
+ rescue Interface::Admin::ExecutionFailedError
26
26
  print result
27
27
  end
28
28
  end
@@ -42,7 +42,7 @@ module Kafkat
42
42
  topic_replica_count = replica_count || t.partitions[0].replicas.size
43
43
 
44
44
  if topic_replica_count > broker_count
45
- print "ERROR: Replication factor is larger than brokers.\n"
45
+ print "ERROR: Replication factor (#{topic_replica_count}) is larger than brokers (#{broker_count}).\n"
46
46
  exit 1
47
47
  end
48
48
 
@@ -80,7 +80,7 @@ module Kafkat
80
80
  print "\nBeginning.\n"
81
81
  result = admin.reassign!(assignments)
82
82
  print "Started.\n"
83
- rescue Admin::ExecutionFailedError
83
+ rescue Interface::Admin::ExecutionFailedError
84
84
  print result
85
85
  end
86
86
  end
@@ -0,0 +1,173 @@
1
+ module Kafkat
2
+ module Command
3
+
4
+ #
5
+ # Command to set the replication factor (RF) of a topic.
6
+ # The command accepts the topic name, the new desired replication factor,
7
+ # and, in case of an increase of the replication factor, a list of broker ids.
8
+ #
9
+ # When reducing the RF, a new partition assigment will be generated by
10
+ # removing the last partition replica of every replica set. The leader partition
11
+ # will not be removed from the replica set to prevent a leader election.
12
+ #
13
+ # When increasing the RF, a new partition assignment will be generated by allocating
14
+ # a new replica to every replica set. The new replica will be assigned to the provided
15
+ # broker list in a round robin fashion.
16
+ # If no broker id is specified on the command line, all brokers will be used.
17
+ #
18
+ #
19
+ class SetReplicationFactor < Base
20
+ register_as 'set-replication-factor'
21
+
22
+ usage 'set-replication-factor [topic] [--newrf <n>] [--brokers id[,id]]',
23
+ 'Set the replication factor of'
24
+
25
+ def run
26
+ topic_name = ARGV.shift unless ARGV[0] && ARGV[0].start_with?('--')
27
+
28
+ all_brokers = zookeeper.get_brokers
29
+ topics = topic_name && zookeeper.get_topics([topic_name])
30
+ topics ||= zookeeper.get_topics
31
+
32
+ opts = Trollop.options do
33
+ opt :brokers, "the comma-separated list of broker the new partitions must be assigned to", type: :string
34
+ opt :newrf, "the new replication factor", type: :integer, required: true
35
+ end
36
+
37
+ broker_ids = opts[:brokers] && opts[:brokers].split(',').map(&:to_i)
38
+ new_rf = opts[:newrf]
39
+
40
+ if new_rf < 1
41
+ puts "ERROR: replication factor is smaller than 1"
42
+ exit 1
43
+ end
44
+
45
+ broker_ids ||= zookeeper.get_brokers.values.map(&:id)
46
+
47
+ all_brokers_id = all_brokers.values.map(&:id)
48
+ broker_ids.each do |id|
49
+ if !all_brokers_id.include?(id)
50
+ puts "ERROR: Broker #{id} is not currently active.\n"
51
+ exit 1
52
+ end
53
+ end
54
+
55
+ broker_count = broker_ids.size
56
+ if new_rf > broker_count
57
+ puts "ERROR: Replication factor is larger than number of brokers.\n"
58
+ exit 1
59
+ end
60
+
61
+ assignments = []
62
+ topics.each do |_, t|
63
+ current_rf = t.partitions[0].replicas.size
64
+ if new_rf < current_rf
65
+ warn_reduce_brokers if opts[:brokers]
66
+ assignments += reduce_rf(t, current_rf, new_rf)
67
+ elsif new_rf > current_rf
68
+ assignments += increase_rf(t, current_rf, new_rf, broker_ids)
69
+ end
70
+ end
71
+
72
+ # ****************
73
+ if assignments.empty?
74
+ puts "No partition reassignment required"
75
+ else
76
+ print "This operation executes the following assignments:\n\n"
77
+ print_assignment_header
78
+ assignments.each { |a| print_assignment(a) }
79
+ print "\n"
80
+
81
+ return unless agree("Proceed (y/n)?")
82
+
83
+ result = nil
84
+ begin
85
+ print "\nBeginning.\n"
86
+ result = admin.reassign!(assignments)
87
+ print "Started.\n"
88
+ rescue Admin::ExecutionFailedError
89
+ print result
90
+ end
91
+ end
92
+ end
93
+
94
+
95
+ #
96
+ # For every partition, remove the last replica from the replica list.
97
+ # If the last replica is the leader, then the previous replica is removed instead.
98
+ #
99
+ def reduce_rf(topic, current_rf, new_rf)
100
+ delta_rf = current_rf - new_rf
101
+ if current_rf == 1
102
+ raise 'Current replication factor if 1. Cannot reduce further.'
103
+ end
104
+ unless delta_rf > 0
105
+ raise "New replication factor (#{new_rf}) must be smaller than current replication factor (#{current_rf})"
106
+ end
107
+ assignments = []
108
+ topic.partitions.map do |p|
109
+ new_replicas = p.replicas
110
+
111
+ (0...delta_rf).each do |_|
112
+ (0...new_replicas.size).each do |i|
113
+ if new_replicas[new_replicas.size-1-i] != p.leader
114
+ new_replicas.delete_at(new_replicas.size-1-i)
115
+ break
116
+ end
117
+ end
118
+ end
119
+
120
+ if new_replicas.size != new_rf
121
+ raise 'Unexpected state'
122
+ end
123
+ assignments << Assignment.new(topic.name, p.id, new_replicas)
124
+ end
125
+ assignments
126
+ end
127
+
128
+
129
+ #
130
+ # For every partition, filter out the brokers that already have a replica for this partition,
131
+ # then pick (new_rf - current_rf) brokers and assign them new replicas.
132
+ #
133
+ # The count of new replicas assigned to the brokers is maintained in order to uniformly assign new replicas.
134
+ #
135
+ def increase_rf(topic, current_rf, new_rf, brokers)
136
+ unless new_rf > current_rf
137
+ raise 'New replication factor must be greater than the current replication factor'
138
+ end
139
+
140
+ delta_rf = new_rf - current_rf
141
+ if delta_rf > brokers.size
142
+ raise "#{delta_rf} new replicas requested for topic #{p.topic_name} but only #{brokers.size} brokers available"
143
+ end
144
+
145
+ broker_counts = brokers.map { |b| {:id => b, :count => 0} }
146
+
147
+ assignments = []
148
+ topic.partitions.map do |p|
149
+ existing_replicas = p.replicas
150
+ pick_from = broker_counts.reject { |b| existing_replicas.include?(b[:id]) }
151
+ if delta_rf > pick_from.size
152
+ raise "Cannot create #{delta_rf} new replicas for partition #{p.topic_name}.#{p.id}, not enough brokers"
153
+ end
154
+ new_replicas = pick_from.sort { |a, b| a[:count] <=> b[:count] }[0...delta_rf]
155
+ new_replicas.each { |b| b[:count] += 1 }
156
+
157
+ final_replicas = existing_replicas + new_replicas.map { |b| b[:id] }
158
+
159
+ assignments << Assignment.new(topic.name, p.id, final_replicas)
160
+ end
161
+ assignments
162
+ end
163
+
164
+ def warn_reduce_brokers
165
+ return if @did_warn_reduce_brokers
166
+ puts "When reducing the replication factor the list of specified brokers is ignored."
167
+ puts "Once the replication factor is set, you can use the reassign command."
168
+ @did_warn_reduce_brokers = true
169
+ end
170
+
171
+ end
172
+ end
173
+ end
@@ -21,7 +21,7 @@ module Kafkat
21
21
  print "\nBeginning shutdown.\n"
22
22
  result = admin.shutdown!(broker_id)
23
23
  print "Started.\n"
24
- rescue Admin::ExecutionFailedError
24
+ rescue Interface::Admin::ExecutionFailedError
25
25
  print result
26
26
  end
27
27
  end
@@ -1,3 +1,3 @@
1
1
  module Kafkat
2
- VERSION = '0.0.9'
2
+ VERSION = '0.0.10'
3
3
  end
metadata CHANGED
@@ -1,20 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kafkat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nelson Gauthier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-14 00:00:00.000000000 Z
11
+ date: 2015-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zk
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ - - ! '>='
18
21
  - !ruby/object:Gem::Version
19
22
  version: 1.9.4
20
23
  type: :runtime
@@ -22,6 +25,9 @@ dependencies:
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.9'
30
+ - - ! '>='
25
31
  - !ruby/object:Gem::Version
26
32
  version: 1.9.4
27
33
  - !ruby/object:Gem::Dependency
@@ -43,6 +49,9 @@ dependencies:
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
54
+ - - ! '>='
46
55
  - !ruby/object:Gem::Version
47
56
  version: 1.6.21
48
57
  type: :runtime
@@ -50,6 +59,9 @@ dependencies:
50
59
  version_requirements: !ruby/object:Gem::Requirement
51
60
  requirements:
52
61
  - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: '1.6'
64
+ - - ! '>='
53
65
  - !ruby/object:Gem::Version
54
66
  version: 1.6.21
55
67
  - !ruby/object:Gem::Dependency
@@ -57,6 +69,9 @@ dependencies:
57
69
  requirement: !ruby/object:Gem::Requirement
58
70
  requirements:
59
71
  - - ~>
72
+ - !ruby/object:Gem::Version
73
+ version: '1.3'
74
+ - - ! '>='
60
75
  - !ruby/object:Gem::Version
61
76
  version: 1.3.5
62
77
  type: :runtime
@@ -64,6 +79,9 @@ dependencies:
64
79
  version_requirements: !ruby/object:Gem::Requirement
65
80
  requirements:
66
81
  - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: '1.3'
84
+ - - ! '>='
67
85
  - !ruby/object:Gem::Version
68
86
  version: 1.3.5
69
87
  - !ruby/object:Gem::Dependency
@@ -111,6 +129,7 @@ files:
111
129
  - lib/kafkat/command/partitions.rb
112
130
  - lib/kafkat/command/reassign.rb
113
131
  - lib/kafkat/command/resign-rewrite.rb
132
+ - lib/kafkat/command/set-replication-factor.rb
114
133
  - lib/kafkat/command/shutdown.rb
115
134
  - lib/kafkat/command/topics.rb
116
135
  - lib/kafkat/config.rb