forked from Shopify/doggy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7895f34
Showing
24 changed files
with
905 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/.bundle/ | ||
/.yardoc | ||
/Gemfile.lock | ||
/_yardoc/ | ||
/coverage/ | ||
/doc/ | ||
/pkg/ | ||
/spec/reports/ | ||
/tmp/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
source 'https://rubygems.org' | ||
|
||
# Specify your gem's dependencies in doggy.gemspec | ||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 Vlad Gorodetsky | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Doggy | ||
|
||
Doggy manages your DataDog dashboards, alerts, monitors, and screenboards. | ||
|
||
## Installation | ||
|
||
Add this line to your Gemfile: | ||
|
||
```ruby | ||
gem 'doggy' | ||
``` | ||
|
||
And then execute: | ||
|
||
$ bundle | ||
|
||
Or install it yourself as: | ||
|
||
$ gem install doggy | ||
|
||
## Usage | ||
|
||
``` | ||
# Export your DataDog credentials or use ejson | ||
$ export DATADOG_API_KEY=api_key_goes_here | ||
$ export DATADOG_APP_KEY=app_key_goes_here | ||
# Download selected items from DataDog | ||
$ doggy pull ID ID | ||
# Download all items | ||
$ doggy pull | ||
# Upload selected items to DataDog | ||
$ doggy push ID ID ID | ||
# Upload all items to DataDog | ||
$ doggy push | ||
# Create a new dashboard | ||
$ doggy create dash 'My New Dash' | ||
# Delete selected items from both DataDog and local storage | ||
$ doggy delete ID ID ID | ||
``` | ||
|
||
Note that we currently don't support global upload due to high risk of overwriting things. We'll turn this feature on after initial testing period. | ||
|
||
## Development | ||
|
||
After checking out the repo, run `bundle install` to install dependencies. | ||
|
||
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). | ||
|
||
## Contributing | ||
|
||
1. Fork it ( https://github.com/bai/doggy/fork ) | ||
2. Create your feature branch (`git checkout -b my-new-feature`) | ||
3. Commit your changes (`git commit -am 'Add some feature'`) | ||
4. Push to the branch (`git push origin my-new-feature`) | ||
5. Create a new Pull Request |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require "bundler/gem_tasks" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/env ruby | ||
|
||
# Exit cleanly from an early interrupt | ||
Signal.trap('INT') { exit 1 } | ||
|
||
require 'bundler/setup' | ||
require 'doggy/cli' | ||
|
||
Doggy::CLI.start(ARGV, :debug => true) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# coding: utf-8 | ||
lib = File.expand_path('../lib', __FILE__) | ||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | ||
require 'doggy/version' | ||
|
||
Gem::Specification.new do |spec| | ||
spec.name = "doggy" | ||
spec.version = Doggy::VERSION | ||
spec.authors = ["Vlad Gorodetsky"] | ||
spec.email = ["[email protected]"] | ||
|
||
spec.summary = %q{Syncs DataDog dashboards, alerts, screenboards, and monitors.} | ||
spec.description = %q{Syncs DataDog dashboards, alerts, screenboards, and monitors.} | ||
spec.homepage = "http://github.com/bai/doggy" | ||
spec.license = "MIT" | ||
|
||
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } | ||
spec.bindir = "bin" | ||
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } | ||
spec.require_paths = ["lib"] | ||
|
||
spec.add_development_dependency "bundler", "~> 1.9" | ||
spec.add_development_dependency "rake", "~> 10.0" | ||
spec.add_dependency "thor", "~> 0.19" | ||
spec.add_dependency "dogapi", "~> 1.17" | ||
spec.add_dependency "thread", "~> 0.2" | ||
spec.add_dependency "ejson", "~> 1.0" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
require 'fileutils' | ||
require 'pathname' | ||
require 'json' | ||
require 'yaml' | ||
require 'dogapi' | ||
|
||
require 'doggy/version' | ||
require 'doggy/client' | ||
require 'doggy/worker' | ||
require 'doggy/serializer/json' | ||
require 'doggy/serializer/yaml' | ||
require 'doggy/model/dash' | ||
require 'doggy/model/monitor' | ||
require 'doggy/model/screen' | ||
|
||
module Doggy | ||
DOG_SKIP_REGEX = /\[dog\s+skip\]/i.freeze | ||
DEFAULT_SERIALIZER_CLASS = Doggy::Serializer::Json | ||
|
||
class DoggyError < StandardError | ||
def self.status_code(code) | ||
define_method(:status_code) { code } | ||
end | ||
end | ||
|
||
class InvalidOption < DoggyError; status_code(15); end | ||
class InvalidItemType < DoggyError; status_code(10); end | ||
|
||
class << self | ||
# @option arguments [Constant] :serializer A specific serializer class to use, will be initialized by doggy and passed the object instance | ||
def serializer(options = {}) | ||
@serializer ||= options[:serializer] ? options[:serializer] : DEFAULT_SERIALIZER_CLASS | ||
end | ||
|
||
def client | ||
Doggy::Client.new | ||
end | ||
|
||
# Absolute path of where alerts are stored on the filesystem. | ||
# | ||
# @return [Pathname] | ||
def alerts_path | ||
@alerts_path ||= Pathname.new('alerts').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) } | ||
end | ||
|
||
# Absolute path of where dashes are stored on the filesystem. | ||
# | ||
# @return [Pathname] | ||
def dashes_path | ||
@dashes_path ||= Pathname.new('dashes').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) } | ||
end | ||
|
||
# Absolute path of where screens are stored on the filesystem. | ||
# | ||
# @return [Pathname] | ||
def screens_path | ||
@screens_path ||= Pathname.new('screens').expand_path(Dir.pwd).expand_path.tap { |path| FileUtils.mkdir_p(path) } | ||
end | ||
|
||
# Cleans up directory | ||
def clean_dir(dir) | ||
Dir.foreach(dir) { |f| fn = File.join(dir, f); File.delete(fn) if f != '.' && f != '..'} | ||
end | ||
|
||
def all_local_items | ||
@all_local_items ||= Dir[Doggy.dashes_path.join('**/*'), Doggy.alerts_path.join('**/*'), Doggy.screens_path.join('**/*')].inject({}) { |memo, file| memo.merge load_item(f) } | ||
end | ||
|
||
def load_item(f) | ||
filetype = File.extname(f) | ||
|
||
item = case filetype | ||
when '.yaml', '.yml' then Doggy::Serializer::Yaml.load(File.read(f)) | ||
when '.json' then Doggy::Serializer::Json.load(File.read(f)) | ||
else raise InvalidItemType | ||
end | ||
|
||
{ [ determine_type(item), item['id'] ] => item } | ||
end | ||
|
||
def determine_type(item) | ||
return 'dash' if item['graphs'] | ||
return 'monitor' if item['message'] | ||
return 'screen' if item['board_title'] | ||
raise InvalidItemType | ||
end | ||
|
||
def emit_shipit_deployment | ||
Doggy.client.dog.emit_event( | ||
Dogapi::Event.new(ENV['REVISION'], msg_title: "ShipIt Deployment by #{ENV['USER']}", tags: %w(audit shipit), source_type_name: 'shipit') | ||
) | ||
rescue => e | ||
puts "Exception: #{e.message}" | ||
end | ||
|
||
def current_version | ||
now = Time.now.to_i | ||
month_ago = now - 3600 * 24 * 30 | ||
events = Doggy.client.dog.stream(month_ago, now, tags: %w(audit shipit))[1]['events'] | ||
|
||
events[0]['text'] # most recetly deployed SHA | ||
rescue => e | ||
puts "Exception: #{e.message}" | ||
end | ||
|
||
def all_remote_dashes | ||
@all_remote_dashes ||= Doggy.client.dog.get_dashboards[1]['dashes'].inject({}) do |memo, dash| | ||
memo.merge([ 'dash', dash['id'] ] => dash) | ||
end | ||
end | ||
|
||
def all_remote_monitors | ||
@all_remote_monitors ||= Doggy.client.dog.get_all_monitors[1].inject({}) do |memo, monitor| | ||
memo.merge([ 'monitor', monitor['id'] ] => monitor) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
require 'thor' | ||
require 'doggy' | ||
|
||
module Doggy | ||
class CLI < Thor | ||
include Thor::Actions | ||
|
||
def self.start(*) | ||
super | ||
rescue Exception => e | ||
raise e | ||
ensure | ||
end | ||
|
||
def initialize(*args) | ||
super | ||
rescue UnknownArgumentError => e | ||
raise Doggy::InvalidOption, e.message | ||
ensure | ||
self.options ||= {} | ||
end | ||
|
||
check_unknown_options!(:except => [:config, :exec]) | ||
stop_on_unknown_option! :exec | ||
|
||
desc "pull [SPACE SEPARATED IDs]", "Pulls objects from DataDog" | ||
long_desc <<-D | ||
Pull objects from DataDog. If pull is successful, Doggy exits with a status of 0. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def pull(*ids) | ||
require 'doggy/cli/pull' | ||
Pull.new(options.dup, ids).run | ||
end | ||
|
||
desc "push [SPACE SEPARATED IDs]", "Pushes objects to DataDog" | ||
long_desc <<-D | ||
Pushes objects to DataDog. If push is successful, Doggy exits with a status of 0. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def push(*ids) | ||
require 'doggy/cli/push' | ||
Push.new(options.dup, ids).run | ||
end | ||
|
||
desc "create OBJECT_TYPE OBJECT_NAME", "Creates a new object on DataDog" | ||
long_desc <<-D | ||
Creates a new object on DataDog. If create is successful, Doggy exits with a status of 0. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def create(kind, name) | ||
require 'doggy/cli/create' | ||
Create.new(options.dup, kind, name).run | ||
end | ||
|
||
desc "delete SPACE SEPARATED IDs", "Deletes objects from DataDog" | ||
long_desc <<-D | ||
Deletes objects from DataDog. If delete is successful, Doggy exits with a status of 0. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def delete(*ids) | ||
require 'doggy/cli/delete' | ||
Delete.new(options.dup, ids).run | ||
end | ||
|
||
desc "mute [SPACE SEPARATED IDs]", "Mutes monitor on DataDog" | ||
long_desc <<-D | ||
Mutes monitor on DataDog. If mute is successful, Doggy exits with a status of 0. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def mute(*ids) | ||
require 'doggy/cli/mute' | ||
Mute.new(options.dup, ids).run | ||
end | ||
|
||
desc "unmute [SPACE SEPARATED IDs]", "Unmutes monitor on DataDog" | ||
long_desc <<-D | ||
Deletes objects from DataDog. If delete is successful, Doggy exits with a status of 0. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def unmute(*ids) | ||
require 'doggy/cli/unmute' | ||
Unmute.new(options.dup, ids).run | ||
end | ||
|
||
desc "version", "Detects the most recent SHA deployed by ShipIt" | ||
long_desc <<-D | ||
Scans DataDog event stream for shipit events what contain most recently deployed version | ||
of DataDog properties. | ||
If not, the error is displayed and Doggy exits status 1. | ||
D | ||
def version | ||
require 'doggy/cli/version' | ||
Version.new.run | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module Doggy | ||
class CLI::Create | ||
attr_reader :options, :kind, :name | ||
|
||
def initialize(options, kind, name) | ||
@options = options | ||
@kind = kind | ||
@name = name | ||
end | ||
|
||
def run | ||
begin | ||
case kind | ||
when 'dash', 'dashboard' then Doggy::Dash.create(name) | ||
when 'alert', 'monitor' then Doggy::Monitor.create(name) | ||
when 'screen', 'screenboard' then Doggy::Screen.create(name) | ||
else puts 'Unknown item type' | ||
end | ||
rescue DoggyError | ||
puts "Create failed." | ||
exit 1 | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.