lbrt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +180 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/exe/lbrt +15 -0
  12. data/lbrt.gemspec +31 -0
  13. data/lib/lbrt.rb +46 -0
  14. data/lib/lbrt/alert.rb +91 -0
  15. data/lib/lbrt/alert/dsl.rb +9 -0
  16. data/lib/lbrt/alert/dsl/context.rb +32 -0
  17. data/lib/lbrt/alert/dsl/context/alert.rb +75 -0
  18. data/lib/lbrt/alert/dsl/context/alert/condition.rb +61 -0
  19. data/lib/lbrt/alert/dsl/converter.rb +113 -0
  20. data/lib/lbrt/alert/exporter.rb +38 -0
  21. data/lib/lbrt/cli.rb +2 -0
  22. data/lib/lbrt/cli/alert.rb +26 -0
  23. data/lib/lbrt/cli/app.rb +15 -0
  24. data/lib/lbrt/cli/service.rb +26 -0
  25. data/lib/lbrt/cli/space.rb +27 -0
  26. data/lib/lbrt/driver.rb +240 -0
  27. data/lib/lbrt/ext/string_ext.rb +25 -0
  28. data/lib/lbrt/logger.rb +32 -0
  29. data/lib/lbrt/service.rb +73 -0
  30. data/lib/lbrt/service/dsl.rb +9 -0
  31. data/lib/lbrt/service/dsl/context.rb +33 -0
  32. data/lib/lbrt/service/dsl/context/service.rb +32 -0
  33. data/lib/lbrt/service/dsl/converter.rb +38 -0
  34. data/lib/lbrt/service/exporter.rb +37 -0
  35. data/lib/lbrt/space.rb +126 -0
  36. data/lib/lbrt/space/dsl.rb +9 -0
  37. data/lib/lbrt/space/dsl/context.rb +29 -0
  38. data/lib/lbrt/space/dsl/context/space.rb +19 -0
  39. data/lib/lbrt/space/dsl/context/space/chart.rb +44 -0
  40. data/lib/lbrt/space/dsl/context/space/chart/stream.rb +48 -0
  41. data/lib/lbrt/space/dsl/converter.rb +107 -0
  42. data/lib/lbrt/space/exporter.rb +56 -0
  43. data/lib/lbrt/utils.rb +64 -0
  44. data/lib/lbrt/version.rb +3 -0
  45. metadata +202 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0587bca6521f9f9dbc40c8d8106ce602c4023242
