qc.rb 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +126 -0
  3. data/bin/qc +36 -7
  4. data/lib/qc.rb +135 -43
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4580a07ef6b2a0ce936e3044b00dc5d1d6d1b777
4
- data.tar.gz: 5eb71554537db1e81fef56c5e337dc7a72859c06
3
+ metadata.gz: 5dccf331efcb29098e651c3865f5d4d63f019586
4
+ data.tar.gz: 066553273f56fcbd831063096393b7bced68ce9c
5
5
  SHA512:
6
- metadata.gz: 673d374b1847215fea439935597aadde90e9b25b7ac29b347dbc889203752f1a12d22712ef443ca3651c400210859ff17177fa6257a10841afc7ba962bfe1c8c
7
- data.tar.gz: fa0e2d2b7bdb3dd6133745e72517451a6b73c177d95ea3e8145f88d5ccda80e14a0babd3bcb49928d5b261bd4d2dd961a441af08dc7e2fba31631dfc6e6d1681
6
+ metadata.gz: 1a25f3e039f696056512a592178509232ade5119662f25eb12f1473d4a1c722d89813cbf809b8f648364ee5f467cf84d5a3c1ecd2269ed14ab443a0700b08077
7
+ data.tar.gz: 4060d4ae2a012ec7ad54ba05763cd7b0a12812948b31730f929be7cbc6714ee843b607af14e8ed93c659d9751800f5e0d6d9f251088c1b5d3f8db55a25ced1fb
data/README.md CHANGED
@@ -2,3 +2,129 @@ qc.rb
2
2
  =====
3
3
 
4
4
  QingCloud API Library to handle instances, networks, etc. on QingCloud.com
5
+
6
+ ### Installation
7
+
8
+ You can install *qc.rb* via RubyGems:
9
+
10
+ ```bash
11
+ gem install qc.rb
12
+ ```
13
+
14
+ ### Important Notice
15
+
16
+ I'm not a native chinese speaker! Yet the complete documentation of QingCloud.com is in chinese! Due to that it is reasonable to expect that my understanding of the API might not be 100% correct! You are very welcome to improve the code!
17
+
18
+ ### Usage
19
+
20
+ You can use *qc.rb* via *qc* as a CLI or direct as a Ruby library.
21
+
22
+ #### SSH
23
+
24
+ Get all public keys:
25
+
26
+ CLI Version:
27
+
28
+ ```bash
29
+ qc ssh describe
30
+ ```
31
+
32
+ .rb Version:
33
+
34
+ ```ruby
35
+ # Each Public Key is available in *s*
36
+ QC::KeyPair.describe {|s| puts s}
37
+ ```
38
+
39
+ #### Instances
40
+
41
+ Get all instances:
42
+
43
+ CLI Version:
44
+
45
+ ```bash
46
+ qc ins describe
47
+ ```
48
+
49
+ .rb Version:
50
+
51
+ ```ruby
52
+ # Each instance is available in *i*
53
+ QC::Instance.describe {|i| puts i}
54
+ ```
55
+
56
+ Create new Instance:
57
+
58
+ ```ruby
59
+ QC::Instance.run instance_name: 'NameOfInstance', login_keypair: 'kp-sadasd67' # => instance_id
60
+ ```
61
+
62
+ Delete Instance:
63
+
64
+ ```ruby
65
+ i = QC::Instance.load 'i-adssad7'
66
+ i.terminate! # => {"action"=>"TerminateInstancesResponse", "job_id"=>"j-asd7djk", "ret_code"=>0}
67
+ ```
68
+
69
+ Add IP device to Instance:
70
+
71
+ ```ruby
72
+ i = QC::Instance.load 'i-adssad7'
73
+ i.ip = 'eip-sadjkdsa7' # => 'eip-sadjkdsa7'
74
+ ```
75
+
76
+ #### IPs
77
+
78
+ Get all IPs:
79
+
80
+ CLI Version:
81
+
82
+ ```bash
83
+ qc ip describe
84
+ ```
85
+
86
+ .rb Version:
87
+
88
+ ```ruby
89
+ # Each IP is available in *i*
90
+ QC::Eip.describe {|i| puts i}
91
+ ```
92
+
93
+ Allocate new IP:
94
+
95
+ ```ruby
96
+ # Create IP width bandwidth 3MB
97
+ Eip.allocate bandwidth: 3 # => eip_id
98
+ ```
99
+
100
+ Release IP:
101
+
102
+ ```ruby
103
+ # Release IP with ID 'eip-12djpg8q'
104
+ Eip.load('eip-12djpg8q').release! # => true | false
105
+ ```
106
+
107
+ Change Bandwidth:
108
+
109
+ ```ruby
110
+ # Change bandwidth of IP with ID 'eip-12djpg8q' to 2MB
111
+ ip = Eip.load('eip-12djpg8q')
112
+ ip.bandwidth = 2 # => 2
113
+ ```
114
+
115
+ #### Volumes
116
+
117
+ Get all Volumes:
118
+
119
+ CLI Version:
120
+
121
+ ```bash
122
+ qc vol describe
123
+ ```
124
+
125
+ .rb Version:
126
+
127
+ ```ruby
128
+ # Each Volume is available in *v*
129
+ QC::Volume.describe {|v| puts v}
130
+ ```
data/bin/qc CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'qc'
3
+ require "#{File.dirname(__FILE__)}/../lib/qc.rb"
4
4
 
