nifcloud 0.0.2

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: 0afd39ff3b060348389f157e449de337dea88331
4
+ data.tar.gz: 947d8505cea05bbe0f37a0cb31a4841c4820311b
5
+ SHA512:
6
+ metadata.gz: b425260f6b0b12f7c8607947de0fc7ae330d3396a91773569dafc2b927077c0a5e980ad9744d0b06ebc467de1ecf4bc73aa56f1baeb291a715c80ed346e1d586
7
+ data.tar.gz: 9c160e5b1aaff8d118c949aaf673163614e73e24ff64bcb0060a5e2075e507e4c763ad386bc80caa65b1aef46b10ce4f47896b333dde751899ff60d2b4df0222
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /vendor/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
14
+
15
+ .vscode/
16
+ .DS_Store
17
+
18
+ *.gem
19
+ *.rbc
20
+ *.swp
21
+ .bundle
22
+ .config
23
+ .yardoc
24
+
25
+ \.idea/
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.4.2
5
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}"}
4
+
5
+ # Specify your gem's dependencies in nifcloud.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Unofficial NIF Cloud SDK for Ruby
2
+
3
+ ## 概要
4
+ ニフクラ(IaaS)から提供されているAPIを利用し、サーバー作成等の操作を可能にするSDKです。
5
+
6
+ ## インストール
7
+ ```
8
+ gem install nifcloud
9
+ ```
10
+
11
+ ## 使い方
12
+ ```
13
+ $ export NIFCLOUD_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXX
14
+ $ export NIFCLOUD_SECRET_ACCESS_KEY=YYYYYYYYYYYYYYYYYYY
15
+ ```
16
+
17
+ ## For Developer
18
+ ```
19
+ $ bundle install --path=vendor/bundle
20
+ $ bundle exec rake
21
+ ```
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |spec|
5
+ spec.pattern = FileList['spec/**/*_spec.rb']
6
+ spec.rspec_opts = ['--color', '--format d']
7
+ end
8
+
9
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nifcloud"
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/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,10 @@
1
+ require 'nifcloud'
2
+ require 'pp'
3
+
4
+ nc = Nifcloud.client(endpoint: 'https://computing.jp-west-1.api.cloud.nifty.com/api', debug: true)
5
+ res = nc.DescribeInstances()
6
+
7
+ pp res
8
+
9
+ pp res.reservationSet[0].groupSet[0].groupId
10
+ pp res.reservationSet[0].instancesSet[0].instanceId
@@ -0,0 +1,14 @@
1
+ module Nifcloud
2
+ class API < Request
3
+ attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
4
+
5
+ def initialize(options={})
6
+ options = Nifcloud.options.merge(options)
7
+ (Configuration::VALID_OPTIONS_KEYS + [:secret_key]).each do |key|
8
+ send("#{key}=", options[key]) if options[key]
9
+ end
10
+
11
+ super
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ class Nifcloud::Client
2
+ module Instances
3
+ def DescribeInstances(options={})
4
+ options[:Action] = 'DescribeInstances'
5
+ get('/', query: options)
6
+ end
7
+
8
+ def DescribeInstanceAttribute(options={})
9
+ options[:Action] = 'DescribeInstanceAttribute'
10
+ get('/', query: options)
11
+ end
12
+
13
+ def ModifyInstanceAttribute(options={})
14
+ options[:Action] = 'ModifyInstanceAttribute'
15
+ get('/', query: options)
16
+ end
17
+
18
+ def RebootInstances(options={})
19
+ options[:Action] = 'RebootInstances'
20
+ get('/', query: options)
21
+ end
22
+
23
+ def RunInstances(options={})
24
+ options[:Action] = 'RunInstances'
25
+ get('/', query: options)
26
+ end
27
+
28
+ def StartInstances(options={})
29
+ options[:Action] = 'StartInstances'
30
+ get('/', query: options)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ module Nifcloud
2
+ class Client < API
3
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each {|f| require f}
4
+
5
+ include Instances
6
+
7
+ def inspect
8
+ inspected = super
9
+
10
+ if @secret_key
11
+ inspected = inspected.sub! @secret_key, only_show_last_four_chars(@secret_key)
12
+ end
13
+
14
+ if @access_key
15
+ inspected = inspected.sub! @access_key, only_show_last_four_chars(@access_key)
16
+ end
17
+
18
+ inspected
19
+ end
20
+
21
+ private
22
+
23
+ def only_show_last_four_chars(key)
24
+ "#{'*'*(key.size - 4)}#{key[-4..-1]}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module Nifcloud
2
+ module Configuration
3
+ VALID_OPTIONS_KEYS = [:endpoint, :secret_key, :access_key, :user_agent, :debug].freeze
4
+ DEFAULT_USER_AGENT = "Nifcloud Ruby Gem #{Nifcloud::VERSION}".freeze
5
+
6
+ attr_accessor(*VALID_OPTIONS_KEYS)
7
+
8
+ def self.extended(base)
9
+ base.reset
10
+ end
11
+
12
+ def configure
13
+ yield self
14
+ end
15
+
16
+ def options
17
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
18
+ option.merge!(key => send(key))
19
+ end
20
+ end
21
+
22
+ def reset
23
+ self.endpoint = ENV['NIFCLOUD_API_ENDPOINT']
24
+ self.secret_key = ENV['NIFCLOUD_API_SECRET_KEY']
25
+ self.access_key = ENV['NIFCLOUD_API_ACCESS_KEY']
26
+ self.debug = nil
27
+ self.user_agent = DEFAULT_USER_AGENT
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,96 @@
1
+ module Nifcloud
2
+ module Error
3
+ # Custom error class for rescuing from all errors.
4
+ class Error < StandardError;
5
+ end
6
+
7
+ # Raised when API endpoint credentials not configured.
8
+ class MissingCredentials < Error;
9
+ end
10
+
11
+ # Raised when impossible to parse response body.
12
+ class Parsing < Error;
13
+ end
14
+
15
+ # Custom error class for rescuing from HTTP response errors.
16
+ class ResponseError < Error
17
+ def initialize(response)
18
+ @response = response
19
+ super(build_error_message)
20
+ end
21
+
22
+ # Status code returned in the http response.
23
+ #
24
+ # @return [Integer]
25
+ def response_status
26
+ (@response != false) ? @response.Code : "?"
27
+ end
28
+
29
+ private
30
+
31
+ # Human friendly message.
32
+ #
33
+ # @return [String]
34
+ def build_error_message
35
+ message = @response.Message if @response != false
36
+ message = "false" if @response == false
37
+
38
+ "Server responded with code #{@response.Code}, \n message: #{handle_message(message)}. \n\n"
39
+ end
40
+
41
+ # Handle error response message in case of nested hashes
42
+ def handle_message(message)
43
+ case message
44
+ #when Nifcloud::ObjectifiedHash
45
+ # message.to_h.sort.map do |key, val|
46
+ # "'#{key}' #{(val.is_a?(Hash) ? val.sort.map { |k, v| "(#{k}: #{v.join(' ')})" } : val).join(' ')}"
47
+ # end.join(', ')
48
+ when Array
49
+ message.join(' ')
50
+ else
51
+ message
52
+ end
53
+ end
54
+ end
55
+
56
+ # Raised when API endpoint returns the HTTP status code 400.
57
+ class BadRequest < ResponseError;
58
+ end
59
+
60
+ # Raised when API endpoint returns the HTTP status code 401.
61
+ class Unauthorized < ResponseError;
62
+ end
63
+
64
+ # Raised when API endpoint returns the HTTP status code 403.
65
+ class Forbidden < ResponseError;
66
+ end
67
+
68
+ # Raised when API endpoint returns the HTTP status code 404.
69
+ class NotFound < ResponseError;
70
+ end
71
+
72
+ # Raised when API endpoint returns the HTTP status code 405.
73
+ class MethodNotAllowed < ResponseError;
74
+ end
75
+
76
+ # Raised when API endpoint returns the HTTP status code 409.
77
+ class Conflict < ResponseError;
78
+ end
79
+
80
+ # Raised when API endpoint returns the HTTP status code 422.
81
+ class Unprocessable < ResponseError;
82
+ end
83
+
84
+ # Raised when API endpoint returns the HTTP status code 500.
85
+ class InternalServerError < ResponseError;
86
+ end
87
+
88
+ # Raised when API endpoint returns the HTTP status code 502.
89
+ class BadGateway < ResponseError;
90
+ end
91
+
92
+ # Raised when API endpoint returns the HTTP status code 503.
93
+ class ServiceUnavailable < ResponseError;
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,29 @@
1
+ module Nifcloud
2
+ module ObjectifiedHash
3
+ def method_missing(meth, *args, &block)
4
+ if args.size == 0
5
+ obj = self[meth.to_s] || self[meth.to_sym]
6
+ if obj.is_a?(Hash) and obj.has_key?('item')
7
+ obj['item'].each do |i|
8
+ i.extend ObjectifiedHash
9
+ end
10
+ obj['item']
11
+ else
12
+ obj.extend ObjectifiedHash
13
+ end
14
+ end
15
+ end
16
+
17
+ def type
18
+ self['type']
19
+ end
20
+
21
+ def has?(key)
22
+ self[key] && !self[key].to_s.empty?
23
+ end
24
+
25
+ def does_not_have?(key)
26
+ self[key].nil? || self[key].to_s.empty?
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,108 @@
1
+ require 'httpclient'
2
+ require 'xmlsimple'
3
+
4
+ module Nifcloud
5
+ class Request
6
+ attr_accessor :secret_key, :access_key, :endpoint
7
+
8
+ def initialize(options={})
9
+ @client = HTTPClient.new default_header: {"User-Agent" => @user_agent}
10
+ @client.debug_dev = $stderr if @debug
11
+ end
12
+
13
+ def get(path, options={})
14
+ set_query(options)
15
+ validate @client.get(@endpoint + path, options)
16
+ end
17
+
18
+ def post(path, options={})
19
+ set_query(options)
20
+ validate @client.post(@endpoint + path, options)
21
+ end
22
+
23
+ def put(path, options={})
24
+ set_query(options)
25
+ validate @client.put(@endpoint + path, options)
26
+ end
27
+
28
+ def delete(path, options={})
29
+ set_query(options)
30
+ validate @client.delete(@endpoint + path, options)
31
+ end
32
+
33
+ def self.set_proxy_config(address=nil, port=nil, username=nil, password=nil)
34
+ @client.proxy = "http://#{address}:#{port}"
35
+ @client.set_proxy_auth(username, password) if username
36
+ end
37
+
38
+ private
39
+
40
+ def parse(xml)
41
+ options = {'forcearray' => ['item', 'member'], 'suppressempty' => nil, 'keeproot' => false}
42
+ body = XmlSimple.xml_in(xml, options)
43
+
44
+ if body.is_a? Hash
45
+ body.extend ObjectifiedHash
46
+ elsif body
47
+ true
48
+ elsif !body
49
+ false
50
+ elsif body.nil?
51
+ false
52
+ else
53
+ raise Error::Parsing.new "Couldn't parse a response body"
54
+ end
55
+ end
56
+
57
+ def validate(response)
58
+ error_klass =
59
+ case response.code
60
+ when 400 then
61
+ Error::BadRequest
62
+ when 401 then
63
+ Error::Unauthorized
64
+ when 403 then
65
+ Error::Forbidden
66
+ when 404 then
67
+ Error::NotFound
68
+ when 405 then
69
+ Error::MethodNotAllowed
70
+ when 409 then
71
+ Error::Conflict
72
+ when 422 then
73
+ Error::Unprocessable
74
+ when 500 then
75
+ Error::InternalServerError
76
+ when 502 then
77
+ Error::BadGateway
78
+ when 503 then
79
+ Error::ServiceUnavailable
80
+ end
81
+
82
+ response_obj = parse response.body
83
+ fail error_klass.new(response_obj.Errors.Error) if error_klass
84
+ response_obj
85
+ end
86
+
87
+ def set_query(options={})
88
+ set_timestamp(options)
89
+ set_access_key(options)
90
+ set_signature(options)
91
+ end
92
+
93
+ def set_timestamp(options)
94
+ options[:query][:Timestamp] = Time.now.strftime("%Y%m%dT%H:%M:%SZ")
95
+ end
96
+
97
+ def set_access_key(options)
98
+ options[:query][:AccessKeyId] = access_key
99
+ end
100
+
101
+ def set_signature(options)
102
+ key = @secret_key
103
+ data = "#{options[:query][:Action]}#{options[:query][:Timestamp]}"
104
+ options[:query][:Signature] = Signature.v0(key, data)
105
+ options[:query][:SignatureVersion] = '0'
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,15 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+ require 'cgi/util'
4
+
5
+ module Nifcloud
6
+ class Signature
7
+ def self.v0(key, data)
8
+ Base64.encode64(OpenSSL::HMAC.digest("sha1", key.encode("utf-8"), data.encode("utf-8"))).chomp
9
+ end
10
+
11
+ def self.v2(key, data)
12
+ CGI.escape(Base64.encode64(OpenSSL::HMAC.digest("sha256", key.encode("utf-8"), data.encode("utf-8"))).chomp)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Nifcloud
2
+ VERSION = "0.0.2"
3
+ end
data/lib/nifcloud.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'nifcloud/version'
2
+ require 'nifcloud/objectified_hash'
3
+ require 'nifcloud/error'
4
+ require 'nifcloud/signature'
5
+ require 'nifcloud/configuration'
6
+ require 'nifcloud/request'
7
+ require 'nifcloud/api'
8
+ require 'nifcloud/client'
9
+
10
+ module Nifcloud
11
+ extend Configuration
12
+
13
+ def self.client(options={})
14
+ Nifcloud::Client.new(options)
15
+ end
16
+
17
+ def self.method_missing(method, *args, &block)
18
+ return super unless client.respond_to?(method)
19
+ client.send(method, *args, &block)
20
+ end
21
+
22
+ def respond_to_missing?(method_name, include_private = false)
23
+ client.respond_to?(method_name) || super
24
+ end
25
+
26
+ def self.http_proxy(address=nil, port=nil, username=nil, password=nil)
27
+ Nifcloud::Request.set_proxy_config(address, port, username, password)
28
+ end
29
+ end
data/nifcloud.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "nifcloud/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nifcloud"
8
+ spec.version = Nifcloud::VERSION
9
+ spec.authors = ["Kazuki Iwata"]
10
+ spec.email = ["kazu.0516.k0n0f@gmail.com"]
11
+
12
+ spec.summary = %q{Unofficial NIFCLOUD SDK for Ruby}
13
+ spec.description = %q{The Unofficial NIFCLOUD SDK for Ruby}
14
+ spec.homepage = "https://github.com/kzmake/nifcloud"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f)}
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'webmock'
27
+
28
+ spec.add_runtime_dependency 'xml-simple'
29
+ spec.add_runtime_dependency 'httpclient'
30
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nifcloud
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kazuki Iwata
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-10-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
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: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: webmock
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
+ - !ruby/object:Gem::Dependency
70
+ name: xml-simple
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: httpclient
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: The Unofficial NIFCLOUD SDK for Ruby
98
+ email:
99
+ - kazu.0516.k0n0f@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".travis.yml"
107
+ - Gemfile
108
+ - README.md
109
+ - Rakefile
110
+ - bin/console
111
+ - bin/setup
112
+ - examples/Instances/DescribeInstances.rb
113
+ - lib/nifcloud.rb
114
+ - lib/nifcloud/api.rb
115
+ - lib/nifcloud/client.rb
116
+ - lib/nifcloud/client/Instances.rb
117
+ - lib/nifcloud/configuration.rb
118
+ - lib/nifcloud/error.rb
119
+ - lib/nifcloud/objectified_hash.rb
120
+ - lib/nifcloud/request.rb
121
+ - lib/nifcloud/signature.rb
122
+ - lib/nifcloud/version.rb
123
+ - nifcloud.gemspec
124
+ homepage: https://github.com/kzmake/nifcloud
125
+ licenses: []
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.6.13
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Unofficial NIFCLOUD SDK for Ruby
147
+ test_files: []