otc-sdk-ruby 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +70 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/lib/otc/asgroup.rb +35 -0
- data/lib/otc/asgroup_instance.rb +10 -0
- data/lib/otc/configuration.rb +39 -0
- data/lib/otc/ecs.rb +39 -0
- data/lib/otc/eip.rb +19 -0
- data/lib/otc/request.rb +74 -0
- data/lib/otc/version.rb +3 -0
- data/lib/otc.rb +10 -0
- data/otc-sdk-ruby.gemspec +24 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e49f1cdfc253705ff4cfd2451d9c549231c22117
|
4
|
+
data.tar.gz: 0923621decd28b4ea3dd86a2d73b3894673fe822
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a7dcd38f9bc15511540a6d0ec02a8149ce1a1d6a6fecaf51dce606d238c1c408870cd598604ae6e337fae7bec187ea943e49d3aaa0332bf86da291ba1c5764c7
|
7
|
+
data.tar.gz: c7e10437c061bd2dee955b8eec35b758a9acf87e2fadbbe78b261593e45fceedefe1c4965eb850303d4e0a9fbcc460a49d2cb52035f01f3d2a54a30c3a6238aa
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Open Telekom Cloud SDK for Ruby
|
2
|
+

|
3
|
+
|
4
|
+
This is a small SDK which wraps the Open Telekom Cloud API. It currently supports only a limited amount of functionalities.
|
5
|
+
|
6
|
+
## Configuration
|
7
|
+
|
8
|
+
The only way to currently authenticate with this library is via a user token. To obtain a token the API requires several credentials.
|
9
|
+
|
10
|
+
- IAM username
|
11
|
+
- IAM password
|
12
|
+
- domainname (can be copied from the "My Credential" screen)
|
13
|
+
- project ID (can be copied from the "My Credential" screen)
|
14
|
+
- region of the project
|
15
|
+
|
16
|
+
```
|
17
|
+
Otc::Configuration.configure do |config|
|
18
|
+
config.username = "testuser"
|
19
|
+
config.password = "test1234"
|
20
|
+
config.domainname = "OTC-EU-DE-001"
|
21
|
+
config.project = "41234123"
|
22
|
+
config.region = "eu-de"
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
## General
|
27
|
+
|
28
|
+
All responses are wrapped by objects that hold their information via method accessors. Example:
|
29
|
+
|
30
|
+
ecs = Otc::ECS.query_one
|
31
|
+
ecs.name # => "cool-server"
|
32
|
+
|
33
|
+
Some information is cached for improved performance using memoization and is therefore not updated on subsequent calls.
|
34
|
+
|
35
|
+
## Auto Scaling
|
36
|
+
|
37
|
+
### Querying
|
38
|
+
|
39
|
+
Otc::ASGroup.query_all # get all auto scaling groups
|
40
|
+
Otc::ASGroup.query_all(name: "my_scaling_group") # get all auto scaling groups filtered by the given name
|
41
|
+
Otc::ASGroup.query_one # get the first auto scaling group
|
42
|
+
Otc::ASGroup.query_one(name: "my_scaling_group") # get the first auto scaling group filtered by the given name
|
43
|
+
|
44
|
+
# convenience methods
|
45
|
+
group = Otc::ASGroup.query_one(name: "my_scaling_group") # => #<Otc::ASGroup>
|
46
|
+
group.instances # get all instances of the auto scaling group
|
47
|
+
|
48
|
+
## EIP
|
49
|
+
|
50
|
+
### Querying
|
51
|
+
|
52
|
+
Otc::EIP.query_all # get all EIPs
|
53
|
+
|
54
|
+
## ECS
|
55
|
+
|
56
|
+
### Querying
|
57
|
+
|
58
|
+
Otc::ECS.query_all # get all ecs
|
59
|
+
Otc::ECS.query_all(name: "my_server") # get all ecs filtered by the given name
|
60
|
+
Otc::ECS.query_one # get the first ecs
|
61
|
+
Otc::ECS.query_one(name: "my_server") # get the first ecs filtered by the given name
|
62
|
+
|
63
|
+
# convenience methods
|
64
|
+
ecs = Otc::ECS.query_one # => #<Otc::ECS>
|
65
|
+
ecs.public_ip # => "160.44.232.150"
|
66
|
+
|
67
|
+
## Known Issues
|
68
|
+
|
69
|
+
- The API uses a limit for nearly every API request but the SDK does not support limits at the moment, so most `query_all` methods won't return all results.
|
70
|
+
- Obtaining the public IP address of an ECS instance is rather cumbersome. There might be a better possibility than comparing the private IP of the ECS instance to the private IP of all EIPs.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "otc"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/lib/otc/asgroup.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require "hashie"
|
2
|
+
|
3
|
+
module Otc
|
4
|
+
class ASGroup < Hashie::Dash
|
5
|
+
class << self
|
6
|
+
def query_all(name: nil)
|
7
|
+
response = Request.get service: "as", path: "/autoscaling-api/v1/#{Configuration.project!}/scaling_group?scaling_group_name=#{name}"
|
8
|
+
JSON.parse(response.body)["scaling_groups"].map do |group|
|
9
|
+
ASGroup.new(group)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def query_one(name: nil)
|
14
|
+
query_all(name: name).first
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
[
|
19
|
+
"networks", "detail", "notifications", "scaling_group_name", "scaling_group_id", "scaling_group_status",
|
20
|
+
"scaling_configuration_id", "scaling_configuration_name", "current_instance_number", "desire_instance_number",
|
21
|
+
"min_instance_number", "max_instance_number", "cool_down_time", "lb_listener_id", "lbaas_listeners",
|
22
|
+
"cloud_location_id", "available_zones", "security_groups", "create_time", "vpc_id", "health_periodic_audit_method",
|
23
|
+
"health_periodic_audit_time", "instance_terminate_policy", "is_scaling", "delete_publicip"
|
24
|
+
].each { |prop| property prop }
|
25
|
+
|
26
|
+
def instances
|
27
|
+
@_instances ||= begin
|
28
|
+
response = Request.get service: "as", path: "/autoscaling-api/v1/#{Configuration.project!}/scaling_group_instance/#{self.scaling_group_id}/list"
|
29
|
+
JSON.parse(response.body)["scaling_group_instances"].map do |group|
|
30
|
+
ASGroupInstance.new(group)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "hashie"
|
2
|
+
|
3
|
+
module Otc
|
4
|
+
class ASGroupInstance < Hashie::Dash
|
5
|
+
[
|
6
|
+
"instance_id", "scaling_group_id", "scaling_group_name", "life_cycle_state", "health_status",
|
7
|
+
"scaling_configuration_name", "scaling_configuration_id", "create_time", "instance_name"
|
8
|
+
].each { |prop| property prop }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Otc
|
2
|
+
class Configuration
|
3
|
+
class MissingError < RuntimeError; end
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :project, :username, :password, :region, :domainname
|
7
|
+
|
8
|
+
def configure
|
9
|
+
yield self
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset
|
13
|
+
@project = nil
|
14
|
+
@username = nil
|
15
|
+
@password = nil
|
16
|
+
@region = nil
|
17
|
+
@domainname = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(m, *args, &block)
|
21
|
+
m_as_string = m.to_s
|
22
|
+
|
23
|
+
if m_as_string.end_with?("!")
|
24
|
+
method = m_as_string.split("!").first.to_sym
|
25
|
+
|
26
|
+
if self.respond_to?(method)
|
27
|
+
send(method).tap do |result|
|
28
|
+
raise MissingError, "missing configuration #{method}" if result.nil?
|
29
|
+
end
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/otc/ecs.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "hashie"
|
2
|
+
|
3
|
+
module Otc
|
4
|
+
class ECS < Hashie::Dash
|
5
|
+
class << self
|
6
|
+
def query_all(name: nil)
|
7
|
+
response = Request.get service: "ecs", path: "/v2/#{Configuration.project!}/servers/detail?name=#{name}"
|
8
|
+
JSON.parse(response.body)["servers"].map do |server|
|
9
|
+
keys_to_delete = server.keys - ECS::ATTRIBUTES
|
10
|
+
keys_to_delete.each { |key| server.delete(key) }
|
11
|
+
|
12
|
+
ECS.new(server)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def query_one(name: nil)
|
17
|
+
query_all(name: name).first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
ATTRIBUTES = [
|
22
|
+
"name", "id", "status", "created", "updated", "flavor", "image", "tenant_id", "key_name",
|
23
|
+
"user_id", "metadata", "hostId", "addresses", "security_groups", "tags", "links", "progress"
|
24
|
+
]
|
25
|
+
|
26
|
+
ATTRIBUTES.each { |prop| property prop }
|
27
|
+
|
28
|
+
def public_ip
|
29
|
+
@_public_ip ||= begin
|
30
|
+
private_addresses = self.addresses.values.flatten.map { |val| val["addr"] }
|
31
|
+
|
32
|
+
eip = EIP.query_all.select { |ip| private_addresses.include?(ip.private_ip_address) }.first
|
33
|
+
if eip
|
34
|
+
eip.public_ip_address
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/otc/eip.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "hashie"
|
2
|
+
|
3
|
+
module Otc
|
4
|
+
class EIP < Hashie::Dash
|
5
|
+
class << self
|
6
|
+
def query_all
|
7
|
+
response = Request.get service: "ecs", path: "/v1/#{Configuration.project!}/publicips"
|
8
|
+
JSON.parse(response.body)["publicips"].map do |ip|
|
9
|
+
EIP.new(ip)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
[
|
15
|
+
"id", "status", "type", "port_id", "public_ip_address", "private_ip_address",
|
16
|
+
"tenant_id", "create_time", "bandwidth_id", "bandwidth_share_type", "bandwidth_size"
|
17
|
+
].each { |prop| property prop }
|
18
|
+
end
|
19
|
+
end
|
data/lib/otc/request.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Otc
|
5
|
+
class Request
|
6
|
+
class UnauthorizedError < RuntimeError; end
|
7
|
+
class ApiError < RuntimeError; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def base_uri(service:, path:)
|
11
|
+
"https://#{service}.#{Configuration.region!}.otc.t-systems.com#{path}"
|
12
|
+
end
|
13
|
+
|
14
|
+
# returns the token if it is still valid (not older than 20 hours)
|
15
|
+
# else obtains a new token
|
16
|
+
def token
|
17
|
+
latest_timestamp = @_token ? @_token[:timestamp] : nil
|
18
|
+
twenty_hours = 20 * 60 * 60
|
19
|
+
|
20
|
+
if latest_timestamp.nil? || latest_timestamp < (Time.now - twenty_hours).to_i
|
21
|
+
body = {
|
22
|
+
auth: {
|
23
|
+
identity: {
|
24
|
+
methods: ["password"],
|
25
|
+
password: {
|
26
|
+
user: {
|
27
|
+
name: Configuration.username!,
|
28
|
+
password: Configuration.password!,
|
29
|
+
domain: { name: Configuration.domainname! }
|
30
|
+
}
|
31
|
+
}
|
32
|
+
},
|
33
|
+
scope: {
|
34
|
+
project: { id: Configuration.project! }
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
response = post(service: "iam", path: "/v3/auth/tokens", body: body.to_json)
|
40
|
+
|
41
|
+
@_token = {
|
42
|
+
token: response.fetch("X-Subject-Token"),
|
43
|
+
timestamp: Time.now.to_i
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
@_token.fetch(:token)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get(service:, path:, authenticated_request: true)
|
51
|
+
uri = URI.parse(base_uri(service: service, path: path))
|
52
|
+
headers = { "X-Auth-Token" => token } if authenticated_request
|
53
|
+
req = Net::HTTP::Get.new(uri.request_uri, headers)
|
54
|
+
send(req, uri)
|
55
|
+
end
|
56
|
+
|
57
|
+
def post(service:, path:, body:)
|
58
|
+
uri = URI.parse(base_uri(service: service, path: path))
|
59
|
+
req = Net::HTTP::Post.new(uri.request_uri, "Content-Type" => "application/json;charset=utf8")
|
60
|
+
req.body = body
|
61
|
+
send(req, uri)
|
62
|
+
end
|
63
|
+
|
64
|
+
def send(req, uri)
|
65
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
66
|
+
http.use_ssl = true
|
67
|
+
http.request(req).tap do |response|
|
68
|
+
raise UnauthorizedError, "could not authorize request" if response.code == "401"
|
69
|
+
raise ApiError, "error during api call: #{response.body}" if response.code.to_i >= 300
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/otc/version.rb
ADDED
data/lib/otc.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "otc/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "otc-sdk-ruby"
|
8
|
+
spec.version = Otc::VERSION
|
9
|
+
spec.authors = ["Streetspotr GmbH"]
|
10
|
+
spec.email = ["devs@streetspotr.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby SDK which wraps the open telekom cloud API}
|
13
|
+
spec.homepage = "https://github.com/streetspotr/otc-sdk-ruby"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_runtime_dependency "hashie"
|
21
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
22
|
+
spec.add_development_dependency "webmock"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: otc-sdk-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Streetspotr GmbH
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashie
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: webmock
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- devs@streetspotr.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/console
|
83
|
+
- lib/otc.rb
|
84
|
+
- lib/otc/asgroup.rb
|
85
|
+
- lib/otc/asgroup_instance.rb
|
86
|
+
- lib/otc/configuration.rb
|
87
|
+
- lib/otc/ecs.rb
|
88
|
+
- lib/otc/eip.rb
|
89
|
+
- lib/otc/request.rb
|
90
|
+
- lib/otc/version.rb
|
91
|
+
- otc-sdk-ruby.gemspec
|
92
|
+
homepage: https://github.com/streetspotr/otc-sdk-ruby
|
93
|
+
licenses: []
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.4.5
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Ruby SDK which wraps the open telekom cloud API
|
115
|
+
test_files: []
|