Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
e85d725873 | |||
d90be18e74 | |||
5c0e4c6b90 | |||
34e2c82e68 | |||
bc53e9f872 | |||
646ab4d18c | |||
aaeb025217 | |||
21e37a7a16 | |||
4e0dfb0356 | |||
84780647da | |||
1645d7881a | |||
88351db20f | |||
18cbf8693f | |||
7d64a2bc4d | |||
4c327e5e32 | |||
a898928bd3 | |||
aba8182422 | |||
5412ab524b |
@ -5,10 +5,23 @@
|
|||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "apiclient.xyz",
|
"gitscope": "apiclient.xyz",
|
||||||
"gitrepo": "hetznercloud",
|
"gitrepo": "hetznercloud",
|
||||||
"description": "an unofficial api client for the hetzner cloud api",
|
"description": "An unofficial TypeScript API client for the Hetzner Cloud API providing easy methods to manage servers, volumes, and firewalls.",
|
||||||
"npmPackagename": "@apiclient.xyz/hetznercloud",
|
"npmPackagename": "@apiclient.xyz/hetznercloud",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"projectDomain": "apiclient.xyz"
|
"projectDomain": "apiclient.xyz",
|
||||||
|
"keywords": [
|
||||||
|
"Hetzner",
|
||||||
|
"Cloud",
|
||||||
|
"API",
|
||||||
|
"TypeScript",
|
||||||
|
"Client",
|
||||||
|
"Servers",
|
||||||
|
"Volumes",
|
||||||
|
"Firewalls",
|
||||||
|
"Automation",
|
||||||
|
"DevOps",
|
||||||
|
"Cloud Infrastructure"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmci": {
|
"npmci": {
|
||||||
|
23
package.json
23
package.json
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@apiclient.xyz/hetznercloud",
|
"name": "@apiclient.xyz/hetznercloud",
|
||||||
"version": "1.0.12",
|
"version": "1.2.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "an unofficial api client for the hetzner cloud api",
|
"description": "An unofficial TypeScript API client for the Hetzner Cloud API providing easy methods to manage servers, volumes, and firewalls.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
"test": "(tstest test/ --web)",
|
"test": "(tstest test/ --web)",
|
||||||
"build": "(tsbuild --web --allowimplicitany)",
|
"build": "(tsbuild --web --allowimplicitany)",
|
||||||
"buildDocs": "(tsdoc)",
|
"buildDocs": "(tsdoc)",
|
||||||
"create": "openapi-generator-cli generate -i https://docs.hetzner.cloud/spec.json -g typescript-node -o ts_openapi"
|
"updateAPI": "openapi-typescript https://docs.hetzner.cloud/spec.json --output ts/openapi.spec.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.25",
|
"@git.zone/tsbuild": "^2.1.25",
|
||||||
@ -21,11 +21,11 @@
|
|||||||
"@git.zone/tstest": "^1.0.44",
|
"@git.zone/tstest": "^1.0.44",
|
||||||
"@push.rocks/qenv": "^6.0.5",
|
"@push.rocks/qenv": "^6.0.5",
|
||||||
"@push.rocks/tapbundle": "^5.0.15",
|
"@push.rocks/tapbundle": "^5.0.15",
|
||||||
"@types/node": "^20.8.7"
|
"@types/node": "^20.11.22",
|
||||||
|
"openapi-typescript": "^6.7.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/smartrequest": "^2.0.21",
|
"@push.rocks/smartrequest": "^2.0.21",
|
||||||
"@tempfix/hetzner-openapi": "^1.0.4",
|
|
||||||
"@tsclass/tsclass": "^4.0.52"
|
"@tsclass/tsclass": "^4.0.52"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -50,5 +50,18 @@
|
|||||||
"cli.js",
|
"cli.js",
|
||||||
"npmextra.json",
|
"npmextra.json",
|
||||||
"readme.md"
|
"readme.md"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"Hetzner",
|
||||||
|
"Cloud",
|
||||||
|
"API",
|
||||||
|
"TypeScript",
|
||||||
|
"Client",
|
||||||
|
"Servers",
|
||||||
|
"Volumes",
|
||||||
|
"Firewalls",
|
||||||
|
"Automation",
|
||||||
|
"DevOps",
|
||||||
|
"Cloud Infrastructure"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
6785
pnpm-lock.yaml
generated
6785
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
0
readme.hints.md
Normal file
0
readme.hints.md
Normal file
283
readme.md
283
readme.md
@ -1,40 +1,267 @@
|
|||||||
# @apiclient.xyz/hetznercloud
|
# @apiclient.xyz/hetznercloud
|
||||||
an unofficial api client for the hetzner cloud api
|
An unofficial API client for the Hetzner Cloud API
|
||||||
|
|
||||||
## Availabililty and Links
|
## Install
|
||||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@apiclient.xyz/hetznercloud)
|
|
||||||
* [gitlab.com (source)](https://gitlab.com/apiclient.xyz/hetznercloud)
|
|
||||||
* [github.com (source mirror)](https://github.com/apiclient.xyz/hetznercloud)
|
|
||||||
* [docs (typedoc)](https://apiclient.xyz.gitlab.io/hetznercloud/)
|
|
||||||
|
|
||||||
## Status for master
|
You can install the `@apiclient.xyz/hetznercloud` package via npm:
|
||||||
|
|
||||||
Status Category | Status Badge
|
```bash
|
||||||
-- | --
|
npm install @apiclient.xyz/hetznercloud
|
||||||
GitLab Pipelines | [](https://lossless.cloud)
|
```
|
||||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
|
||||||
npm | [](https://lossless.cloud)
|
Or using yarn:
|
||||||
Snyk | [](https://lossless.cloud)
|
|
||||||
TypeScript Support | [](https://lossless.cloud)
|
```bash
|
||||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
yarn add @apiclient.xyz/hetznercloud
|
||||||
Code Style | [](https://lossless.cloud)
|
```
|
||||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
|
||||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
|
||||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
A modern approach to talking to the hetzner API.
|
|
||||||
|
The `@apiclient.xyz/hetznercloud` package provides a modern approach to interact with the Hetzner Cloud API. Below are some detailed examples demonstrating the usage of this package for different scenarios like managing accounts, servers, volumes, and firewalls.
|
||||||
|
|
||||||
|
### Initial Setup
|
||||||
|
|
||||||
|
To begin using the package, you need to import it and initialize your Hetzner account with an API token:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// assuming top level await here
|
import { HetznerAccount, HetznerServer, Volume, HetznerFirewall } from '@apiclient.xyz/hetznercloud';
|
||||||
import hetznerCloud from '@apiclient.xyz/hetznercloud'
|
|
||||||
const myhetznerAccount = new hetznerCloud.HetznerAccount('myToken');
|
// Initialize Hetzner account
|
||||||
const servers = await myhetznerAccount.getServers();
|
const myHetznerAccount = new HetznerAccount('yourHetznerApiToken');
|
||||||
for (const server of servers) {
|
```
|
||||||
|
|
||||||
|
### Managing Servers
|
||||||
|
|
||||||
|
#### Creating a Server
|
||||||
|
|
||||||
|
You can create a new server using the `createServer` method in the `HetznerAccount` class. Provide the necessary options such as name, type, location, labels, and optional user data:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const newServer = await myHetznerAccount.createServer({
|
||||||
|
name: 'my-server',
|
||||||
|
type: 'cpx31',
|
||||||
|
location: 'nbg1',
|
||||||
|
labels: {
|
||||||
|
purpose: 'test'
|
||||||
|
},
|
||||||
|
userData: '#!/bin/bash\necho Hello from your new server!'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('New server details:', newServer.data);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Listing Servers
|
||||||
|
|
||||||
|
To list all servers in your account, you can use the `getServers` method:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const servers = await myHetznerAccount.getServers();
|
||||||
|
console.log('Current servers:', servers);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filtering Servers by Labels
|
||||||
|
|
||||||
|
You can filter servers based on specific labels:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const filteredServers = await myHetznerAccount.getServersByLabel({ purpose: 'test' });
|
||||||
|
console.log('Filtered servers:', filteredServers);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Deleting a Server
|
||||||
|
|
||||||
|
To delete a server, call the `delete` method on the server instance:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const serverToDelete = filteredServers[0]; // Example, choose the first filtered server
|
||||||
|
await serverToDelete.delete();
|
||||||
|
console.log('Server deleted successfully');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Managing Volumes
|
||||||
|
|
||||||
|
#### Creating a Volume
|
||||||
|
|
||||||
|
To create a new volume, use the `Volume.create` method, passing in the necessary options:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const newVolume = await Volume.create(myHetznerAccount, {
|
||||||
|
name: 'my-volume',
|
||||||
|
size: 10, // Size in GB
|
||||||
|
location: 'nbg1',
|
||||||
|
labels: {
|
||||||
|
purpose: 'test-volume'
|
||||||
|
},
|
||||||
|
server: newServer // Attach the volume to a specific server (newServer in this case)
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('New volume details:', newVolume.data);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Listing Volumes
|
||||||
|
|
||||||
|
You can list all volumes in your account with the `getVolumes` method:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const volumes = await Volume.getVolumes(myHetznerAccount);
|
||||||
|
console.log('Current volumes:', volumes);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filtering Volumes by Labels
|
||||||
|
|
||||||
|
To filter volumes based on specific labels:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const filteredVolumes = await Volume.getVolumesByLabel(myHetznerAccount, { purpose: 'test-volume' });
|
||||||
|
console.log('Filtered volumes:', filteredVolumes);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Deleting a Volume
|
||||||
|
|
||||||
|
To delete a volume, call the `delete` method on the volume instance:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const volumeToDelete = filteredVolumes[0]; // Example, choose the first filtered volume
|
||||||
|
await volumeToDelete.delete();
|
||||||
|
console.log('Volume deleted successfully');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Managing Firewalls
|
||||||
|
|
||||||
|
#### Creating a Firewall
|
||||||
|
|
||||||
|
To create a new firewall, use the `create` method in the `HetznerFirewall` class:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const newFirewall = await HetznerFirewall.create(myHetznerAccount, {
|
||||||
|
name: 'my-firewall',
|
||||||
|
labels: {
|
||||||
|
purpose: 'test-firewall'
|
||||||
|
},
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
direction: 'in',
|
||||||
|
protocol: 'tcp',
|
||||||
|
port: '80',
|
||||||
|
source_ips: ['0.0.0.0/0', '::/0']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
direction: 'in',
|
||||||
|
protocol: 'tcp',
|
||||||
|
port: '443',
|
||||||
|
source_ips: ['0.0.0.0/0', '::/0']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('New firewall details:', newFirewall.data);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Listing Firewalls
|
||||||
|
|
||||||
|
To list all firewalls in your account:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const firewalls = await HetznerFirewall.getFirewalls(myHetznerAccount);
|
||||||
|
console.log('Current firewalls:', firewalls);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filtering Firewalls by Labels
|
||||||
|
|
||||||
|
To filter firewalls based on specific labels:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const filteredFirewalls = await HetznerFirewall.getFirewallsByLabel(myHetznerAccount, { purpose: 'test-firewall' });
|
||||||
|
console.log('Filtered firewalls:', filteredFirewalls);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Deleting a Firewall
|
||||||
|
|
||||||
|
To delete a firewall, call the `delete` method on the firewall instance:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const firewallToDelete = filteredFirewalls[0]; // Example, choose the first filtered firewall
|
||||||
|
await firewallToDelete.delete();
|
||||||
|
console.log('Firewall deleted successfully');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Full Lifecycle Management
|
||||||
|
|
||||||
|
Here is a complete example that demonstrates the full lifecycle of creating, listing, filtering, and deleting servers, volumes, and firewalls:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { HetznerAccount, HetznerServer, Volume, HetznerFirewall } from '@apiclient.xyz/hetznercloud';
|
||||||
|
|
||||||
|
// Initialize Hetzner account
|
||||||
|
const myHetznerAccount = new HetznerAccount('yourHetznerApiToken');
|
||||||
|
|
||||||
|
// Step 1: Create a new server
|
||||||
|
const newServer = await myHetznerAccount.createServer({
|
||||||
|
name: 'my-server',
|
||||||
|
type: 'cpx31',
|
||||||
|
location: 'nbg1',
|
||||||
|
labels: { purpose: 'test' },
|
||||||
|
userData: '#!/bin/bash\necho Hello from your new server!'
|
||||||
|
});
|
||||||
|
console.log('New server created:', newServer.data);
|
||||||
|
|
||||||
|
// Step 2: Create a new volume and attach it to the server
|
||||||
|
const newVolume = await Volume.create(myHetznerAccount, {
|
||||||
|
name: 'my-volume',
|
||||||
|
size: 10, // GB
|
||||||
|
location: 'nbg1',
|
||||||
|
labels: { purpose: 'test-volume' },
|
||||||
|
server: newServer
|
||||||
|
});
|
||||||
|
console.log('New volume created:', newVolume.data);
|
||||||
|
|
||||||
|
// Step 3: Create a new firewall and attach rules to it
|
||||||
|
const newFirewall = await HetznerFirewall.create(myHetznerAccount, {
|
||||||
|
name: 'my-firewall',
|
||||||
|
labels: { purpose: 'test-firewall' },
|
||||||
|
rules: [
|
||||||
|
{ direction: 'in', protocol: 'tcp', port: '80', source_ips: ['0.0.0.0/0', '::/0'] },
|
||||||
|
{ direction: 'in', protocol: 'tcp', port: '443', source_ips: ['0.0.0.0/0', '::/0'] }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
console.log('New firewall created:', newFirewall.data);
|
||||||
|
|
||||||
|
// Step 4: List all servers, volumes, and firewalls
|
||||||
|
const servers = await myHetznerAccount.getServers();
|
||||||
|
console.log('All servers:', servers);
|
||||||
|
|
||||||
|
const volumes = await Volume.getVolumes(myHetznerAccount);
|
||||||
|
console.log('All volumes:', volumes);
|
||||||
|
|
||||||
|
const firewalls = await HetznerFirewall.getFirewalls(myHetznerAccount);
|
||||||
|
console.log('All firewalls:', firewalls);
|
||||||
|
|
||||||
|
// Step 5: Filter servers, volumes, and firewalls by labels
|
||||||
|
const filteredServers = await myHetznerAccount.getServersByLabel({ purpose: 'test' });
|
||||||
|
console.log('Filtered servers:', filteredServers);
|
||||||
|
|
||||||
|
const filteredVolumes = await Volume.getVolumesByLabel(myHetznerAccount, { purpose: 'test-volume' });
|
||||||
|
console.log('Filtered volumes:', filteredVolumes);
|
||||||
|
|
||||||
|
const filteredFirewalls = await HetznerFirewall.getFirewallsByLabel(myHetznerAccount, { purpose: 'test-firewall' });
|
||||||
|
console.log('Filtered firewalls:', filteredFirewalls);
|
||||||
|
|
||||||
|
// Step 6: Cleanup - Delete created resources
|
||||||
|
for (const server of filteredServers) {
|
||||||
await server.delete();
|
await server.delete();
|
||||||
|
console.log('Server deleted:', server.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const volume of filteredVolumes) {
|
||||||
|
await volume.delete();
|
||||||
|
console.log('Volume deleted:', volume.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const firewall of filteredFirewalls) {
|
||||||
|
await firewall.delete();
|
||||||
|
console.log('Firewall deleted:', firewall.data);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Legal
|
This comprehensive example demonstrates how you can manage your Hetzner resources using the `@apiclient.xyz/hetznercloud` package efficiently and effectively.
|
||||||
> MIT licensed | **©** [Task Venture Capital GmbH](https://task.vc)
|
undefined
|
||||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
|
@ -36,7 +36,7 @@ const testserver = tap.test('should be able to create a server', async (toolsArg
|
|||||||
tap.test('should be able to delete a server', async () => {
|
tap.test('should be able to delete a server', async () => {
|
||||||
const testServer: hetznercloud.HetznerServer =
|
const testServer: hetznercloud.HetznerServer =
|
||||||
await (testserver.testResultPromise as Promise<hetznercloud.HetznerServer>);
|
await (testserver.testResultPromise as Promise<hetznercloud.HetznerServer>);
|
||||||
// await testServer.delete();
|
await testServer.delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.start();
|
tap.start();
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@apiclient.xyz/hetznercloud',
|
name: '@apiclient.xyz/hetznercloud',
|
||||||
version: '1.0.12',
|
version: '1.2.0',
|
||||||
description: 'an unofficial api client for the hetzner cloud api'
|
description: 'An unofficial TypeScript API client for the Hetzner Cloud API providing easy methods to manage servers, volumes, and firewalls.'
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,10 @@ export class HetznerAccount {
|
|||||||
return HetznerServer.getServers(this);
|
return HetznerServer.getServers(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getServersByLabel(labelObject: plugins.tsclass.typeFestOwn.SecondArgument<typeof HetznerServer.getServersByLabel>) {
|
||||||
|
return HetznerServer.getServersByLabel(this, labelObject);
|
||||||
|
}
|
||||||
|
|
||||||
public async createServer(optionsArg: plugins.tsclass.typeFestOwn.SecondArgument<typeof HetznerServer.create>) {
|
public async createServer(optionsArg: plugins.tsclass.typeFestOwn.SecondArgument<typeof HetznerServer.create>) {
|
||||||
return HetznerServer.create(this, optionsArg);
|
return HetznerServer.create(this, optionsArg);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
// Hetzner Cloud Firewall Class
|
||||||
|
import type { HetznerAccount } from './classes.account.js';
|
||||||
|
import * as plugins from './hetznercloud.plugins.js';
|
||||||
|
import * as types from './types.js';
|
||||||
|
|
||||||
|
export class HetznerFirewall {
|
||||||
|
// STATIC
|
||||||
|
public static create = async (
|
||||||
|
hetznerAccountRefArg: HetznerAccount,
|
||||||
|
optionsArg: {
|
||||||
|
name: string;
|
||||||
|
labels?: {[key: string]: string},
|
||||||
|
rules: types.IFirewall['rules'],
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const firewall = new HetznerFirewall(hetznerAccountRefArg);
|
||||||
|
|
||||||
|
const createFirewallUrl = '/firewalls';
|
||||||
|
const createFirewallPayload: types.TFirewallCreateRequestBody = {
|
||||||
|
name: optionsArg.name,
|
||||||
|
labels: optionsArg.labels || {} as any,
|
||||||
|
rules: optionsArg.rules
|
||||||
|
};
|
||||||
|
const response = await firewall.hetznerAccountRef.request(
|
||||||
|
'POST',
|
||||||
|
createFirewallUrl,
|
||||||
|
createFirewallPayload
|
||||||
|
);
|
||||||
|
firewall.data = (response.body as types.TFirewallCreateResponseBody).firewall;
|
||||||
|
return firewall;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getFirewalls = async (hetznerAccountRefArg: HetznerAccount) => {
|
||||||
|
const firewallsGetUrl = '/firewalls';
|
||||||
|
const response = await hetznerAccountRefArg.request('GET', firewallsGetUrl, {});
|
||||||
|
const firewallsDataArray = (response.body as types.TFirewallsGetResponseBody).firewalls;
|
||||||
|
const firewalls: HetznerFirewall[] = [];
|
||||||
|
for (const firewallData of firewallsDataArray) {
|
||||||
|
const firewall = new HetznerFirewall(hetznerAccountRefArg);
|
||||||
|
firewall.data = firewallData;
|
||||||
|
firewalls.push(firewall);
|
||||||
|
}
|
||||||
|
return firewalls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getFirewallsByLabel = async (hetznerAccountRefArg: HetznerAccount, labelObject: {[key: string]: string}) => {
|
||||||
|
const firewalls = await HetznerFirewall.getFirewalls(hetznerAccountRefArg);
|
||||||
|
const results: HetznerFirewall[] = [];
|
||||||
|
for (const firewall of firewalls) {
|
||||||
|
let isMatch = true;
|
||||||
|
for (const key in labelObject) {
|
||||||
|
if (firewall.data.labels[key] !== labelObject[key]) {
|
||||||
|
isMatch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) {
|
||||||
|
results.push(firewall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INSTANCE
|
||||||
|
public data: types.IFirewall;
|
||||||
|
public hetznerAccountRef: HetznerAccount;
|
||||||
|
|
||||||
|
constructor(hetznerAccountRefArg: HetznerAccount) {
|
||||||
|
this.hetznerAccountRef = hetznerAccountRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async delete() {
|
||||||
|
await this.hetznerAccountRef.request('DELETE', `/firewalls/${this.data.id}`, {});
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,8 @@ export class HetznerServer {
|
|||||||
name: string;
|
name: string;
|
||||||
type: types.THetznerCloudServerName;
|
type: types.THetznerCloudServerName;
|
||||||
location: types.THetznerCloudLocationName;
|
location: types.THetznerCloudLocationName;
|
||||||
labels: {[key: string]: string},
|
labels?: {[key: string]: string},
|
||||||
|
userData?: string,
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const server = new HetznerServer(hetznerAccountRefArg);
|
const server = new HetznerServer(hetznerAccountRefArg);
|
||||||
@ -23,6 +24,7 @@ export class HetznerServer {
|
|||||||
start_after_create: true,
|
start_after_create: true,
|
||||||
labels: optionsArg.labels || {} as any,
|
labels: optionsArg.labels || {} as any,
|
||||||
location: optionsArg.location,
|
location: optionsArg.location,
|
||||||
|
user_data: optionsArg.userData || '',
|
||||||
public_net: {
|
public_net: {
|
||||||
enable_ipv4: true,
|
enable_ipv4: true,
|
||||||
enable_ipv6: true,
|
enable_ipv6: true,
|
||||||
@ -50,6 +52,23 @@ export class HetznerServer {
|
|||||||
return servers;
|
return servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async getServersByLabel(hetznerAccountRefArg: HetznerAccount, labelObject: {[key: string]: string}) {
|
||||||
|
const servers = await HetznerServer.getServers(hetznerAccountRefArg);
|
||||||
|
const results: HetznerServer[] = [];
|
||||||
|
for (const server of servers) {
|
||||||
|
let isMatch = true;
|
||||||
|
for (const key in labelObject) {
|
||||||
|
if (server.data.labels[key] !== labelObject[key]) {
|
||||||
|
isMatch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) {
|
||||||
|
results.push(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
public hetznerAccountRef: HetznerAccount;
|
public hetznerAccountRef: HetznerAccount;
|
||||||
public data: types.IServer;
|
public data: types.IServer;
|
||||||
|
77
ts/classes.volume.ts
Normal file
77
ts/classes.volume.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import type { HetznerAccount } from './classes.account.js';
|
||||||
|
import type { HetznerServer } from './classes.server.js';
|
||||||
|
import * as plugins from './hetznercloud.plugins.js';
|
||||||
|
import * as types from './types.js';
|
||||||
|
|
||||||
|
export class HetznerVolume {
|
||||||
|
public static create = async (
|
||||||
|
hetznerAccountRefArg: HetznerAccount,
|
||||||
|
optionsArg: {
|
||||||
|
name: string;
|
||||||
|
size: number;
|
||||||
|
location: types.THetznerCloudLocationName;
|
||||||
|
labels?: {[key: string]: string},
|
||||||
|
server: HetznerServer,
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const volume = new HetznerVolume(hetznerAccountRefArg);
|
||||||
|
|
||||||
|
const createVolumeUrl = '/volumes';
|
||||||
|
const createVolumePayload: types.TVolumeCreateRequestBody = {
|
||||||
|
name: optionsArg.name,
|
||||||
|
size: optionsArg.size,
|
||||||
|
location: optionsArg.location,
|
||||||
|
labels: optionsArg.labels || {} as any,
|
||||||
|
server: optionsArg.server.data.id,
|
||||||
|
format: 'xfs'
|
||||||
|
};
|
||||||
|
const response = await volume.hetznerAccountRef.request(
|
||||||
|
'POST',
|
||||||
|
createVolumeUrl,
|
||||||
|
createVolumePayload
|
||||||
|
);
|
||||||
|
volume.data = (response.body as types.TVolumeCreateResponseBody).volume;
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getVolumes = async (hetznerAccountRefArg: HetznerAccount) => {
|
||||||
|
const volumesGetUrl = '/volumes';
|
||||||
|
const response = await hetznerAccountRefArg.request('GET', volumesGetUrl, {});
|
||||||
|
const volumesDataArray = (response.body as types.TVolumeGetResponseBody).volumes;
|
||||||
|
const volumes: HetznerVolume[] = [];
|
||||||
|
for (const volumeData of volumesDataArray) {
|
||||||
|
const volume = new HetznerVolume(hetznerAccountRefArg);
|
||||||
|
volume.data = volumeData;
|
||||||
|
volumes.push(volume);
|
||||||
|
}
|
||||||
|
return volumes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getVolumesByLabel = async (hetznerAccountRefArg: HetznerAccount, labelObject: {[key: string]: string}) => {
|
||||||
|
const volumes = await HetznerVolume.getVolumes(hetznerAccountRefArg);
|
||||||
|
const results: HetznerVolume[] = [];
|
||||||
|
for (const volume of volumes) {
|
||||||
|
let isMatch = true;
|
||||||
|
for (const key in labelObject) {
|
||||||
|
if (volume.data.labels[key] !== labelObject[key]) {
|
||||||
|
isMatch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) {
|
||||||
|
results.push(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public data: types.IVolume;
|
||||||
|
public hetznerAccountRef: HetznerAccount;
|
||||||
|
|
||||||
|
constructor(hetznerAccountRefArg: HetznerAccount) {
|
||||||
|
this.hetznerAccountRef = hetznerAccountRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public delete = async () => {
|
||||||
|
await this.hetznerAccountRef.request('DELETE', `/volumes/${this.data.id}`, {});
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,3 @@
|
|||||||
import * as hetznerOpenapi from '@tempfix/hetzner-openapi';
|
|
||||||
|
|
||||||
export {
|
|
||||||
hetznerOpenapi
|
|
||||||
}
|
|
||||||
|
|
||||||
// @push.rocks
|
// @push.rocks
|
||||||
import * as smartrequest from '@push.rocks/smartrequest';
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
|
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
export * from './classes.account.js';
|
export * from './classes.account.js';
|
||||||
export * from './classes.server.js';
|
export * from './classes.server.js';
|
||||||
|
export * from './classes.volume.js';
|
||||||
|
export * from './classes.firewall.js';
|
||||||
|
25285
ts/openapi.spec.ts
Normal file
25285
ts/openapi.spec.ts
Normal file
File diff suppressed because it is too large
Load Diff
30
ts/types.ts
30
ts/types.ts
@ -1,14 +1,16 @@
|
|||||||
import * as plugins from './hetznercloud.plugins.js';
|
import * as plugins from './hetznercloud.plugins.js';
|
||||||
|
import * as hetznerOpenapiSpec from './openapi.spec.js';
|
||||||
|
|
||||||
// datacenters
|
// datacenters
|
||||||
export type TDatacenters = plugins.hetznerOpenapi.paths['/datacenters']['get']['responses']['200']['content']['application/json'];
|
export type TDatacenters = hetznerOpenapiSpec.paths['/datacenters']['get']['responses']['200']['content']['application/json'];
|
||||||
|
|
||||||
// servers
|
// servers
|
||||||
export type IServer = plugins.hetznerOpenapi.paths['/servers/{id}']['get']['responses']['200']['content']['application/json']['server'];
|
export type IServer = hetznerOpenapiSpec.paths['/servers/{id}']['get']['responses']['200']['content']['application/json']['server'];
|
||||||
export type TServersGetRequestBody = {};
|
export type TServersGetRequestBody = {};
|
||||||
export type TServersGetResponseBody = plugins.hetznerOpenapi.paths['/servers']['get']['responses']['200']['content']['application/json'];
|
export type TServersGetResponseBody = hetznerOpenapiSpec.paths['/servers']['get']['responses']['200']['content']['application/json'];
|
||||||
export type TServerCreateRequestBody = plugins.hetznerOpenapi.paths['/servers']['post']['requestBody']['content']['application/json'];
|
export type TServerCreateRequestBody = hetznerOpenapiSpec.paths['/servers']['post']['requestBody']['content']['application/json'];
|
||||||
export type TServerCreateResponseBody = plugins.hetznerOpenapi.paths['/servers']['post']['responses']['201']['content']['application/json'];
|
export type TServerCreateResponseBody = hetznerOpenapiSpec.paths['/servers']['post']['responses']['201']['content']['application/json'];
|
||||||
|
export type TServerDeleteRequestBody = hetznerOpenapiSpec.paths['/servers/{id}']['delete'];
|
||||||
|
|
||||||
// server types
|
// server types
|
||||||
export type THetznerCloudServerName =
|
export type THetznerCloudServerName =
|
||||||
@ -39,4 +41,20 @@ export type THetznerCloudServerName =
|
|||||||
| 'cpx90';
|
| 'cpx90';
|
||||||
|
|
||||||
// location types
|
// location types
|
||||||
export type THetznerCloudLocationName = 'fsn1' | 'nbg1' | 'hel1' | 'ash' | 'hil';
|
export type THetznerCloudLocationName = 'fsn1' | 'nbg1' | 'hel1' | 'ash' | 'hil';
|
||||||
|
|
||||||
|
// volumes
|
||||||
|
export type IVolume = hetznerOpenapiSpec.paths['/volumes/{id}']['get']['responses']['200']['content']['application/json']['volume'];
|
||||||
|
export type TVolumeGetRequestBody = {};
|
||||||
|
export type TVolumeGetResponseBody = hetznerOpenapiSpec.paths['/volumes']['get']['responses']['200']['content']['application/json'];
|
||||||
|
export type TVolumeCreateRequestBody = hetznerOpenapiSpec.paths['/volumes']['post']['requestBody']['content']['application/json'];
|
||||||
|
export type TVolumeCreateResponseBody = hetznerOpenapiSpec.paths['/volumes']['post']['responses']['201']['content']['application/json'];
|
||||||
|
export type TVolumeDeleteRequestBody = hetznerOpenapiSpec.paths['/volumes/{id}']['delete'];
|
||||||
|
|
||||||
|
// firewalls
|
||||||
|
export type IFirewall = hetznerOpenapiSpec.paths['/firewalls/{id}']['get']['responses']['200']['content']['application/json']['firewall'];
|
||||||
|
export type TFirewallsGetRequestBody = {};
|
||||||
|
export type TFirewallsGetResponseBody = hetznerOpenapiSpec.paths['/firewalls']['get']['responses']['200']['content']['application/json'];
|
||||||
|
export type TFirewallCreateRequestBody = hetznerOpenapiSpec.paths['/firewalls']['post']['requestBody']['content']['application/json'];
|
||||||
|
export type TFirewallCreateResponseBody = hetznerOpenapiSpec.paths['/firewalls']['post']['responses']['201']['content']['application/json'];
|
||||||
|
export type TFirewallDeleteRequestBody = hetznerOpenapiSpec.paths['/firewalls/{id}']['delete'];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user