5
5
  def help_header cmd, options
6
6
  <<HEADER
@@ -16,24 +16,53 @@ HEADER
16
16
  end
17
17
 
18
18
  case ARGV[0]
19
+ when 'vol'
20
+ case ARGV[1]
21
+ when 'describe'
22
+ QC::Volume.describe {|v| puts v}
23
+ else
24
+ puts help_header('vol [option]', <<HELP)
25
+ describe List all volumes
26
+ HELP
27
+ end
19
28
  when 'ssh'
20
29
  case ARGV[1]
21
- when 'list'
22
- QC::SSH.each {|s| puts s}
30
+ when 'describe'
31
+ QC::KeyPair.describe {|s| puts s}
23
32
  else
24
33
  puts help_header('ssh [option]', <<HELP)
25
- list List all public keys
34
+ describe List all public keys
26
35
  HELP
27
36
  end
28
37
  when 'ins'
29
38
  case ARGV[1]
30
- when 'list'
31
- QC::Instance.each {|s| puts s}
39
+ when 'describe'
40
+ QC::Instance.describe {|i| puts i}
32
41
  else
33
42
  puts help_header('ins [option]', <<HELP)
34
- list List all machines
43
+ describe List all machines
44
+ HELP
45
+ end
46
+ when 'ip'
47
+ case ARGV[1]
48
+ when 'describe'
49
+ QC::Eip.describe {|s| puts s}
50
+ else
51
+ puts help_header('ip [option]', <<HELP)
52
+ describe List all IPs
35
53
  HELP
36
54
  end
55
+
56
+ when 'img'
57
+ case ARGV[1]
58
+ when 'describe'
59
+ QC::Image.describe.sort.each {|s| puts s}
60
+ else
61
+ puts help_header('img [option]', <<HELP)
62
+ describe List all Images
63
+ HELP
64
+ end
65
+
37
66
  else
38
67
  puts help_header('[option]', <<HELP)
39
68
  ssh SSH Key Management
data/lib/qc.rb CHANGED
@@ -7,7 +7,7 @@ require 'yaml'
7
7
  require 'fileutils'
8
8
 
9
9
  module QC
10
- VERSION = '0.0.1'
10
+ VERSION = '0.0.2'
11
11
 
12
12
  def QC.load_config key
13
13
  f = File.expand_path('~/.qingcloud/config.yaml')
@@ -56,58 +56,135 @@ module QC
56
56
  url_b64_hmac = CGI.escape(b64_hmac)
57
57
  end
58
58
 
59
- class SSH
60
- def initialize s
61
- @id = s['keypair_id']
62
- @name = s['keypair_name']
63
- @date = s['create_time']
64
- @e_method = s['encrypt_method']
65
- @desc = s['description']
66
- @key = s['pub_key']
59
+ class DataType
60
+ attr_reader :result
61
+
62
+ @identifier = 'NOT_IMPLEMENTED'
63
+
64
+ def initialize h
65
+ @values = h
67
66
  end
68
67
 
69
68
  def to_s
70
- <<STR
71
- ID: "#{@id}"
72
- Name: "#{@name}"
73
- Creation Date: "#{@date}"
74
- Encryption Method: "#{@e_method}"
75
- Description: "#{@desc}"
76
- Public Key:
77
- "#{@key}"
78
- STR
69
+ @values.to_yaml
70
+ end
71
+
72
+ def method_missing met
73
+ if @values.has_key? met.to_s
74
+ @values[met.to_s]
75
+ else
76
+ raise NoMethodError.new "undefined method `#{met}'"
77
+ end
78
+ end
79
+
80
+ def self.describe p = {}, &block
81
+ req = QC::API::Request.new "Describe#{@identifier}s", p
82
+ @result = req.execute!(QC::Key)
83
+ if block_given?
84
+ @result["#{@identifier.downcase}_set"].to_a.each {|s| block.call(self.new(s))}
85
+ else
86
+ @result["#{@identifier.downcase}_set"].to_a.map {|s| self.new(s)}
87
+ end
88
+ end
89
+ end
90
+
91
+ class KeyPair < DataType
92
+ @identifier = 'KeyPair'
93
+ end
94
+
95
+ class Instance < DataType
96
+ @identifier = 'Instance'
97
+
98
+ def Instance.run p = {image_id: 'precisex64a', instance_name: nil, count: 1, login_mode: 'keypair',
99
+ login_keypair: nil, login_passwd: nil, security_group: nil, zone: nil, instance_type: 'small_b'}
100
+ p[:image_id] = 'precisex64a' if p[:image_id].nil?
101
+ p[:login_mode] = 'keypair' if p[:login_mode].nil?
102
+ p[:instance_type] = 'small_b' if p[:instance_type].nil?
103
+ p['vxnets.1'] = 'vxnet-0' if p['vxnets.1'].nil?
104
+ ret = API::Request.execute! 'RunInstances', p
105
+ ret['instances']
106
+ end
107
+
108
+ def Instance.load instance_id
109
+ Instance.describe('instances.1' => instance_id)[0]
110
+ end
111
+
112
+ def terminate!
113
+ p = {'instances.1' => @values['instance_id']}
114
+ API::Request.execute!('TerminateInstances', p)
115
+ end
116
+
117
+ def ip= eip_id
118
+ p = {'instance' => @values['instance_id'], 'eip' => eip_id}
119
+ API::Request.execute!('AssociateEip', p)
120
+ end
121
+ end
122
+
123
+ class Volume < DataType
124
+ @identifier = 'Volume'
125
+ end
126
+
127
+ class Eip < DataType
128
+ @identifier = 'Eip'
129
+
130
+ def Eip.allocate p = {bandwidth: 1, eip_name: nil, count: 1, need_icp: nil, zone: nil}
131
+ ret = API::Request.execute! 'AllocateEips', p
132
+ if ret.respond_to? :has_key?
133
+ ret['eips']
134
+ else
135
+ false
136
+ end
137
+ end
138
+
139
+ def Eip.release eips: [], zone: nil
140
+ if eips.size > 0
141
+ p = {}
142
+ 1.upto(eips.size).each { |i| p["eips.#{i}"] = eips[i-1] }
143
+ p[:zone] = zone
144
+ API::Request.execute!('ReleaseEips', p)
145
+ else
146
+ false
147
+ end
79
148
  end
80
149
 
81
- def SSH.each &block
82
- r = QC::API::Request.new 'DescribeKeyPairs'
83
- r.execute!(QC::Key)['keypair_set'].to_a.each {|s| block.call(SSH.new(s))}
150
+ def Eip.load eip_id
151
+ Eip.describe('eips.1' => eip_id)[0]
152
+ end
153
+
154
+ def bandwidth= b
155
+ p = {'eips.1' => @values['eip_id'], 'bandwidth' => b}
156
+ ret = API::Request.execute!('ChangeEipsBandwidth', p)
157
+ if ret.respond_to? :has_key?
158
+ b
159
+ else
160
+ false
161
+ end
162
+ end
163
+
164
+ def release!
165
+ p = {'eips.1' => @values['eip_id']}
166
+ API::Request.execute!('ReleaseEips', p)
84
167
  end
85
168
  end
86
169
 
87
- class Instance
88
- def initialize s
89
- @id = s['instance_id']
90
- @name = s['instance_name']
91
- @type = s['instance_type']
92
- @vcpu = s['vcpu_current']
93
- @desc = s['description']
94
- @status = s['status']
170
+ class Image < DataType
171
+ include Comparable
172
+ @identifier = 'Image'
173
+
174
+ def Image.describe p = {}, &block
175
+ _p = p.dup
176
+ unless _p.has_key? 'provider'
177
+ _p['provider'] = 'system'
178
+ end
179
+ super _p, &block
95
180
  end
96
181
 
97
182
  def to_s
98
- <<STR
99
- ID: "#{@id}"
100
- Name: "#{@name}"
101
- Type: "#{@type}"
102
- VCPU: "#{@vcpu}"
103
- Description: "#{@desc}"
104
- Status: "#{@status}"
105
- STR
183
+ [@values['image_id'], @values['image_name']].to_yaml
106
184
  end
107
185
 
108
- def Instance.each &block
109
- r = QC::API::Request.new 'DescribeInstances'
110
- r.execute!(QC::Key)['instance_set'].to_a.each {|s| block.call(Instance.new(s))}
186
+ def <=> o
187
+ @values['image_id'] <=> o.image_id
111
188
  end
112
189
  end
113
190
 
@@ -115,7 +192,17 @@ STR
115
192
  class Request
116
193
  attr_reader :response
117
194
 
118
- def initialize action, extra_params = []
195
+ def Request.execute! a, p = {}
196
+ req = QC::API::Request.new a, p
197
+ @result = req.execute!(QC::Key)
198
+ if @result['ret_code'] == 0
199
+ @result
200
+ else
201
+ raise ArgumentError.new("#{@result['ret_code']}: #{@result['message']}")
202
+ end
203
+ end
204
+
205
+ def initialize action, extra_params = {}
119
206
  @response = :not_requested
120
207
 
121
208
  @params = []
@@ -123,8 +210,13 @@ STR
123
210
  @params << ['access_key_id', QC::AccessKeyId]
124
211
  @params << ['signature_method', 'HmacSHA256']
125
212
  @params << ['signature_version', 1]
126
- @params << ['zone', QC::Zone]
127
- extra_params.each {|i| @params << i}
213
+ zone_set = false
214
+ extra_params.each_pair do |k,v|
215
+ zone_set = true if k == 'zone'
216
+ next if v.nil?
217
+ @params << [k.to_s, v]
218
+ end
219
+ @params << ['zone', QC::Zone] unless zone_set
128
220
  end
129
221
 
130
222
  def execute!(key)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qc.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Bovensiepen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-15 00:00:00.000000000 Z
11
+ date: 2014-02-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: QingCloud API Library to handle instances, networks, internetconnections,
14
14
  etc. on QingCloud.com