4
+ data.tar.gz: 090509bf9e71de9643137d1e8e35afb2be48ca3e
5
+ SHA512:
6
+ metadata.gz: b80a14bd9e249bc96d72ee969d7cafa9029cbb4454372d50405866db39de6ec989f934b4e0fb4876ea52594dfba4dd8814597952d94e017b28afa67e03a78587
7
+ data.tar.gz: 672c628fc54edc1356c8cac95a5d816fc52cf2b183ab7dc3237088aefd5d69a86e5b1eb4e48d0a8fcf22f7f31a75d4b5ecf4247c0451877e091349e35e9819eb
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ test.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lbrt.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Genki Sugawara
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,180 @@
1
+ # Lbrt
2
+
3
+ A tool to manage Librato. It defines the state of Librato using DSL, and updates Librato according to DSL.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'lbrt'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install lbrt
20
+
21
+ ## Usage
22
+
23
+ ```sh
24
+ $ lbrt
25
+ Commands:
26
+ lbrt alert SUBCOMMAND # Manage alerts
27
+ lbrt help [COMMAND] # Describe available commands or one specific command
28
+ lbrt service SUBCOMMAND # Manage services
29
+ lbrt space SUBCOMMAND # Manage spaces
30
+
31
+ Options:
32
+ [--user=USER]
33
+ # Default: ENV['LIBRATO_USER']
34
+ [--token=TOKEN]
35
+ # Default: ENV['LIBRATO_TOKEN]
36
+ [--color], [--no-color]
37
+ # Default: true
38
+ [--debug], [--no-debug]
39
+
40
+ $ lbrt help alert
41
+ Commands:
42
+ lbrt alert apply FILE # Apply alerts
43
+ lbrt alert export [FILE] # Export alerts
44
+ lbrt alert help [COMMAND] # Describe subcommands or one specific subcommand
45
+
46
+ Options:
47
+ [--target=TARGET]
48
+
49
+ $ lbrt help service
50
+ Commands:
51
+ lbrt service apply FILE # Apply services
52
+ lbrt service export [FILE] # Export services
53
+ lbrt service help [COMMAND] # Describe subcommands or one specific subcommand
54
+
55
+ Options:
56
+ [--target=TARGET]
57
+
58
+ $ lbrt help space
59
+ Commands:
60
+ lbrt space apply FILE # Apply spaces
61
+ lbrt space export [FILE] # Export spaces
62
+ lbrt space help [COMMAND] # Describe subcommands or one specific subcommand
63
+
64
+ Options:
65
+ [--target=TARGET]
66
+ [--export-concurrency=N]
67
+ # Default: 32
68
+ ```
69
+
70
+ ### Export/Apply
71
+
72
+ ```sh
73
+ $ lbrt space export space.rb
74
+
75
+ $ cat space.rb
76
+ space "My Space" do
77
+ chart "My Chart" do
78
+ type "line"
79
+ stream do
80
+ metric "login-delay"
81
+ type "gauge"
82
+ ...
83
+
84
+ $ lbrt space apply space.rb --dry-run
85
+
86
+ $ lbrt space apply space.rb
87
+ ```
88
+
89
+ # DSL Example
90
+
91
+ ## Sevice
92
+
93
+ ```ruby
94
+ service "mail", "my email" do
95
+ settings "addresses"=>"sugawara@example.com"
96
+ end
97
+
98
+ service "slack", "my slack" do
99
+ settings "url"=>"https://hooks.slack.com/services/..."
100
+ end
101
+ ```
102
+
103
+ ## Alert
104
+
105
+ ```ruby
106
+ alert "alert1" do
107
+ description "My Alert1"
108
+ attributes "runbook_url"=>"http://example.com"
109
+ active true
110
+ rearm_seconds 600
111
+ rearm_per_signal false
112
+
113
+ condition do
114
+ type "below"
115
+ metric_name "login-delay"
116
+ source "foo.bar.com"
117
+ threshold 1.0
118
+ summary_function "sum"
119
+ end
120
+
121
+ service "mail", "my email"
122
+ end
123
+
124
+ alert "alert2" do
125
+ description "My Alert2"
126
+ active true
127
+ rearm_seconds 600
128
+ rearm_per_signal true
129
+
130
+ condition do
131
+ type "absent"
132
+ metric_name "login-delay2"
133
+ source nil
134
+ duration 600
135
+ end
136
+
137
+ service "slack", "my slack"
138
+ end
139
+ ```
140
+
141
+ ## Space
142
+
143
+ ```ruby
144
+ space "My Space1" do
145
+ chart "chart1" do
146
+ type "stacked"
147
+ stream do
148
+ metric "login-delay"
149
+ type "gauge"
150
+ source "*"
151
+ group_function "average"
152
+ summary_function "average"
153
+ end
154
+ end
155
+ end
156
+
157
+ space "My Space2" do
158
+ chart "chart1" do
159
+ type "line"
160
+ stream do
161
+ metric "login-delay"
162
+ type "gauge"
163
+ source "*"
164
+ group_function "breakout"
165
+ summary_function "average"
166
+ end
167
+ end
168
+
169
+ chart "chart2" do
170
+ type "line"
171
+ stream do
172
+ metric "login-delay2"
173
+ type "gauge"
174
+ source "*"
175
+ group_function "breakout"
176
+ summary_function "average"
177
+ end
178
+ end
179
+ end
180
+ ```
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "lbrt"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('../../lib', __FILE__)
3
+ require 'lbrt'
4
+
5
+ debug = ARGV.any? {|i| i == '--debug' }
6
+
7
+ begin
8
+ Lbrt::CLI::App.start(ARGV)
9
+ rescue => e
10
+ if debug
11
+ raise e
12
+ else
13
+ $stderr.puts "ERROR: #{e}".red
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lbrt/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'lbrt'
8
+ spec.version = Lbrt::VERSION
9
+ spec.authors = ['Genki Sugawara']
10
+ spec.email = ['sgwr_dts@yahoo.co.jp']
11
+
12
+ spec.summary = %q{A tool to manage Librato. It defines the state of Librato using DSL, and updates Librato according to DSL.}
13
+ spec.description = %q{A tool to manage Librato. It defines the state of Librato using DSL, and updates Librato according to DSL.}
14
+ spec.homepage = 'https://github.com/winebarrel/lbrt'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'diffy'
23
+ spec.add_dependency 'librato-client'
24
+ spec.add_dependency 'parallel'
25
+ spec.add_dependency 'term-ansicolor'
26
+ spec.add_dependency 'thor'
27
+
28
+ spec.add_development_dependency 'bundler'
29
+ spec.add_development_dependency 'rake'
30
+ spec.add_development_dependency 'rspec', '>= 3.0.0'
31
+ end
@@ -0,0 +1,46 @@
1
+ require 'diffy'
2
+ require 'librato/client'
3
+ require 'logger'
4
+ require 'parallel'
5
+ require 'singleton'
6
+ require 'tempfile'
7
+ require 'term/ansicolor'
8
+ require 'thor'
9
+
10
+ require 'lbrt/ext/string_ext'
11
+
12
+ require 'lbrt/version'
13
+ require 'lbrt/logger'
14
+ require 'lbrt/utils'
15
+
16
+ require 'lbrt/cli'
17
+ require 'lbrt/cli/alert'
18
+ require 'lbrt/cli/service'
19
+ require 'lbrt/cli/space'
20
+ require 'lbrt/cli/app'
21
+
22
+ require 'lbrt/driver'
23
+
24
+ require 'lbrt/space'
25
+ require 'lbrt/space/dsl'
26
+ require 'lbrt/space/dsl/context'
27
+ require 'lbrt/space/dsl/context/space'
28
+ require 'lbrt/space/dsl/context/space/chart'
29
+ require 'lbrt/space/dsl/context/space/chart/stream'
30
+ require 'lbrt/space/dsl/converter'
31
+ require 'lbrt/space/exporter'
32
+
33
+ require 'lbrt/alert'
34
+ require 'lbrt/alert/dsl'
35
+ require 'lbrt/alert/dsl/context'
36
+ require 'lbrt/alert/dsl/context/alert'
37
+ require 'lbrt/alert/dsl/context/alert/condition'
38
+ require 'lbrt/alert/dsl/converter'
39
+ require 'lbrt/alert/exporter'
40
+
41
+ require 'lbrt/service'
42
+ require 'lbrt/service/dsl'
43
+ require 'lbrt/service/dsl/context'
44
+ require 'lbrt/service/dsl/context/service'
45
+ require 'lbrt/service/dsl/converter'
46
+ require 'lbrt/service/exporter'
@@ -0,0 +1,91 @@
1
+ class Lbrt::Alert
2
+ include Lbrt::Logger::Helper
3
+
4
+ def initialize(client, options = {})
5
+ @client = client
6
+ @options = options
7
+ @driver = Lbrt::Driver.new(@client, @options)
8
+ end
9
+
10
+ def export(export_options = {})
11
+ exported = Lbrt::Alert::Exporter.export(@client, @options)
12
+ Lbrt::Alert::DSL.convert(exported, @options)
13
+ end
14
+
15
+ def apply(file)
16
+ walk(file)
17
+ end
18
+
19
+ private
20
+
21
+ def walk(file)
22
+ expected = load_file(file)
23
+ actual = Lbrt::Alert::Exporter.export(@client, @options)
24
+ walk_alerts(expected, actual)
25
+ end
26
+
27
+ def walk_alerts(expected, actual)
28
+ updated = false
29
+
30
+ expected.each do |name, expected_alert|
31
+ next unless Lbrt::Utils.matched?(name, @options[:target])
32
+ actual_alert = actual.delete(name)
33
+
34
+ if actual_alert
35
+ updated = walk_alert(name, expected_alert, actual_alert) || updated
36
+ else
37
+ updated = @driver.create_alert(name, expected_alert) || updated
38
+ end
39
+ end
40
+
41
+ actual.each do |name, actual_alert|
42
+ next unless Lbrt::Utils.matched?(name, @options[:target])
43
+ updated = @driver.delete_alert(name, actual_alert) || updated
44
+ end
45
+
46
+ updated
47
+ end
48
+
49
+ def walk_alert(name, expected, actual)
50
+ updated = false
51
+
52
+ actual_without_id = actual.dup
53
+ alert_id = actual_without_id.delete('id')
54
+
55
+ if differ?(expected, actual_without_id)
56
+ updated = @driver.update_alert(name, expected.merge('id' => alert_id), actual) || updated
57
+ end
58
+
59
+ updated
60
+ end
61
+
62
+ def differ?(alert1, alert2)
63
+ alert1 = normalize(alert1)
64
+ alert2 = normalize(alert2)
65
+ alert1 != alert2
66
+ end
67
+
68
+ def normalize(alert)
69
+ alert = alert.dup
70
+
71
+ alert['conditions'] = alert.fetch('conditions').map {|i|
72
+ i.delete('id')
73
+ i
74
+ }.sort_by(&:to_s)
75
+
76
+ alert['services'] = alert.fetch('services').map {|i| i.fetch('id') }.sort
77
+ alert
78
+ end
79
+
80
+ def load_file(file)
81
+ if file.kind_of?(String)
82
+ open(file) do |f|
83
+ Lbrt::Alert::DSL.parse(@client, f.read, file)
84
+ end
85
+ elsif [File, Tempfile].any? {|i| file.kind_of?(i) }
86
+ Lbrt::Alert::DSL.parse(@client, file.read, file.path)
87
+ else
88
+ raise TypeError, "can't convert #{file} into File"
89
+ end
90
+ end
91
+ end