deis-client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 58e6e3b57178229a12238962facc11faa3e81cb1
4
+ data.tar.gz: 69ca12a1ffda0e319ca5d2229cb2349ef401253f
5
+ SHA512:
6
+ metadata.gz: a015c5ac514dceb06d4460be73c1cb09fdbc4674de061b9c2fb8c392d04a167aca37c7ce165e07ef30fb076080d14972c46ace05f815e4f0fe00842b6d18779a
7
+ data.tar.gz: 701a4f5f4848ed78552048b7c952d8d120a817e81aacd0db5a68d27390521f87e719122684bc31f540f163fe7d9b563a421cb40338b726c98b3d2d47cfb29074
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ # Gemfile.lock
31
+ # .ruby-version
32
+ # .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 AnyPresence, Inc.
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # deis-client
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'deis-client'
3
+ s.version = '0.0.1'
4
+ s.date = '2015-07-08'
5
+ s.summary = "Deis REST operations in a Ruby gem."
6
+ s.description = "Deis Platform REST (V1.5) client for Ruby."
7
+ s.authors = ["AnyPresence"]
8
+ s.email = 'engineering@anypresence.com'
9
+ s.files = `git ls-files -z`.split("\0")
10
+ s.homepage = 'http://rubygems.org/gems/deis_client'
11
+ s.license = 'MIT'
12
+ s.add_dependency('rest-client', '>= 1.6.7', '< 2.0')
13
+ s.required_ruby_version = '>= 1.9.3'
14
+ end
@@ -0,0 +1,174 @@
1
+ require 'uri'
2
+ require 'rest-client'
3
+
4
+ class DeisError < StandardError
5
+ end
6
+
7
+ class DeisClient
8
+ attr_reader :user_token
9
+
10
+ REQUEST_TIMEOUT = 180 #seconds
11
+ VERIFY_SSL = false
12
+
13
+ def initialize(controller_uri, username, password, mock=false)
14
+ @mock = mock
15
+ raise DeisError.new("No username or password detected!") if username.nil? || password.nil?
16
+ raise DeisError.new("You must specify a URI for Deis controller!") unless controller_uri =~ /\A#{URI::regexp}\z/
17
+ @deis_controller = controller_uri
18
+ login(username, password)
19
+ self
20
+ end
21
+
22
+ def login(username, password)
23
+ if @mock
24
+ @user_token = "ABC123"
25
+ else
26
+ payload = {"username" => username, "password" => password}
27
+ response = RestClient::Request.execute(:method => :post, :url => login_url, :payload => payload.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => {:content_type => :json, :accept => :json})
28
+ body = JSON.parse response.body
29
+ @user_token = body.fetch('token')
30
+ end
31
+ end
32
+
33
+ def app_create(app_name)
34
+ if @mock
35
+ {}
36
+ else
37
+ payload = app_name.nil? ? Hash.new : {"id" => app_name}
38
+ response = RestClient::Request.execute(:method => :post, :url => apps_url, :payload => payload.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
39
+ JSON.parse response.body
40
+ end
41
+ end
42
+
43
+ def app_destroy(app_name)
44
+ raise DeisError.new("App name is required") if app_name.nil?
45
+ if @mock
46
+ {}
47
+ else
48
+ response = RestClient::Request.execute(:method => :delete, :url => app_url(app_name), :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
49
+ response.code == 204
50
+ end
51
+ end
52
+
53
+ def app_scale(app_name, process_type, process_count)
54
+ raise DeisError.new("App name is required") if app_name.nil?
55
+ raise DeisError.new("Process type is required. Supported values are 'web' or 'worker'") unless ["web", "worker"].include? process_type
56
+ raise DeisError.new("Process count is required") unless process_count.is_a? Fixnum
57
+ raise DeisError.new("Process count cannnot be negative") if process_count < 0
58
+ if @mock
59
+ false
60
+ else
61
+ payload = {process_type => process_count}
62
+ response = RestClient::Request.execute(:method => :post, :url => scale_url(app_name), :payload => payload.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
63
+ response.code == 204
64
+ end
65
+ end
66
+
67
+ def app_restart(app_name)
68
+ raise DeisError.new("App name is required") if app_name.nil?
69
+ if @mock
70
+ false
71
+ else
72
+ response = RestClient::Request.execute(:method => :post, :url => app_restart_url(app_name), :payload => {}.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
73
+ response.code == 200
74
+ end
75
+ end
76
+
77
+
78
+ def key_add(user_name, ssh_public_key)
79
+ raise DeisError.new("Username is required") if user_name.nil?
80
+ raise DeisError.new("SSH key is required") if ssh_public_key.nil?
81
+ if @mock
82
+ {}
83
+ else
84
+ payload = {"id" => user_name, "public" => ssh_public_key}
85
+ response = RestClient::Request.execute(:method => :post, :url => keys_url, :payload => payload.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
86
+ JSON.parse response.body
87
+ end
88
+ end
89
+
90
+ def config_set(app_name, config_hash={})
91
+ raise DeisError.new("App name is required") if app_name.nil?
92
+ if @mock || config_hash.empty?
93
+ {}
94
+ else
95
+ payload = {"values" => config_hash}
96
+ response = RestClient::Request.execute(:method => :post, :url => config_url(app_name), :payload => payload.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
97
+ JSON.parse response.body
98
+ end
99
+ end
100
+
101
+ def config_get(app_name)
102
+ raise DeisError.new("App name is required") if app_name.nil?
103
+ if @mock
104
+ {}
105
+ else
106
+ response = RestClient::Request.execute(:method => :get, :url => config_url(app_name), :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
107
+ hash = JSON.parse response.body
108
+ hash["values"]
109
+ end
110
+ end
111
+
112
+ def logs_get(app_name)
113
+ raise DeisError.new("App name is required") if app_name.nil?
114
+ if @mock
115
+ {}
116
+ else
117
+ RestClient::Request.execute(:method => :get, :url => log_url(app_name), :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
118
+ end
119
+ end
120
+
121
+ def command_run(app_name, command)
122
+ raise DeisError.new("App name is required") if app_name.nil?
123
+ raise DeisError.new("Command string is required") if command.nil?
124
+ if @mock
125
+ {}
126
+ else
127
+ payload = {"command" => command}
128
+ response = RestClient::Request.execute(:method => :post, :url => command_run_url(app_name), :payload => payload.to_json, :timeout => REQUEST_TIMEOUT, :verify_ssl => VERIFY_SSL, :headers => headers)
129
+ JSON.parse response.body
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ def login_url
136
+ "#{@deis_controller}/v1/auth/login/"
137
+ end
138
+
139
+ def apps_url
140
+ "#{@deis_controller}/v1/apps/"
141
+ end
142
+
143
+ def app_url(app_name)
144
+ "#{apps_url}#{app_name}/"
145
+ end
146
+
147
+ def app_restart_url(app_name)
148
+ "#{app_url(app_name)}containers/restart/"
149
+ end
150
+
151
+ def config_url(app_name)
152
+ "#{app_url(app_name)}config/"
153
+ end
154
+
155
+ def scale_url(app_name)
156
+ "#{app_url(app_name)}scale/"
157
+ end
158
+
159
+ def log_url(app_name)
160
+ "#{app_url(app_name)}logs/"
161
+ end
162
+
163
+ def command_run_url(app_name)
164
+ "#{app_url(app_name)}run/"
165
+ end
166
+
167
+ def keys_url
168
+ "#{@deis_controller}/v1/keys/"
169
+ end
170
+
171
+ def headers
172
+ {:Authorization => "token #{@user_token}", :content_type => :json, :accept => :json}
173
+ end
174
+ end
@@ -0,0 +1,112 @@
1
+ require 'minitest/autorun'
2
+ require 'deis_client'
3
+
4
+ class DeisClientTest < Minitest::Test
5
+ def self.test_order
6
+ :alpha
7
+ end
8
+
9
+ def setup
10
+ @username = ENV['DEIS_ADMIN_USER'] || 'humpty'
11
+ @password = ENV['DEIS_ADMIN_PASSWORD'] || 'dumpty'
12
+ @mock = true
13
+ @instance_name = 'luxury-jumpsuit'
14
+ @client = DeisClient.new(ENV['DEIS_CONTROLLER'] || "http://controller.example.com",
15
+ @username,
16
+ @password,
17
+ @mock
18
+ )
19
+ @key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDZ47ISBG2bIQYV62g5qC58tRvHKh+OMITuxT/YyZzIZYmpDncmDLvaBVX7e3/V5d4CdJui/0pHGW/lnUtUUnTwexO1RABPENiCmUQAD7+QZbKyrYE43GHcXcZjEnAJIDt0FmRjGPFr99x/1kuKCAsouly6uTeRgt3DIjJWCkfvo5PBsdezgChcMCj3EDBqlR83qNFnL+at2I73Fv7GdNV/n7ORSru9POUGAqjdAv2jw02eZYKrxCZPRGimYRe+o0G7aMc6GDjWmonSL08yLryKIjrBD7C+YAzO8Z9UTF2EjgHQ2pKGQuPB5YS8X5APGQAy7HVWlMgBK6jcDuKz9ITLcKkkLUpX4ILch3ppR9OahxYCyJsTegHE3Vwtd0lP53eP/XsPOtMmd+gMch+N/HcK8N9U3c/3+LQpof1KG/SzFvOcplj7G29FDuMI9ziFkOxj7HBjJb4q3LYvOHAfFJIdmLcEH5ckyodxVRCKkravMJRT9X9S8G2MkX+J9/qH/3HNedgvWuqvtCdaozWnjTTU2yoLKUdoMKt1FHRLNLJKFdi27+sapTfP0Cs4IR8LY9sZw1LRk7YzCz21nb5jQs6X/npt2Szv7z0WZ/QUl81jQN6iVY4A5XZDy5cx9mXkxuBYSMl1PMLOR2k30bk6hnTmurhHFAgcDdmOQ3qhq9eUmQ== user@example.com"
20
+ end
21
+
22
+
23
+ def test_app_create
24
+ response = @client.app_create(nil)
25
+ unless @mock
26
+ app = response["id"]
27
+ assert response["id"]
28
+ assert response["owner"] == @username
29
+ assert response["uuid"]
30
+ response = @client.logs_get(app)
31
+ assert response.size > 0
32
+ response = @client.app_destroy(app)
33
+ end
34
+ end
35
+
36
+ =begin
37
+ def test_key_add
38
+ assert_raises(DeisError) {
39
+ @client.key_add(nil, nil)
40
+ }
41
+ response = @client.key_add(@username, @key)
42
+ unless @mock
43
+ assert response["id"]
44
+ assert response["owner"] == @username
45
+ assert response["public"] == @key
46
+ end
47
+ end
48
+ =end
49
+
50
+ def test_config
51
+ assert_raises(DeisError) {
52
+ @client.config_set(nil, nil)
53
+ }
54
+ response = @client.app_create(nil)
55
+ app_name = response["id"]
56
+ unless @mock
57
+ assert @client.config_set(app_name, {}).empty?
58
+ configs = {"HELLO" => "world", "PLATFORM" => "deis"}
59
+ response = @client.config_set(app_name, configs)
60
+ assert response["values"].has_key?("HELLO")
61
+ assert response["values"].has_key?("PLATFORM")
62
+ assert response["values"].has_value?("world")
63
+ assert response["values"].has_value?("deis")
64
+
65
+ stored_config = @client.config_get(app_name)
66
+ assert stored_config.has_key?("HELLO")
67
+ assert stored_config.has_key?("PLATFORM")
68
+ assert stored_config.has_value?("world")
69
+ assert stored_config.has_value?("deis")
70
+
71
+ response = @client.config_set(app_name, "BUILDPACK_URL" => "https://github.com/AnyPresence/heroku-buildpack-node")
72
+ assert response["values"].has_key?("BUILDPACK_URL")
73
+
74
+ response = @client.app_destroy(app_name)
75
+ end
76
+ end
77
+
78
+ def test_command_run
79
+ assert_raises(DeisError) {
80
+ @client.config_set(nil, nil)
81
+ }
82
+ unless @mock
83
+ response = @client.command_run(@instance_name, "echo stuff")
84
+ assert response.first == 0
85
+ assert response.last.strip.end_with? "stuff"
86
+ end
87
+ end
88
+
89
+ def test_app_scale
90
+ assert_raises(DeisError) {
91
+ @client.app_scale(nil, "nil", "nil")
92
+ }
93
+ assert_raises(DeisError) {
94
+ @client.app_scale("my-app", "proc", 1)
95
+ }
96
+ assert_raises(DeisError) {
97
+ @client.app_scale("my-app", "web", -1)
98
+ }
99
+ unless @instance_name.nil?
100
+ @client.app_scale(@instance_name, "web", 2)
101
+ end
102
+ end
103
+
104
+ def test_app_restart
105
+ assert_raises(DeisError) {
106
+ @client.app_restart(nil)
107
+ }
108
+ unless @instance_name.nil?
109
+ @client.app_restart(@instance_name)
110
+ end
111
+ end
112
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deis-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - AnyPresence
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.7
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.7
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ description: Deis Platform REST (V1.5) client for Ruby.
34
+ email: engineering@anypresence.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - ".gitignore"
40
+ - LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - deis_client.gemspec
44
+ - lib/deis_client.rb
45
+ - test/test_deis_client.rb
46
+ homepage: http://rubygems.org/gems/deis_client
47
+ licenses:
48
+ - MIT
49
+ metadata: {}
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 1.9.3
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 2.4.5.1
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: Deis REST operations in a Ruby gem.
70
+ test_files: []