@highstate/yandex 0.19.1 → 0.21.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.
@@ -0,0 +1,17 @@
1
+ // @bun
2
+ // src/provider.ts
3
+ import { output, toPromise } from "@highstate/pulumi";
4
+ import { Provider } from "@highstate/yandex-sdk";
5
+ async function createProvider(connection, cloudId) {
6
+ return await toPromise(output(connection).apply((connection2) => {
7
+ return new Provider(connection2.cloudId, {
8
+ serviceAccountKeyFile: connection2.authorizedKeyJson.value,
9
+ cloudId: cloudId ?? connection2.cloudId,
10
+ folderId: connection2.defaultFolderId,
11
+ zone: connection2.defaultZone,
12
+ regionId: connection2.regionId
13
+ });
14
+ }));
15
+ }
16
+
17
+ export { createProvider };
@@ -1,10 +1,10 @@
1
- import { yandex } from '@highstate/library';
2
- import { forUnit, toPromise, output } from '@highstate/pulumi';
3
- import { Provider, getIamServiceAccount, getResourcemanagerFolder } from '@highstate/yandex-sdk';
4
-
1
+ // @bun
5
2
  // src/connection/index.ts
3
+ import { yandex } from "@highstate/library";
4
+ import { forUnit, makeEntityOutput, toPromise } from "@highstate/pulumi";
5
+ import { getIamServiceAccount, getResourcemanagerFolder, Provider } from "@highstate/yandex-sdk";
6
6
  var { args, secrets, outputs } = forUnit(yandex.connection);
7
- var serviceAccountKeyFileString = await toPromise(secrets.serviceAccountKeyFile);
7
+ var serviceAccountKeyFileString = await toPromise(secrets.authorizedKeyJson);
8
8
  var keyFileData = JSON.parse(serviceAccountKeyFileString);
9
9
  var serviceAccountId = keyFileData.service_account_id;
