Skip to content

Instantly share code, notes, and snippets.

@m-shibata
Created December 7, 2015 16:26
Embed
What would you like to do?
swift for swift
#!/usr/bin/env swift
import Glibc
let config = [
"tenantName": "",
"tenantId": "",
"username": "",
"password": "",
"configfile": ".conoha",
]
enum ConoHaMethod {
case Put
case Get
case Unknown
}
let CURL_GET = "curl -s -X GET -H \"Accept: application/json\""
let CURL_PUT = "curl -s -X PUT -H \"Accept: application/json\""
let CURL_POST = "curl -s -X POST -H \"Accept: application/json\""
let CURL_HEAD = "curl -s --head -H \"Accept: application/json\""
let CONOHA_API_IDENTIFY = "https://identity.tyo1.conoha.io/v2.0/tokens"
let CONOHA_API_SWIFT = "https://object-storage.tyo1.conoha.io/v1"
func usage() {
print("Usage: conoha put | get container file")
}
func execToString(command: String) -> String {
let fp = popen(command, "r")
if fp == nil {
return ""
}
var data = String()
let buffer = [CChar](count: 1024, repeatedValue: 0)
while fgets(UnsafeMutablePointer(buffer), Int32(buffer.count), fp) != nil {
if let read = String.fromCString(buffer) {
data += read
}
}
if pclose(fp) != 0 {
return ""
}
return data
}
func isExpired(expire: String) -> Bool {
var expireTm = tm()
var buffer: [Character] = []
// parse YYYY-mm-ddTHH:MM:SSZ
for i in 0...3 { buffer.append(expire[expire.startIndex.advancedBy(i)]) }
expireTm.tm_year = Int32(String(buffer))! - 1900
buffer = []
for i in 5...6 { buffer.append(expire[expire.startIndex.advancedBy(i)]) }
expireTm.tm_mon = Int32(String(buffer))! - 1
buffer = []
for i in 8...9 { buffer.append(expire[expire.startIndex.advancedBy(i)]) }
expireTm.tm_mday = Int32(String(buffer))!
buffer = []
for i in 11...12 { buffer.append(expire[expire.startIndex.advancedBy(i)]) }
expireTm.tm_hour = Int32(String(buffer))!
buffer = []
for i in 14...15 { buffer.append(expire[expire.startIndex.advancedBy(i)]) }
expireTm.tm_min = Int32(String(buffer))!
buffer = []
for i in 17...18 { buffer.append(expire[expire.startIndex.advancedBy(i)]) }
expireTm.tm_sec = Int32(String(buffer))!
buffer = []
let expireTime = mktime(&expireTm)
// get current time
var currentTime = time(nil)
currentTime += 60
return currentTime > expireTime
}
func getToken() -> String {
// set config file name
let pwent = getpwuid(getuid())
let homeDir = String.fromCString(pwent.memory.pw_dir)
if homeDir == nil {
print("Error: failed to get home directory")
exit(1)
}
let configFile = homeDir! + "/" + config["configfile"]!
// check old token
var token = ["", ""]
if access(configFile, R_OK) == 0 {
var data = String()
let buffer = [CChar](count: 1024, repeatedValue: 0)
let fp = fopen(configFile, "r")
while fgets(UnsafeMutablePointer(buffer), Int32(buffer.count), fp) != nil {
if let read = String.fromCString(buffer) {
data += read
}
}
fclose(fp)
token = data.characters.split("\n").map { String($0) }
if token.count == 2 {
// check expires
if !isExpired(token[1]) {
return token[0]
} else {
print("Token is expired, retrieve new token")
}
}
}
// get new token
var json_auth = "'{ \"auth\": { \"tenantName\": \"\(config["tenantName"]!)\", "
json_auth += "\"passwordCredentials\": { \"username\": \"\(config["username"]!)\", "
json_auth += "\"password\": \"\(config["password"]!)\" } } }'"
var cmd = "\(CURL_POST) -d \(json_auth) \(CONOHA_API_IDENTIFY) | "
cmd += "jq -r \".access.token.id, .access.token.expires\""
token = execToString(cmd).characters.split("\n").map { String($0) }
if token.count != 2 {
print("Error: failed to get tokenId/expires")
exit(1)
}
// save new token
cmd = "echo -n \"\(token[0])\\n\(token[1])\" > \(configFile)"
execToString(cmd)
return token[0]
}
func createContainer(token: String, container: String) -> Bool {
let api = CONOHA_API_SWIFT + "/nc_" + config["tenantId"]!
// container already exists?
var cmd_check = "\(CURL_HEAD) -H \"X-Auth-Token: \(token)\" "
cmd_check += "\(api)/\(container) | "
cmd_check += "head -1 | grep \" 20[0-9] \""
if execToString(cmd_check) != "" {
return true
}
// create container
var cmd_create = "\(CURL_PUT) -H \"X-Auth-Token: \(token)\" "
cmd_create += "\(api)/\(container)"
if execToString(cmd_create) != "" {
print("Error: failed to create \"\(container)\" container")
return false
}
// recheck container exists
if execToString(cmd_check) != "" {
return true
}
print("Error: \"\(container)\" container not found")
return false
}
func upload(token: String, container: String, file: String) -> Bool {
let api = CONOHA_API_SWIFT + "/nc_" + config["tenantId"]!
// upload_file
var cmd = "\(CURL_PUT) -H \"X-Auth-Token: \(token)\" "
cmd += "\(api)/\(container)/\(file) -T \(file)"
if execToString(cmd) != "" {
print("Error: failed to upload \"\(container)/\(file)\"")
return false
}
return true
}
func download(token: String, container: String, file: String) -> Bool {
let api = CONOHA_API_SWIFT + "/nc_" + config["tenantId"]!
// file exits?
var cmd_check = "\(CURL_HEAD) -H \"X-Auth-Token: \(token)\" "
cmd_check += "\(api)/\(container)/\(file) | "
cmd_check += "head -1 | grep \" 20[0-9] \""
if execToString(cmd_check) == "" {
print("\"\(container)/\(file)\" is not found")
return false
}
// download_file
var cmd = "\(CURL_GET) -H \"X-Auth-Token: \(token)\" "
cmd += "\(api)/\(container)/\(file) -O \(file)"
if execToString(cmd) != "" {
print("Error: failed to download \"\(container)/\(file)\"")
return false
}
return true
}
// main routine
if Process.argc != 4 {
usage()
exit(1)
}
var method = ConoHaMethod.Unknown
var container = String()
var file = String()
switch Process.arguments[1] {
case "put":
method = ConoHaMethod.Put
container = Process.arguments[2]
file = Process.arguments[3]
if access(file, R_OK) != 0 {
print("\(file) not found")
exit(1)
}
break
case "get":
method = ConoHaMethod.Get
container = Process.arguments[2]
file = Process.arguments[3]
if access(file, R_OK) == 0 {
print("Warning: \(file) will be overwritten")
}
break
default:
method = ConoHaMethod.Unknown
}
if method == ConoHaMethod.Unknown {
print("Error: unknown method: \(Process.arguments[1])")
usage()
exit(1)
}
if execToString("which jq") == "" {
print("Error: not found jq command")
}
let token = getToken()
if !createContainer(token, container: container) {
exit(1)
}
switch (method) {
case ConoHaMethod.Get:
if !download(token, container: container, file: file) {
exit(1)
}
break
case ConoHaMethod.Put:
if !upload(token, container: container, file: file) {
exit(1)
}
break
case ConoHaMethod.Unknown:
assert(false, "unexpected method value")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment