qingcloud-sdk 0.2.3

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/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # QingCloud::SDK
2
+
3
+ SDK for QingCloud
4
+
5
+ ## Install from RubyGems
6
+
7
+ $ gem install qingcloud-sdk
8
+
9
+
10
+ ## Install from Source Code
11
+
12
+ Get Code from Github:
13
+
14
+ $ git clone git@github.com:prettyxw/qingcloud-sdk-ruby.git
15
+
16
+ Build and Install with Bundle:
17
+
18
+ $ cd qingcloud-sdk-ruby && bundle exec rake install
19
+
20
+ ## Install using Gemfile
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ ```ruby
25
+ gem 'qingcloud-sdk', git: 'https://github.com/prettyxw/qingcloud-sdk-ruby'
26
+ ```
27
+
28
+ And then execute:
29
+
30
+ $ bundle install
31
+
32
+ ## Uninstall
33
+
34
+ Using gem to remove this package:
35
+
36
+ $ gem uninstall qingcloud-sdk
37
+
38
+ ## Getting Started
39
+
40
+ Before your start, please go to [QingCloud Console](https://console.qingcloud.com/access_keys/) to create a pair of QingCloud API keys.
41
+
42
+ ## Code Example
43
+
44
+ ### Create Connection and Service
45
+
46
+ ```ruby
47
+ require 'qingcloud/sdk'
48
+
49
+ # Create Connection and Service
50
+
51
+ connector = QingCloud::SDK::Client::Connector.init(
52
+ 'qy_access_key_id', 'qy_secret_access_key'
53
+ )
54
+
55
+ service = QingCloud::SDK::Client::Service.new connector
56
+
57
+ # Describe Instances
58
+
59
+ service.describe_instances zone: 'ap1'
60
+
61
+ puts service.response
62
+
63
+ # Run Instances
64
+
65
+ service.run_instances(
66
+ image_id: 'centos7x64b',
67
+ cpu: 1,
68
+ memory: 1024,
69
+ login_mode: 'keypair',
70
+ login_keypair: 'keypair-id',
71
+ zone: 'ap1'
72
+ )
73
+
74
+ puts service.response
75
+
76
+ # Terminate Instances
77
+
78
+ service.describe_instances instances: ['instance-id'], zone: 'ap1'
79
+
80
+ puts service.response
81
+ ```
82
+ ### Describe Zones
83
+
84
+
85
+
86
+ ## Contributing
87
+
88
+ 1. Fork it ( https://github.com/prettyxw/qingcloud-sdk-ruby/fork )
89
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
90
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
91
+ 4. Push to the branch (`git push origin my-new-feature`)
92
+ 5. Create a new Pull Request
93
+
94
+ LICENSE
95
+ -------
96
+ The GPL License. Read [GNU General Public License](http://www.gnu.org/licenses/gpl.html) for further information.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Run with `rake spec`
6
+ RSpec::Core::RakeTask.new(:spec)
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "qingcloud/sdk"
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
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,89 @@
1
+ require 'cgi'
2
+ require 'openssl'
3
+ require 'base64'
4
+ require 'net/http'
5
+
6
+ module QingCloud
7
+ module SDK
8
+ module Client
9
+
10
+ class Connector
11
+
12
+ attr_accessor :access_key
13
+ attr_accessor :secret_key
14
+
15
+ def initialize(access_key, secret_key)
16
+ raise Error::ParameterError, 'Load API Key' unless access_key && access_key.length > 0
17
+ raise Error::ParameterError, 'Load API Key' unless secret_key && secret_key.length > 0
18
+
19
+ self.access_key = access_key
20
+ self.secret_key = secret_key
21
+ end
22
+
23
+ def self.init(access_key, secret_key)
24
+ Connector.new access_key, secret_key
25
+ end
26
+
27
+ def self.init_with_config_file
28
+ config_map = {}
29
+ content = Utility.file_manager.read_config_file
30
+ config_map = Utility.json_parser.decode content if content
31
+ Connector.new config_map['qy_access_key_id'], config_map['qy_secret_access_key']
32
+ end
33
+
34
+ def fetch(action, params={})
35
+ raise Error::ParameterError, 'Check API Request' unless action && action.length > 0
36
+
37
+ params.update(
38
+ action: action,
39
+ time_stamp: Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ'),
40
+ access_key_id: access_key,
41
+ version: 1,
42
+ signature_method: 'HmacSHA256',
43
+ signature_version: 1,
44
+ )
45
+
46
+ request_body = params.sort.map { |key, value|
47
+ if value.is_a? Array
48
+ value.map { |v|
49
+ "#{CGI.escape key.to_s}.#{value.index(v)+1}=#{CGI.escape v.to_s}"
50
+ }.join('&')
51
+ else
52
+ "#{CGI.escape key.to_s}=#{CGI.escape value.to_s}"
53
+ end
54
+ }.join('&')
55
+
56
+ signature = Base64.encode64(
57
+ OpenSSL::HMAC.digest(
58
+ OpenSSL::Digest.new('sha256'),
59
+ self.secret_key,
60
+ "GET\n/iaas/\n#{request_body}"
61
+ )
62
+ ).strip
63
+
64
+ request_url = "#{Contract::API_URL}#{request_body}&signature=#{CGI.escape signature}"
65
+
66
+ # Log
67
+ Utility.logger.info request_url
68
+
69
+ response = Net::HTTPResponse.new 1.1, 500, 'Error'
70
+
71
+ begin
72
+ response = Net::HTTP.get_response URI(request_url)
73
+ rescue
74
+ raise Error::NetworkError
75
+ end
76
+
77
+ raise Error::ServerError, response.code unless response.code == '200'
78
+
79
+ # Log
80
+ Utility.logger.info response.body
81
+
82
+ Utility.json_parser.decode response.body
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,73 @@
1
+ module QingCloud
2
+ module SDK
3
+ module Client
4
+
5
+ class Foundation
6
+
7
+ ERROR_CODE_MAP = {
8
+ 1100 => 'Request Format Invalid',
9
+ 1200 => 'Authentication Failed',
10
+ 1300 => 'Request Expired',
11
+ 1400 => 'Request Denied',
12
+ 2100 => 'Resource Not Found',
13
+ 2400 => 'Balance Insufficient',
14
+ 2500 => 'Over Quota',
15
+ 5000 => 'Internal Error',
16
+ 5100 => 'Server Busy',
17
+ 5200 => 'Resources Inadequate',
18
+ 5300 => 'Server Updating',
19
+ }
20
+
21
+ attr_accessor :response
22
+
23
+ def initialize(connector)
24
+ @connector = connector
25
+ end
26
+
27
+ private
28
+
29
+ def fetch_response(action, params={})
30
+
31
+ params.map { |key, value|
32
+ params.delete key unless (value.is_a? Numeric) || (value && value.length > 0)
33
+ }
34
+
35
+ response_body = @connector.fetch action, params
36
+
37
+ raise Error::APIError, 'No Response Data Received' unless response_body['ret_code']
38
+
39
+ self.response = response_body
40
+
41
+ if response_body['ret_code'] != 0
42
+ raise Error::APIError, response_body['message'] || ERROR_CODE_MAP[response_body['ret_code']]
43
+ end
44
+ end
45
+
46
+ def merge_maps(maps)
47
+ final = {}
48
+ maps.map { |map| final.merge! map }
49
+ final
50
+ end
51
+
52
+ def build_fetch(action_name)
53
+ "
54
+ fetch_response(
55
+ \"#{action_name}\",
56
+ eval('merge_maps(method(__method__).parameters.map { |_, p| {p.to_sym => eval(p.to_s)} })')
57
+ )
58
+ "
59
+ end
60
+
61
+ def build_fetch_match
62
+ "
63
+ fetch_response(
64
+ __method__.to_s.split('_').map{ |w| w.capitalize! }.join,
65
+ eval('merge_maps(method(__method__).parameters.map { |_, p| {p.to_sym => eval(p.to_s)} })')
66
+ )
67
+ "
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end