Last active
January 6, 2016 11:44
-
-
Save penguin2716/cdfbfb5503d2b9be9342 to your computer and use it in GitHub Desktop.
ConoHaのAPIを簡単に叩くためのスクリプト.環境変数に必要な認証情報をセットして使ってね.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
#-*- coding: utf-8 -*- | |
require 'net/http' | |
require 'uri' | |
require 'json' | |
require 'pp' | |
require 'optparse' | |
PRINT_CREDENTIALS = false | |
CONOHA_TENANT_ID = ENV["CONOHA_TENANT_ID"] | |
CONOHA_API_USER = ENV["CONOHA_API_USER"] | |
CONOHA_API_PASS = ENV["CONOHA_API_PASS"] | |
CONOHA_API_TOKEN = ENV["CONOHA_API_TOKEN"] | |
if [CONOHA_TENANT_ID, CONOHA_API_USER, CONOHA_API_PASS].include? nil | |
puts <<EOS | |
Please set following environment values first: | |
- CONOHA_TENANT_ID | |
- CONOHA_API_USER | |
- CONOHA_API_PASS | |
EOS | |
exit 1 | |
end | |
if PRINT_CREDENTIALS | |
puts "CONOHA_TENANT_ID=#{CONOHA_TENANT_ID}" | |
puts "CONOHA_API_USER=#{CONOHA_API_USER}" | |
puts "CONOHA_API_PASS=#{CONOHA_API_PASS}" | |
puts "CONOHA_API_TOKEN=#{CONOHA_API_TOKEN}" | |
end | |
# Tokyo only | |
ACCOUNT_BASE_URI = "https://account.tyo1.conoha.io/v1/#{CONOHA_TENANT_ID}" | |
DNS_BASE_URI = "https://dns-service.tyo1.conoha.io/" | |
OBJECT_STORAGE_BASE_URI = "https://object-storage.tyo1.conoha.io/v1/nc_#{CONOHA_TENANT_ID}" | |
# Region wide | |
REGION = "tyo1" | |
COMPUTE_BASE_URI = "https://compute.#{REGION}.conoha.io/v2/#{CONOHA_TENANT_ID}" | |
VOLUME_BASE_URI = "https://block-storage.#{REGION}.conoha.io/v2/#{CONOHA_TENANT_ID}" | |
DATABASE_BASE_URI = "https://database-hosting.#{REGION}.conoha.io/v1" | |
IMAGE_BASE_URI = "https://image-service.#{REGION}.conoha.io/" | |
MAIL_BASE_URI = "https://mail-hosting.#{REGION}.conoha.io/v1" | |
IDENTITY_BASE_URI = "https://identity.#{REGION}.conoha.io/v2.0" | |
NETWORK_BASE_URI = "https://networking.#{REGION}.conoha.io/" | |
URI_BASE = { | |
:account => ACCOUNT_BASE_URI, | |
:dns => DNS_BASE_URI, | |
:object_storage => OBJECT_STORAGE_BASE_URI, | |
:compute => COMPUTE_BASE_URI, | |
:volume => VOLUME_BASE_URI, | |
:database => DATABASE_BASE_URI, | |
:image => IMAGE_BASE_URI, | |
:mail => MAIL_BASE_URI, | |
:identity => IDENTITY_BASE_URI, | |
:network => NETWORK_BASE_URI | |
} | |
$options = {} | |
$options[:headers] = [] | |
$options[:method] = :get | |
$options[:output_priority] = "hbr" | |
$options[:field_separator] = "/" | |
$options[:output] = "-" | |
def call_rest(method, service, api_path, data = nil) | |
url = URI_BASE[service.to_sym] | |
until api_path.empty? | |
url = url + "/" + api_path.first.to_s | |
api_path.shift | |
end | |
response = nil | |
uri = URI.parse(url) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
header = {} | |
header["Accept"] = "application/json" | |
header["Content-Type"] = "text/json" | |
header["X-Auth-Token"] = CONOHA_API_TOKEN if CONOHA_API_TOKEN | |
$options[:headers].each do |key, value| | |
header[key] = value | |
end | |
path = uri.path | |
path += "?#{uri.query}" if uri.query | |
if [:post, :put].include? method | |
res = http.method(method).call(path, data, header) | |
else | |
res = http.method(method).call(path, header) | |
end | |
return res | |
end | |
def request_token | |
credentials = { "auth" => | |
{ "passwordCredentials" => | |
{ "username" => CONOHA_API_USER, | |
"password" => CONOHA_API_PASS }, | |
"tenantId" => CONOHA_TENANT_ID } }.to_json | |
res = call_rest(:post, "identity", ["tokens"], credentials) | |
return JSON.parse(res.body)["access"]["token"]["id"] if res | |
return nil | |
end | |
def filter(hash, query) | |
queries = query.sub(/^\//, "*/").gsub("//", "/*/").gsub("//", "/*/").split($options[:field_separator]) | |
begin | |
queries.each do |key| | |
if key =~ /^\d+$/ | |
hash = hash[key.to_i] | |
elsif key =~ /^select:[^=]+=.+$/ | |
m = /^select:([^=]+)=(.+)$/.match(key) | |
hash.select!{|item| item[m.captures[0]].to_s == m.captures[1]} | |
elsif key =~ /^list:.+$/ | |
m = /^list:(.+)$/.match(key) | |
hash.map!{|item| item[m.captures[0]]} | |
elsif key == "*" | |
if hash.instance_of? Array | |
hash = hash.first | |
elsif hash.instance_of? Hash | |
hash = hash[hash.keys.first] | |
end | |
else | |
hash = hash[key] | |
end | |
end | |
hash | |
rescue | |
puts "parse error" | |
exit 1 | |
end | |
end | |
def print_help | |
puts <<EOS | |
Usage: #{$0} [-s] <service> <path> <options> | |
Options: | |
-m, --method={get,post,put,copy,delete} | |
use specified method. The default is "get". | |
-d, --data=text | |
set text data to post. | |
-T, --upload-file=filename | |
specify output filename to upload for put method. | |
-O, --output=filename | |
write response body to the specified filename. implies "-o b". | |
-s, --service=text | |
select a service from the followings. | |
valid services: account, dns, object_storage, compute, volume, database, | |
image, mail, identity, network. | |
Note: "-s" is omissible; "compute" is automatically replaced to "-s compute" | |
-o, --output-priority=text | |
set priority of output format. | |
h: hash | |
b: body | |
r: raw | |
default: "hbr" | |
-f, --filter=text | |
filter json output with specified filter string. | |
special options: | |
select:key=value | |
list:key | |
-F, --field-separator=text | |
set field separator for the filter option. | |
The default is "/". | |
-H, --header=key:value | |
append additional header. | |
-h, --help | |
print this message. | |
Examples: | |
#{$0} account billing-invoices | |
#{$0} compute servers | |
#{$0} compute servers/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/action -m post -d '{\"vncKeymap\": \"en-us\"}' | |
#{$0} compute flavors -f "flavors/list:name" | |
#{$0} compute flavors -f "flavors/select:name=g-2gb" | |
#{$0} compute flavors -f "flavors/select:name=g-2gb/0/id" | |
#{$0} object_storage -m post -H "X-Account-Meta-Quota-Giga-Bytes:100" | |
#{$0} object_storage -m put dir1 | |
#{$0} object_storage -m put dir1/object1.img -T path/to/object1.img | |
#{$0} object_storage -m copy dir1/object1.img -H Destination:dir1/object2.img | |
#{$0} object_storage -m get dir1/object1.img -O save/to/object1.img | |
#{$0} object_storage -m delete dir1 | |
For more information, please visit official API reference: https://www.conoha.jp/docs/index.html | |
EOS | |
end | |
if CONOHA_API_TOKEN.nil? | |
puts "Please set API token with following command:" | |
puts "$ export CONOHA_API_TOKEN=#{request_token}" | |
exit 1 | |
end | |
if ARGV.empty? | |
print_help | |
exit 1 | |
end | |
parser = OptionParser.new | |
parser.on('--header=VAL', '-H') { |h| | |
begin | |
m = /^([^:=]+)[:=](.+)$/.match(h) | |
$options[:headers] << [m.captures[0], m.captures[1]] | |
rescue | |
puts "invalid option (header)" | |
exit 1 | |
end | |
} | |
parser.on('--data=VAL', '-d') { |d| $options[:data] = d } | |
parser.on('--method=VAL', '-m') { |m| $options[:method] = m.to_sym } | |
parser.on('--upload-file=VAL', '-T') { |f| $options[:upload_file] = f } | |
parser.on('--service=VAL', '-s') { |s| $options[:service] = s } | |
parser.on('--output-priority=VAL', '-o') { |priority| | |
$options[:output_priority] = priority | |
} | |
parser.on('--filter=VAL', '-f') { |filter| $options[:filter] = filter } | |
parser.on('--field-separator=VAL', '-F') { |fs| $options[:field_separator] = fs } | |
parser.on('--help', '-h') { | |
print_help | |
exit 0 | |
} | |
parser.on('--output=VAL', '-O') { |output| $options[:output] = output } | |
parser.parse!(ARGV) | |
case ARGV.first | |
when "account", "dns", "object_storage", "compute", "volume", "database", "image", "mail", "identity", "network" | |
ARGV.insert(0, "-s") | |
end | |
parser.parse!(ARGV) | |
method = $options[:method] | |
response = nil | |
case method | |
when :get, :delete, :copy | |
response = call_rest(method, $options[:service], ARGV) | |
when :post, :put | |
response = nil | |
if $options[:upload_file] | |
binary = open($options[:upload_file], 'r').read | |
response = call_rest(method, $options[:service], ARGV, binary) | |
elsif $options[:data] | |
response = call_rest(method, $options[:service], ARGV, $options[:data]) | |
else | |
response = call_rest(method, $options[:service], ARGV, nil) | |
end | |
else | |
print_help | |
end | |
$options[:output_priority].split("").each do |type| | |
begin | |
case type | |
when "h" | |
hash = JSON.parse(response.body) | |
if $options[:filter] | |
pp filter(hash, $options[:filter]) | |
else | |
pp hash | |
end | |
when "b" | |
if response.body | |
next if response.body.empty? | |
if $options[:output] != "-" | |
file = open($options[:output], 'w') | |
file.write(response.body) | |
file.close | |
else | |
pp response.body | |
end | |
else | |
next | |
end | |
when "r" | |
pp response | |
end | |
break | |
rescue | |
next | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment