esteem 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 340aa00a323b11ea872b48a404e951df6eabb2eb
4
+ data.tar.gz: e9b5ee78c4c9f76e0b041617f7984f88f884526b
5
+ SHA512:
6
+ metadata.gz: 8ff6c19a502f907dd2a30d0391042e13f8bd1b646ed19d8a634a54044e2d3db6c22bb89cb820cdbf57fe1f7b233bd8b83b3b52b91cf4537475d46fcec7daf832
7
+ data.tar.gz: 3cc3b6cf92f7c058a9724b8b23c61f772c087bd38dceb330e9545e82732a02ced2b13ce46d8030c3a4a2e73b79346e80700859fbc54b56be7d2e4f982923f71e
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ *~
2
+ *.gem
3
+ *.log
4
+ *.out
5
+ *.pid
6
+ *.swp
7
+ .DS_Store
8
+ .yardoc
9
+ doc
10
+ pkg
11
+ tmp
12
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'pry'
7
+ gem 'rake'
8
+ gem 'yard'
9
+ gem 'version'
10
+ gem 'rubygems-tasks'
11
+ end
12
+
13
+ group :test do
14
+ gem 'minitest'
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2015 Sean Clemmer
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
+ PERFORMANCE OF THIS SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'rake'
4
+
5
+ require 'rake/testtask'
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.test_files = FileList['test/test*.rb']
9
+ test.verbose = true
10
+ end
11
+
12
+ task default: :test
13
+
14
+
15
+ require 'yard'
16
+ YARD::Rake::YardocTask.new do |t|
17
+ t.files = %w[ --readme Readme.md lib/**/*.rb - VERSION ]
18
+ end
19
+
20
+
21
+ require 'rubygems/tasks'
22
+ Gem::Tasks.new push: true, sign: {} do |tasks|
23
+ tasks.console.command = 'pry'
24
+ end
25
+ Gem::Tasks::Sign::Checksum.new sha2: true
26
+
27
+
28
+ require 'rake/version_task'
29
+ Rake::VersionTask.new
data/Readme.md ADDED
@@ -0,0 +1,3 @@
1
+ # Esteem
2
+
3
+ Tips, tricks and scripts for managing time-based Elasticsearch indexes.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/esteem ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'esteem'
3
+ rc = Esteem::Main.start ARGV
4
+ exit rc unless rc.nil?
data/esteem.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path(File.join('..', 'lib'), __FILE__)
3
+ require 'esteem/metadata'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'esteem'
7
+ s.version = Esteem::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.author = Esteem::AUTHOR
10
+ s.license = Esteem::LICENSE
11
+ s.homepage = Esteem::HOMEPAGE
12
+ s.email = Esteem::EMAIL
13
+ s.summary = Esteem::SUMMARY
14
+ s.description = Esteem::SUMMARY + '.'
15
+
16
+ s.add_runtime_dependency 'thor', '~> 0'
17
+ s.add_runtime_dependency 'slog', '~> 1.1'
18
+ s.add_runtime_dependency 'oj', '~> 2.11'
19
+ s.add_runtime_dependency 'rest-client', '~> 1.7'
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- test/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File::basename(f) }
24
+ s.require_paths = %w[ lib ]
25
+ end
@@ -0,0 +1,28 @@
1
+ require 'thor/util'
2
+ require 'thor/actions'
3
+
4
+
5
+ module Esteem
6
+
7
+ # Mixins for Esteem's Thor subclasses.
8
+ module Helpers
9
+
10
+ # Save the canonical implementation of "puts"
11
+ alias_method :old_puts, :puts
12
+
13
+ # Monkeypatch puts to support Thor::Shell::Color.
14
+ def puts *args
15
+ return old_puts if args.empty?
16
+ old_puts shell.set_color(*args)
17
+ end
18
+
19
+
20
+ # Shortcut for Thor::Util.
21
+ def util ; Thor::Util end
22
+
23
+
24
+ # Shortcut for Thor::Actions.
25
+ def actions ; Thor::Actions end
26
+
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ require 'thor'
2
+ require 'slog'
3
+
4
+ require_relative 'reindex'
5
+ require_relative 'helpers'
6
+ require_relative 'metadata'
7
+
8
+
9
+ module Esteem
10
+
11
+ # Esteem's entrypoint.
12
+ class Main < Thor
13
+ include Esteem::Helpers
14
+
15
+
16
+ desc 'version', 'Echo the application version'
17
+ def version
18
+ puts VERSION
19
+ return nil
20
+ end
21
+
22
+
23
+ desc 'art', 'View the application art'
24
+ def art
25
+ puts
26
+ puts ART
27
+ puts
28
+ return nil
29
+ end
30
+
31
+
32
+ desc 'reindex', 'Move data to a new index gracefully'
33
+ option :update, type: :boolean, aliases: %w[ -u ]
34
+ option :frame, type: :numeric, aliases: %w[ -f ], default: 1000
35
+ option :source, type: :string, aliases: %w[ -s ], required: true
36
+ option :destination, type: :string, aliases: %w[ -d ], required: true
37
+ def reindex
38
+ reindex = Reindex.new \
39
+ update: options.update?,
40
+ frame: options.frame,
41
+ src: options.source,
42
+ dst: options.destination
43
+ return reindex.success
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ # Esteem gives you confidence!
2
+ module Esteem
3
+
4
+ # Pull the project version out of the VERSION file
5
+ VERSION = File.read(File.join(File.dirname(__FILE__), '..', '..', 'VERSION')).strip
6
+
7
+ # A quick summary for use in the command-line interface
8
+ SUMMARY = 'Tips, tricks and scripts for managing time-based Elasticsearch indexes'
9
+
10
+ # Take credit for your work
11
+ AUTHOR = 'Sean Clemmer'
12
+
13
+ # Like the MIT license, but even simpler
14
+ LICENSE = 'ISC'
15
+
16
+ # Where you should look first
17
+ HOMEPAGE = 'https://github.com/sczizzo/esteem'
18
+
19
+ # Take responsibility for your work
20
+ EMAIL = 'EMAIL'
21
+
22
+ # Every project deserves its own ASCII art
23
+ ART = <<-'EOART'
24
+ ____ ____ ____
25
+ | ..'''' `````|````` | | .'. .`.
26
+ |______ .'' | |______ |______ .' ` `.
27
+ | ..' | | | .' `.
28
+ |___________ ....'' | |___________ |___________ .' `.
29
+ EOART
30
+ end
@@ -0,0 +1,151 @@
1
+ require 'oj'
2
+ require 'rest-client'
3
+
4
+
5
+ Oj.default_options = { mode: :compat }
6
+
7
+ module Esteem
8
+
9
+ # Cribbed from geronime's "es-reindex" script: https://github.com/geronime/es-reindex
10
+ class Reindex
11
+ attr_reader :success
12
+
13
+
14
+ # Perform a new reindex job. Success or failure will be reported by the
15
+ # read-only "success" attribute.
16
+ #
17
+ # @option [String] :source URL for source index and type
18
+ # @option [String] :destination URL for destination index
19
+ # @option [Integer] :frame Scroll window size
20
+ # @option [Boolean] :update Set to update existing documents
21
+ def initialize source:, destination:, frame:, update:
22
+ src, dst = source, destination
23
+ @success = false
24
+
25
+ type, src = src.reverse.split('/', 2).map(&:reverse)
26
+
27
+ surl, durl, sidx, didx = '', '', '', ''
28
+ [[src, surl, sidx], [dst, durl, didx]].each{|param, url, idx|
29
+ if param =~ %r{^(.*)/(.*?)$}
30
+ url.replace $1
31
+ idx.replace $2
32
+ else
33
+ url.replace 'http://127.0.0.1:9200'
34
+ idx.replace param
35
+ end
36
+ }
37
+
38
+ puts "Copying '%s/%s/%s' to '%s/%s'" % [ surl, sidx, type, durl, didx ]
39
+
40
+ scount = retried_request :get, "#{surl}/#{sidx}/#{type}/_count?q=*"
41
+ scount = Oj.load(scount)['count'].to_i
42
+
43
+ puts "%d documents" % scount
44
+
45
+ if scount == 0
46
+ puts "Hey, this index is empty! Skipping..."
47
+ @success = true
48
+ return
49
+ end
50
+
51
+ t, done = Time.now, 0
52
+ shards = retried_request :get, "#{surl}/#{sidx}/_count?q=*"
53
+ shards = Oj.load(shards)['_shards']['total'].to_i
54
+ scan = retried_request(:get, "#{surl}/#{sidx}/#{type}/_search?search_type=scan&scroll=10m&size=#{frame / shards}")
55
+ scan = Oj.load scan
56
+ scroll_id = scan['_scroll_id']
57
+ total = scan['hits']['total']
58
+ printf " %u/%u (%.1f%%) done.\r", done, total, 0
59
+
60
+ bulk_op = update ? "index" : "create"
61
+
62
+ loop do
63
+ data = retried_request(:get, "#{surl}/_search/scroll?scroll=10m&scroll_id=#{scroll_id}")
64
+ data = Oj.load data
65
+ break if data['hits']['hits'].empty?
66
+
67
+ scroll_id = data['_scroll_id']
68
+ bulk = ''
69
+
70
+ data['hits']['hits'].each do |doc|
71
+ bulk << %Q({"#{bulk_op}": {"_index" : "#{didx}", "_id" : "#{
72
+ doc['_id']}", "_type" : "#{doc['_type']}"}}\n)
73
+ bulk << Oj.dump(doc['_source']) + "\n"
74
+ done += 1
75
+ end
76
+
77
+ unless bulk.empty?
78
+ bulk << "\n" # empty line in the end required
79
+ retried_request :post, "#{durl}/_bulk", bulk
80
+ end
81
+
82
+ eta = total * (Time.now - t) / done
83
+ printf " %u/%u (%.1f%%) done in %s, E.T.A.: %s.\r",
84
+ done, total, 100.0 * done / total, tm_len(Time.now - t), t + eta
85
+ end
86
+
87
+ printf "#{' ' * 80}\r %u/%u done in %s.\n",
88
+ done, total, tm_len(Time.now - t)
89
+
90
+
91
+
92
+ tries = 0
93
+ dcount = -1
94
+
95
+ puts "Waiting for documents to appear in index..."
96
+ until total <= dcount
97
+ dcount = retried_request :get, "#{durl}/#{didx}/#{type}/_count"
98
+ dcount = Oj.load(dcount)['count'].to_i
99
+ tries += 1
100
+
101
+ if tries > 30
102
+ puts "Too many tries!"
103
+ @success = false
104
+ return
105
+ end
106
+
107
+ sleep 15
108
+ end
109
+
110
+ if done != dcount
111
+ puts "Incomplete done! %d != %d" % [ done, dcount ]
112
+ @success = false
113
+ return
114
+ end
115
+
116
+ @success = true
117
+ end
118
+
119
+
120
+
121
+ private
122
+
123
+ def tm_len l
124
+ t = []
125
+ t.push l/86400; l %= 86400
126
+ t.push l/3600; l %= 3600
127
+ t.push l/60; l %= 60
128
+ t.push l
129
+ out = sprintf '%u', t.shift
130
+ out = out == '0' ? '' : out + ' days, '
131
+ out += sprintf('%u:%02u:%02u', *t)
132
+ out
133
+ end
134
+
135
+
136
+ def retried_request method, url, data=nil
137
+ while true
138
+ begin
139
+ return data ?
140
+ RestClient.send(method, url, data) :
141
+ RestClient.send(method, url)
142
+ rescue RestClient::ResourceNotFound # no point to retry
143
+ return nil
144
+ rescue => e
145
+ warn "\nRetrying #{method.to_s.upcase} ERROR: #{e.class} - #{e.message}"
146
+ end
147
+ end
148
+ end
149
+
150
+ end
151
+ end
data/lib/esteem.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative 'esteem/main'
@@ -0,0 +1,27 @@
1
+ require 'tmpdir'
2
+ require 'logger'
3
+ require 'tempfile'
4
+ require 'fileutils'
5
+ require 'pathname'
6
+
7
+ require 'minitest/autorun'
8
+
9
+ require_relative '../lib/esteem'
10
+
11
+
12
+
13
+ class TestEsteem < MiniTest::Test
14
+ def setup
15
+ @tmpdir = Dir.mktmpdir
16
+ @logger = Logger.new STDERR
17
+ @logger.level = Logger::WARN
18
+ end
19
+
20
+ def teardown
21
+ FileUtils.rm_rf @tmpdir
22
+ end
23
+
24
+ def test_something
25
+ assert true
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: esteem
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sean Clemmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: slog
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: oj
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.11'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ description: Tips, tricks and scripts for managing time-based Elasticsearch indexes.
70
+ email: EMAIL
71
+ executables:
72
+ - esteem
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE
79
+ - Rakefile
80
+ - Readme.md
81
+ - VERSION
82
+ - bin/esteem
83
+ - esteem.gemspec
84
+ - lib/esteem.rb
85
+ - lib/esteem/helpers.rb
86
+ - lib/esteem/main.rb
87
+ - lib/esteem/metadata.rb
88
+ - lib/esteem/reindex.rb
89
+ - test/test_esteem.rb
90
+ homepage: https://github.com/sczizzo/esteem
91
+ licenses:
92
+ - ISC
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Tips, tricks and scripts for managing time-based Elasticsearch indexes
114
+ test_files:
115
+ - test/test_esteem.rb