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 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
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.2
5
+ before_install: gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in otc-sdk-ruby.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Open Telekom Cloud SDK for Ruby
2
+ ![Build Status](https://travis-ci.org/streetspotr/otc-sdk-ruby.svg?branch=master)
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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
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__)
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Otc
2
+ VERSION = "0.1.0"
3
+ end
data/lib/otc.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "otc/version"
2
+ require "otc/configuration"
3
+ require "otc/request"
4
+ require "otc/asgroup"
5
+ require "otc/asgroup_instance"
6
+ require "otc/eip"
7
+ require "otc/ecs"
8
+
9
+ module Otc
10
+ end
@@ -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: []