mystro-client 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ .mystro
20
+ config
21
+ log
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ # Changelog
2
+
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mystro-client.gemspec
4
+ gemspec
5
+
6
+ gem "mystro-common", :path => "../common"
7
+ gem "awesome_print"
8
+
9
+ gem "mongo"
10
+ gem "bson_ext"
11
+
12
+ gem "chef", "~> 10.20.0"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Shawn Catanzarite
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Mystro::Client
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'mystro-client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install mystro-client
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ def changelog(last=nil, single=false)
4
+ command="git --no-pager log --format='%an::::%h::::%s'"
5
+
6
+ list = `git tag`
7
+
8
+ puts "# Changelog"
9
+ puts
10
+
11
+ ordered = list.lines.sort_by {|e| (a,b,c) = e.gsub(/^v/,"").split("."); "%3d%3d%3d" % [a, b, c]}
12
+
13
+ ordered.reject{|e| (a,b,c,d) = e.split("."); !d.nil?}.reverse_each do |t|
14
+ tag = t.chomp
15
+
16
+ if last
17
+ check = { }
18
+ out = []
19
+ log = `#{command} #{last}...#{tag}`
20
+ log.lines.each do |line|
21
+ (who, hash, msg) = line.split('::::')
22
+ unless check[msg]
23
+ unless msg =~ /^Merge branch/ || msg =~ /CHANGELOG/ || msg =~ /^(v|version|changes for|preparing|ready for release|ready to release|bump version)*\s*(v|version)*\d+\.\d+\.\d+/
24
+ msg.gsub(" *", "\n*").gsub(/^\*\*/, " *").lines.each do |l|
25
+ line = l =~ /^(\s+)*\*/ ? l : "* #{l}"
26
+ out << line
27
+ end
28
+ check[msg] = hash
29
+ end
30
+ end
31
+ end
32
+ puts "## #{last}:"
33
+ out.each { |e| puts e }
34
+ #puts log
35
+ puts
36
+ end
37
+
38
+ last = tag
39
+ exit if single
40
+ end
41
+ end
42
+
43
+ desc "generate changelog output"
44
+ task :changelog do
45
+ changelog
46
+ end
47
+
48
+ desc "show current changes (changelog output from HEAD to most recent tag)"
49
+ task :current do
50
+ changelog("HEAD",true)
51
+ end
data/bin/mystro ADDED
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'clamp'
5
+ require 'awesome_print'
6
+ require 'active_support/all'
7
+
8
+ require 'mystro/client'
9
+
10
+ name = File.basename(__FILE__)
11
+
12
+ def get_client(klass, account=nil)
13
+ s = Mystro.config.server
14
+ a = account || Mystro.config.default_account
15
+ t = Mystro.config.token
16
+ #Mystro::Log.debug "server: '#{s}' account: '#{a}' token: '#{t}'"
17
+ Mystro::Client.new(klass, s, a, t)
18
+ end
19
+
20
+ module Mystro
21
+ class Command < Clamp::Command
22
+ option %w{-a --account}, "ACCOUNT", "the account to filter with", default: nil, environment_variable: "MYSTRO_ACCOUNT"
23
+ option %w{-d --debug}, :flag, "turn on debugging", default: false do |v|
24
+ Mystro::Log.console_debug
25
+ end
26
+ option %w{-q --quiet}, :flag, "turn off uncessary messages", default: false do |v|
27
+ Mystro::Log.console_quiet
28
+ end
29
+ subcommand "ssh", "ssh to server" do
30
+ option %w{-x --user}, "USER", "the user to connect as", default: "ubuntu"
31
+ option %w{-o --options}, "[OPTIONS]", "additional ssh options"
32
+ parameter "PATTERN ...", "name or pattern of server"
33
+
34
+ def execute
35
+ client = get_client(:compute, account)
36
+ list = client.search(pattern_list.join(","))
37
+
38
+ raise "no servers matched" if list.count == 0
39
+ raise "more than one server found: #{list.map{|e| e["name"]}.join(", ")}" if list.count > 1
40
+
41
+ o = list.first
42
+ host = o["long"] || o["dns"]
43
+
44
+ raise "host name not set" unless host
45
+
46
+ Mystro::Log.info "connecting as #{user} to #{o["long"] if o["long"]} (#{o["dns"]}) : #{options}"
47
+ exec("ssh #{options} #{user}@#{host}")
48
+ end
49
+ end
50
+ subcommand "csshx", "use csshx to connect to all servers of environment" do
51
+ option %w{-x --user}, "USER", "the user to connect as", default: "ubuntu"
52
+ parameter "PATTERN ...", "name or pattern of servers"
53
+
54
+ def execute
55
+ client = get_client(:compute, account)
56
+ list = client.search(pattern_list.join(","))
57
+ puts "servers found: #{list.map{|e| e["name"]}.join(", ")}"
58
+ cmd = "csshx --login #{user} #{list.map {|e| e["long"]||e["dns"]}.join(" ")}"
59
+ puts "cmd: #{cmd}"
60
+ exec(cmd)
61
+ end
62
+ end
63
+
64
+ subcommand "compute", "manage computes" do
65
+ self.default_subcommand = "list"
66
+ subcommand "list", "list computes" do
67
+ def execute
68
+ client = get_client(:compute, account)
69
+ list = client.list
70
+ Mystro::Log.warn Mystro::CLI.list(%w{Account Environment Name Roles IP DNS}, list)
71
+ end
72
+ end
73
+ subcommand "search", "list computes" do
74
+ parameter "[PATTERN] ...", "show only matching this pattern"
75
+ def execute
76
+ client = get_client(:compute, account)
77
+ list = client.search(pattern_list.join(","))
78
+ Mystro::Log.warn Mystro::CLI.list(%w{Account Environment Name Roles IP DNS}, list)
79
+ end
80
+ end
81
+ end
82
+
83
+ subcommand "balancer", "manage balancers" do
84
+ self.default_subcommand = "list"
85
+ subcommand "list", "list balancers" do
86
+ def execute
87
+ client = get_client(:balancer, account)
88
+ list = client.list
89
+ Mystro::Log.warn Mystro::CLI.list(%{Account Name}, list)
90
+ end
91
+ end
92
+ end
93
+
94
+ subcommand "account", "manage accounts" do
95
+ self.default_subcommand = "list"
96
+ subcommand "list", "list accounts" do
97
+ def execute
98
+ ap Mystro.config.to_hash
99
+ client = get_client(:account, account)
100
+ list = client.list
101
+ Mystro::Log.warn Mystro::CLI.list(%w{Name Enabled File}, list)
102
+ end
103
+ end
104
+ end
105
+
106
+ subcommand "template", "manage templates" do
107
+ self.default_subcommand = "list"
108
+ subcommand "list", "list templates" do
109
+ def execute
110
+ ap Mystro.config.to_hash
111
+ client = get_client(:template, account)
112
+ list = client.list
113
+ Mystro::Log.warn Mystro::CLI.list(%w{Name Enabled File}, list)
114
+ end
115
+ end
116
+ end
117
+
118
+ subcommand "environment", "manage environments" do
119
+ self.default_subcommand = "list"
120
+ subcommand "list", "list environments" do
121
+ def execute
122
+ client = get_client(:environment, account)
123
+ list = client.list
124
+ Mystro::Log.warn Mystro::CLI.list(%w{Deleting Name Template Computes Balancers}, list)
125
+ end
126
+ end
127
+
128
+ subcommand "show", "show environment" do
129
+ parameter "name", "id or name of environment"
130
+ def execute
131
+ client = get_client(:environment, account)
132
+ response = client.show(name)
133
+ Mystro::Log.warn Mystro::CLI.show(response) if response && response.count > 0
134
+ end
135
+ end
136
+
137
+ subcommand "destroy", "destroy environment" do
138
+ parameter "name", "id or name of environment"
139
+ def execute
140
+ client = get_client(:environment, account)
141
+ env = client.show(name)
142
+ raise "environment not found" unless env["id"]
143
+ response = client.destroy(env["id"])
144
+ if response && response.count > 0
145
+ Mystro::Log.warn Mystro::CLI.show(response)
146
+ end
147
+ end
148
+ end
149
+
150
+ subcommand "create", "create environment" do
151
+ parameter "NAME", "the name of the environment"
152
+ parameter "TEMPLATE", "the template to use"
153
+ option %w{-p --protected}, :flag, "set protected flag on environment", default: false
154
+
155
+ def execute
156
+ client = get_client(:environment, account)
157
+ response = client.create(name, template, protected?)
158
+ if response && response.count > 0
159
+ Mystro::Log.warn Mystro::CLI.show(response)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ begin
168
+ Mystro::Plugin.run("commands:loaded", Mystro::Command)
169
+ Mystro::Command.run
170
+ rescue => e
171
+ Mystro::Log.error "error: #{e.message}"
172
+ Mystro::Log.debug e
173
+ exit 1
174
+ end
@@ -0,0 +1,9 @@
1
+ module Mystro
2
+ module Client
3
+ class Account < Base
4
+ def list
5
+ api_get("accounts")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ require "terminal-table"
2
+ module Mystro
3
+ module CLI
4
+ class << self
5
+ def table(head, rows=nil)
6
+ if rows
7
+ t = Terminal::Table.new :headings => head, :rows => rows
8
+ else
9
+ t = Terminal::Table.new :rows => rows
10
+ end
11
+ t
12
+ end
13
+
14
+ def list(keys, list)
15
+ #ap list
16
+ rows = []
17
+ list.each do |l|
18
+ row = []
19
+ keys.each do |k|
20
+ row << (l[k] || l[k.downcase] || l[k.to_sym] || l[k.downcase.to_sym])
21
+ end
22
+ rows << row
23
+ end
24
+ table(keys, rows)
25
+ end
26
+
27
+ def show(obj)
28
+ keys = obj.keys
29
+ rows = []
30
+ keys.each do |k|
31
+ rows << [k, obj[k]]
32
+ end
33
+ table(%w{key value}, rows)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ module Mystro
2
+ module Client
3
+ class Compute < Base
4
+ def list
5
+ api_get("computes")
6
+ end
7
+
8
+ def search(pattern)
9
+ api_get("computes/search/#{pattern}")
10
+ end
11
+
12
+ def show(id)
13
+ api_get("computes/#{id}")
14
+ end
15
+
16
+ #def create
17
+ #
18
+ #end
19
+
20
+ def destroy(id)
21
+ api_get("computes/#{id}")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ module Mystro
2
+ module Client
3
+ class Environment < Base
4
+ def list
5
+ api_get("environments")
6
+ end
7
+
8
+ def show(id)
9
+ api_get("environments/#{id}")
10
+ end
11
+
12
+ def create(name, template, protected)
13
+ api_post("environments", { name: nil, template: nil, protected: protected })
14
+ end
15
+
16
+ def destroy(id)
17
+ api_delete("environments/#{id}")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ module Mystro
2
+ module Client
3
+ class Template < Base
4
+ def list
5
+ api_get("templates")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ unless defined?(Mystro::Client::Version)
2
+ module Mystro
3
+ module Client
4
+ module Version
5
+ MAJOR = 0
6
+ MINOR = 1
7
+ TINY = 0
8
+ TAG = "rc1"
9
+ STRING = [MAJOR, MINOR, TINY, TAG].compact.join('.')
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,86 @@
1
+ require 'active_support/all'
2
+ require "httparty"
3
+
4
+ require 'mystro-common'
5
+ require "mystro/client/version"
6
+ require "mystro/client/cli"
7
+
8
+ module Mystro
9
+ module Client
10
+ class << self
11
+ def new(klass, server, account, token=nil)
12
+ k = "Mystro::Client::#{klass.to_s.capitalize}".constantize
13
+ k.new(server,account,token)
14
+ rescue => e
15
+ Mystro::Log.error "class #{klass} not found or error instantiating"
16
+ Mystro::Log.debug e
17
+ raise "class #{klass} not found or error instantiating, #{e.message}"
18
+ end
19
+ end
20
+
21
+ class Base
22
+ include HTTParty
23
+
24
+ def initialize(server, account, token=nil)
25
+ @server = server
26
+ @token = token
27
+ @account = account
28
+ end
29
+
30
+ private
31
+
32
+ def baseurl
33
+ HTTParty.normalize_base_uri(@server)
34
+ end
35
+
36
+ def url(uri)
37
+ "#{baseurl}/#{uri}?token=#@token"
38
+ end
39
+
40
+ def api_get(u)
41
+ api_call(:get, u)
42
+ end
43
+
44
+ def api_post(u, data, headers={ })
45
+ api_call(:post, u, data, headers)
46
+ end
47
+
48
+ def api_delete(u)
49
+ api_call(:delete, u)
50
+ end
51
+
52
+ def api_call(m, u, data={}, headers={})
53
+ raise "account must be set" unless @account
54
+ method = m.to_sym
55
+ url = url("api/accounts/#@account/#{u}")
56
+
57
+ Mystro::Log.debug "<= #{url}"
58
+ Mystro::Log.debug "=> #{data}" if data && data.count > 0
59
+
60
+ r = self.class.send(method, url, body: data.to_json, headers: { 'Content-Type' => 'application/json' }.merge(headers))
61
+ Mystro::Log.debug "== #{r.response.class} #{r.response.code} #{r}"
62
+
63
+ api_response_error?(r.response)
64
+
65
+ if r.body
66
+ JSON.parse(r.body)
67
+ else
68
+ {}
69
+ end
70
+ #rescue => e
71
+ # { error: e.message, backtrace: e.backtrace }
72
+ end
73
+
74
+ def api_response_error?(r)
75
+ raise "client error, #{r.code}\n#{r.body}" if r.is_a?(Net::HTTPClientError)
76
+ raise "server error, #{r.code}\n#{r.body}" if r.is_a?(Net::HTTPServerError)
77
+ raise "unknown error, #{r.code}\n#{r.body}" if r.is_a?(Net::HTTPUnknownResponse)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ require "mystro/client/compute"
84
+ require "mystro/client/environment"
85
+ require "mystro/client/template"
86
+ require "mystro/client/account"
@@ -0,0 +1,2 @@
1
+ require "mystro/client"
2
+
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mystro/client/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "mystro-client"
8
+ gem.version = Mystro::Client::Version::STRING
9
+ gem.authors = ["Shawn Catanzarite"]
10
+ gem.email = ["me@shawncatz.com"]
11
+ gem.description = %q{mystro client}
12
+ gem.summary = %q{mystro client}
13
+ gem.homepage = "http://github.com/mystro/client"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "httparty" # talk to server's json api
21
+ gem.add_dependency "clamp"
22
+ gem.add_dependency "terminal-table"
23
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mystro-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.rc1
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Shawn Catanzarite
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: clamp
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: terminal-table
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: mystro client
63
+ email:
64
+ - me@shawncatz.com
65
+ executables:
66
+ - mystro
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - CHANGELOG.md
72
+ - Gemfile
73
+ - LICENSE.txt
74
+ - README.md
75
+ - Rakefile
76
+ - bin/mystro
77
+ - lib/mystro-client.rb
78
+ - lib/mystro/client.rb
79
+ - lib/mystro/client/account.rb
80
+ - lib/mystro/client/cli.rb
81
+ - lib/mystro/client/compute.rb
82
+ - lib/mystro/client/environment.rb
83
+ - lib/mystro/client/template.rb
84
+ - lib/mystro/client/version.rb
85
+ - mystro-client.gemspec
86
+ homepage: http://github.com/mystro/client
87
+ licenses: []
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>'
102
+ - !ruby/object:Gem::Version
103
+ version: 1.3.1
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 1.8.24
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: mystro client
110
+ test_files: []