@ebowwa/hetzner 0.1.0 → 0.2.1
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.
- package/actions.js +721 -439
- package/auth.js +15 -11
- package/bootstrap/cloud-init.js +109 -65
- package/bootstrap/firewall.js +30 -17
- package/bootstrap/genesis.js +89 -71
- package/bootstrap/index.js +31 -7
- package/bootstrap/kernel-hardening.js +10 -6
- package/bootstrap/kernel-hardening.test.js +182 -0
- package/bootstrap/security-audit.js +10 -6
- package/bootstrap/ssh-hardening.js +10 -6
- package/client.js +180 -83
- package/config.js +4 -2
- package/errors.js +183 -108
- package/index.js +57 -12
- package/index.ts +4 -0
- package/onboarding/doppler.ts +116 -0
- package/onboarding/git.ts +133 -0
- package/onboarding/index.ts +18 -0
- package/onboarding/onboarding.ts +193 -0
- package/onboarding/tailscale.ts +159 -0
- package/onboarding/types.ts +115 -0
- package/package.json +11 -6
- package/pricing.js +216 -113
- package/schemas.js +322 -315
- package/server-status.js +122 -0
- package/servers.js +530 -287
- package/ssh-keys.js +153 -63
- package/ssh-setup.js +253 -0
- package/ssh-setup.ts +1 -1
- package/types.js +11 -8
- package/types.ts +6 -6
- package/volumes.js +205 -82
package/volumes.js
CHANGED
|
@@ -1,15 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Hetzner Volume Operations
|
|
3
4
|
*
|
|
4
5
|
* Provides methods for managing Hetzner Cloud volumes.
|
|
5
6
|
* See: https://docs.hetzner.cloud/#volumes
|
|
6
7
|
*/
|
|
8
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
18
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
19
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
20
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
21
|
+
function step(op) {
|
|
22
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
23
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
24
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
25
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
26
|
+
switch (op[0]) {
|
|
27
|
+
case 0: case 1: t = op; break;
|
|
28
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
29
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
30
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
31
|
+
default:
|
|
32
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
33
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
34
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
35
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
36
|
+
if (t[2]) _.ops.pop();
|
|
37
|
+
_.trys.pop(); continue;
|
|
38
|
+
}
|
|
39
|
+
op = body.call(thisArg, _);
|
|
40
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
41
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.VolumeOperations = void 0;
|
|
7
46
|
/**
|
|
8
47
|
* Volume operations for Hetzner Cloud API
|
|
9
48
|
*/
|
|
10
|
-
|
|
11
|
-
client
|
|
12
|
-
constructor(client) {
|
|
49
|
+
var VolumeOperations = /** @class */ (function () {
|
|
50
|
+
function VolumeOperations(client) {
|
|
13
51
|
this.client = client;
|
|
14
52
|
}
|
|
15
53
|
/**
|
|
@@ -18,63 +56,101 @@ export class VolumeOperations {
|
|
|
18
56
|
* @param options - List options (name, status, sort, etc.)
|
|
19
57
|
* @returns Array of volumes
|
|
20
58
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
59
|
+
VolumeOperations.prototype.list = function (options) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
61
|
+
var params, endpoint, response;
|
|
62
|
+
return __generator(this, function (_a) {
|
|
63
|
+
switch (_a.label) {
|
|
64
|
+
case 0:
|
|
65
|
+
params = new URLSearchParams();
|
|
66
|
+
if (options === null || options === void 0 ? void 0 : options.name)
|
|
67
|
+
params.set("name", options.name);
|
|
68
|
+
if (options === null || options === void 0 ? void 0 : options.status)
|
|
69
|
+
params.set("status", options.status);
|
|
70
|
+
if (options === null || options === void 0 ? void 0 : options.sort)
|
|
71
|
+
params.set("sort", options.sort);
|
|
72
|
+
if (options === null || options === void 0 ? void 0 : options.label_selector)
|
|
73
|
+
params.set("label_selector", options.label_selector);
|
|
74
|
+
endpoint = "/volumes".concat(params.toString() ? "?".concat(params) : "");
|
|
75
|
+
return [4 /*yield*/, this.client.request(endpoint)];
|
|
76
|
+
case 1:
|
|
77
|
+
response = _a.sent();
|
|
78
|
+
return [2 /*return*/, response.volumes || []];
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
};
|
|
35
83
|
/**
|
|
36
84
|
* Get a specific volume by ID
|
|
37
85
|
*
|
|
38
86
|
* @param id - Volume ID
|
|
39
87
|
* @returns Volume details
|
|
40
88
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
89
|
+
VolumeOperations.prototype.get = function (id) {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
91
|
+
var response;
|
|
92
|
+
return __generator(this, function (_a) {
|
|
93
|
+
switch (_a.label) {
|
|
94
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(id))];
|
|
95
|
+
case 1:
|
|
96
|
+
response = _a.sent();
|
|
97
|
+
return [2 /*return*/, response.volume];
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
};
|
|
45
102
|
/**
|
|
46
103
|
* Create a new volume
|
|
47
104
|
*
|
|
48
105
|
* @param options - Volume creation options
|
|
49
106
|
* @returns Created volume with action info
|
|
50
107
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
108
|
+
VolumeOperations.prototype.create = function (options) {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
110
|
+
var response;
|
|
111
|
+
var _a;
|
|
112
|
+
return __generator(this, function (_b) {
|
|
113
|
+
switch (_b.label) {
|
|
114
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes", {
|
|
115
|
+
method: "POST",
|
|
116
|
+
body: JSON.stringify({
|
|
117
|
+
name: options.name,
|
|
118
|
+
size: options.size,
|
|
119
|
+
server: options.server,
|
|
120
|
+
location: options.location,
|
|
121
|
+
automount: (_a = options.automount) !== null && _a !== void 0 ? _a : true,
|
|
122
|
+
format: options.format,
|
|
123
|
+
labels: options.labels,
|
|
124
|
+
}),
|
|
125
|
+
})];
|
|
126
|
+
case 1:
|
|
127
|
+
response = _b.sent();
|
|
128
|
+
return [2 /*return*/, response];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
63
131
|
});
|
|
64
|
-
|
|
65
|
-
}
|
|
132
|
+
};
|
|
66
133
|
/**
|
|
67
134
|
* Delete a volume
|
|
68
135
|
*
|
|
69
136
|
* @param id - Volume ID
|
|
70
137
|
* @returns Action response
|
|
71
138
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
139
|
+
VolumeOperations.prototype.delete = function (id) {
|
|
140
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
141
|
+
var response;
|
|
142
|
+
return __generator(this, function (_a) {
|
|
143
|
+
switch (_a.label) {
|
|
144
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(id), {
|
|
145
|
+
method: "DELETE",
|
|
146
|
+
})];
|
|
147
|
+
case 1:
|
|
148
|
+
response = _a.sent();
|
|
149
|
+
return [2 /*return*/, response.action];
|
|
150
|
+
}
|
|
151
|
+
});
|
|
75
152
|
});
|
|
76
|
-
|
|
77
|
-
}
|
|
153
|
+
};
|
|
78
154
|
/**
|
|
79
155
|
* Attach a volume to a server
|
|
80
156
|
*
|
|
@@ -83,28 +159,47 @@ export class VolumeOperations {
|
|
|
83
159
|
* @param automount - Automatically mount the volume
|
|
84
160
|
* @returns Action response
|
|
85
161
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
162
|
+
VolumeOperations.prototype.attach = function (volumeId_1, serverId_1) {
|
|
163
|
+
return __awaiter(this, arguments, void 0, function (volumeId, serverId, automount) {
|
|
164
|
+
var response;
|
|
165
|
+
if (automount === void 0) { automount = true; }
|
|
166
|
+
return __generator(this, function (_a) {
|
|
167
|
+
switch (_a.label) {
|
|
168
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/attach"), {
|
|
169
|
+
method: "POST",
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
server: serverId,
|
|
172
|
+
automount: automount,
|
|
173
|
+
}),
|
|
174
|
+
})];
|
|
175
|
+
case 1:
|
|
176
|
+
response = _a.sent();
|
|
177
|
+
return [2 /*return*/, response.action];
|
|
178
|
+
}
|
|
179
|
+
});
|
|
93
180
|
});
|
|
94
|
-
|
|
95
|
-
}
|
|
181
|
+
};
|
|
96
182
|
/**
|
|
97
183
|
* Detach a volume from a server
|
|
98
184
|
*
|
|
99
185
|
* @param volumeId - Volume ID
|
|
100
186
|
* @returns Action response
|
|
101
187
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
188
|
+
VolumeOperations.prototype.detach = function (volumeId) {
|
|
189
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
190
|
+
var response;
|
|
191
|
+
return __generator(this, function (_a) {
|
|
192
|
+
switch (_a.label) {
|
|
193
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/detach"), {
|
|
194
|
+
method: "POST",
|
|
195
|
+
})];
|
|
196
|
+
case 1:
|
|
197
|
+
response = _a.sent();
|
|
198
|
+
return [2 /*return*/, response.action];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
105
201
|
});
|
|
106
|
-
|
|
107
|
-
}
|
|
202
|
+
};
|
|
108
203
|
/**
|
|
109
204
|
* Resize a volume
|
|
110
205
|
*
|
|
@@ -112,13 +207,22 @@ export class VolumeOperations {
|
|
|
112
207
|
* @param size - New size in GB (must be larger than current)
|
|
113
208
|
* @returns Action response
|
|
114
209
|
*/
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
210
|
+
VolumeOperations.prototype.resize = function (volumeId, size) {
|
|
211
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
212
|
+
var response;
|
|
213
|
+
return __generator(this, function (_a) {
|
|
214
|
+
switch (_a.label) {
|
|
215
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/resize"), {
|
|
216
|
+
method: "POST",
|
|
217
|
+
body: JSON.stringify({ size: size }),
|
|
218
|
+
})];
|
|
219
|
+
case 1:
|
|
220
|
+
response = _a.sent();
|
|
221
|
+
return [2 /*return*/, response.action];
|
|
222
|
+
}
|
|
223
|
+
});
|
|
119
224
|
});
|
|
120
|
-
|
|
121
|
-
}
|
|
225
|
+
};
|
|
122
226
|
/**
|
|
123
227
|
* Change volume protection
|
|
124
228
|
*
|
|
@@ -126,15 +230,24 @@ export class VolumeOperations {
|
|
|
126
230
|
* @param deleteProtection - Enable delete protection
|
|
127
231
|
* @returns Action response
|
|
128
232
|
*/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
233
|
+
VolumeOperations.prototype.changeProtection = function (volumeId, deleteProtection) {
|
|
234
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
235
|
+
var response;
|
|
236
|
+
return __generator(this, function (_a) {
|
|
237
|
+
switch (_a.label) {
|
|
238
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId, "/actions/change_protection"), {
|
|
239
|
+
method: "POST",
|
|
240
|
+
body: JSON.stringify({
|
|
241
|
+
delete: deleteProtection,
|
|
242
|
+
}),
|
|
243
|
+
})];
|
|
244
|
+
case 1:
|
|
245
|
+
response = _a.sent();
|
|
246
|
+
return [2 /*return*/, response.action];
|
|
247
|
+
}
|
|
248
|
+
});
|
|
135
249
|
});
|
|
136
|
-
|
|
137
|
-
}
|
|
250
|
+
};
|
|
138
251
|
/**
|
|
139
252
|
* Update volume labels
|
|
140
253
|
*
|
|
@@ -142,13 +255,22 @@ export class VolumeOperations {
|
|
|
142
255
|
* @param labels - New labels
|
|
143
256
|
* @returns Updated volume
|
|
144
257
|
*/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
258
|
+
VolumeOperations.prototype.updateLabels = function (volumeId, labels) {
|
|
259
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
260
|
+
var response;
|
|
261
|
+
return __generator(this, function (_a) {
|
|
262
|
+
switch (_a.label) {
|
|
263
|
+
case 0: return [4 /*yield*/, this.client.request("/volumes/".concat(volumeId), {
|
|
264
|
+
method: "PUT",
|
|
265
|
+
body: JSON.stringify({ labels: labels }),
|
|
266
|
+
})];
|
|
267
|
+
case 1:
|
|
268
|
+
response = _a.sent();
|
|
269
|
+
return [2 /*return*/, response.volume];
|
|
270
|
+
}
|
|
271
|
+
});
|
|
149
272
|
});
|
|
150
|
-
|
|
151
|
-
}
|
|
273
|
+
};
|
|
152
274
|
/**
|
|
153
275
|
* Get volume pricing information
|
|
154
276
|
* Calculates monthly cost based on size (€0.008/GB per month)
|
|
@@ -156,17 +278,18 @@ export class VolumeOperations {
|
|
|
156
278
|
* @param sizeInGB - Volume size in GB
|
|
157
279
|
* @returns Monthly and hourly pricing
|
|
158
280
|
*/
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
281
|
+
VolumeOperations.calculatePrice = function (sizeInGB) {
|
|
282
|
+
var PRICE_PER_GB_MONTHLY = 0.008; // €0.008 per GB per month
|
|
283
|
+
var HOURS_PER_MONTH = 730; // Average
|
|
284
|
+
var monthly = sizeInGB * PRICE_PER_GB_MONTHLY;
|
|
285
|
+
var hourly = monthly / HOURS_PER_MONTH;
|
|
164
286
|
return {
|
|
165
287
|
size: sizeInGB,
|
|
166
288
|
monthly: Math.round(monthly * 100) / 100,
|
|
167
289
|
hourly: Math.round(hourly * 10000) / 10000,
|
|
168
290
|
currency: "EUR",
|
|
169
291
|
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
292
|
+
};
|
|
293
|
+
return VolumeOperations;
|
|
294
|
+
}());
|
|
295
|
+
exports.VolumeOperations = VolumeOperations;
|