mystro-client 0.1.0.rc1

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.
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: []