neonctl 2.6.0 → 2.8.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/commands/branches.js +15 -0
- package/commands/branches.test.js +44 -0
- package/commands/projects.js +50 -4
- package/commands/roles.js +5 -0
- package/package.json +2 -2
- package/parameters.gen.js +14 -10
package/commands/branches.js
CHANGED
|
@@ -80,6 +80,11 @@ export const builder = (argv) => argv
|
|
|
80
80
|
hidden: true,
|
|
81
81
|
default: '{}',
|
|
82
82
|
},
|
|
83
|
+
'schema-only': {
|
|
84
|
+
describe: 'Create a schema-only branch. Requires exactly one read-write compute.',
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
default: false,
|
|
87
|
+
},
|
|
83
88
|
}), (args) => create(args))
|
|
84
89
|
.command('reset <id|name>', 'Reset a branch', (yargs) => yargs.options({
|
|
85
90
|
parent: {
|
|
@@ -218,10 +223,20 @@ const create = async (props) => {
|
|
|
218
223
|
}
|
|
219
224
|
return { parent_id: branch.id };
|
|
220
225
|
})();
|
|
226
|
+
// Validate schema-only branch requirements
|
|
227
|
+
if (props.schemaOnly) {
|
|
228
|
+
if (!props.compute) {
|
|
229
|
+
throw new Error('Schema-only branches require a compute endpoint');
|
|
230
|
+
}
|
|
231
|
+
if (props.type !== EndpointType.ReadWrite) {
|
|
232
|
+
throw new Error('Schema-only branches require a read-write compute endpoint');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
221
235
|
const { data } = await retryOnLock(() => props.apiClient.createProjectBranch(props.projectId, {
|
|
222
236
|
branch: {
|
|
223
237
|
name: props.name,
|
|
224
238
|
...parentProps,
|
|
239
|
+
...(props.schemaOnly ? { init_source: 'schema-only' } : {}),
|
|
225
240
|
},
|
|
226
241
|
endpoints: props.compute
|
|
227
242
|
? [
|
|
@@ -136,6 +136,50 @@ describe('branches', () => {
|
|
|
136
136
|
'0.5-2',
|
|
137
137
|
]);
|
|
138
138
|
});
|
|
139
|
+
test('create schema-only branch', async ({ testCliCommand }) => {
|
|
140
|
+
await testCliCommand([
|
|
141
|
+
'branches',
|
|
142
|
+
'create',
|
|
143
|
+
'--project-id',
|
|
144
|
+
'test',
|
|
145
|
+
'--name',
|
|
146
|
+
'test_branch',
|
|
147
|
+
'--schema-only',
|
|
148
|
+
]);
|
|
149
|
+
});
|
|
150
|
+
test('create schema-only branch fails without compute', async ({ testCliCommand, }) => {
|
|
151
|
+
await testCliCommand([
|
|
152
|
+
'branches',
|
|
153
|
+
'create',
|
|
154
|
+
'--project-id',
|
|
155
|
+
'test',
|
|
156
|
+
'--name',
|
|
157
|
+
'test_branch',
|
|
158
|
+
'--schema-only',
|
|
159
|
+
'--no-compute',
|
|
160
|
+
], {
|
|
161
|
+
mockDir: 'main',
|
|
162
|
+
code: 1,
|
|
163
|
+
stderr: 'ERROR: Schema-only branches require a compute endpoint',
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
test('create schema-only branch fails with read-only compute', async ({ testCliCommand, }) => {
|
|
167
|
+
await testCliCommand([
|
|
168
|
+
'branches',
|
|
169
|
+
'create',
|
|
170
|
+
'--project-id',
|
|
171
|
+
'test',
|
|
172
|
+
'--name',
|
|
173
|
+
'test_branch',
|
|
174
|
+
'--schema-only',
|
|
175
|
+
'--type',
|
|
176
|
+
'read_only',
|
|
177
|
+
], {
|
|
178
|
+
mockDir: 'main',
|
|
179
|
+
code: 1,
|
|
180
|
+
stderr: 'ERROR: Schema-only branches require a read-write compute endpoint',
|
|
181
|
+
});
|
|
182
|
+
});
|
|
139
183
|
/* delete */
|
|
140
184
|
test('delete by id', async ({ testCliCommand }) => {
|
|
141
185
|
await testCliCommand([
|
package/commands/projects.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { log } from '../log.js';
|
|
2
|
-
import { projectCreateRequest } from '../parameters.gen.js';
|
|
2
|
+
import { projectCreateRequest, projectUpdateRequest, } from '../parameters.gen.js';
|
|
3
3
|
import { writer } from '../writer.js';
|
|
4
4
|
import { psql } from '../utils/psql.js';
|
|
5
5
|
import { updateContextFile } from '../context.js';
|
|
@@ -39,6 +39,16 @@ export const builder = (argv) => {
|
|
|
39
39
|
await list(args);
|
|
40
40
|
})
|
|
41
41
|
.command('create', 'Create a project', (yargs) => yargs.options({
|
|
42
|
+
'block-public-connections': {
|
|
43
|
+
describe: projectCreateRequest['project.settings.block_public_connections']
|
|
44
|
+
.description,
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
},
|
|
47
|
+
'block-vpc-connections': {
|
|
48
|
+
describe: projectCreateRequest['project.settings.block_vpc_connections']
|
|
49
|
+
.description,
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
},
|
|
42
52
|
name: {
|
|
43
53
|
describe: projectCreateRequest['project.name'].description,
|
|
44
54
|
type: 'string',
|
|
@@ -77,14 +87,26 @@ export const builder = (argv) => {
|
|
|
77
87
|
await create(args);
|
|
78
88
|
})
|
|
79
89
|
.command('update <id>', 'Update a project', (yargs) => yargs.options({
|
|
80
|
-
|
|
81
|
-
describe:
|
|
82
|
-
|
|
90
|
+
'block-vpc-connections': {
|
|
91
|
+
describe: projectUpdateRequest['project.settings.block_vpc_connections']
|
|
92
|
+
.description +
|
|
93
|
+
' Use --block-vpc-connections=false to set the value to false.',
|
|
94
|
+
type: 'boolean',
|
|
95
|
+
},
|
|
96
|
+
'block-public-connections': {
|
|
97
|
+
describe: projectUpdateRequest['project.settings.block_public_connections']
|
|
98
|
+
.description +
|
|
99
|
+
' Use --block-public-connections=false to set the value to false.',
|
|
100
|
+
type: 'boolean',
|
|
83
101
|
},
|
|
84
102
|
cu: {
|
|
85
103
|
describe: 'The number of Compute Units. Could be a fixed size (e.g. "2") or a range delimited by a dash (e.g. "0.5-3").',
|
|
86
104
|
type: 'string',
|
|
87
105
|
},
|
|
106
|
+
name: {
|
|
107
|
+
describe: projectUpdateRequest['project.name'].description,
|
|
108
|
+
type: 'string',
|
|
109
|
+
},
|
|
88
110
|
}), async (args) => {
|
|
89
111
|
await update(args);
|
|
90
112
|
})
|
|
@@ -139,6 +161,18 @@ const list = async (props) => {
|
|
|
139
161
|
};
|
|
140
162
|
const create = async (props) => {
|
|
141
163
|
const project = {};
|
|
164
|
+
if (props.blockPublicConnections !== undefined) {
|
|
165
|
+
if (!project.settings) {
|
|
166
|
+
project.settings = {};
|
|
167
|
+
}
|
|
168
|
+
project.settings.block_public_connections = props.blockPublicConnections;
|
|
169
|
+
}
|
|
170
|
+
if (props.blockVpcConnections !== undefined) {
|
|
171
|
+
if (!project.settings) {
|
|
172
|
+
project.settings = {};
|
|
173
|
+
}
|
|
174
|
+
project.settings.block_vpc_connections = props.blockVpcConnections;
|
|
175
|
+
}
|
|
142
176
|
if (props.name) {
|
|
143
177
|
project.name = props.name;
|
|
144
178
|
}
|
|
@@ -189,6 +223,18 @@ const deleteProject = async (props) => {
|
|
|
189
223
|
};
|
|
190
224
|
const update = async (props) => {
|
|
191
225
|
const project = {};
|
|
226
|
+
if (props.blockPublicConnections !== undefined) {
|
|
227
|
+
if (!project.settings) {
|
|
228
|
+
project.settings = {};
|
|
229
|
+
}
|
|
230
|
+
project.settings.block_public_connections = props.blockPublicConnections;
|
|
231
|
+
}
|
|
232
|
+
if (props.blockVpcConnections !== undefined) {
|
|
233
|
+
if (!project.settings) {
|
|
234
|
+
project.settings = {};
|
|
235
|
+
}
|
|
236
|
+
project.settings.block_vpc_connections = props.blockVpcConnections;
|
|
237
|
+
}
|
|
192
238
|
if (props.name) {
|
|
193
239
|
project.name = props.name;
|
|
194
240
|
}
|
package/commands/roles.js
CHANGED
|
@@ -25,6 +25,10 @@ export const builder = (argv) => argv
|
|
|
25
25
|
type: 'string',
|
|
26
26
|
demandOption: true,
|
|
27
27
|
},
|
|
28
|
+
'no-login': {
|
|
29
|
+
describe: 'Create a passwordless role that cannot login',
|
|
30
|
+
boolean: true,
|
|
31
|
+
},
|
|
28
32
|
}), (args) => create(args))
|
|
29
33
|
.command('delete <role>', 'Delete a role', (yargs) => yargs, (args) => deleteRole(args));
|
|
30
34
|
export const handler = (args) => {
|
|
@@ -42,6 +46,7 @@ export const create = async (props) => {
|
|
|
42
46
|
const { data } = await retryOnLock(() => props.apiClient.createProjectBranchRole(props.projectId, branchId, {
|
|
43
47
|
role: {
|
|
44
48
|
name: props.name,
|
|
49
|
+
no_login: props['no-login'],
|
|
45
50
|
},
|
|
46
51
|
}));
|
|
47
52
|
writer(props).end(data.role, {
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"url": "git+ssh://git@github.com/neondatabase/neonctl.git"
|
|
6
6
|
},
|
|
7
7
|
"type": "module",
|
|
8
|
-
"version": "2.
|
|
8
|
+
"version": "2.8.0",
|
|
9
9
|
"description": "CLI tool for NeonDB Cloud management",
|
|
10
10
|
"main": "index.js",
|
|
11
11
|
"author": "NeonDB",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"vitest": "^1.6.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@neondatabase/api-client": "1.
|
|
57
|
+
"@neondatabase/api-client": "1.12.0",
|
|
58
58
|
"@segment/analytics-node": "^1.0.0-beta.26",
|
|
59
59
|
"axios": "^1.4.0",
|
|
60
60
|
"axios-debug-log": "^1.0.0",
|
package/parameters.gen.js
CHANGED
|
@@ -97,7 +97,7 @@ export const projectCreateRequest = {
|
|
|
97
97
|
},
|
|
98
98
|
'project.default_endpoint_settings.suspend_timeout_seconds': {
|
|
99
99
|
type: "number",
|
|
100
|
-
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the
|
|
100
|
+
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the default value.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe minimum value is `60` seconds (1 minute).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Scale to zero configuration](https://neon.tech/docs/manage/endpoints#scale-to-zero-configuration).\n",
|
|
101
101
|
demandOption: false,
|
|
102
102
|
},
|
|
103
103
|
'project.pg_version': {
|
|
@@ -194,7 +194,7 @@ export const projectUpdateRequest = {
|
|
|
194
194
|
},
|
|
195
195
|
'project.default_endpoint_settings.suspend_timeout_seconds': {
|
|
196
196
|
type: "number",
|
|
197
|
-
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the
|
|
197
|
+
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the default value.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe minimum value is `60` seconds (1 minute).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Scale to zero configuration](https://neon.tech/docs/manage/endpoints#scale-to-zero-configuration).\n",
|
|
198
198
|
demandOption: false,
|
|
199
199
|
},
|
|
200
200
|
'project.history_retention_seconds': {
|
|
@@ -239,11 +239,10 @@ export const branchCreateRequest = {
|
|
|
239
239
|
description: "Whether to create the branch as archived\n",
|
|
240
240
|
demandOption: false,
|
|
241
241
|
},
|
|
242
|
-
'branch.
|
|
242
|
+
'branch.init_source': {
|
|
243
243
|
type: "string",
|
|
244
|
-
description: "The type
|
|
244
|
+
description: "The initialization source type for the branch. Valid values are `schema-only` and `parent-data`.\nThis parameter is under active development and may change its semantics in the future.\n",
|
|
245
245
|
demandOption: false,
|
|
246
|
-
choices: ["empty"],
|
|
247
246
|
},
|
|
248
247
|
};
|
|
249
248
|
export const branchCreateRequestEndpointOptions = {
|
|
@@ -260,7 +259,7 @@ export const branchCreateRequestEndpointOptions = {
|
|
|
260
259
|
},
|
|
261
260
|
'suspend_timeout_seconds': {
|
|
262
261
|
type: "number",
|
|
263
|
-
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the
|
|
262
|
+
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the default value.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe minimum value is `60` seconds (1 minute).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Scale to zero configuration](https://neon.tech/docs/manage/endpoints#scale-to-zero-configuration).\n",
|
|
264
263
|
demandOption: false,
|
|
265
264
|
},
|
|
266
265
|
};
|
|
@@ -321,14 +320,14 @@ export const endpointCreateRequest = {
|
|
|
321
320
|
},
|
|
322
321
|
'endpoint.suspend_timeout_seconds': {
|
|
323
322
|
type: "number",
|
|
324
|
-
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the
|
|
323
|
+
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the default value.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe minimum value is `60` seconds (1 minute).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Scale to zero configuration](https://neon.tech/docs/manage/endpoints#scale-to-zero-configuration).\n",
|
|
325
324
|
demandOption: false,
|
|
326
325
|
},
|
|
327
326
|
};
|
|
328
327
|
export const endpointUpdateRequest = {
|
|
329
328
|
'endpoint.branch_id': {
|
|
330
329
|
type: "string",
|
|
331
|
-
description: "DEPRECATED: This field will be removed in a future release.\nThe destination branch ID. The destination branch must not have an
|
|
330
|
+
description: "DEPRECATED: This field will be removed in a future release.\nThe destination branch ID. The destination branch must not have an existing read-write endpoint.\n",
|
|
332
331
|
demandOption: false,
|
|
333
332
|
},
|
|
334
333
|
'endpoint.provisioner': {
|
|
@@ -359,14 +358,14 @@ export const endpointUpdateRequest = {
|
|
|
359
358
|
},
|
|
360
359
|
'endpoint.suspend_timeout_seconds': {
|
|
361
360
|
type: "number",
|
|
362
|
-
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the
|
|
361
|
+
description: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the default value.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe minimum value is `60` seconds (1 minute).\nThe maximum value is `604800` seconds (1 week). For more information, see\n[Scale to zero configuration](https://neon.tech/docs/manage/endpoints#scale-to-zero-configuration).\n",
|
|
363
362
|
demandOption: false,
|
|
364
363
|
},
|
|
365
364
|
};
|
|
366
365
|
export const databaseCreateRequest = {
|
|
367
366
|
'database.name': {
|
|
368
367
|
type: "string",
|
|
369
|
-
description: "The name of the
|
|
368
|
+
description: "The name of the database\n",
|
|
370
369
|
demandOption: true,
|
|
371
370
|
},
|
|
372
371
|
'database.owner_name': {
|
|
@@ -381,4 +380,9 @@ export const roleCreateRequest = {
|
|
|
381
380
|
description: "The role name. Cannot exceed 63 bytes in length.\n",
|
|
382
381
|
demandOption: true,
|
|
383
382
|
},
|
|
383
|
+
'role.no_login': {
|
|
384
|
+
type: "boolean",
|
|
385
|
+
description: "Whether to create a role that cannot login.\n",
|
|
386
|
+
demandOption: false,
|
|
387
|
+
},
|
|
384
388
|
};
|