doggy 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +53 -7
- data/examples/my-monitor.rb +14 -0
- data/exe/doggy +5 -2
- data/lib/doggy.rb +38 -71
- data/lib/doggy/cli.rb +21 -12
- data/lib/doggy/cli/delete.rb +1 -1
- data/lib/doggy/cli/edit.rb +14 -0
- data/lib/doggy/cli/pull.rb +3 -9
- data/lib/doggy/cli/sha.rb +12 -0
- data/lib/doggy/cli/version.rb +1 -6
- data/lib/doggy/definition.rb +9 -0
- data/lib/doggy/dsl.rb +73 -0
- data/lib/doggy/errors.rb +12 -0
- data/lib/doggy/friendly_errors.rb +76 -0
- data/lib/doggy/model/dash.rb +32 -39
- data/lib/doggy/model/monitor.rb +35 -36
- data/lib/doggy/model/screen.rb +21 -25
- data/lib/doggy/shared_helpers.rb +36 -0
- data/lib/doggy/version.rb +1 -1
- metadata +10 -3
- data/lib/doggy/cli/create.rb +0 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae47149af8df1d2a4f5e977b85ec4659b396c524
|
|
4
|
+
data.tar.gz: 4ba1dffaf222c19e4c6a6f6f64c75643d9bb4924
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 256336173e7b014f436b936a57eca85b9d73f9eae3dbab1a8cd73cb41b6617dc89ff4b0ee6499329270b862213816b5019be9857b57f6d2f1f056262ecaadd3f
|
|
7
|
+
data.tar.gz: 16d53a9d77766dcc441f49cf2ee8b12ee9636fed3cf155f54eb4576eb1cc624385fa20072deeff91fa8ff23a2eb26763c6e8a9d1be148f30bb4e177350cf6dc4
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -18,13 +18,32 @@ Or install it yourself as:
|
|
|
18
18
|
|
|
19
19
|
$ gem install doggy
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Authentication
|
|
22
|
+
|
|
23
|
+
To authenticate, you need to set API and APP keys for your DataDog account.
|
|
24
|
+
|
|
25
|
+
#### Environment variables
|
|
26
|
+
|
|
27
|
+
Export `DATADOG_API_KEY` and `DATADOG_APP_KEY` environment variables and `doggy` will catch them up automatically.
|
|
28
|
+
|
|
29
|
+
#### ejson
|
|
22
30
|
|
|
31
|
+
Set up `ejson` by putting `secrets.ejson` in your root object store.
|
|
32
|
+
|
|
33
|
+
#### json (plaintext)
|
|
34
|
+
|
|
35
|
+
If you're feeling adventurous, just put plaintext `secrets.json` in your root object store like this:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"datadog_api_key": "key1",
|
|
40
|
+
"datadog_app_key": "key2"
|
|
41
|
+
}
|
|
23
42
|
```
|
|
24
|
-
# Export your DataDog credentials or use ejson
|
|
25
|
-
$ export DATADOG_API_KEY=api_key_goes_here
|
|
26
|
-
$ export DATADOG_APP_KEY=app_key_goes_here
|
|
27
43
|
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```bash
|
|
28
47
|
# Download selected items from DataDog
|
|
29
48
|
$ doggy pull ID ID
|
|
30
49
|
|
|
@@ -37,14 +56,41 @@ $ doggy push ID ID ID
|
|
|
37
56
|
# Upload all items to DataDog
|
|
38
57
|
$ doggy push
|
|
39
58
|
|
|
40
|
-
#
|
|
41
|
-
$ doggy
|
|
59
|
+
# Edit a dashboard in WYSIWYG
|
|
60
|
+
$ doggy edit ID
|
|
42
61
|
|
|
43
62
|
# Delete selected items from both DataDog and local storage
|
|
44
63
|
$ doggy delete ID ID ID
|
|
64
|
+
|
|
65
|
+
# Mute monitor(s) forever
|
|
66
|
+
$ doggy mute ID ID ID
|
|
67
|
+
|
|
68
|
+
# Unmute monitor(s)
|
|
69
|
+
$ doggy unmute ID ID ID
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Example object definition
|
|
73
|
+
|
|
74
|
+
#### Ruby DSL
|
|
75
|
+
|
|
76
|
+
A DataDog object will be populated from `obj()` hash as shown below.
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
created_at = Time.parse('2015-01-01 14:00:01').to_i * 1000
|
|
80
|
+
|
|
81
|
+
query = "sum(last_1m):sum:Engine.current_thrust.status{status:error}.as_count() < 50"
|
|
82
|
+
|
|
83
|
+
obj({
|
|
84
|
+
created_at: created_at,
|
|
85
|
+
id: 100500,
|
|
86
|
+
message: "Houston, we have a problem @pagerduty-Houston",
|
|
87
|
+
name: "Engine thrust",
|
|
88
|
+
query: query,
|
|
89
|
+
type: "query alert"
|
|
90
|
+
})
|
|
45
91
|
```
|
|
46
92
|
|
|
47
|
-
|
|
93
|
+
For more examples, check the `examples` directory.
|
|
48
94
|
|
|
49
95
|
## Development
|
|
50
96
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
created_at = Time.parse('2015-01-01 14:00:01').to_i * 1000
|
|
2
|
+
|
|
3
|
+
query <<-QUERY
|
|
4
|
+
sum(last_1m):sum:Engine.current_thrust.status{status:error}.as_count() < 50
|
|
5
|
+
QUERY
|
|
6
|
+
|
|
7
|
+
obj({
|
|
8
|
+
created_at: created_at,
|
|
9
|
+
id: 100500,
|
|
10
|
+
message: "Houston, we have a problem @pagerduty-Houston",
|
|
11
|
+
name: "Engine thrust",
|
|
12
|
+
query: query,
|
|
13
|
+
type: "query alert"
|
|
14
|
+
})
|
data/exe/doggy
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
Signal.trap('INT') { exit 1 }
|
|
5
5
|
|
|
6
6
|
require 'bundler/setup'
|
|
7
|
-
require 'doggy/
|
|
7
|
+
require 'doggy/friendly_errors'
|
|
8
8
|
|
|
9
|
-
Doggy
|
|
9
|
+
Doggy.with_friendly_errors do
|
|
10
|
+
require 'doggy/cli'
|
|
11
|
+
Doggy::CLI.start(ARGV, :debug => true)
|
|
12
|
+
end
|
data/lib/doggy.rb
CHANGED
|
@@ -4,9 +4,15 @@ require 'json'
|
|
|
4
4
|
require 'yaml'
|
|
5
5
|
require 'dogapi'
|
|
6
6
|
|
|
7
|
+
require 'doggy/friendly_errors'
|
|
8
|
+
|
|
7
9
|
require 'doggy/version'
|
|
10
|
+
require 'doggy/errors'
|
|
11
|
+
require 'doggy/shared_helpers'
|
|
8
12
|
require 'doggy/client'
|
|
9
13
|
require 'doggy/worker'
|
|
14
|
+
require 'doggy/definition'
|
|
15
|
+
require 'doggy/dsl'
|
|
10
16
|
require 'doggy/serializer/json'
|
|
11
17
|
require 'doggy/serializer/yaml'
|
|
12
18
|
require 'doggy/model/dash'
|
|
@@ -14,18 +20,9 @@ require 'doggy/model/monitor'
|
|
|
14
20
|
require 'doggy/model/screen'
|
|
15
21
|
|
|
16
22
|
module Doggy
|
|
17
|
-
DOG_SKIP_REGEX =
|
|
23
|
+
DOG_SKIP_REGEX = /😱|:scream:/i.freeze
|
|
24
|
+
MANAGED_BY_DOGGY_REGEX = /🐶|\:dog\:/i.freeze
|
|
18
25
|
DEFAULT_SERIALIZER_CLASS = Doggy::Serializer::Json
|
|
19
|
-
MAX_TRIES = 5
|
|
20
|
-
|
|
21
|
-
class DoggyError < StandardError
|
|
22
|
-
def self.status_code(code)
|
|
23
|
-
define_method(:status_code) { code }
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
class InvalidOption < DoggyError; status_code(15); end
|
|
28
|
-
class InvalidItemType < DoggyError; status_code(10); end
|
|
29
26
|
|
|
30
27
|
class << self
|
|
31
28
|
# @option arguments [Constant] :serializer A specific serializer class to use, will be initialized by doggy and passed the object instance
|
|
@@ -37,50 +34,42 @@ module Doggy
|
|
|
37
34
|
Doggy::Client.new
|
|
38
35
|
end
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# @return [Pathname]
|
|
43
|
-
def alerts_path
|
|
44
|
-
@alerts_path ||= Pathname.new('alerts').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) }
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Absolute path of where dashes are stored on the filesystem.
|
|
48
|
-
#
|
|
49
|
-
# @return [Pathname]
|
|
50
|
-
def dashes_path
|
|
51
|
-
@dashes_path ||= Pathname.new('dashes').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) }
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Absolute path of where screens are stored on the filesystem.
|
|
55
|
-
#
|
|
56
|
-
# @return [Pathname]
|
|
57
|
-
def screens_path
|
|
58
|
-
@screens_path ||= Pathname.new('screens').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) }
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Cleans up directory
|
|
62
|
-
def clean_dir(dir)
|
|
63
|
-
Dir.foreach(dir) { |f| fn = File.join(dir, f); File.delete(fn) if f != '.' && f != '..'}
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def all_local_items
|
|
67
|
-
@all_local_items ||= Dir[Doggy.dashes_path.join('**/*'), Doggy.alerts_path.join('**/*'), Doggy.screens_path.join('**/*')].inject({}) { |memo, file| memo.merge load_item(f) }
|
|
37
|
+
def objects_path
|
|
38
|
+
@objects_path ||= Pathname.new('objects').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) }
|
|
68
39
|
end
|
|
69
40
|
|
|
70
41
|
def load_item(f)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
item = case filetype
|
|
42
|
+
item = case File.extname(f)
|
|
74
43
|
when '.yaml', '.yml' then Doggy::Serializer::Yaml.load(File.read(f))
|
|
75
44
|
when '.json' then Doggy::Serializer::Json.load(File.read(f))
|
|
45
|
+
when '.rb' then Doggy::Dsl.evaluate(f).obj
|
|
76
46
|
else raise InvalidItemType
|
|
77
47
|
end
|
|
78
48
|
|
|
79
|
-
|
|
49
|
+
# Hackery to support legacy dash format
|
|
50
|
+
{
|
|
51
|
+
[
|
|
52
|
+
determine_type(item), item['id'] || item['dash']['id']
|
|
53
|
+
] => item['dash'] ? item['dash'] : item
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def edit(id_or_filename)
|
|
58
|
+
if id_or_filename =~ /json|yml|yaml/
|
|
59
|
+
item_from_filename = Doggy.load_item(Doggy.objects_path.join(id_or_filename))
|
|
60
|
+
id = item_from_filename.keys[0][1]
|
|
61
|
+
else
|
|
62
|
+
id = id_or_filename
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
object = (item_from_filename || all_local_items).detect { |(type, object_id), object| object_id.to_s == id.to_s }
|
|
66
|
+
if object && object[0] && object[0][0] && type = object[0][0].sub(/^[a-z\d]*/) { $&.capitalize }
|
|
67
|
+
Object.const_get("Doggy::#{type}").edit(id)
|
|
68
|
+
end
|
|
80
69
|
end
|
|
81
70
|
|
|
82
71
|
def determine_type(item)
|
|
83
|
-
return 'dash' if item['graphs']
|
|
72
|
+
return 'dash' if item['graphs'] || item['dash']
|
|
84
73
|
return 'monitor' if item['message']
|
|
85
74
|
return 'screen' if item['board_title']
|
|
86
75
|
raise InvalidItemType
|
|
@@ -94,24 +83,7 @@ module Doggy
|
|
|
94
83
|
puts "Exception: #{e.message}"
|
|
95
84
|
end
|
|
96
85
|
|
|
97
|
-
def
|
|
98
|
-
tries = 0
|
|
99
|
-
while tries < times
|
|
100
|
-
begin
|
|
101
|
-
yield
|
|
102
|
-
break
|
|
103
|
-
rescue => e
|
|
104
|
-
error "Caught error in create_record! attempt #{tries}..."
|
|
105
|
-
error "#{e.class.name}: #{e.message}"
|
|
106
|
-
error "#{e.backtrace.join("\n")}"
|
|
107
|
-
tries += 1
|
|
108
|
-
|
|
109
|
-
raise e if tries >= times && reraise
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def current_version
|
|
86
|
+
def current_sha
|
|
115
87
|
now = Time.now.to_i
|
|
116
88
|
month_ago = now - 3600 * 24 * 30
|
|
117
89
|
events = Doggy.client.dog.stream(month_ago, now, tags: %w(audit shipit))[1]['events']
|
|
@@ -121,15 +93,10 @@ module Doggy
|
|
|
121
93
|
puts "Exception: #{e.message}"
|
|
122
94
|
end
|
|
123
95
|
|
|
124
|
-
def
|
|
125
|
-
@
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def all_remote_monitors
|
|
131
|
-
@all_remote_monitors ||= Doggy.client.dog.get_all_monitors[1].inject({}) do |memo, monitor|
|
|
132
|
-
memo.merge([ 'monitor', monitor['id'] ] => monitor)
|
|
96
|
+
def all_local_items
|
|
97
|
+
@all_local_items ||= Dir[Doggy.objects_path.join('**/*')].inject({}) do |memo, file|
|
|
98
|
+
next if File.directory?(file)
|
|
99
|
+
memo.merge!(load_item(file))
|
|
133
100
|
end
|
|
134
101
|
end
|
|
135
102
|
end
|
data/lib/doggy/cli.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Doggy
|
|
|
23
23
|
check_unknown_options!(:except => [:config, :exec])
|
|
24
24
|
stop_on_unknown_option! :exec
|
|
25
25
|
|
|
26
|
-
desc "pull
|
|
26
|
+
desc "pull OBJECT_ID OBJECT_ID OBJECT_ID", "Pulls objects from DataDog"
|
|
27
27
|
long_desc <<-D
|
|
28
28
|
Pull objects from DataDog. If pull is successful, Doggy exits with a status of 0.
|
|
29
29
|
If not, the error is displayed and Doggy exits status 1.
|
|
@@ -33,7 +33,7 @@ module Doggy
|
|
|
33
33
|
Pull.new(options.dup, ids).run
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
desc "push [
|
|
36
|
+
desc "push [OBJECT_ID OBJECT_ID OBJECT_ID]", "Pushes objects to DataDog"
|
|
37
37
|
long_desc <<-D
|
|
38
38
|
Pushes objects to DataDog. If push is successful, Doggy exits with a status of 0.
|
|
39
39
|
If not, the error is displayed and Doggy exits status 1.
|
|
@@ -43,17 +43,17 @@ module Doggy
|
|
|
43
43
|
Push.new(options.dup, ids).run
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
desc "
|
|
46
|
+
desc "edit OBJECT_ID", "Edit an existing object on DataDog"
|
|
47
47
|
long_desc <<-D
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
Opens default browser pointing to an object to edit it visually. After you finish, it will
|
|
49
|
+
display edit result.
|
|
50
50
|
D
|
|
51
|
-
def
|
|
52
|
-
require 'doggy/cli/
|
|
53
|
-
|
|
51
|
+
def edit(id)
|
|
52
|
+
require 'doggy/cli/edit'
|
|
53
|
+
Edit.new(options.dup, id).run
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
desc "delete
|
|
56
|
+
desc "delete OBJECT_ID OBJECT_ID OBJECT_ID", "Deletes objects from DataDog"
|
|
57
57
|
long_desc <<-D
|
|
58
58
|
Deletes objects from DataDog. If delete is successful, Doggy exits with a status of 0.
|
|
59
59
|
If not, the error is displayed and Doggy exits status 1.
|
|
@@ -63,7 +63,7 @@ module Doggy
|
|
|
63
63
|
Delete.new(options.dup, ids).run
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
desc "mute
|
|
66
|
+
desc "mute OBJECT_ID OBJECT_ID OBJECT_ID", "Mutes monitor on DataDog"
|
|
67
67
|
long_desc <<-D
|
|
68
68
|
Mutes monitor on DataDog. If mute is successful, Doggy exits with a status of 0.
|
|
69
69
|
If not, the error is displayed and Doggy exits status 1.
|
|
@@ -73,7 +73,7 @@ module Doggy
|
|
|
73
73
|
Mute.new(options.dup, ids).run
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
desc "unmute
|
|
76
|
+
desc "unmute OBJECT_ID OBJECT_ID OBJECT_ID", "Unmutes monitor on DataDog"
|
|
77
77
|
long_desc <<-D
|
|
78
78
|
Deletes objects from DataDog. If delete is successful, Doggy exits with a status of 0.
|
|
79
79
|
If not, the error is displayed and Doggy exits status 1.
|
|
@@ -83,12 +83,21 @@ module Doggy
|
|
|
83
83
|
Unmute.new(options.dup, ids).run
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
desc "
|
|
86
|
+
desc "sha", "Detects the most recent SHA deployed by ShipIt"
|
|
87
87
|
long_desc <<-D
|
|
88
88
|
Scans DataDog event stream for shipit events what contain most recently deployed version
|
|
89
89
|
of DataDog properties.
|
|
90
90
|
If not, the error is displayed and Doggy exits status 1.
|
|
91
91
|
D
|
|
92
|
+
def sha
|
|
93
|
+
require 'doggy/cli/sha'
|
|
94
|
+
Sha.new.run
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
desc "version", "Prints Doggy version"
|
|
98
|
+
long_desc <<-D
|
|
99
|
+
Prints Doggy version
|
|
100
|
+
D
|
|
92
101
|
def version
|
|
93
102
|
require 'doggy/cli/version'
|
|
94
103
|
Version.new.run
|
data/lib/doggy/cli/delete.rb
CHANGED
data/lib/doggy/cli/pull.rb
CHANGED
|
@@ -9,15 +9,9 @@ module Doggy
|
|
|
9
9
|
|
|
10
10
|
def run
|
|
11
11
|
begin
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Doggy::Screen.download(ids)
|
|
16
|
-
else
|
|
17
|
-
Doggy::Dash.download_all
|
|
18
|
-
Doggy::Monitor.download_all
|
|
19
|
-
Doggy::Screen.download_all
|
|
20
|
-
end
|
|
12
|
+
Doggy::Dash.download(ids)
|
|
13
|
+
Doggy::Monitor.download(ids)
|
|
14
|
+
Doggy::Screen.download(ids)
|
|
21
15
|
rescue DoggyError
|
|
22
16
|
puts "Pull failed."
|
|
23
17
|
exit 1
|
data/lib/doggy/cli/version.rb
CHANGED
data/lib/doggy/dsl.rb
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module Doggy
|
|
2
|
+
class Dsl
|
|
3
|
+
def self.evaluate(object_file)
|
|
4
|
+
builder = new
|
|
5
|
+
builder.eval_file(object_file)
|
|
6
|
+
builder.to_definition
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@obj = {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def eval_file(object_file, contents = nil)
|
|
14
|
+
contents ||= File.open(object_file.to_s, "rb") { |f| f.read }
|
|
15
|
+
instance_eval(contents, object_file.to_s, 1)
|
|
16
|
+
rescue Exception => e
|
|
17
|
+
message = "There was an error " \
|
|
18
|
+
"#{e.is_a?(ObjectFileEvalError) ? "evaluating" : "parsing"} " \
|
|
19
|
+
"`#{File.basename object_file.to_s}`: #{e.message}"
|
|
20
|
+
|
|
21
|
+
raise DSLError.new(message, object_file, e.backtrace, contents)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def obj(structure)
|
|
25
|
+
@obj = structure
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @return [Definition] the parsed object definition.
|
|
29
|
+
def to_definition
|
|
30
|
+
Definition.new(@obj)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def method_missing(name, *args)
|
|
34
|
+
raise Doggy::ObjectFileError, "Undefined local variable or method `#{name}' for object file"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
class DSLError < Doggy::ObjectFileError
|
|
40
|
+
# @return [String] the message that should be presented to the user.
|
|
41
|
+
attr_reader :message
|
|
42
|
+
|
|
43
|
+
# @return [String] the path of the dsl file that raised the exception.
|
|
44
|
+
attr_reader :dsl_path
|
|
45
|
+
|
|
46
|
+
# @return [Exception] the backtrace of the exception raised by the evaluation of the dsl file.
|
|
47
|
+
attr_reader :backtrace
|
|
48
|
+
|
|
49
|
+
# @param [Exception] backtrace @see backtrace
|
|
50
|
+
# @param [String] dsl_path @see dsl_path
|
|
51
|
+
def initialize(message, dsl_path, backtrace, contents = nil)
|
|
52
|
+
@status_code = $!.respond_to?(:status_code) && $!.status_code
|
|
53
|
+
|
|
54
|
+
@message = message
|
|
55
|
+
@dsl_path = dsl_path
|
|
56
|
+
@backtrace = backtrace
|
|
57
|
+
@contents = contents
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def status_code
|
|
61
|
+
@status_code || super
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [String] the contents of the DSL that cause the exception to
|
|
65
|
+
# be raised.
|
|
66
|
+
def contents
|
|
67
|
+
@contents ||= begin
|
|
68
|
+
dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/doggy/errors.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Doggy
|
|
2
|
+
class DoggyError < StandardError
|
|
3
|
+
def self.status_code(code)
|
|
4
|
+
define_method(:status_code) { code }
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class ObjectFileError < DoggyError; status_code(12); end
|
|
9
|
+
class ObjectFileEvalError < DoggyError; status_code(11); end
|
|
10
|
+
class InvalidOption < DoggyError; status_code(15); end
|
|
11
|
+
class InvalidItemType < DoggyError; status_code(10); end
|
|
12
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
require 'thor'
|
|
3
|
+
require 'doggy'
|
|
4
|
+
|
|
5
|
+
module Doggy
|
|
6
|
+
def self.with_friendly_errors
|
|
7
|
+
yield
|
|
8
|
+
rescue Doggy::Dsl::DSLError => e
|
|
9
|
+
puts e.message
|
|
10
|
+
exit e.status_code
|
|
11
|
+
rescue Doggy::DoggyError => e
|
|
12
|
+
puts e.message
|
|
13
|
+
puts e
|
|
14
|
+
exit e.status_code
|
|
15
|
+
rescue Thor::AmbiguousTaskError => e
|
|
16
|
+
puts e.message
|
|
17
|
+
exit 15
|
|
18
|
+
rescue Thor::UndefinedTaskError => e
|
|
19
|
+
puts e.message
|
|
20
|
+
exit 15
|
|
21
|
+
rescue Thor::Error => e
|
|
22
|
+
puts e.message
|
|
23
|
+
exit 1
|
|
24
|
+
rescue Interrupt => e
|
|
25
|
+
puts "\nQuitting..."
|
|
26
|
+
puts e
|
|
27
|
+
exit 1
|
|
28
|
+
rescue SystemExit => e
|
|
29
|
+
exit e.status
|
|
30
|
+
rescue Exception => e
|
|
31
|
+
request_issue_report_for(e)
|
|
32
|
+
exit 1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.request_issue_report_for(e)
|
|
36
|
+
puts <<-EOS.gsub(/^ {6}/, "")
|
|
37
|
+
--- ERROR REPORT TEMPLATE -------------------------------------------------------
|
|
38
|
+
- What did you do?
|
|
39
|
+
|
|
40
|
+
I ran the command `#{$PROGRAM_NAME} #{ARGV.join(" ")}`
|
|
41
|
+
|
|
42
|
+
- What did you expect to happen?
|
|
43
|
+
|
|
44
|
+
I expected Doggy to...
|
|
45
|
+
|
|
46
|
+
- What happened instead?
|
|
47
|
+
|
|
48
|
+
Instead, what actually happened was...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
Error details
|
|
52
|
+
|
|
53
|
+
#{e.class}: #{e.message}
|
|
54
|
+
#{e.backtrace.join("\n ")}
|
|
55
|
+
|
|
56
|
+
--- TEMPLATE END ----------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
EOS
|
|
59
|
+
|
|
60
|
+
puts "Unfortunately, an unexpected error occurred, and Doggy cannot continue."
|
|
61
|
+
|
|
62
|
+
puts <<-EOS.gsub(/^ {6}/, "")
|
|
63
|
+
|
|
64
|
+
First, try this link to see if there are any existing issue reports for this error:
|
|
65
|
+
#{issues_url(e)}
|
|
66
|
+
|
|
67
|
+
If there aren't any reports for this error yet, please create copy and paste the report template above into a new issue. Don't forget to anonymize any private data! The new issue form is located at:
|
|
68
|
+
https://github.com/bai/doggy/issues/new
|
|
69
|
+
EOS
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.issues_url(exception)
|
|
73
|
+
"https://github.com/bai/doggy/search?q=" \
|
|
74
|
+
"#{CGI.escape(exception.message.lines.first.chomp)}&type=Issues"
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/doggy/model/dash.rb
CHANGED
|
@@ -1,26 +1,9 @@
|
|
|
1
1
|
module Doggy
|
|
2
2
|
class Dash
|
|
3
|
-
def initialize(**options)
|
|
4
|
-
@id = options[:id]
|
|
5
|
-
@title = options[:title] || raw_local['title']
|
|
6
|
-
@description = options[:description] || raw_local['description']
|
|
7
|
-
@graphs = options[:graphs] || raw_local['graphs']
|
|
8
|
-
@template_variables = options[:template_variables] || raw_local['template_variables']
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def self.download_all
|
|
12
|
-
ids = Doggy.client.dog.get_dashboards[1]['dashes'].map { |d| d['id'] }
|
|
13
|
-
puts "Downloading #{ids.size} dashboards..."
|
|
14
|
-
Doggy.clean_dir(Doggy.dashes_path)
|
|
15
|
-
download(ids)
|
|
16
|
-
rescue => e
|
|
17
|
-
puts "Exception: #{e.message}"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
3
|
def self.upload_all
|
|
21
|
-
|
|
22
|
-
puts "Uploading #{
|
|
23
|
-
upload(
|
|
4
|
+
objects = all_local_items.find_all { |(type, id), object| type == 'dash' }
|
|
5
|
+
puts "Uploading #{objects.size} dashboards"
|
|
6
|
+
upload(objects.map { |(type, id), object| id })
|
|
24
7
|
rescue => e
|
|
25
8
|
puts "Exception: #{e.message}"
|
|
26
9
|
end
|
|
@@ -33,20 +16,23 @@ module Doggy
|
|
|
33
16
|
Doggy::Worker.new(threads: Doggy::Worker::CONCURRENT_STREAMS) { |id| new(id: id).push }.call([*ids])
|
|
34
17
|
end
|
|
35
18
|
|
|
36
|
-
def self.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
19
|
+
def self.edit(id)
|
|
20
|
+
system %{open "https://app.datadoghq.com/dash/#{id}"}
|
|
21
|
+
if SharedHelpers.agree("Are you done?")
|
|
22
|
+
puts 'Here is the output of your edit:'
|
|
23
|
+
puts Doggy::Serializer::Json.dump(new(id: id).raw)
|
|
24
|
+
else
|
|
25
|
+
puts "run, rabbit run / dig that hole, forget the sun / and when at last the work is done / don't sit down / it's time to dig another one"
|
|
26
|
+
edit(id)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(**options)
|
|
31
|
+
@id = options[:id]
|
|
32
|
+
@title = options[:title] || raw_local['title']
|
|
33
|
+
@description = options[:description] || raw_local['description']
|
|
34
|
+
@graphs = options[:graphs] || raw_local['graphs']
|
|
35
|
+
@template_variables = options[:template_variables] || raw_local['template_variables']
|
|
50
36
|
end
|
|
51
37
|
|
|
52
38
|
def raw
|
|
@@ -58,7 +44,10 @@ module Doggy
|
|
|
58
44
|
|
|
59
45
|
def raw_local
|
|
60
46
|
return {} unless File.exists?(path)
|
|
61
|
-
@raw_local ||=
|
|
47
|
+
@raw_local ||= begin
|
|
48
|
+
object = Doggy.serializer.load(File.read(path))
|
|
49
|
+
object['dash'] ? object['dash'] : object
|
|
50
|
+
end
|
|
62
51
|
end
|
|
63
52
|
|
|
64
53
|
def save
|
|
@@ -72,12 +61,17 @@ module Doggy
|
|
|
72
61
|
def push
|
|
73
62
|
return unless File.exists?(path)
|
|
74
63
|
return if @title =~ Doggy::DOG_SKIP_REGEX
|
|
64
|
+
return unless Doggy.determine_type(raw_local) == 'dash'
|
|
65
|
+
|
|
66
|
+
# Managed by doggy (TM)
|
|
67
|
+
@title = @title =~ MANAGED_BY_DOGGY_REGEX ? @title : @title + " 🐶"
|
|
68
|
+
|
|
75
69
|
if @id
|
|
76
|
-
|
|
70
|
+
SharedHelpers.with_retry do
|
|
77
71
|
Doggy.client.dog.update_dashboard(@id, @title, @description, @graphs, @template_variables)
|
|
78
72
|
end
|
|
79
73
|
else
|
|
80
|
-
|
|
74
|
+
SharedHelpers.with_retry do
|
|
81
75
|
dash = Doggy.client.dog.create_dashboard(@title, @description, @graphs)
|
|
82
76
|
end
|
|
83
77
|
# FIXME: Remove duplication
|
|
@@ -88,13 +82,12 @@ module Doggy
|
|
|
88
82
|
|
|
89
83
|
def delete
|
|
90
84
|
Doggy.client.dog.delete_dashboard(@id)
|
|
91
|
-
File.unlink(path)
|
|
92
85
|
end
|
|
93
86
|
|
|
94
87
|
private
|
|
95
88
|
|
|
96
89
|
def path
|
|
97
|
-
"#{Doggy.
|
|
90
|
+
"#{Doggy.objects_path}/#{@id}.json"
|
|
98
91
|
end
|
|
99
92
|
end
|
|
100
93
|
end
|
data/lib/doggy/model/monitor.rb
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
module Doggy
|
|
2
2
|
class Monitor
|
|
3
|
-
def initialize(**options)
|
|
4
|
-
@id = options[:id]
|
|
5
|
-
@query = options[:query]
|
|
6
|
-
@silenced = options[:silenced]
|
|
7
|
-
@name = options[:name]
|
|
8
|
-
@timeout_h = options[:timeout_h]
|
|
9
|
-
@message = options[:message]
|
|
10
|
-
@notify_audit = options[:notify_audit]
|
|
11
|
-
@notify_no_data = options[:notify_no_data]
|
|
12
|
-
@renotify_interval = options[:renotify_interval]
|
|
13
|
-
@escalation_message = options[:escalation_message]
|
|
14
|
-
@no_data_timeframe = options[:no_data_timeframe]
|
|
15
|
-
@silenced_timeout_ts = options[:silenced_timeout_ts]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.download_all
|
|
19
|
-
ids = Doggy.client.dog.get_all_alerts[1]['alerts'].map { |d| d['id'] }
|
|
20
|
-
puts "Downloading #{ids.size} alerts..."
|
|
21
|
-
Doggy.clean_dir(Doggy.alerts_path)
|
|
22
|
-
download(ids)
|
|
23
|
-
rescue => e
|
|
24
|
-
puts "Exception: #{e.message}"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
3
|
def self.upload_all
|
|
28
|
-
|
|
29
|
-
puts "Uploading #{
|
|
30
|
-
upload(
|
|
4
|
+
objects = all_local_items.find_all { |(type, id), object| type == 'monitor' }
|
|
5
|
+
puts "Uploading #{objects.size} monitors"
|
|
6
|
+
upload(objects.map { |(type, id), object| id })
|
|
31
7
|
rescue => e
|
|
32
8
|
puts "Exception: #{e.message}"
|
|
33
9
|
end
|
|
@@ -48,11 +24,30 @@ module Doggy
|
|
|
48
24
|
Doggy::Worker.new(threads: Doggy::Worker::CONCURRENT_STREAMS) { |id| new(id: id).unmute }.call([*ids])
|
|
49
25
|
end
|
|
50
26
|
|
|
51
|
-
def self.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
27
|
+
def self.edit(id)
|
|
28
|
+
system %{open "https://app.datadoghq.com/monitors##{id}"}
|
|
29
|
+
if SharedHelpers.agree("Are you done?")
|
|
30
|
+
puts 'Here is the output of your edit:'
|
|
31
|
+
puts Doggy::Serializer::Json.dump(new(id: id).raw)
|
|
32
|
+
else
|
|
33
|
+
puts "run, rabbit run / dig that hole, forget the sun / and when at last the work is done / don't sit down / it's time to dig another one"
|
|
34
|
+
edit(id)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def initialize(**options)
|
|
39
|
+
@id = options[:id]
|
|
40
|
+
@query = options[:query]
|
|
41
|
+
@silenced = options[:silenced]
|
|
42
|
+
@name = options[:name]
|
|
43
|
+
@timeout_h = options[:timeout_h]
|
|
44
|
+
@message = options[:message]
|
|
45
|
+
@notify_audit = options[:notify_audit]
|
|
46
|
+
@notify_no_data = options[:notify_no_data]
|
|
47
|
+
@renotify_interval = options[:renotify_interval]
|
|
48
|
+
@escalation_message = options[:escalation_message]
|
|
49
|
+
@no_data_timeframe = options[:no_data_timeframe]
|
|
50
|
+
@silenced_timeout_ts = options[:silenced_timeout_ts]
|
|
56
51
|
end
|
|
57
52
|
|
|
58
53
|
def raw
|
|
@@ -94,10 +89,15 @@ module Doggy
|
|
|
94
89
|
|
|
95
90
|
def push
|
|
96
91
|
return if @name =~ Doggy::DOG_SKIP_REGEX
|
|
92
|
+
return unless Doggy.determine_type(raw_local) == 'monitor'
|
|
93
|
+
|
|
94
|
+
# Managed by doggy (TM)
|
|
95
|
+
@name = @name =~ MANAGED_BY_DOGGY_REGEX ? @name : @name + " 🐶"
|
|
96
|
+
|
|
97
97
|
if @id
|
|
98
98
|
return unless File.exists?(path)
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
SharedHelpers.with_retry do
|
|
101
101
|
Doggy.client.dog.update_monitor(@id, @query || raw_local['query'], {
|
|
102
102
|
name: @name || raw_local['name'],
|
|
103
103
|
timeout_h: @timeout_h || raw_local['timeout_h'],
|
|
@@ -114,7 +114,7 @@ module Doggy
|
|
|
114
114
|
})
|
|
115
115
|
end
|
|
116
116
|
else
|
|
117
|
-
|
|
117
|
+
SharedHelpers.with_retry do
|
|
118
118
|
result = Doggy.client.dog.monitor('metric alert', @query, name: @name)
|
|
119
119
|
end
|
|
120
120
|
@id = result[1]['id']
|
|
@@ -123,13 +123,12 @@ module Doggy
|
|
|
123
123
|
|
|
124
124
|
def delete
|
|
125
125
|
Doggy.client.dog.delete_alert(@id)
|
|
126
|
-
File.unlink(path)
|
|
127
126
|
end
|
|
128
127
|
|
|
129
128
|
private
|
|
130
129
|
|
|
131
130
|
def path
|
|
132
|
-
"#{Doggy.
|
|
131
|
+
"#{Doggy.objects_path}/#{@id}.json"
|
|
133
132
|
end
|
|
134
133
|
|
|
135
134
|
def mute_state_for(id)
|
data/lib/doggy/model/screen.rb
CHANGED
|
@@ -1,23 +1,9 @@
|
|
|
1
1
|
module Doggy
|
|
2
2
|
class Screen
|
|
3
|
-
def initialize(**options)
|
|
4
|
-
@id = options[:id]
|
|
5
|
-
@description = options[:description] || raw_local
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def self.download_all
|
|
9
|
-
ids = Doggy.client.dog.get_all_screenboards[1]['screenboards'].map { |d| d['id'] }
|
|
10
|
-
puts "Downloading #{ids.size} screenboards..."
|
|
11
|
-
Doggy.clean_dir(Doggy.screens_path)
|
|
12
|
-
download(ids)
|
|
13
|
-
rescue => e
|
|
14
|
-
puts "Exception: #{e.message}"
|
|
15
|
-
end
|
|
16
|
-
|
|
17
3
|
def self.upload_all
|
|
18
|
-
|
|
19
|
-
puts "Uploading #{
|
|
20
|
-
upload(
|
|
4
|
+
objects = all_local_items.find_all { |(type, id), object| type == 'screen' }
|
|
5
|
+
puts "Uploading #{objects.size} screens"
|
|
6
|
+
upload(objects.map { |(type, id), object| id })
|
|
21
7
|
rescue => e
|
|
22
8
|
puts "Exception: #{e.message}"
|
|
23
9
|
end
|
|
@@ -30,10 +16,20 @@ module Doggy
|
|
|
30
16
|
Doggy::Worker.new(threads: Doggy::Worker::CONCURRENT_STREAMS) { |id| new(id: id).push }.call([*ids])
|
|
31
17
|
end
|
|
32
18
|
|
|
33
|
-
def self.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
def self.edit(id)
|
|
20
|
+
system %{open "https://app.datadoghq.com/screen/#{id}"}
|
|
21
|
+
if SharedHelpers.agree("Are you done?")
|
|
22
|
+
puts 'Here is the output of your edit:'
|
|
23
|
+
puts Doggy::Serializer::Json.dump(new(id: id).raw)
|
|
24
|
+
else
|
|
25
|
+
puts "run, rabbit run / dig that hole, forget the sun / and when at last the work is done / don't sit down / it's time to dig another one"
|
|
26
|
+
edit(id)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(**options)
|
|
31
|
+
@id = options[:id]
|
|
32
|
+
@description = options[:description] || raw_local
|
|
37
33
|
end
|
|
38
34
|
|
|
39
35
|
def raw
|
|
@@ -57,12 +53,13 @@ module Doggy
|
|
|
57
53
|
|
|
58
54
|
def push
|
|
59
55
|
return if @description =~ Doggy::DOG_SKIP_REGEX
|
|
56
|
+
return unless Doggy.determine_type(raw_local) == 'screen'
|
|
60
57
|
if @id
|
|
61
|
-
|
|
58
|
+
SharedHelpers.with_retry do
|
|
62
59
|
Doggy.client.dog.update_screenboard(@id, @description)
|
|
63
60
|
end
|
|
64
61
|
else
|
|
65
|
-
|
|
62
|
+
SharedHelpers.with_retry do
|
|
66
63
|
result = Doggy.client.dog.create_screenboard(@description)
|
|
67
64
|
end
|
|
68
65
|
@id = result[1]['id']
|
|
@@ -72,13 +69,12 @@ module Doggy
|
|
|
72
69
|
|
|
73
70
|
def delete
|
|
74
71
|
Doggy.client.dog.delete_screenboard(@id)
|
|
75
|
-
File.unlink(path)
|
|
76
72
|
end
|
|
77
73
|
|
|
78
74
|
private
|
|
79
75
|
|
|
80
76
|
def path
|
|
81
|
-
"#{Doggy.
|
|
77
|
+
"#{Doggy.objects_path}/#{@id}.json"
|
|
82
78
|
end
|
|
83
79
|
end
|
|
84
80
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Doggy
|
|
2
|
+
module SharedHelpers
|
|
3
|
+
MAX_TRIES = 5
|
|
4
|
+
|
|
5
|
+
def self.strip_heredoc(string)
|
|
6
|
+
indent = string.scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
|
|
7
|
+
string.gsub(/^[ \t]{#{indent}}/, '')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.with_retry(times: MAX_TRIES, reraise: false)
|
|
11
|
+
tries = 0
|
|
12
|
+
while tries < times
|
|
13
|
+
begin
|
|
14
|
+
yield
|
|
15
|
+
break
|
|
16
|
+
rescue => e
|
|
17
|
+
error "Caught error! Attempt #{tries}..."
|
|
18
|
+
error "#{e.class.name}: #{e.message}"
|
|
19
|
+
error "#{e.backtrace.join("\n")}"
|
|
20
|
+
tries += 1
|
|
21
|
+
|
|
22
|
+
raise e if tries >= times && reraise
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.agree(prompt)
|
|
28
|
+
raise Error, "Not a tty" unless $stdin.tty?
|
|
29
|
+
|
|
30
|
+
puts prompt + " (Y/N)"
|
|
31
|
+
line = $stdin.readline.chomp.upcase
|
|
32
|
+
puts
|
|
33
|
+
line == "Y"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/doggy/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: doggy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vlad Gorodetsky
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-09-
|
|
11
|
+
date: 2015-09-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -111,22 +111,29 @@ files:
|
|
|
111
111
|
- bin/console
|
|
112
112
|
- bin/setup
|
|
113
113
|
- doggy.gemspec
|
|
114
|
+
- examples/my-monitor.rb
|
|
114
115
|
- exe/doggy
|
|
115
116
|
- lib/doggy.rb
|
|
116
117
|
- lib/doggy/cli.rb
|
|
117
|
-
- lib/doggy/cli/create.rb
|
|
118
118
|
- lib/doggy/cli/delete.rb
|
|
119
|
+
- lib/doggy/cli/edit.rb
|
|
119
120
|
- lib/doggy/cli/mute.rb
|
|
120
121
|
- lib/doggy/cli/pull.rb
|
|
121
122
|
- lib/doggy/cli/push.rb
|
|
123
|
+
- lib/doggy/cli/sha.rb
|
|
122
124
|
- lib/doggy/cli/unmute.rb
|
|
123
125
|
- lib/doggy/cli/version.rb
|
|
124
126
|
- lib/doggy/client.rb
|
|
127
|
+
- lib/doggy/definition.rb
|
|
128
|
+
- lib/doggy/dsl.rb
|
|
129
|
+
- lib/doggy/errors.rb
|
|
130
|
+
- lib/doggy/friendly_errors.rb
|
|
125
131
|
- lib/doggy/model/dash.rb
|
|
126
132
|
- lib/doggy/model/monitor.rb
|
|
127
133
|
- lib/doggy/model/screen.rb
|
|
128
134
|
- lib/doggy/serializer/json.rb
|
|
129
135
|
- lib/doggy/serializer/yaml.rb
|
|
136
|
+
- lib/doggy/shared_helpers.rb
|
|
130
137
|
- lib/doggy/version.rb
|
|
131
138
|
- lib/doggy/worker.rb
|
|
132
139
|
homepage: http://github.com/bai/doggy
|
data/lib/doggy/cli/create.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
module Doggy
|
|
2
|
-
class CLI::Create
|
|
3
|
-
attr_reader :options, :kind, :name
|
|
4
|
-
|
|
5
|
-
def initialize(options, kind, name)
|
|
6
|
-
@options = options
|
|
7
|
-
@kind = kind
|
|
8
|
-
@name = name
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def run
|
|
12
|
-
begin
|
|
13
|
-
case kind
|
|
14
|
-
when 'dash', 'dashboard' then Doggy::Dash.create(name)
|
|
15
|
-
when 'alert', 'monitor' then Doggy::Monitor.create(name)
|
|
16
|
-
when 'screen', 'screenboard' then Doggy::Screen.create(name)
|
|
17
|
-
else puts 'Unknown item type'
|
|
18
|
-
end
|
|
19
|
-
rescue DoggyError
|
|
20
|
-
puts "Create failed."
|
|
21
|
-
exit 1
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|