generated from openpeeps/pistachio
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: George Lemon <georgelemon@protonmail.com>
- Loading branch information
1 parent
5198270
commit 4fa7218
Showing
7 changed files
with
403 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,5 @@ testresults/ | |
/tests/* | ||
!/tests/*.nim | ||
!/tests/*.nims | ||
.env | ||
endpoints.md |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Package | ||
|
||
version = "0.1.0" | ||
author = "George Lemon" | ||
description = "Asynchronous Nim client for interacting with Hetzner Cloud API" | ||
license = "MIT" | ||
srcDir = "src" | ||
|
||
|
||
# Dependencies | ||
|
||
requires "nim >= 2.0.2" | ||
requires "jsony" | ||
|
||
task build_action, "build /action": | ||
exec "nim c -d:ssl -o:./bin/action src/hetzner/action.nim" | ||
|
||
task build_certificate, "build /certficates": | ||
exec "nim c -d:ssl -o:./bin/certificates src/hetzner/certificate.nim" | ||
|
||
task build_network, "build /networks": | ||
exec "nim c -d:ssl -o:./bin/networks src/hetzner/network.nim" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# This is just an example to get you started. A typical library package | ||
# exports the main API in this file. Note that you cannot rename this file | ||
# but you can remove it if you wish. | ||
|
||
proc add*(x, y: int): int = | ||
## Adds two numbers together. | ||
return x + y |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# Asynchronous Nim client for | ||
# interacting with the Hetzner Cloud API | ||
# | ||
# (c) 2023 George Lemon | MIT License | ||
# Made by Humans from OpenPeeps | ||
# https://github.com/openpeeps/hetzner-nim | ||
|
||
import std/times | ||
import pkg/jsony | ||
import ./meta | ||
|
||
## Actions show the results and progress of asynchronous requests to the API. | ||
## Check Hetzner API Reference: https://docs.hetzner.cloud/#actions | ||
|
||
type | ||
ActionStatus* = enum | ||
actionStatusRunning = "running" | ||
actionStatusSuccess = "success" | ||
actionStatusError = "error" | ||
|
||
Action* = object | ||
id: int64 | ||
command: string | ||
status: ActionStatus | ||
progress: int | ||
started, finished: Time | ||
error: ActionError | ||
resources: seq[ActionResource] | ||
|
||
ActionResourceType* = enum | ||
actionResourceTypeServer = "server" | ||
actionResourceTypeImage = "image" | ||
actionResourceTypeISO = "iso" | ||
actionResourceTypeFloatingIP = "floating_ip" | ||
actionResourceTypeVolume = "volume" | ||
|
||
ActionResource* = object | ||
id: int64 | ||
`type`: ActionResourceType | ||
|
||
ActionError* = ref object | ||
code: string | ||
message: string | ||
|
||
Actions* = object | ||
actions: seq[Action] | ||
meta: Pagination | ||
|
||
ActionClient* = ref object of HetznerClient | ||
|
||
|
||
# | ||
# `/actions` | ||
# | ||
# proc newActionClient*(): ActionClient = | ||
# ## Create a new HttpClient for GET `/action` | ||
|
||
proc sort*(client: ActionClient, filters: varargs[string]): ActionClient {.discardable.} = | ||
## Sort actions by field and direction. Can be used multiple times. | ||
## For more information, see [Sorting](https://docs.hetzner.cloud/#sorting) | ||
assert client.uri == epActions | ||
client.multiQuery["sort"] = filters.toSeq | ||
result = client | ||
|
||
proc status*(client: ActionClient, x: set[ActionStatus]): ActionClient {.discardable.} = | ||
## Filter the actions by status. Can be used multiple times. | ||
## The response will only contain actions matching the specified statuses | ||
assert client.uri == epActions | ||
client.multiQuery["status"] = x.toSeq.mapit($it) | ||
result = client | ||
|
||
proc page*(client: ActionClient, i: int64): ActionClient {.discardable.} = | ||
## Maximum number of entries returned per page. | ||
## For more information, see [Pagination](https://docs.hetzner.cloud/#pagination) | ||
client.query["page"] = $i | ||
result = client | ||
|
||
proc perPage*(client: ActionClient, i: int64): ActionClient {.discardable.} = | ||
## Page number to return. For more information | ||
client.query["per_page"] = $i | ||
result = client | ||
|
||
proc get*(client: ActionClient): Future[Actions] {.async.} = | ||
let res = await client.getHetzner() | ||
let body = await res.body | ||
fromJSON body, Actions | ||
|
||
proc `$`*(certs: Actions): string = | ||
## Serialize available Actions | ||
toJSON certs | ||
|
||
when isMainModule: | ||
import pkg/dotenv | ||
from std/os import getEnv | ||
from std/macros import getProjectPath | ||
|
||
dotenv.load(getProjectPath()) | ||
|
||
var hcloud = initHetzner(getEnv("hetznerApiKey")) | ||
var client = newClient[ActionClient](hcloud, epActions) | ||
|
||
let actions: Actions = waitFor client.get() | ||
echo actions |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Asynchronous Nim client for | ||
# interacting with the Hetzner Cloud API | ||
# | ||
# (c) 2023 George Lemon | MIT License | ||
# Made by Humans from OpenPeeps | ||
# https://github.com/openpeeps/hetzner-nim | ||
|
||
import std/times | ||
import pkg/jsony | ||
import ./meta | ||
|
||
type | ||
CertificateStatus* = enum | ||
certificateStatusIssuance | ||
certificateStatusRenewal | ||
certificateStatusError | ||
|
||
CertificateType* = enum | ||
certificateTypeUploaded = "uploaded" | ||
certificateTypeManaged = "managed" | ||
|
||
Certificate* = ref object | ||
id: int64 | ||
name: string | ||
labels: seq[string] | ||
`type`: CertificateType | ||
certificate: string | ||
created: Time | ||
not_valid_before, not_valid_after: Time | ||
domain_names: seq[string] | ||
fingerprint: string | ||
status: CertificateStatus | ||
|
||
Certificates* = ref object | ||
certificates: seq[Certificate] | ||
meta: Pagination | ||
|
||
CertificateClient* = ref object of HetznerClient | ||
|
||
proc get*(client: CertificateClient): Future[Certificates] {.async.} = | ||
## Make a `GET` request to retrieve all `Certificates` | ||
let res = await client.getHetzner() | ||
let body = await res.body | ||
fromJSON body, Certificates | ||
|
||
proc `$`*(certs: Certificates): string = | ||
## Serialize available `Certificates` | ||
toJSON certs | ||
|
||
when isMainModule: | ||
import pkg/dotenv | ||
from std/os import getEnv | ||
from std/macros import getProjectPath | ||
|
||
dotenv.load(getProjectPath()) | ||
var hcloud = initHetzner(getEnv("hetznerApiKey")) | ||
var client = newClient[CertificateClient](hcloud, epCertificates) | ||
let certs = waitFor client.get() | ||
echo certs |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Asynchronous Nim client for | ||
# interacting with the Hetzner Cloud API | ||
# | ||
# (c) 2023 George Lemon | MIT License | ||
# Made by Humans from OpenPeeps | ||
# https://github.com/openpeeps/hetzner-nim | ||
|
||
import std/[asyncdispatch, httpclient, tables, | ||
strutils, sequtils, times] | ||
|
||
import pkg/jsony | ||
|
||
from std/httpcore import HttpMethod | ||
|
||
export HttpMethod, asyncdispatch, httpclient, | ||
tables, sequtils | ||
|
||
type | ||
HetznerEndpoint* = enum | ||
# Action | ||
epAction = "action" | ||
epActions = "actions" | ||
# Certifications | ||
epCertificates = "certificates" | ||
epCertificate = "certificates/{$1}" | ||
# Datacenters | ||
epDatacenters = "datacenters" | ||
epDatacenter = "datacenter/{$1}" | ||
|
||
epNetworks = "networks" | ||
epNetwork = "networks/{$1}" | ||
|
||
HetznerClient* = ref object of RootObj | ||
uri*: HetznerEndpoint | ||
httpClient*: AsyncHttpClient | ||
query*: QueryTable | ||
multiQuery*: MultiQueryTable | ||
|
||
QueryTable* = OrderedTable[string, string] | ||
MultiQueryTable* = OrderedTable[string, seq[string]] | ||
|
||
Pagination* = object | ||
page, per_page, previous_page, | ||
next_page, last_page, total_entries: int | ||
|
||
HetznerCloud* = ref object | ||
apiKey: string | ||
|
||
const baseHetznerUri = "https://api.hetzner.cloud/v1/" | ||
|
||
proc initHetzner*(key: string): HetznerCloud = | ||
## Initialize a new HetznerCloud | ||
HetznerCloud(apiKey: key) | ||
|
||
proc newClient*[T: HetznerClient](hcloud: HetznerCloud, endpoint: HetznerEndpoint): T = | ||
new(result) | ||
result.uri = endpoint | ||
result.httpClient = newAsyncHttpClient() | ||
result.httpClient.headers = newHttpHeaders({ | ||
"Authorization": "Bearer " & hcloud.apiKey | ||
}) | ||
|
||
proc `$`*(query: QueryTable): string = | ||
## Convert `query` QueryTable to string | ||
if query.len > 0: | ||
add result, "&" | ||
add result, join(query.keys.toSeq.mapIt(it & "=" & query[it]), "&") | ||
|
||
proc `$`*(query: MultiQueryTable): string = | ||
## Convert `query` MultiQuerytable to string | ||
if query.len > 0: | ||
add result, "?" | ||
var i = 0 | ||
let len = query.len - 1 | ||
for k, x in query: | ||
if x.len == 1: | ||
add result, k | ||
add result, "=" & x[0] | ||
else: | ||
add result, join(x.mapIt(k & "=" & it), "&") | ||
if i != len: | ||
add result, "&" | ||
inc i | ||
|
||
# | ||
# JSONY hooks | ||
# | ||
proc parseHook*(s: string, i: var int, v: var Time) = | ||
var str: string | ||
parseHook(s, i, str) | ||
v = parseTime(str, "yyyy-MM-dd'T'hh:mm:sszzz", local()) | ||
|
||
proc dumpHook*(s: var string, v: Time) = | ||
add s, '"' | ||
add s, v.format("yyyy-MM-dd'T'hh:mm:sszzz", local()) | ||
add s, '"' | ||
|
||
proc endpoint*(uri: HetznerEndpoint, | ||
multiQuery: MultiQueryTable, query: QueryTable): string = | ||
## Return the url string of an endpoint | ||
result = baseHetznerUri & $uri & $multiQuery & $query | ||
|
||
proc getHetzner*(client: HetznerClient): Future[AsyncResponse] {.async.} = | ||
## Make a GET request using an instance of `HetznerClient` | ||
let uri = client.uri.endpoint(client.multiQuery, client.query) | ||
result = await client.httpClient.request(uri, HttpGet) | ||
client.httpClient.close() | ||
|
Oops, something went wrong.