smartdc 1.3.0 → 2.0.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.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -19
  3. data/.travis.yml +1 -1
  4. data/Gemfile +5 -11
  5. data/README.md +25 -40
  6. data/Rakefile +5 -5
  7. data/bin/sdc +4 -380
  8. data/config.ru +2 -0
  9. data/lib/smartdc.rb +23 -15
  10. data/lib/smartdc/api/analytics.rb +19 -36
  11. data/lib/smartdc/api/analytics/heatmap.rb +6 -15
  12. data/lib/smartdc/api/datacenters.rb +7 -16
  13. data/lib/smartdc/api/images.rb +11 -0
  14. data/lib/smartdc/api/keys.rb +13 -23
  15. data/lib/smartdc/api/machines.rb +26 -60
  16. data/lib/smartdc/api/machines/metadata.rb +15 -0
  17. data/lib/smartdc/api/machines/snapshots.rb +23 -0
  18. data/lib/smartdc/api/machines/tags.rb +19 -0
  19. data/lib/smartdc/api/packages.rb +7 -17
  20. data/lib/smartdc/auth.rb +39 -5
  21. data/lib/smartdc/cli.rb +65 -0
  22. data/lib/smartdc/cli/analytic.rb +52 -0
  23. data/lib/smartdc/cli/datacenter.rb +15 -0
  24. data/lib/smartdc/cli/image.rb +19 -0
  25. data/lib/smartdc/cli/key.rb +26 -0
  26. data/lib/smartdc/cli/machine.rb +79 -0
  27. data/lib/smartdc/cli/machine/metadata.rb +30 -0
  28. data/lib/smartdc/cli/machine/snapshot.rb +38 -0
  29. data/lib/smartdc/cli/machine/tag.rb +33 -0
  30. data/lib/smartdc/cli/package.rb +17 -0
  31. data/lib/smartdc/cli_configure.rb +81 -0
  32. data/lib/smartdc/cli_helper.rb +111 -0
  33. data/lib/smartdc/client.rb +33 -28
  34. data/lib/smartdc/configure.rb +30 -0
  35. data/lib/smartdc/default.rb +35 -0
  36. data/lib/smartdc/version.rb +1 -1
  37. data/smartdc.gemspec +20 -16
  38. data/spec/cassettes/analytics/create.yml +64 -0
  39. data/spec/cassettes/analytics/describe.yml +123 -0
  40. data/spec/cassettes/analytics/destroy.yml +56 -0
  41. data/spec/cassettes/analytics/index.yml +62 -0
  42. data/spec/cassettes/analytics/show.yml +62 -0
  43. data/spec/cassettes/analytics/value.yml +62 -0
  44. data/spec/cassettes/datacenters/index.yml +62 -0
  45. data/spec/cassettes/datacenters/show.yml +64 -0
  46. data/spec/cassettes/images/index.yml +519 -0
  47. data/spec/cassettes/images/show.yml +63 -0
  48. data/spec/cassettes/keys/create.yml +65 -0
  49. data/spec/cassettes/keys/destroy.yml +56 -0
  50. data/spec/cassettes/keys/index.yml +63 -0
  51. data/spec/cassettes/keys/show.yml +63 -0
  52. data/spec/cassettes/machines/create.yml +65 -0
  53. data/spec/cassettes/machines/destroy.yml +56 -0
  54. data/spec/cassettes/machines/index.yml +67 -0
  55. data/spec/cassettes/machines/metadata/destroy.yml +56 -0
  56. data/spec/cassettes/machines/metadata/index.yml +62 -0
  57. data/spec/cassettes/machines/metadata/update.yml +64 -0
  58. data/spec/cassettes/machines/reboot.yml +58 -0
  59. data/spec/cassettes/machines/show.yml +63 -0
  60. data/spec/cassettes/machines/snapshots/create.yml +62 -0
  61. data/spec/cassettes/machines/snapshots/destroy.yml +56 -0
  62. data/spec/cassettes/machines/snapshots/index.yml +62 -0
  63. data/spec/cassettes/machines/snapshots/show.yml +62 -0
  64. data/spec/cassettes/machines/snapshots/start.yml +58 -0
  65. data/spec/cassettes/machines/start.yml +58 -0
  66. data/spec/cassettes/machines/stop.yml +58 -0
  67. data/spec/cassettes/machines/tags/create.yml +64 -0
  68. data/spec/cassettes/machines/tags/destroy.yml +56 -0
  69. data/spec/cassettes/machines/tags/index.yml +62 -0
  70. data/spec/cassettes/machines/tags/show.yml +62 -0
  71. data/spec/cassettes/packages/index.yml +123 -0
  72. data/spec/cassettes/packages/show.yml +63 -0
  73. data/spec/fixtures/config/sdccfg +4 -0
  74. data/spec/fixtures/ssh/id_rsa +27 -0
  75. data/spec/fixtures/ssh/id_rsa.pub +1 -0
  76. data/spec/smartdc/api/analytics_spec.rb +47 -0
  77. data/spec/smartdc/api/datacenters_spec.rb +19 -0
  78. data/spec/smartdc/api/images_spec.rb +19 -0
  79. data/spec/smartdc/api/keys_spec.rb +34 -0
  80. data/spec/smartdc/api/machines/metadata_spec.rb +27 -0
  81. data/spec/smartdc/api/machines/snapshots_spec.rb +38 -0
  82. data/spec/smartdc/api/machines/tags_spec.rb +33 -0
  83. data/spec/smartdc/api/machines_spec.rb +59 -0
  84. data/spec/smartdc/api/packages_spec.rb +19 -0
  85. data/spec/smartdc/auth_spec.rb +25 -0
  86. data/spec/smartdc/cli_configure_spec.rb +32 -0
  87. data/spec/smartdc/client_spec.rb +11 -0
  88. data/spec/smartdc_spec.rb +44 -0
  89. data/spec/spec_helper.rb +25 -8
  90. metadata +176 -83
  91. data/lib/cli_helper.rb +0 -126
  92. data/lib/configure.rb +0 -125
  93. data/lib/smartdc/api/datasets.rb +0 -20
  94. data/lib/smartdc/api/machine/metadata.rb +0 -24
  95. data/lib/smartdc/api/machine/snapshots.rb +0 -35
  96. data/lib/smartdc/api/machine/tags.rb +0 -29
  97. data/lib/smartdc/error.rb +0 -35
  98. data/lib/smartdc/request.rb +0 -83
  99. data/lib/smartdc/response.rb +0 -25
  100. data/lib/smartdc/response/raise_error.rb +0 -38
  101. data/spec/fixtures/analytics.json +0 -26
  102. data/spec/fixtures/datacenter.json +0 -4
  103. data/spec/fixtures/datacenters.json +0 -3
  104. data/spec/fixtures/datasets.json +0 -38
  105. data/spec/fixtures/keys.json +0 -14
  106. data/spec/fixtures/machines.json +0 -36
  107. data/spec/fixtures/packages.json +0 -18
  108. data/spec/fixtures/snapshots.json +0 -8
  109. data/spec/fixtures/tag.json +0 -3
  110. data/spec/unit/smartdc/api/analytics_spec.rb +0 -48
  111. data/spec/unit/smartdc/api/datacenters_spec.rb +0 -28
  112. data/spec/unit/smartdc/api/datasets_spec.rb +0 -28
  113. data/spec/unit/smartdc/api/keys_spec.rb +0 -48
  114. data/spec/unit/smartdc/api/machine/metadata_spec.rb +0 -38
  115. data/spec/unit/smartdc/api/machine/snapshots_spec.rb +0 -48
  116. data/spec/unit/smartdc/api/machine/tags_spec.rb +0 -48
  117. data/spec/unit/smartdc/api/machines_spec.rb +0 -48
  118. data/spec/unit/smartdc/api/packages_spec.rb +0 -28
  119. data/spec/unit/smartdc/client_spec.rb +0 -40
  120. data/spec/unit/smartdc_spec.rb +0 -9