10
10
  var provider = new Provider("yandex", {
@@ -12,25 +12,31 @@ var provider = new Provider("yandex", {
12
12
  zone: args.region.defaultZone,
13
13
  regionId: args.region.id
14
14
  });
15
- var serviceAccount = await getIamServiceAccount(
16
- { serviceAccountId },
17
- { provider }
18
- );
15
+ var serviceAccount = await getIamServiceAccount({ serviceAccountId }, { provider });
19
16
  var folder = await getResourcemanagerFolder({ folderId: serviceAccount.folderId }, { provider });
20
17
  if (!folder.cloudId) {
21
18
  throw new Error("Could not determine cloud ID from folder");
22
19
  }
23
- var connection = output({
24
- serviceAccountKeyFile: secrets.serviceAccountKeyFile,
25
- cloudId: folder.cloudId,
26
- defaultFolderId: serviceAccount.folderId,
27
- defaultZone: args.region.defaultZone,
28
- regionId: args.region.id
20
+ var connection = makeEntityOutput({
21
+ entity: yandex.connectionEntity,
22
+ identity: keyFileData.service_account_id,
23
+ meta: {
24
+ title: serviceAccount.name,
25
+ description: `Authorized as SA "${serviceAccount.name}" (ID: ${serviceAccount.id}) in folder "${folder.name}" (ID: ${folder.id})`
26
+ },
27
+ value: {
28
+ authorizedKeyJson: secrets.authorizedKeyJson,
29
+ cloudId: folder.cloudId,
30
+ defaultFolderId: serviceAccount.folderId,
31
+ defaultZone: args.region.defaultZone,
32
+ regionId: args.region.id,
33
+ serviceAccountId: serviceAccount.id
34
+ }
29
35
  });
30
36
  var connection_default = outputs({
31
37
  connection,
32
38
  $statusFields: {
33
- cloudId: {
39
+ defaultCloudId: {
34
40
  meta: {
35
41
  icon: "mdi:cloud"
36
42
  },
@@ -44,7 +50,6 @@ var connection_default = outputs({
44
50
  }
45
51
  }
46
52
  });
47
-
48
- export { connection_default as default };
49
- //# sourceMappingURL=index.js.map
50
- //# sourceMappingURL=index.js.map
53
+ export {
54
+ connection_default as default
55
+ };
@@ -1,31 +1,34 @@
1
- import { createProvider } from '../chunk-MK37EG4O.js';
2
- import { yandex } from '@highstate/library';
3
- import { forUnit, getResourceComment } from '@highstate/pulumi';
4
- import { ComputeDisk } from '@highstate/yandex-sdk';
1
+ // @bun
2
+ import {
3
+ createProvider
4
+ } from "../chunk-09r4wmhq.js";
5
5
 
6
+ // src/disk/index.ts
7
+ import { yandex } from "@highstate/library";
8
+ import { forUnit, getResourceComment, makeEntityOutput } from "@highstate/pulumi";
9
+ import { ComputeDisk } from "@highstate/yandex-sdk";
6
10
  var { name, args, inputs, outputs } = forUnit(yandex.disk);
7
11
  var provider = await createProvider(inputs.connection);
8
12
  var diskName = args.diskName ?? name;
9
- var disk = new ComputeDisk(
10
- "disk",
11
- {
12
- name: diskName,
13
- description: getResourceComment(),
14
- type: args.type,
15
- size: args.size,
16
- allowRecreate: false
17
- },
18
- { provider, protect: true }
19
- );
13
+ var disk = new ComputeDisk("disk", {
14
+ name: diskName,
15
+ description: getResourceComment(),
16
+ type: args.type,
17
+ size: args.size,
18
+ allowRecreate: false
19
+ }, { provider, protect: true });
20
20
  var disk_default = outputs({
21
- disk: {
22
- id: disk.id
23
- },
21
+ disk: makeEntityOutput({
22
+ entity: yandex.diskEntity,
23
+ identity: disk.id,
24
+ value: {
25
+ id: disk.id
26
+ }
27
+ }),
24
28
  $statusFields: {
25
29
  id: disk.id
26
30
  }
27
31
  });
28
-
29
- export { disk_default as default };
30
- //# sourceMappingURL=index.js.map
31
- //# sourceMappingURL=index.js.map
32
+ export {
33
+ disk_default as default
34
+ };
@@ -1,20 +1,31 @@
1
- import { createProvider } from '../chunk-MK37EG4O.js';
2
- import { yandex } from '@highstate/library';
3
- import { forUnit } from '@highstate/pulumi';
4
- import { getComputeImage } from '@highstate/yandex-sdk';
1
+ // @bun
2
+ import {
3
+ createProvider
4
+ } from "../chunk-09r4wmhq.js";
5
5
 
6
+ // src/existing-image/index.ts
7
+ import { yandex } from "@highstate/library";
8
+ import { forUnit, makeEntityOutput } from "@highstate/pulumi";
9
+ import { getComputeImage } from "@highstate/yandex-sdk";
6
10
  var { args, inputs, outputs } = forUnit(yandex.existingImage);
7
11
  var provider = await createProvider(inputs.connection);
8
- var image = await getComputeImage({ imageId: args.id }, { provider });
9
- var existing_image_default = outputs({
10
- image: {
11
- id: image.id
12
+ var ycImage = await getComputeImage({ imageId: args.id }, { provider });
13
+ var image = makeEntityOutput({
14
+ entity: yandex.imageEntity,
15
+ identity: ycImage.id,
16
+ meta: {
17
+ title: ycImage.name
12
18
  },
19
+ value: {
20
+ id: ycImage.id
21
+ }
22
+ });
23
+ var existing_image_default = outputs({
24
+ image,
13
25
  $statusFields: {
14
- name: image.name
26
+ name: ycImage.name
15
27
  }
16
28
  });
17
-
18
- export { existing_image_default as default };
19
- //# sourceMappingURL=index.js.map
20
- //# sourceMappingURL=index.js.map
29
+ export {
30
+ existing_image_default as default
31
+ };
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "sourceHashes": {
3
- "./dist/connection/index.js": 3477658120,
4
- "./dist/disk/index.js": 791560135,
5
- "./dist/existing-image/index.js": 2230254918,
6
- "./dist/virtual-machine/index.js": 3453488910
3
+ "./dist/connection/index.js": 1297805961,
4
+ "./dist/disk/index.js": 872672425,
5
+ "./dist/existing-image/index.js": 1667771667,
6
+ "./dist/virtual-machine/index.js": 1341835348,
7
+ "./dist/instance-group/index.js": 2144968854
7
8
  }
8
9
  }
@@ -0,0 +1,189 @@
1
+ // @bun
2
+ import {
3
+ createProvider
4
+ } from "../chunk-09r4wmhq.js";
5
+
6
+ // src/instance-group/index.ts
7
+ import {
8
+ createServerBundle,
9
+ generatePassword,
10
+ generateSshPrivateKey,
11
+ l3EndpointToString,
12
+ parseEndpoint,
13
+ sshPrivateKeyToKeyPair
14
+ } from "@highstate/common";
15
+ import { trimIndentation } from "@highstate/contract";
16
+ import { yandex } from "@highstate/library";
17
+ import { forUnit, getResourceComment, interpolate, toPromise } from "@highstate/pulumi";
18
+ import {
19
+ ComputeDisk,
20
+ ComputeInstanceGroup,
21
+ getVpcSubnet,
22
+ KmsSymmetricKey,
23
+ VpcAddress
24
+ } from "@highstate/yandex-sdk";
25
+ var { name, args, getSecret, inputs, outputs } = forUnit(yandex.instanceGroup);
26
+ var groupName = args.groupName ?? name;
27
+ var provider = await createProvider(inputs.connection, args.cloudId);
28
+ var sshKeyPair = inputs.sshKeyPair ?? getSecret("sshPrivateKey", generateSshPrivateKey).apply(sshPrivateKeyToKeyPair);
29
+ var rootPassword = getSecret("rootPassword", generatePassword);
30
+ var subnetId = args.network.subnetId;
31
+ if (!subnetId) {
32
+ const defaultSubnetName = await toPromise(interpolate`default-${inputs.connection.defaultZone}`);
33
+ const subnet = await getVpcSubnet({
34
+ folderId: await toPromise(inputs.connection.defaultFolderId),
35
+ name: defaultSubnetName
36
+ }, { provider });
37
+ if (!subnet.id) {
38
+ throw new Error(`Could not find default subnet '${defaultSubnetName}' in zone ${inputs.connection.defaultZone}`);
39
+ }
40
+ subnetId = subnet.id;
41
+ }
42
+ var encryptionKeyId;
43
+ if (args.bootDisk.encrypted) {
44
+ const encryptionKey = new KmsSymmetricKey("encryption-key", {
45
+ name: groupName,
46
+ description: getResourceComment(),
47
+ folderId: args.folderId ?? inputs.connection.defaultFolderId
48
+ }, { provider });
49
+ encryptionKeyId = encryptionKey.id;
50
+ }
51
+ var disks = Array.from({ length: args.size }, (_, i) => {
52
+ return new ComputeDisk(`disk-${i + 1}`, {
53
+ name: `${groupName}-${i + 1}`,
54
+ type: args.bootDisk.type,
55
+ size: args.bootDisk.size,
56
+ imageId: inputs.image.id,
57
+ allowRecreate: false,
58
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
59
+ zone: inputs.connection.defaultZone,
60
+ kmsKeyId: encryptionKeyId
61
+ }, { provider, ignoreChanges: ["imageId"] });
62
+ });
63
+ var internalAddresses = Array.from({ length: args.size }, (_, i) => {
64
+ return new VpcAddress(`internal-address-${i + 1}`, {
65
+ name: `${groupName}-internal-${i + 1}`,
66
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
67
+ description: getResourceComment(),
68
+ internalIpv4Address: {
69
+ subnetId
70
+ }
71
+ }, { provider });
72
+ });
73
+ var publicAddresses;
74
+ if (args.network.assignPublicIp && args.network.reservePublicIp) {
75
+ publicAddresses = Array.from({ length: args.size }, (_, i) => {
76
+ return new VpcAddress(`address-${i + 1}`, {
77
+ name: `${groupName}-${i + 1}`,
78
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
79
+ description: getResourceComment(),
80
+ externalIpv4Address: {
81
+ zoneId: inputs.connection.defaultZone
82
+ }
83
+ }, { provider });
84
+ });
85
+ }
86
+ var userData = interpolate`
87
+ #cloud-config
88
+ hostname: ${groupName}-{instance.index}
89
+ users:
90
+ - name: root
91
+ ssh-authorized-keys:
92
+ - ${sshKeyPair.publicKey}
93
+ sudo: ALL=(ALL) NOPASSWD:ALL
94
+ `.apply(trimIndentation);
95
+ var instanceGroup = new ComputeInstanceGroup("instance-group", {
96
+ name: groupName,
97
+ description: getResourceComment(),
98
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
99
+ allocationPolicy: {
100
+ zones: [inputs.connection.defaultZone]
101
+ },
102
+ deployPolicy: {
103
+ maxExpansion: 0,
104
+ maxUnavailable: 1
105
+ },
106
+ scalePolicy: {
107
+ fixedScale: {
108
+ size: args.size
109
+ }
110
+ },
111
+ instanceTemplate: {
112
+ name: `${groupName}-{instance.index}`,
113
+ description: getResourceComment(),
114
+ platformId: args.platformId,
115
+ resources: {
116
+ cores: args.resources.cores,
117
+ memory: args.resources.memory,
118
+ coreFraction: args.resources.coreFraction
119
+ },
120
+ schedulingPolicy: {
121
+ preemptible: args.preemptible
122
+ },
123
+ bootDisk: {
124
+ diskId: `{disk_{instance.index}}`
125
+ },
126
+ networkInterfaces: [
127
+ {
128
+ subnetIds: [subnetId],
129
+ ipAddress: `{internal_address_{instance.index}}`,
130
+ nat: args.network.assignPublicIp,
131
+ natIpAddress: publicAddresses ? `{address_{instance.index}}` : undefined
132
+ }
133
+ ],
134
+ metadata: {
135
+ "user-data": userData
136
+ }
137
+ },
138
+ variables: {
139
+ ...Object.fromEntries(disks.map((_, i) => [`disk_${i + 1}`, disks[i].id])),
140
+ ...Object.fromEntries(internalAddresses.map((_, i) => [
141
+ `internal_address_${i + 1}`,
142
+ internalAddresses[i].internalIpv4Address.apply((a) => a.address)
143
+ ])),
144
+ ...publicAddresses ? Object.fromEntries(publicAddresses.map((_, i) => [
145
+ `address_${i + 1}`,
146
+ publicAddresses[i].externalIpv4Address.apply((a) => a.address)
147
+ ])) : {}
148
+ },
149
+ serviceAccountId: inputs.connection.serviceAccountId
150
+ }, { provider });
151
+ var terminals = [];
152
+ var instances = await toPromise(instanceGroup.instances);
153
+ var servers = await toPromise(instances.map(async (instance, i) => {
154
+ const firstInterface = instance.networkInterfaces[0];
155
+ const publicIp = args.network.assignPublicIp ? firstInterface?.natIpAddress : firstInterface?.ipAddress;
156
+ if (!publicIp) {
157
+ throw new Error("No IP address assigned to instance");
158
+ }
159
+ const endpoint = parseEndpoint(publicIp, 3);
160
+ const { server, terminal } = await createServerBundle({
161
+ name: `${groupName}-${i + 1}`,
162
+ endpoints: [endpoint],
163
+ sshArgs: args.ssh,
164
+ sshPassword: rootPassword,
165
+ sshKeyPair
166
+ });
167
+ if (terminal) {
168
+ const rawTerminal = await toPromise(terminal);
169
+ terminals.push({
170
+ ...rawTerminal,
171
+ name: `ssh-${i + 1}`,
172
+ meta: {
173
+ title: `Shell (${i + 1})`
174
+ }
175
+ });
176
+ }
177
+ return server;
178
+ }));
179
+ var instance_group_default = outputs({
180
+ servers,
181
+ $statusFields: {
182
+ id: instanceGroup.id,
183
+ endpoints: servers.flatMap((server) => server.endpoints).map(l3EndpointToString)
184
+ },
185
+ $terminals: terminals
186
+ });
187
+ export {
188
+ instance_group_default as default
189
+ };
@@ -1,45 +1,63 @@
1
- import { createProvider } from '../chunk-MK37EG4O.js';
2
- import { sshPrivateKeyToKeyPair, generateSshPrivateKey, generatePassword, parseEndpoint, createServerBundle, l3EndpointToString } from '@highstate/common';
3
- import { trimIndentation } from '@highstate/contract';
4
- import { yandex } from '@highstate/library';
5
- import { forUnit, toPromise, interpolate, getResourceComment } from '@highstate/pulumi';
6
- import { getVpcSubnet, ComputeDisk, VpcAddress, ComputeInstance } from '@highstate/yandex-sdk';
1
+ // @bun
2
+ import {
3
+ createProvider
4
+ } from "../chunk-09r4wmhq.js";
7
5
 
6
+ // src/virtual-machine/index.ts
7
+ import {
8
+ createServerBundle,
9
+ generatePassword,
10
+ generateSshPrivateKey,
11
+ l3EndpointToString,
12
+ parseEndpoint,
13
+ sshPrivateKeyToKeyPair
14
+ } from "@highstate/common";
15
+ import { trimIndentation } from "@highstate/contract";
16
+ import { yandex } from "@highstate/library";
17
+ import { forUnit, getResourceComment, interpolate, toPromise } from "@highstate/pulumi";
18
+ import {
19
+ ComputeDisk,
20
+ ComputeInstance,
21
+ getVpcSubnet,
22
+ KmsSymmetricKey,
23
+ VpcAddress
24
+ } from "@highstate/yandex-sdk";
8
25
  var { name, args, getSecret, inputs, outputs } = forUnit(yandex.virtualMachine);
9
26
  var vmName = args.vmName ?? name;
10
- var provider = await createProvider(inputs.connection);
11
- var sshKeyPair = inputs.sshKeyPair ?? sshPrivateKeyToKeyPair(getSecret("sshPrivateKey", generateSshPrivateKey));
27
+ var provider = await createProvider(inputs.connection, args.cloudId);
28
+ var sshKeyPair = inputs.sshKeyPair ?? getSecret("sshPrivateKey", generateSshPrivateKey).apply(sshPrivateKeyToKeyPair);
12
29
  var rootPassword = getSecret("rootPassword", generatePassword);
13
30
  var subnetId = args.network.subnetId;
14
31
  if (!subnetId) {
15
32
  const defaultSubnetName = await toPromise(interpolate`default-${inputs.connection.defaultZone}`);
16
- const subnet = await getVpcSubnet(
17
- {
18
- folderId: await toPromise(inputs.connection.defaultFolderId),
19
- name: defaultSubnetName
20
- },
21
- { provider }
22
- );
33
+ const subnet = await getVpcSubnet({
34
+ folderId: await toPromise(inputs.connection.defaultFolderId),
35
+ name: defaultSubnetName
36
+ }, { provider });
23
37
  if (!subnet.id) {
24
- throw new Error(
25
- `Could not find default subnet '${defaultSubnetName}' in zone ${inputs.connection.defaultZone}`
26
- );
38
+ throw new Error(`Could not find default subnet '${defaultSubnetName}' in zone ${inputs.connection.defaultZone}`);
27
39
  }
28
40
  subnetId = subnet.id;
29
41
  }
30
- var disk = new ComputeDisk(
31
- "disk",
32
- {
42
+ var encryptionKeyId;
43
+ if (args.bootDisk.encrypted) {
44
+ const encryptionKey = new KmsSymmetricKey("encryption-key", {
33
45
  name: vmName,
34
- type: args.bootDisk.type,
35
- size: args.bootDisk.size,
36
- imageId: inputs.image.id,
37
- allowRecreate: false,
38
- folderId: inputs.connection.defaultFolderId,
39
- zone: inputs.connection.defaultZone
40
- },
41
- { provider, ignoreChanges: ["imageId"] }
42
- );
46
+ description: getResourceComment(),
47
+ folderId: args.folderId ?? inputs.connection.defaultFolderId
48
+ }, { provider });
49
+ encryptionKeyId = encryptionKey.id;
50
+ }
51
+ var disk = new ComputeDisk("disk", {
52
+ name: vmName,
53
+ type: args.bootDisk.type,
54
+ size: args.bootDisk.size,
55
+ imageId: inputs.image.id,
56
+ allowRecreate: false,
57
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
58
+ zone: inputs.connection.defaultZone,
59
+ kmsKeyId: encryptionKeyId
60
+ }, { provider, ignoreChanges: ["imageId"] });
43
61
  var userData = interpolate`
44
62
  #cloud-config
45
63
  hostname: ${vmName}
@@ -49,56 +67,50 @@ var userData = interpolate`
49
67
  - ${sshKeyPair.publicKey}
50
68
  sudo: ALL=(ALL) NOPASSWD:ALL
51
69
  `.apply(trimIndentation);
52
- var address;
70
+ var publicAddress;
53
71
  if (args.network.assignPublicIp && args.network.reservePublicIp) {
54
- address = new VpcAddress(
55
- "address",
56
- {
57
- name: vmName,
58
- description: getResourceComment(),
59
- externalIpv4Address: {
60
- zoneId: inputs.connection.defaultZone
61
- }
62
- },
63
- { provider }
64
- );
65
- }
66
- var instance = new ComputeInstance(
67
- "virtual-machine",
68
- {
72
+ publicAddress = new VpcAddress("address", {
69
73
  name: vmName,
74
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
70
75
  description: getResourceComment(),
71
- folderId: inputs.connection.defaultFolderId,
72
- zone: inputs.connection.defaultZone,
73
- platformId: args.platformId,
74
- allowStoppingForUpdate: true,
75
- resources: {
76
- cores: args.resources.cores,
77
- memory: args.resources.memory,
78
- coreFraction: args.resources.coreFraction
79
- },
80
- bootDisk: {
81
- diskId: disk.id
82
- },
83
- networkInterfaces: [
84
- {
85
- subnetId,
86
- nat: args.network.assignPublicIp,
87
- natIpAddress: address ? address.externalIpv4Address.apply((a) => a.address) : void 0
88
- }
89
- ],
90
- metadata: {
91
- "user-data": userData
76
+ externalIpv4Address: {
77
+ zoneId: inputs.connection.defaultZone
92
78
  }
79
+ }, { provider });
80
+ }
81
+ var instance = new ComputeInstance("virtual-machine", {
82
+ name: vmName,
83
+ description: getResourceComment(),
84
+ folderId: args.folderId ?? inputs.connection.defaultFolderId,
85
+ zone: inputs.connection.defaultZone,
86
+ platformId: args.platformId,
87
+ allowStoppingForUpdate: true,
88
+ resources: {
89
+ cores: args.resources.cores,
90
+ memory: args.resources.memory,
91
+ coreFraction: args.resources.coreFraction
92
+ },
93
+ schedulingPolicy: {
94
+ preemptible: args.preemptible
93
95
  },
94
- { provider, ignoreChanges: ["bootDisk"] }
95
- );
96
- var publicIp = await toPromise(
97
- instance.networkInterfaces.apply((ni) => {
98
- const firstInterface = ni[0];
99
- return args.network.assignPublicIp ? firstInterface?.natIpAddress : firstInterface?.ipAddress;
100
- })
101
- );
96
+ bootDisk: {
97
+ diskId: disk.id
98
+ },
99
+ networkInterfaces: [
100
+ {
101
+ subnetId,
102
+ nat: args.network.assignPublicIp,
103
+ natIpAddress: publicAddress ? publicAddress.externalIpv4Address.apply((a) => a.address) : undefined
104
+ }
105
+ ],
106
+ metadata: {
107
+ "user-data": userData
108
+ }
109
+ }, { provider, ignoreChanges: ["bootDisk"] });
110
+ var publicIp = await toPromise(instance.networkInterfaces.apply((ni) => {
111
+ const firstInterface = ni[0];
112
+ return args.network.assignPublicIp ? firstInterface?.natIpAddress : firstInterface?.ipAddress;
113
+ }));
102
114
  if (!publicIp) {
103
115
  throw new Error("No IP address assigned to instance");
104
116
  }
@@ -119,7 +131,6 @@ var virtual_machine_default = outputs({
119
131
  },
120
132
  $terminals: [terminal]
121
133
  });
122
-
123
- export { virtual_machine_default as default };
124
- //# sourceMappingURL=index.js.map
125
- //# sourceMappingURL=index.js.map
134
+ export {
135
+ virtual_machine_default as default
136
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/yandex",
3
- "version": "0.19.1",
3
+ "version": "0.21.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -9,7 +9,8 @@
9
9
  "./connection": "./dist/connection/index.js",
10
10
  "./disk": "./dist/disk/index.js",
11
11
  "./existing-image": "./dist/existing-image/index.js",
12
- "./virtual-machine": "./dist/virtual-machine/index.js"
12
+ "./virtual-machine": "./dist/virtual-machine/index.js",
13
+ "./instance-group": "./dist/instance-group/index.js"
13
14
  },
14
15
  "publishConfig": {
15
16
  "access": "public"
@@ -19,27 +20,27 @@
19
20
  "stdlib"
20
21
  ]
21
22
  },
23
+ "scripts": {
24
+ "build": "highstate build",
25
+ "typecheck": "tsgo --noEmit --skipLibCheck",
26
+ "biome": "biome check --write --unsafe --error-on-warnings",
27
+ "biome:check": "biome check --error-on-warnings",
28
+ "generate-sdks": "./scripts/generate-sdks.sh"
29
+ },
22
30
  "dependencies": {
23
- "@pulumi/pulumi": "3.198.0",
24
- "@highstate/common": "0.19.1",
25
- "@highstate/contract": "0.19.1",
26
- "@highstate/yandex-sdk": "0.14.0",
27
- "@highstate/library": "0.19.1",
28
- "@highstate/pulumi": "0.19.1"
31
+ "@highstate/common": "0.20.0",
32
+ "@highstate/contract": "0.20.0",
33
+ "@highstate/library": "0.20.0",
34
+ "@highstate/pulumi": "0.20.0",
35
+ "@highstate/yandex-sdk": "0.19.1",
36
+ "@pulumi/pulumi": "3.232.0"
29
37
  },
30
38
  "devDependencies": {
31
39
  "@biomejs/biome": "2.2.0",
32
- "@typescript/native-preview": "^7.0.0-dev.20250920.1",
33
- "@highstate/cli": "0.19.1"
40
+ "@highstate/cli": "0.20.0",
41
+ "@typescript/native-preview": "^7.0.0-dev.20250920.1"
34
42
  },
35
43
  "repository": {
36
44
  "url": "https://github.com/highstate-io/highstate"
37
- },
38
- "scripts": {
39
- "build": "highstate build",
40
- "typecheck": "tsgo --noEmit --skipLibCheck",
41
- "biome": "biome check --write --unsafe --error-on-warnings",
42
- "biome:check": "biome check --error-on-warnings",
43
- "generate-sdks": "./scripts/generate-sdks.sh"
44
45
  }
45
- }
46
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Exeteres
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,21 +0,0 @@
1
- import { toPromise, output } from '@highstate/pulumi';
2
- import { Provider } from '@highstate/yandex-sdk';
3
-
4
- // src/provider.ts
5
- async function createProvider(connection) {
6
- return await toPromise(
7
- output(connection).apply((connection2) => {
8
- return new Provider(connection2.cloudId, {
9
- serviceAccountKeyFile: connection2.serviceAccountKeyFile,
10
- cloudId: connection2.cloudId,
11
- folderId: connection2.defaultFolderId,
12
- zone: connection2.defaultZone,
13
- regionId: connection2.regionId
14
- });
15
- })
16
- );
17
- }
18
-
19
- export { createProvider };
20
- //# sourceMappingURL=chunk-MK37EG4O.js.map
21
- //# sourceMappingURL=chunk-MK37EG4O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/provider.ts"],"names":["connection"],"mappings":";;;;AAKA,eAAsB,eAAe,UAAA,EAAyD;AAC5F,EAAA,OAAO,MAAM,SAAA;AAAA,IACX,MAAA,CAAO,UAAU,CAAA,CAAE,KAAA,CAAM,CAAAA,WAAAA,KAAc;AACrC,MAAA,OAAO,IAAI,QAAA,CAASA,WAAAA,CAAW,OAAA,EAAS;AAAA,QACtC,uBAAuBA,WAAAA,CAAW,qBAAA;AAAA,QAClC,SAASA,WAAAA,CAAW,OAAA;AAAA,QACpB,UAAUA,WAAAA,CAAW,eAAA;AAAA,QACrB,MAAMA,WAAAA,CAAW,WAAA;AAAA,QACjB,UAAUA,WAAAA,CAAW;AAAA,OACtB,CAAA;AAAA,IACH,CAAC;AAAA,GACH;AACF","file":"chunk-MK37EG4O.js","sourcesContent":["import type { yandex } from \"@highstate/library\"\nimport type { Input } from \"@highstate/pulumi\"\nimport { output, toPromise } from \"@highstate/pulumi\"\nimport { Provider } from \"@highstate/yandex-sdk\"\n\nexport async function createProvider(connection: Input<yandex.Connection>): Promise<Provider> {\n return await toPromise(\n output(connection).apply(connection => {\n return new Provider(connection.cloudId, {\n serviceAccountKeyFile: connection.serviceAccountKeyFile,\n cloudId: connection.cloudId,\n folderId: connection.defaultFolderId,\n zone: connection.defaultZone,\n regionId: connection.regionId,\n })\n }),\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/connection/index.ts"],"names":[],"mappings":";;;;;AAKA,IAAM,EAAE,IAAA,EAAM,OAAA,EAAS,SAAQ,GAAI,OAAA,CAAQ,OAAO,UAAU,CAAA;AAO5D,IAAM,2BAAA,GAA8B,MAAM,SAAA,CAAU,OAAA,CAAQ,qBAAqB,CAAA;AACjF,IAAM,WAAA,GAAqC,IAAA,CAAK,KAAA,CAAM,2BAA2B,CAAA;AACjF,IAAM,mBAAmB,WAAA,CAAY,kBAAA;AAGrC,IAAM,QAAA,GAAW,IAAI,QAAA,CAAS,QAAA,EAAU;AAAA,EACtC,qBAAA,EAAuB,2BAAA;AAAA,EACvB,IAAA,EAAM,KAAK,MAAA,CAAO,WAAA;AAAA,EAClB,QAAA,EAAU,KAAK,MAAA,CAAO;AACxB,CAAC,CAAA;AAGD,IAAM,iBAAiB,MAAM,oBAAA;AAAA,EAC3B,EAAE,gBAAA,EAAmC;AAAA,EACrC,EAAE,QAAA;AACJ,CAAA;AAGA,IAAM,MAAA,GAAS,MAAM,wBAAA,CAAyB,EAAE,QAAA,EAAU,eAAe,QAAA,EAAS,EAAG,EAAE,QAAA,EAAU,CAAA;AACjG,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,EAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAC5D;AAEA,IAAM,aAAwC,MAAA,CAAO;AAAA,EACnD,uBAAuB,OAAA,CAAQ,qBAAA;AAAA,EAC/B,SAAS,MAAA,CAAO,OAAA;AAAA,EAChB,iBAAiB,cAAA,CAAe,QAAA;AAAA,EAChC,WAAA,EAAa,KAAK,MAAA,CAAO,WAAA;AAAA,EACzB,QAAA,EAAU,KAAK,MAAA,CAAO;AACxB,CAAC,CAAA;AAED,IAAO,qBAAQ,OAAA,CAAQ;AAAA,EACrB,UAAA;AAAA,EAEA,aAAA,EAAe;AAAA,IACb,OAAA,EAAS;AAAA,MACP,IAAA,EAAM;AAAA,QACJ,IAAA,EAAM;AAAA,OACR;AAAA,MACA,OAAO,UAAA,CAAW;AAAA,KACpB;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,IAAA,EAAM;AAAA,OACR;AAAA,MACA,OAAO,UAAA,CAAW;AAAA;AACpB;AAEJ,CAAC","file":"index.js","sourcesContent":["import type { Output } from \"@highstate/pulumi\"\nimport { yandex } from \"@highstate/library\"\nimport { forUnit, output, toPromise } from \"@highstate/pulumi\"\nimport { getIamServiceAccount, getResourcemanagerFolder, Provider } from \"@highstate/yandex-sdk\"\n\nconst { args, secrets, outputs } = forUnit(yandex.connection)\n\n// parse service account key file to extract service account ID\ntype ServiceAccountKeyFile = {\n service_account_id: string\n}\n\nconst serviceAccountKeyFileString = await toPromise(secrets.serviceAccountKeyFile)\nconst keyFileData: ServiceAccountKeyFile = JSON.parse(serviceAccountKeyFileString)\nconst serviceAccountId = keyFileData.service_account_id\n\n// create provider for auto-discovery\nconst provider = new Provider(\"yandex\", {\n serviceAccountKeyFile: serviceAccountKeyFileString,\n zone: args.region.defaultZone,\n regionId: args.region.id,\n})\n\n// auto-discover service account details to get folder and cloud\nconst serviceAccount = await getIamServiceAccount(\n { serviceAccountId: serviceAccountId },\n { provider },\n)\n\n// auto-discover cloud ID from folder\nconst folder = await getResourcemanagerFolder({ folderId: serviceAccount.folderId }, { provider })\nif (!folder.cloudId) {\n throw new Error(\"Could not determine cloud ID from folder\")\n}\n\nconst connection: Output<yandex.Connection> = output({\n serviceAccountKeyFile: secrets.serviceAccountKeyFile,\n cloudId: folder.cloudId,\n defaultFolderId: serviceAccount.folderId,\n defaultZone: args.region.defaultZone,\n regionId: args.region.id,\n})\n\nexport default outputs({\n connection,\n\n $statusFields: {\n cloudId: {\n meta: {\n icon: \"mdi:cloud\",\n },\n value: connection.cloudId,\n },\n defaultFolderId: {\n meta: {\n icon: \"mdi:folder\",\n },\n value: connection.defaultFolderId,\n },\n },\n})\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/disk/index.ts"],"names":[],"mappings":";;;;;AAKA,IAAM,EAAE,MAAM,IAAA,EAAM,MAAA,EAAQ,SAAQ,GAAI,OAAA,CAAQ,OAAO,IAAI,CAAA;AAE3D,IAAM,QAAA,GAAW,MAAM,cAAA,CAAe,MAAA,CAAO,UAAU,CAAA;AAEvD,IAAM,QAAA,GAAW,KAAK,QAAA,IAAY,IAAA;AAElC,IAAM,OAAO,IAAI,WAAA;AAAA,EACf,MAAA;AAAA,EACA;AAAA,IACE,IAAA,EAAM,QAAA;AAAA,IACN,aAAa,kBAAA,EAAmB;AAAA,IAChC,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA;AACvB,CAAA;AAEA,IAAO,eAAQ,OAAA,CAAQ;AAAA,EACrB,IAAA,EAAM;AAAA,IACJ,IAAI,IAAA,CAAK;AAAA,GACX;AAAA,EACA,aAAA,EAAe;AAAA,IACb,IAAI,IAAA,CAAK;AAAA;AAEb,CAAC","file":"index.js","sourcesContent":["import { yandex } from \"@highstate/library\"\nimport { forUnit, getResourceComment } from \"@highstate/pulumi\"\nimport { ComputeDisk } from \"@highstate/yandex-sdk\"\nimport { createProvider } from \"../provider\"\n\nconst { name, args, inputs, outputs } = forUnit(yandex.disk)\n\nconst provider = await createProvider(inputs.connection)\n\nconst diskName = args.diskName ?? name\n\nconst disk = new ComputeDisk(\n \"disk\",\n {\n name: diskName,\n description: getResourceComment(),\n type: args.type,\n size: args.size,\n allowRecreate: false,\n },\n { provider, protect: true },\n)\n\nexport default outputs({\n disk: {\n id: disk.id,\n },\n $statusFields: {\n id: disk.id,\n },\n})\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/existing-image/index.ts"],"names":[],"mappings":";;;;;AAKA,IAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAQ,GAAI,OAAA,CAAQ,OAAO,aAAa,CAAA;AAE9D,IAAM,QAAA,GAAW,MAAM,cAAA,CAAe,MAAA,CAAO,UAAU,CAAA;AAEvD,IAAM,KAAA,GAAQ,MAAM,eAAA,CAAgB,EAAE,OAAA,EAAS,KAAK,EAAA,EAAG,EAAG,EAAE,QAAA,EAAU,CAAA;AAEtE,IAAO,yBAAQ,OAAA,CAAQ;AAAA,EACrB,KAAA,EAAO;AAAA,IACL,IAAI,KAAA,CAAM;AAAA,GACZ;AAAA,EACA,aAAA,EAAe;AAAA,IACb,MAAM,KAAA,CAAM;AAAA;AAEhB,CAAC","file":"index.js","sourcesContent":["import { yandex } from \"@highstate/library\"\nimport { forUnit } from \"@highstate/pulumi\"\nimport { getComputeImage } from \"@highstate/yandex-sdk\"\nimport { createProvider } from \"../provider\"\n\nconst { args, inputs, outputs } = forUnit(yandex.existingImage)\n\nconst provider = await createProvider(inputs.connection)\n\nconst image = await getComputeImage({ imageId: args.id }, { provider })\n\nexport default outputs({\n image: {\n id: image.id,\n },\n $statusFields: {\n name: image.name,\n },\n})\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/virtual-machine/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n createServerBundle,\n generatePassword,\n generateSshPrivateKey,\n l3EndpointToString,\n parseEndpoint,\n sshPrivateKeyToKeyPair,\n} from \"@highstate/common\"\nimport { trimIndentation } from \"@highstate/contract\"\nimport { yandex } from \"@highstate/library\"\nimport { forUnit, getResourceComment, interpolate, toPromise } from \"@highstate/pulumi\"\nimport { ComputeDisk, ComputeInstance, getVpcSubnet, VpcAddress } from \"@highstate/yandex-sdk\"\nimport { createProvider } from \"../provider\"\n\nconst { name, args, getSecret, inputs, outputs } = forUnit(yandex.virtualMachine)\n\nconst vmName = args.vmName ?? name\n\nconst provider = await createProvider(inputs.connection)\n\nconst sshKeyPair =\n inputs.sshKeyPair ?? sshPrivateKeyToKeyPair(getSecret(\"sshPrivateKey\", generateSshPrivateKey))\n\nconst rootPassword = getSecret(\"rootPassword\", generatePassword)\n\n// auto-discover subnet if not specified\nlet subnetId = args.network.subnetId\nif (!subnetId) {\n const defaultSubnetName = await toPromise(interpolate`default-${inputs.connection.defaultZone}`)\n const subnet = await getVpcSubnet(\n {\n folderId: await toPromise(inputs.connection.defaultFolderId),\n name: defaultSubnetName,\n },\n { provider },\n )\n\n if (!subnet.id) {\n throw new Error(\n `Could not find default subnet '${defaultSubnetName}' in zone ${inputs.connection.defaultZone}`,\n )\n }\n\n subnetId = subnet.id\n}\n\n// create the disk\nconst disk = new ComputeDisk(\n \"disk\",\n {\n name: vmName,\n type: args.bootDisk.type,\n size: args.bootDisk.size,\n imageId: inputs.image.id,\n allowRecreate: false,\n folderId: inputs.connection.defaultFolderId,\n zone: inputs.connection.defaultZone,\n },\n { provider, ignoreChanges: [\"imageId\"] },\n)\n\n// create cloud-init user data\nconst userData = interpolate`\n #cloud-config\n hostname: ${vmName}\n users:\n - name: root\n ssh-authorized-keys:\n - ${sshKeyPair.publicKey}\n sudo: ALL=(ALL) NOPASSWD:ALL\n`.apply(trimIndentation)\n\nlet address: VpcAddress | undefined\n\nif (args.network.assignPublicIp && args.network.reservePublicIp) {\n address = new VpcAddress(\n \"address\",\n {\n name: vmName,\n description: getResourceComment(),\n externalIpv4Address: {\n zoneId: inputs.connection.defaultZone,\n },\n },\n { provider },\n )\n}\n\n// create the instance\nconst instance = new ComputeInstance(\n \"virtual-machine\",\n {\n name: vmName,\n description: getResourceComment(),\n folderId: inputs.connection.defaultFolderId,\n zone: inputs.connection.defaultZone,\n platformId: args.platformId,\n allowStoppingForUpdate: true,\n\n resources: {\n cores: args.resources.cores,\n memory: args.resources.memory,\n coreFraction: args.resources.coreFraction,\n },\n\n bootDisk: {\n diskId: disk.id,\n },\n\n networkInterfaces: [\n {\n subnetId: subnetId,\n nat: args.network.assignPublicIp,\n natIpAddress: address ? address.externalIpv4Address.apply(a => a!.address) : undefined,\n },\n ],\n\n metadata: {\n \"user-data\": userData,\n },\n },\n { provider, ignoreChanges: [\"bootDisk\"] },\n)\n\n// get the IP address\nconst publicIp = await toPromise(\n instance.networkInterfaces.apply(ni => {\n const firstInterface = ni[0]\n return args.network.assignPublicIp ? firstInterface?.natIpAddress : firstInterface?.ipAddress\n }),\n)\n\nif (!publicIp) {\n throw new Error(\"No IP address assigned to instance\")\n}\n\nconst endpoint = parseEndpoint(publicIp, 3)\n\nconst { server, terminal } = await createServerBundle({\n name: vmName,\n endpoints: [endpoint],\n sshArgs: args.ssh,\n sshPassword: rootPassword,\n sshKeyPair,\n})\n\nexport default outputs({\n server,\n\n $statusFields: {\n id: instance.id,\n endpoints: [l3EndpointToString(endpoint)],\n hostname: server.hostname,\n },\n\n $terminals: [terminal],\n})\n"]}