@ebowwa/hetzner 0.1.0
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 +802 -0
- package/actions.ts +1053 -0
- package/auth.js +35 -0
- package/auth.ts +37 -0
- package/bootstrap/FIREWALL.md +326 -0
- package/bootstrap/KERNEL-HARDENING.md +258 -0
- package/bootstrap/SECURITY-INTEGRATION.md +281 -0
- package/bootstrap/TESTING.md +301 -0
- package/bootstrap/cloud-init.js +279 -0
- package/bootstrap/cloud-init.ts +394 -0
- package/bootstrap/firewall.js +279 -0
- package/bootstrap/firewall.ts +342 -0
- package/bootstrap/genesis.js +406 -0
- package/bootstrap/genesis.ts +518 -0
- package/bootstrap/index.js +35 -0
- package/bootstrap/index.ts +71 -0
- package/bootstrap/kernel-hardening.js +266 -0
- package/bootstrap/kernel-hardening.test.ts +230 -0
- package/bootstrap/kernel-hardening.ts +272 -0
- package/bootstrap/security-audit.js +118 -0
- package/bootstrap/security-audit.ts +124 -0
- package/bootstrap/ssh-hardening.js +182 -0
- package/bootstrap/ssh-hardening.ts +192 -0
- package/client.js +137 -0
- package/client.ts +177 -0
- package/config.js +5 -0
- package/config.ts +5 -0
- package/errors.js +270 -0
- package/errors.ts +371 -0
- package/index.js +28 -0
- package/index.ts +55 -0
- package/package.json +56 -0
- package/pricing.js +284 -0
- package/pricing.ts +422 -0
- package/schemas.js +660 -0
- package/schemas.ts +765 -0
- package/server-status.ts +81 -0
- package/servers.js +424 -0
- package/servers.ts +568 -0
- package/ssh-keys.js +90 -0
- package/ssh-keys.ts +122 -0
- package/ssh-setup.ts +218 -0
- package/types.js +96 -0
- package/types.ts +389 -0
- package/volumes.js +172 -0
- package/volumes.ts +229 -0
package/ssh-keys.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hetzner SSH key operations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import type {
|
|
7
|
+
HetznerSSHKey,
|
|
8
|
+
CreateSSHKeyOptions,
|
|
9
|
+
} from "./types.js";
|
|
10
|
+
import type { HetznerClient } from "./client.js";
|
|
11
|
+
import {
|
|
12
|
+
HetznerListSSHKeysResponseSchema,
|
|
13
|
+
HetznerGetSSHKeyResponseSchema,
|
|
14
|
+
HetznerCreateSSHKeyRequestSchema,
|
|
15
|
+
HetznerCreateSSHKeyResponseSchema,
|
|
16
|
+
} from "./schemas.js";
|
|
17
|
+
|
|
18
|
+
export class SSHKeyOperations {
|
|
19
|
+
constructor(private client: HetznerClient) {}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* List all SSH keys
|
|
23
|
+
*/
|
|
24
|
+
async list(): Promise<HetznerSSHKey[]> {
|
|
25
|
+
const response = await this.client.request<{ ssh_keys: HetznerSSHKey[] }>(
|
|
26
|
+
"/ssh_keys",
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Validate response with Zod
|
|
30
|
+
const validated = HetznerListSSHKeysResponseSchema.safeParse(response);
|
|
31
|
+
if (!validated.success) {
|
|
32
|
+
console.warn('Hetzner list SSH keys validation warning:', validated.error.issues);
|
|
33
|
+
return response.ssh_keys; // Return unvalidated data for backward compatibility
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return validated.data.ssh_keys;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get a specific SSH key by ID or name
|
|
41
|
+
*/
|
|
42
|
+
async get(idOrName: number | string): Promise<HetznerSSHKey> {
|
|
43
|
+
const endpoint = typeof idOrName === 'number'
|
|
44
|
+
? `/ssh_keys/${idOrName}`
|
|
45
|
+
: `/ssh_keys?name=${encodeURIComponent(idOrName)}`;
|
|
46
|
+
|
|
47
|
+
const response = await this.client.request<{ ssh_key: HetznerSSHKey }>(
|
|
48
|
+
endpoint,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// Validate response with Zod
|
|
52
|
+
const validated = HetznerGetSSHKeyResponseSchema.safeParse(response);
|
|
53
|
+
if (!validated.success) {
|
|
54
|
+
console.warn('Hetzner get SSH key validation warning:', validated.error.issues);
|
|
55
|
+
return response.ssh_key; // Return unvalidated data for backward compatibility
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return validated.data.ssh_key;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create a new SSH key
|
|
63
|
+
*
|
|
64
|
+
* @param options - SSH key creation options
|
|
65
|
+
* @returns Created SSH key
|
|
66
|
+
*/
|
|
67
|
+
async create(options: CreateSSHKeyOptions): Promise<HetznerSSHKey> {
|
|
68
|
+
// Validate input with Zod
|
|
69
|
+
const validatedOptions = HetznerCreateSSHKeyRequestSchema.safeParse(options);
|
|
70
|
+
if (!validatedOptions.success) {
|
|
71
|
+
throw new Error(`Invalid SSH key options: ${validatedOptions.error.issues.map(i => i.message).join(', ')}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const body = {
|
|
75
|
+
name: validatedOptions.data.name,
|
|
76
|
+
public_key: validatedOptions.data.public_key,
|
|
77
|
+
...(validatedOptions.data.labels && { labels: validatedOptions.data.labels }),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const response = await this.client.request<{ ssh_key: HetznerSSHKey }>(
|
|
81
|
+
"/ssh_keys",
|
|
82
|
+
{
|
|
83
|
+
method: "POST",
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Validate response with Zod
|
|
89
|
+
const validated = HetznerCreateSSHKeyResponseSchema.safeParse(response);
|
|
90
|
+
if (!validated.success) {
|
|
91
|
+
console.warn('Hetzner create SSH key validation warning:', validated.error.issues);
|
|
92
|
+
return response.ssh_key; // Return unvalidated data for backward compatibility
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return validated.data.ssh_key;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Delete an SSH key
|
|
100
|
+
*
|
|
101
|
+
* @param id - SSH key ID
|
|
102
|
+
*/
|
|
103
|
+
async delete(id: number): Promise<void> {
|
|
104
|
+
await this.client.request(
|
|
105
|
+
`/ssh_keys/${id}`,
|
|
106
|
+
{ method: "DELETE" }
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Find an SSH key by name
|
|
112
|
+
* Returns undefined if not found
|
|
113
|
+
*/
|
|
114
|
+
async findByName(name: string): Promise<HetznerSSHKey | undefined> {
|
|
115
|
+
try {
|
|
116
|
+
const keys = await this.list();
|
|
117
|
+
return keys.find(key => key.name === name);
|
|
118
|
+
} catch {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/ssh-setup.ts
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSH Key Management for Hetzner
|
|
3
|
+
*
|
|
4
|
+
* This module ensures SSH keys are properly configured between:
|
|
5
|
+
* 1. Local machine (~/.ssh/)
|
|
6
|
+
* 2. Hetzner Cloud API
|
|
7
|
+
*
|
|
8
|
+
* PROBLEM:
|
|
9
|
+
* - Creating random keys in Hetzner doesn't work because we need the matching private key locally
|
|
10
|
+
* - Password auth is unreliable and often disabled
|
|
11
|
+
* - IP reuse causes known_hosts conflicts
|
|
12
|
+
*
|
|
13
|
+
* SOLUTION:
|
|
14
|
+
* - Always use existing local keys or create new key pairs
|
|
15
|
+
* - Upload public key to Hetzner, keep private key local
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
19
|
+
import { join } from "path";
|
|
20
|
+
import crypto from "crypto";
|
|
21
|
+
import { SSHPresets, SSHFlags, buildSSHArgs, sshConfig } from "@codespaces/ssh";
|
|
22
|
+
|
|
23
|
+
interface SSHKey {
|
|
24
|
+
id: number;
|
|
25
|
+
name: string;
|
|
26
|
+
fingerprint: string;
|
|
27
|
+
public_key: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface LocalKeyPair {
|
|
31
|
+
name: string;
|
|
32
|
+
publicKey: string;
|
|
33
|
+
privateKeyPath: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const HETZNER_SSH_DIR = join(process.env.HOME || "", ".ssh");
|
|
37
|
+
const HETZNER_KEY_PREFIX = "hetzner-codespaces";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get or create a local SSH key pair for Hetzner
|
|
41
|
+
* Returns the key name to use with Hetzner API
|
|
42
|
+
*/
|
|
43
|
+
export async function getOrCreateHetznerSSHKey(): Promise<LocalKeyPair> {
|
|
44
|
+
// Check for existing Hetzner keys
|
|
45
|
+
const existingKey = findExistingHetznerKey();
|
|
46
|
+
if (existingKey) {
|
|
47
|
+
console.log(`✓ Using existing SSH key: ${existingKey.name}`);
|
|
48
|
+
return existingKey;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Create new key pair
|
|
52
|
+
console.log("Creating new SSH key pair for Hetzner...");
|
|
53
|
+
return createNewKeyPair();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Find existing Hetzner SSH key in local ~/.ssh/
|
|
58
|
+
*/
|
|
59
|
+
function findExistingHetznerKey(): LocalKeyPair | null {
|
|
60
|
+
const privateKeyPath = join(HETZNER_SSH_DIR, `${HETZNER_KEY_PREFIX}`);
|
|
61
|
+
const publicKeyPath = `${privateKeyPath}.pub`;
|
|
62
|
+
|
|
63
|
+
if (!existsSync(privateKeyPath) || !existsSync(publicKeyPath)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const publicKey = readFileSync(publicKeyPath, "utf-8").trim();
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
name: HETZNER_KEY_PREFIX,
|
|
71
|
+
publicKey,
|
|
72
|
+
privateKeyPath,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a new SSH key pair for Hetzner
|
|
78
|
+
*/
|
|
79
|
+
function createNewKeyPair(): LocalKeyPair {
|
|
80
|
+
const keyName = `${HETZNER_KEY_PREFIX}-${Date.now()}`;
|
|
81
|
+
const privateKeyPath = join(HETZNER_SSH_DIR, keyName);
|
|
82
|
+
const publicKeyPath = `${privateKeyPath}.pub`;
|
|
83
|
+
|
|
84
|
+
// Generate new ed25519 key pair
|
|
85
|
+
try {
|
|
86
|
+
// Bun.spawn automatically escapes arguments to prevent shell injection
|
|
87
|
+
Bun.spawnSync(["ssh-keygen", "-t", "ed25519", "-f", privateKeyPath, "-N", "", "-C", keyName], {
|
|
88
|
+
stdout: "ignore",
|
|
89
|
+
stderr: "ignore",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Set proper permissions
|
|
93
|
+
Bun.spawnSync(["chmod", "600", privateKeyPath], { stdout: "ignore", stderr: "ignore" });
|
|
94
|
+
Bun.spawnSync(["chmod", "644", publicKeyPath], { stdout: "ignore", stderr: "ignore" });
|
|
95
|
+
|
|
96
|
+
const publicKey = readFileSync(publicKeyPath, "utf-8").trim();
|
|
97
|
+
|
|
98
|
+
console.log(`✓ Created new SSH key: ${keyName}`);
|
|
99
|
+
console.log(` Private: ${privateKeyPath}`);
|
|
100
|
+
console.log(` Public: ${publicKeyPath}`);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
name: keyName,
|
|
104
|
+
publicKey,
|
|
105
|
+
privateKeyPath,
|
|
106
|
+
};
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw new Error(`Failed to create SSH key: ${error}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Ensure SSH key exists in Hetzner
|
|
114
|
+
* Returns the SSH key name to use when creating servers
|
|
115
|
+
*/
|
|
116
|
+
export async function ensureHetznerSSHKey(
|
|
117
|
+
hetznerAPI: (endpoint: string, method: string, body?: unknown) => Promise<Response>
|
|
118
|
+
): Promise<string> {
|
|
119
|
+
// 1. Get or create local key pair
|
|
120
|
+
const localKey = await getOrCreateHetznerSSHKey();
|
|
121
|
+
|
|
122
|
+
// 2. Check if key exists in Hetzner
|
|
123
|
+
const existingKeys = await hetznerAPI("/ssh_keys", "GET", null)
|
|
124
|
+
.then((r) => r.json())
|
|
125
|
+
.then((data) => data.ssh_keys as SSHKey[]);
|
|
126
|
+
|
|
127
|
+
// 3. Find matching key by public key
|
|
128
|
+
const matchingKey = existingKeys.find((k) => k.public_key.trim() === localKey.publicKey.trim());
|
|
129
|
+
|
|
130
|
+
if (matchingKey) {
|
|
131
|
+
console.log(`✓ SSH key already exists in Hetzner: ${matchingKey.name} (${matchingKey.id})`);
|
|
132
|
+
return matchingKey.name; // Use existing key name
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 4. Upload new key to Hetzner
|
|
136
|
+
console.log(`Uploading SSH key to Hetzner: ${localKey.name}...`);
|
|
137
|
+
const createResponse = await hetznerAPI("/ssh_keys", "POST", {
|
|
138
|
+
name: localKey.name,
|
|
139
|
+
public_key: localKey.publicKey,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (!createResponse.ok) {
|
|
143
|
+
const error = await createResponse.text();
|
|
144
|
+
throw new Error(`Failed to upload SSH key to Hetzner: ${error}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const createdKey = (await createResponse.json()) as SSHKey;
|
|
148
|
+
console.log(`✓ SSH key uploaded: ${createdKey.name} (${createdKey.id})`);
|
|
149
|
+
|
|
150
|
+
return createdKey.name;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Clear known_hosts entry for an IP (to fix IP reuse issues)
|
|
155
|
+
*/
|
|
156
|
+
export function clearKnownHosts(ip: string): void {
|
|
157
|
+
try {
|
|
158
|
+
// Bun.spawn automatically escapes arguments to prevent shell injection
|
|
159
|
+
Bun.spawnSync(["ssh-keygen", "-R", ip], { stdout: "ignore", stderr: "ignore" });
|
|
160
|
+
console.log(`✓ Cleared known_hosts entry for ${ip}`);
|
|
161
|
+
} catch {
|
|
162
|
+
// Ignore if entry doesn't exist
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Test SSH connection to a server using typed flags
|
|
168
|
+
*/
|
|
169
|
+
export async function testSSHConnection(
|
|
170
|
+
ip: string,
|
|
171
|
+
privateKeyPath: string,
|
|
172
|
+
username: string = "root"
|
|
173
|
+
): Promise<boolean> {
|
|
174
|
+
try {
|
|
175
|
+
// Build SSH args using typed flags
|
|
176
|
+
const flags = [
|
|
177
|
+
...SSHPresets.default,
|
|
178
|
+
SSHFlags.identity(privateKeyPath),
|
|
179
|
+
sshConfig("ConnectTimeout", "10"),
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
const sshArgs = buildSSHArgs(flags, ip, username);
|
|
183
|
+
sshArgs.push("echo", "connected");
|
|
184
|
+
|
|
185
|
+
// Bun.spawn automatically escapes arguments to prevent shell injection
|
|
186
|
+
const proc = Bun.spawn(sshArgs, {
|
|
187
|
+
stdout: "ignore",
|
|
188
|
+
stderr: "ignore",
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Wait for process to complete with timeout
|
|
192
|
+
const timeout = setTimeout(() => proc.kill(), 15000);
|
|
193
|
+
await proc.exited;
|
|
194
|
+
clearTimeout(timeout);
|
|
195
|
+
|
|
196
|
+
return proc.exitCode === 0;
|
|
197
|
+
} catch {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Full workflow: Prepare SSH keys before creating servers
|
|
204
|
+
*/
|
|
205
|
+
export async function prepareSSHKeys(
|
|
206
|
+
hetznerAPI: (endpoint: string, method: string, body?: unknown) => Promise<Response>
|
|
207
|
+
): Promise<{
|
|
208
|
+
sshKeyName: string;
|
|
209
|
+
privateKeyPath: string;
|
|
210
|
+
}> {
|
|
211
|
+
const sshKeyName = await ensureHetznerSSHKey(hetznerAPI);
|
|
212
|
+
const localKey = await getOrCreateHetznerSSHKey();
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
sshKeyName,
|
|
216
|
+
privateKeyPath: localKey.privateKeyPath,
|
|
217
|
+
};
|
|
218
|
+
}
|
package/types.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hetzner Cloud API types
|
|
3
|
+
*/
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Import shared status enums
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { EnvironmentStatus, ActionStatus, VolumeStatus, } from "@ebowwa/codespaces-types/compile";
|
|
8
|
+
// Re-export for convenience
|
|
9
|
+
export { EnvironmentStatus, ActionStatus, VolumeStatus };
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Action Types
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Action command types from Hetzner Cloud API
|
|
15
|
+
*/
|
|
16
|
+
export var ActionCommand;
|
|
17
|
+
(function (ActionCommand) {
|
|
18
|
+
// Server actions
|
|
19
|
+
ActionCommand["CreateServer"] = "create_server";
|
|
20
|
+
ActionCommand["DeleteServer"] = "delete_server";
|
|
21
|
+
ActionCommand["StartServer"] = "start_server";
|
|
22
|
+
ActionCommand["StopServer"] = "stop_server";
|
|
23
|
+
ActionCommand["RebootServer"] = "reboot_server";
|
|
24
|
+
ActionCommand["ResetServer"] = "reset_server";
|
|
25
|
+
ActionCommand["ShutdownServer"] = "shutdown_server";
|
|
26
|
+
ActionCommand["Poweroff"] = "poweroff";
|
|
27
|
+
ActionCommand["ChangeServerType"] = "change_server_type";
|
|
28
|
+
ActionCommand["RebuildServer"] = "rebuild_server";
|
|
29
|
+
ActionCommand["EnableBackup"] = "enable_backup";
|
|
30
|
+
ActionCommand["DisableBackup"] = "disable_backup";
|
|
31
|
+
ActionCommand["CreateImage"] = "create_image";
|
|
32
|
+
ActionCommand["ChangeDnsPtr"] = "change_dns_ptr";
|
|
33
|
+
ActionCommand["AttachToNetwork"] = "attach_to_network";
|
|
34
|
+
ActionCommand["DetachFromNetwork"] = "detach_from_network";
|
|
35
|
+
ActionCommand["ChangeAliasIps"] = "change_alias_ips";
|
|
36
|
+
ActionCommand["EnableRescue"] = "enable_rescue";
|
|
37
|
+
ActionCommand["DisableRescue"] = "disable_rescue";
|
|
38
|
+
ActionCommand["ChangeProtection"] = "change_protection";
|
|
39
|
+
// Volume actions
|
|
40
|
+
ActionCommand["CreateVolume"] = "create_volume";
|
|
41
|
+
ActionCommand["DeleteVolume"] = "delete_volume";
|
|
42
|
+
ActionCommand["AttachVolume"] = "attach_volume";
|
|
43
|
+
ActionCommand["DetachVolume"] = "detach_volume";
|
|
44
|
+
ActionCommand["ResizeVolume"] = "resize_volume";
|
|
45
|
+
ActionCommand["VolumeChangeProtection"] = "volume_change_protection";
|
|
46
|
+
// Network actions
|
|
47
|
+
ActionCommand["AddSubnet"] = "add_subnet";
|
|
48
|
+
ActionCommand["DeleteSubnet"] = "delete_subnet";
|
|
49
|
+
ActionCommand["AddRoute"] = "add_route";
|
|
50
|
+
ActionCommand["DeleteRoute"] = "delete_route";
|
|
51
|
+
ActionCommand["ChangeIpRange"] = "change_ip_range";
|
|
52
|
+
ActionCommand["NetworkChangeProtection"] = "network_change_protection";
|
|
53
|
+
// Floating IP actions
|
|
54
|
+
ActionCommand["AssignFloatingIp"] = "assign_floating_ip";
|
|
55
|
+
ActionCommand["UnassignFloatingIp"] = "unassign_floating_ip";
|
|
56
|
+
ActionCommand["FloatingIpChangeDnsPtr"] = "floating_ip_change_dns_ptr";
|
|
57
|
+
ActionCommand["FloatingIpChangeProtection"] = "floating_ip_change_protection";
|
|
58
|
+
// Load Balancer actions
|
|
59
|
+
ActionCommand["CreateLoadBalancer"] = "create_load_balancer";
|
|
60
|
+
ActionCommand["DeleteLoadBalancer"] = "delete_load_balancer";
|
|
61
|
+
ActionCommand["AddTarget"] = "add_target";
|
|
62
|
+
ActionCommand["RemoveTarget"] = "remove_target";
|
|
63
|
+
ActionCommand["AddService"] = "add_service";
|
|
64
|
+
ActionCommand["UpdateService"] = "update_service";
|
|
65
|
+
ActionCommand["DeleteService"] = "delete_service";
|
|
66
|
+
ActionCommand["LoadBalancerAttachToNetwork"] = "load_balancer_attach_to_network";
|
|
67
|
+
ActionCommand["LoadBalancerDetachFromNetwork"] = "load_balancer_detach_from_network";
|
|
68
|
+
ActionCommand["ChangeAlgorithm"] = "change_algorithm";
|
|
69
|
+
ActionCommand["ChangeType"] = "change_type";
|
|
70
|
+
ActionCommand["LoadBalancerChangeProtection"] = "load_balancer_change_protection";
|
|
71
|
+
// Certificate actions
|
|
72
|
+
ActionCommand["IssueCertificate"] = "issue_certificate";
|
|
73
|
+
ActionCommand["RetryCertificate"] = "retry_certificate";
|
|
74
|
+
// Firewall actions
|
|
75
|
+
ActionCommand["SetFirewallRules"] = "set_firewall_rules";
|
|
76
|
+
ActionCommand["ApplyFirewall"] = "apply_firewall";
|
|
77
|
+
ActionCommand["RemoveFirewall"] = "remove_firewall";
|
|
78
|
+
ActionCommand["FirewallChangeProtection"] = "firewall_change_protection";
|
|
79
|
+
// Image actions
|
|
80
|
+
ActionCommand["ImageChangeProtection"] = "image_change_protection";
|
|
81
|
+
})(ActionCommand || (ActionCommand = {}));
|
|
82
|
+
/**
|
|
83
|
+
* Resource types that can be affected by actions
|
|
84
|
+
*/
|
|
85
|
+
export var ResourceType;
|
|
86
|
+
(function (ResourceType) {
|
|
87
|
+
ResourceType["Server"] = "server";
|
|
88
|
+
ResourceType["Volume"] = "volume";
|
|
89
|
+
ResourceType["Network"] = "network";
|
|
90
|
+
ResourceType["FloatingIp"] = "floating_ip";
|
|
91
|
+
ResourceType["LoadBalancer"] = "load_balancer";
|
|
92
|
+
ResourceType["Certificate"] = "certificate";
|
|
93
|
+
ResourceType["Firewall"] = "firewall";
|
|
94
|
+
ResourceType["Image"] = "image";
|
|
95
|
+
})(ResourceType || (ResourceType = {}));
|
|
96
|
+
//# sourceMappingURL=types.js.map
|