@@ -1,126 +0,0 @@
1
- require 'thor'
2
- require 'thor/group'
3
- require 'terminal-table'
4
- require 'smartdc'
5
- require 'configure'
6
- include Configure
7
-
8
- def config(options={})
9
- cfg = Configure.read
10
-
11
- if !options.empty?
12
- options.each do |key, value|
13
- cfg[key.to_sym] = value
14
- end
15
- end
16
-
17
- cfg
18
- end
19
-
20
- def sdc(options)
21
- Smartdc.new(options)
22
- end
23
-
24
- def opt(argument, options={})
25
- opts = {}
26
- opts = opts.merge(options)
27
- opts['raw'] = true if argument.include?('--raw') or argument.include?('-r')
28
- opts['debug'] = true if argument.include?('--debug') or argument.include?('-d')
29
- opts
30
- end
31
-
32
- def output(response, options={})
33
- if options['raw']
34
- puts response.body
35
- else
36
- if response.status < 300
37
- if options[:table]
38
- case options[:table]
39
- when :h
40
- puts horizontal(response.content, options)
41
- when :v
42
- puts vertical(response.content, options)
43
- end
44
- else
45
- if options[:message]
46
- puts options[:message]
47
- else
48
- puts response.content[options[:only].to_s]
49
- end
50
- end
51
- else
52
- puts vertical(response.content)
53
- end
54
- end
55
- end
56
-
57
- def horizontal(content, options={})
58
- options[:include] ||= []
59
- options[:exclude] ||= []
60
- rows = []
61
- headings = nil
62
-
63
- content.each do |row|
64
- options[:exclude].each do |col|
65
- row.delete(col.to_s)
66
- end
67
-
68
- if !options[:include].empty?
69
- cols = {}
70
- options[:include].each do |col|
71
- cols[col.to_s] = row[col.to_s] if row.key?(col.to_s)
72
- end
73
- row = cols
74
- end
75
-
76
- rows << row.values
77
- headings = row.keys if headings.nil?
78
- end
79
-
80
- Terminal::Table.new :headings => headings, :rows => rows if !content.empty?
81
- end
82
-
83
- def vertical(content, options={})
84
- options[:exclude] ||= []
85
- options[:exclude].each do |col|
86
- content.delete(col.to_s)
87
- end
88
-
89
- rows = []
90
- content.to_a.each do |row|
91
- rows << row
92
- end
93
-
94
- Terminal::Table.new :headings => ['key','value'], :rows => rows if !content.empty?
95
- end
96
-
97
- def describe(name, content, options)
98
- if options['all'] or options['output'] == name
99
- options[:exclude] ||= []
100
- rows = []
101
-
102
- content[name].each do |row|
103
- cols = []
104
- if options[:cols] == :all
105
- options[:exclude].each do |col|
106
- row.delete(col.to_s)
107
- end
108
- cols = row.values
109
- else
110
- options[:cols].each do |col|
111
- if col == 'key'
112
- cols << row[0]
113
- else
114
- cols << row[1][col]
115
- end
116
- end
117
- end
118
- rows << cols
119
- end
120
-
121
- title = options['all'] ? name : nil
122
- headings = options[:cols] == :all ? content[name][0].keys : options[:cols]
123
- puts Terminal::Table.new :title => title, :headings => headings, :rows => rows
124
- puts if options['all']
125
- end
126
- end
@@ -1,125 +0,0 @@
1
- module Configure
2
- def self.read()
3
- begin
4
- config = {}
5
- File.open(path, 'r') do |file|
6
- file.each do |row|
7
- row.chomp!
8
- cols = row.split(/\s+=\s+/)
9
- config[cols[0].to_sym] = cols[1]
10
- end
11
- end
12
- rescue
13
- config = {}
14
- ensure
15
- return config
16
- end
17
- end
18
-
19
- def self.write(config)
20
- File.open(path, 'w') do |file|
21
- config.each do |key, value|
22
- file.puts "#{key} = #{value}"
23
- end
24
- end
25
- end
26
-
27
- def self.init
28
- config = self.read
29
-
30
- output = <<EOS
31
- .
32
- |
33
- .-. .--. .-.| .-.
34
- : + : `--.( | (
35
- `-' `--' `-'`- `-'
36
- Smart Data Center Command Line Interface
37
- http://apidocs.joyent.com/sdcapidoc/cloudapi/
38
-
39
- EOS
40
- puts output
41
-
42
- config[:hostname] ||= 'api.example.com'
43
- print "Hostname (#{config[:hostname]}): "
44
- stdin = STDIN.gets.chomp.to_s
45
- config[:hostname] = stdin if !stdin.empty?
46
-
47
- config[:username] ||= ENV['USER']
48
- print "Username (#{config[:username]}): "
49
- stdin = STDIN.gets.chomp.to_s
50
- config[:username] = stdin if !stdin.empty?
51
-
52
- config[:password] ||= ''
53
- print "Password: "
54
- stdin = STDIN.gets.chomp.to_s
55
- config[:password] = stdin if !stdin.empty?
56
-
57
- config[:version] ||= '~6.5 '
58
- print "Version (#{config[:version]}): "
59
- stdin = STDIN.gets.chomp.to_s
60
- config[:version] = stdin if !stdin.empty?
61
-
62
- puts
63
- puts "New settings:"
64
- puts "Hostname: #{config[:hostname]}"
65
- puts "Username: #{config[:username]}"
66
- puts "Password:"
67
- puts "Version: #{config[:version]}"
68
- puts
69
-
70
- self.write config
71
- end
72
-
73
- def self.key(keys)
74
- config = self.read
75
- use_key = 0
76
- rsa_path = nil
77
-
78
- puts "SSH Key Settings:"
79
- keys.each_with_index do |key, i|
80
- puts "#{i+1}) #{key['name']}"
81
- end
82
-
83
- if !keys.empty?
84
- puts "0) Add new key"
85
- print "Select SSH key: "
86
- stdin = STDIN.gets.chomp.to_s
87
- use_key = stdin.to_i if !stdin.empty?
88
- end
89
-
90
- if use_key > 0
91
- config[:use_key] = keys[use_key-1]['name']
92
- else
93
- config[:use_key] ||= 'id_rsa'
94
- print "Key name (#{config[:use_key]}): "
95
- stdin = STDIN.gets.chomp.to_s
96
- config[:use_key] = stdin if !stdin.empty?
97
-
98
- rsa_path = File.join(ENV["HOME"], '/.ssh/id_rsa.pub')
99
- print "Public key path (#{rsa_path}): "
100
- stdin = STDIN.gets.chomp.to_s
101
- rsa_path = stdin if !stdin.empty?
102
- end
103
-
104
- config[:rsa_path] ||= File.join(ENV["HOME"], '/.ssh/id_rsa')
105
- print "Private key path (#{config[:rsa_path]}): "
106
- stdin = STDIN.gets.chomp.to_s
107
- config[:rsa_path] = stdin if !stdin.empty?
108
- puts
109
-
110
- self.write config
111
- rsa_path
112
- end
113
-
114
- private
115
-
116
- def path
117
- config = '.sdccfg'
118
- file = File.join(File.dirname(__FILE__), '..', config)
119
- if File.exist?(file)
120
- file
121
- else
122
- File.join(ENV["HOME"], config)
123
- end
124
- end
125
- end
@@ -1,20 +0,0 @@
1
- module Smartdc
2
- module Api
3
- class Datasets
4
- attr_reader :request
5
-
6
- def initialize(options)
7
- @request = Smartdc::Request.new(options)
8
- end
9
-
10
- def read(id)
11
- raise ArgumentError unless id
12
- request.get('my/datasets/' + id.to_s)
13
- end
14
-
15
- def all(query={})
16
- request.get('my/datasets', query)
17
- end
18
- end
19
- end
20
- end
@@ -1,24 +0,0 @@
1
- module Smartdc::Api
2
- module Machine
3
- class Metadata
4
- attr_reader :request
5
-
6
- def initialize(id, options)
7
- @id = id
8
- @request = Smartdc::Request.new(options)
9
- end
10
-
11
- def create(raw={})
12
- request.post('my/machines/' + @id.to_s + '/metadata/', raw)
13
- end
14
-
15
- def read(query={})
16
- request.get('my/machines/' + @id.to_s + '/metadata', query)
17
- end
18
-
19
- def destroy(id=nil)
20
- request.del('my/machines/' + @id.to_s + '/metadata/' + id.to_s)
21
- end
22
- end
23
- end
24
- end
@@ -1,35 +0,0 @@
1
- module Smartdc::Api
2
- module Machine
3
- class Snapshots
4
- attr_reader :request
5
-
6
- def initialize(id, options)
7
- @id = id
8
- @request = Smartdc::Request.new(options)
9
- end
10
-
11
- def create(raw={})
12
- request.post('my/machines/' + @id.to_s + '/snapshots/', raw)
13
- end
14
-
15
- def read(id)
16
- raise ArgumentError unless id
17
- request.get('my/machines/' + @id.to_s + '/snapshots/' + id.to_s)
18
- end
19
-
20
- def all(query={})
21
- request.get('my/machines/' + @id.to_s + '/snapshots', query)
22
- end
23
-
24
- def destroy(id)
25
- raise ArgumentError unless id
26
- request.del('my/machines/' + @id.to_s + '/snapshots/' + id.to_s)
27
- end
28
-
29
- def start(id)
30
- raise ArgumentError unless id
31
- request.post('my/machines/' + @id.to_s + '/snapshots/' + id.to_s)
32
- end
33
- end
34
- end
35
- end
@@ -1,29 +0,0 @@
1
- module Smartdc::Api
2
- module Machine
3
- class Tags
4
- attr_reader :request
5
-
6
- def initialize(id, options)
7
- @id = id
8
- @request = Smartdc::Request.new(options)
9
- end
10
-
11
- def create(raw={})
12
- request.post('my/machines/' + @id.to_s + '/tags/', raw)
13
- end
14
-
15
- def read(id)
16
- raise ArgumentError unless id
17
- request.get('my/machines/' + @id.to_s + '/tags/' + id.to_s)
18
- end
19
-
20
- def all(query={})
21
- request.get('my/machines/' + @id.to_s + '/tags', query)
22
- end
23
-
24
- def destroy(id=nil)
25
- request.del('my/machines/' + @id.to_s + '/tags/' + id.to_s)
26
- end
27
- end
28
- end
29
- end
@@ -1,35 +0,0 @@
1
- module Smartdc
2
- class Error < StandardError
3
- attr_reader :response
4
-
5
- def initialize(response)
6
- @response = response
7
- begin
8
- body = JSON.parse(response[:body])
9
- if body['error_message']
10
- super(body['error_message'])
11
- else
12
- super(response[:body])
13
- end
14
- rescue
15
- super(response[:body])
16
- end
17
- end
18
-
19
- def response_status
20
- response[:status]
21
- end
22
- end
23
-
24
- class Error::BadRequest < Smartdc::Error; end
25
- class Error::Unauthorized < Smartdc::Error; end
26
- class Error::Forbidden < Smartdc::Error; end
27
- class Error::NotFound < Smartdc::Error; end
28
- class Error::MethodNotAllowed < Smartdc::Error; end
29
- class Error::NotAcceptable < Smartdc::Error; end
30
- class Error::Conflict < Smartdc::Error; end
31
- class Error::InternalServerError < Smartdc::Error; end
32
- class Error::NotImplemented < Smartdc::Error; end
33
- class Error::BadGateway < Smartdc::Error; end
34
- class Error::ServiceUnavailable < Smartdc::Error; end
35
- end
@@ -1,83 +0,0 @@
1
- require 'json'
2
- require 'faraday'
3
- require 'smartdc/auth'
4
- #require 'smartdc/response/raise_error'
5
-
6
- module Smartdc
7
- class Request
8
- def initialize(options)
9
- @options = options
10
- end
11
-
12
- def get(path, query={})
13
- request(:get, path, query, {})
14
- end
15
-
16
- def post(path, raw={})
17
- request(:post, path, {}, raw)
18
- end
19
-
20
- def put(path, raw={})
21
- request(:put, path, {}, raw)
22
- end
23
-
24
- def del(path, query={})
25
- request(:delete, path, query, {})
26
- end
27
-
28
- def request(method, path, query={}, raw={})
29
- path = path.gsub(/^my/, @options[:username])
30
- res = connection.send(method) do |req|
31
- case method
32
- when :get
33
- req.url path, query
34
- when :post, :put
35
- req.path = path
36
- req.body = raw.to_json unless raw.empty?
37
- when :delete
38
- req.url path
39
- end
40
-
41
- if @options[:debug]
42
- print 'Request: '
43
- puts "method: #{req.method.to_s}"
44
- puts "path: #{req.path}"
45
- puts "params: #{req.params}"
46
- puts "headers: #{req.headers}"
47
- puts "body: #{req.body}"
48
- end
49
- end
50
-
51
- if @options[:debug]
52
- print 'Response: '
53
- puts "status: #{res.status}"
54
- puts "headers: #{res.headers}"
55
- puts "body: #{res.body}"
56
- end
57
-
58
- Smartdc::Response.new(res)
59
- end
60
-
61
- private
62
-
63
- def connection
64
- options = {
65
- :url => 'https://' + @options[:hostname],
66
- :ssl => {:verify => false},
67
- :headers => {
68
- :date => Time.now.gmtime.to_s,
69
- 'content-type'=>'application/json',
70
- 'x-api-version' => @options[:version]
71
- }
72
- }
73
-
74
- options[:headers][:authorization] = Smartdc::Auth::sign(options, @options) if @options[:rsa_path] && !@options[:password]
75
-
76
- Faraday.new(options) do |builder|
77
- builder.request :basic_auth, @options[:username], @options[:password] if @options[:password]
78
- # builder.use Smartdc::Response::RaiseError
79
- builder.adapter Faraday.default_adapter
80
- end
81
- end
82
- end
83
- end