@appliance.sh/api-server 1.16.0 → 1.17.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/package.json +3 -6
- package/src/services/pulumi.service.ts +9 -143
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appliance.sh/api-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Eliot Lim",
|
|
6
6
|
"repository": "https://github.com/appliance-sh/appliance.sh",
|
|
@@ -19,11 +19,8 @@
|
|
|
19
19
|
"test:e2e": "vitest run --config vitest.e2e.config.ts"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@appliance.sh/infra": "1.
|
|
23
|
-
"@appliance.sh/sdk": "1.
|
|
24
|
-
"@pulumi/aws": "^7.16.0",
|
|
25
|
-
"@pulumi/aws-native": "^1.48.0",
|
|
26
|
-
"@pulumi/pulumi": "^3.216.0",
|
|
22
|
+
"@appliance.sh/infra": "1.17.0",
|
|
23
|
+
"@appliance.sh/sdk": "1.17.0",
|
|
27
24
|
"express": "^5.2.1"
|
|
28
25
|
},
|
|
29
26
|
"devDependencies": {
|
|
@@ -1,146 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import {
|
|
2
|
+
ApplianceDeploymentService,
|
|
3
|
+
createApplianceDeploymentService,
|
|
4
|
+
type PulumiAction,
|
|
5
|
+
type PulumiResult,
|
|
6
|
+
} from '@appliance.sh/infra';
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
export interface PulumiResult {
|
|
10
|
-
action: PulumiAction;
|
|
11
|
-
ok: boolean;
|
|
12
|
-
idempotentNoop: boolean;
|
|
13
|
-
message: string;
|
|
14
|
-
stackName: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
class PulumiService {
|
|
18
|
-
private readonly projectName = 'appliance-api-managed-proj';
|
|
19
|
-
|
|
20
|
-
private readonly baseConfig = process.env.APPLIANCE_BASE_CONFIG
|
|
21
|
-
? applianceBaseConfig.parse(JSON.parse(process.env.APPLIANCE_BASE_CONFIG))
|
|
22
|
-
: undefined;
|
|
23
|
-
private readonly region = this.baseConfig?.aws.region || 'us-east-1';
|
|
24
|
-
|
|
25
|
-
private inlineProgram() {
|
|
26
|
-
return async () => {
|
|
27
|
-
const name = 'appliance';
|
|
28
|
-
|
|
29
|
-
if (!this.baseConfig) {
|
|
30
|
-
throw new Error('Missing base config');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const regionalProvider = new aws.Provider(`${name}-regional`, {
|
|
34
|
-
region: (this.baseConfig?.aws.region as aws.Region) ?? 'ap-southeast-1',
|
|
35
|
-
});
|
|
36
|
-
const globalProvider = new aws.Provider(`${name}-global`, {
|
|
37
|
-
region: 'us-east-1',
|
|
38
|
-
});
|
|
39
|
-
const nativeRegionalProvider = new awsNative.Provider(`${name}-native-regional`, {
|
|
40
|
-
region: (this.baseConfig?.aws.region as awsNative.Region) ?? 'ap-southeast-1',
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const nativeGlobalProvider = new awsNative.Provider(`${name}-native-global`, {
|
|
44
|
-
region: 'us-east-1',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const applianceStack = new ApplianceStack(
|
|
48
|
-
`${name}-stack`,
|
|
49
|
-
{
|
|
50
|
-
tags: { project: name },
|
|
51
|
-
config: this.baseConfig,
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
globalProvider,
|
|
55
|
-
provider: regionalProvider,
|
|
56
|
-
nativeProvider: nativeRegionalProvider,
|
|
57
|
-
nativeGlobalProvider: nativeGlobalProvider,
|
|
58
|
-
}
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
applianceStack,
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private async getOrCreateStack(stackName: string): Promise<auto.Stack> {
|
|
68
|
-
const program = this.inlineProgram();
|
|
69
|
-
const envVars: Record<string, string> = {
|
|
70
|
-
AWS_REGION: this.region,
|
|
71
|
-
};
|
|
72
|
-
if (!this.baseConfig) {
|
|
73
|
-
throw new Error('Missing base config');
|
|
74
|
-
}
|
|
75
|
-
if (this.baseConfig) {
|
|
76
|
-
envVars['PULUMI_BACKEND_URL'] = this.baseConfig.stateBackendUrl;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const stack = await auto.LocalWorkspace.createOrSelectStack(
|
|
80
|
-
{ projectName: this.projectName, stackName, program },
|
|
81
|
-
{ envVars }
|
|
82
|
-
);
|
|
83
|
-
await stack.setConfig('aws:region', { value: this.baseConfig.aws.region });
|
|
84
|
-
return stack;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private async selectExistingStack(stackName: string): Promise<auto.Stack> {
|
|
88
|
-
const envVars: Record<string, string> = {
|
|
89
|
-
AWS_REGION: this.region,
|
|
90
|
-
};
|
|
91
|
-
if (!this.baseConfig) {
|
|
92
|
-
throw new Error('Missing base config');
|
|
93
|
-
}
|
|
94
|
-
if (this.baseConfig) {
|
|
95
|
-
envVars['PULUMI_BACKEND_URL'] = this.baseConfig.stateBackendUrl;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const ws = await auto.LocalWorkspace.create({
|
|
99
|
-
projectSettings: { name: this.projectName, runtime: 'nodejs' },
|
|
100
|
-
envVars,
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
return auto.Stack.createOrSelect(stackName, ws);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async deploy(stackName = 'appliance-api-managed'): Promise<PulumiResult> {
|
|
107
|
-
const stack = await this.getOrCreateStack(stackName);
|
|
108
|
-
const result = await stack.up({ onOutput: (m) => console.log(m) });
|
|
109
|
-
const changes = result.summary.resourceChanges || {};
|
|
110
|
-
const totalChanges = Object.entries(changes)
|
|
111
|
-
.filter(([k]) => k !== 'same')
|
|
112
|
-
.reduce((acc, [, v]) => acc + (v || 0), 0);
|
|
113
|
-
const idempotentNoop = totalChanges === 0;
|
|
114
|
-
return {
|
|
115
|
-
action: 'deploy',
|
|
116
|
-
ok: true,
|
|
117
|
-
idempotentNoop,
|
|
118
|
-
message: idempotentNoop ? 'No changes (idempotent)' : 'Stack updated',
|
|
119
|
-
stackName,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async destroy(stackName = 'appliance-api-managed'): Promise<PulumiResult> {
|
|
124
|
-
try {
|
|
125
|
-
const stack = await this.selectExistingStack(stackName);
|
|
126
|
-
await stack.destroy({ onOutput: (m) => console.log(m) });
|
|
127
|
-
return { action: 'destroy', ok: true, idempotentNoop: false, message: 'Stack resources deleted', stackName };
|
|
128
|
-
} catch (e) {
|
|
129
|
-
if (!(e instanceof Error)) throw e;
|
|
130
|
-
const msg = String(e?.message || e);
|
|
131
|
-
if (msg.includes('no stack named') || msg.includes('not found')) {
|
|
132
|
-
return {
|
|
133
|
-
action: 'destroy',
|
|
134
|
-
ok: true,
|
|
135
|
-
idempotentNoop: true,
|
|
136
|
-
message: 'Stack not found (idempotent)',
|
|
137
|
-
stackName,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
throw e;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
8
|
+
// Re-export types for consumers
|
|
9
|
+
export type { PulumiAction, PulumiResult };
|
|
144
10
|
|
|
145
11
|
// Export a singleton instance
|
|
146
|
-
export const pulumiService =
|
|
12
|
+
export const pulumiService: ApplianceDeploymentService = createApplianceDeploymentService();
|