neonctl 2.4.0 → 2.5.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/bootstrap/index.js +3 -1
- package/commands/branches.js +4 -2
- package/commands/index.js +2 -0
- package/commands/projects.js +1 -1
- package/commands/schema_diff.js +6 -3
- package/commands/vpc_endpoints.js +134 -0
- package/commands/vpc_endpoints.test.js +69 -0
- package/package.json +2 -2
- package/parameters.gen.js +70 -23
- package/utils/enrichers.js +19 -2
|
@@ -135,7 +135,9 @@ function applyMigrations({ options, appName, connectionString, }) {
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
async function deployApp({ props, options, devBranchName, project, appName, environmentVariables, }) {
|
|
138
|
-
let { data: { branches }, } = await props.apiClient.listProjectBranches(
|
|
138
|
+
let { data: { branches }, } = await props.apiClient.listProjectBranches({
|
|
139
|
+
projectId: project.id,
|
|
140
|
+
});
|
|
139
141
|
branches = branches.filter((branch) => branch.name !== devBranchName);
|
|
140
142
|
let branchId;
|
|
141
143
|
if (branches.length === 0) {
|
package/commands/branches.js
CHANGED
|
@@ -179,14 +179,16 @@ export const handler = (args) => {
|
|
|
179
179
|
return args;
|
|
180
180
|
};
|
|
181
181
|
const list = async (props) => {
|
|
182
|
-
const { data } = await props.apiClient.listProjectBranches(
|
|
182
|
+
const { data } = await props.apiClient.listProjectBranches({
|
|
183
|
+
projectId: props.projectId,
|
|
184
|
+
});
|
|
183
185
|
writer(props).end(data.branches, {
|
|
184
186
|
fields: BRANCH_FIELDS,
|
|
185
187
|
});
|
|
186
188
|
};
|
|
187
189
|
const create = async (props) => {
|
|
188
190
|
const branches = await props.apiClient
|
|
189
|
-
.listProjectBranches(props.projectId)
|
|
191
|
+
.listProjectBranches({ projectId: props.projectId })
|
|
190
192
|
.then(({ data }) => data.branches);
|
|
191
193
|
const parentProps = (() => {
|
|
192
194
|
if (!props.parent) {
|
package/commands/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as auth from './auth.js';
|
|
2
2
|
import * as projects from './projects.js';
|
|
3
3
|
import * as ipAllow from './ip_allow.js';
|
|
4
|
+
import * as vpcEndpoints from './vpc_endpoints.js';
|
|
4
5
|
import * as users from './user.js';
|
|
5
6
|
import * as orgs from './orgs.js';
|
|
6
7
|
import * as branches from './branches.js';
|
|
@@ -16,6 +17,7 @@ export default [
|
|
|
16
17
|
orgs,
|
|
17
18
|
projects,
|
|
18
19
|
ipAllow,
|
|
20
|
+
vpcEndpoints,
|
|
19
21
|
branches,
|
|
20
22
|
databases,
|
|
21
23
|
roles,
|
package/commands/projects.js
CHANGED
package/commands/schema_diff.js
CHANGED
|
@@ -64,7 +64,6 @@ const fetchSchema = async (pointInTime, database, props) => {
|
|
|
64
64
|
projectId: props.projectId,
|
|
65
65
|
branchId: pointInTime.branchId,
|
|
66
66
|
db_name: database.name,
|
|
67
|
-
role: database.owner_name,
|
|
68
67
|
...pointInTimeParams(pointInTime),
|
|
69
68
|
})
|
|
70
69
|
.then((response) => response.data.sql ?? '');
|
|
@@ -128,7 +127,9 @@ export const parseSchemaDiffParams = async (props) => {
|
|
|
128
127
|
props.baseBranch = props.branch;
|
|
129
128
|
}
|
|
130
129
|
else if (props.branch) {
|
|
131
|
-
const { data } = await props.apiClient.listProjectBranches(
|
|
130
|
+
const { data } = await props.apiClient.listProjectBranches({
|
|
131
|
+
projectId: props.projectId,
|
|
132
|
+
});
|
|
132
133
|
const contextBranch = data.branches.find((b) => b.id === props.branch || b.name === props.branch);
|
|
133
134
|
if (contextBranch?.parent_id == undefined) {
|
|
134
135
|
throw new Error(`No branch specified. Your context branch (${props.branch}) has no parent, so no comparison is possible.`);
|
|
@@ -137,7 +138,9 @@ export const parseSchemaDiffParams = async (props) => {
|
|
|
137
138
|
props.compareSource = '^parent';
|
|
138
139
|
}
|
|
139
140
|
else {
|
|
140
|
-
const { data } = await props.apiClient.listProjectBranches(
|
|
141
|
+
const { data } = await props.apiClient.listProjectBranches({
|
|
142
|
+
projectId: props.projectId,
|
|
143
|
+
});
|
|
141
144
|
const defaultBranch = data.branches.find((b) => b.default);
|
|
142
145
|
if (defaultBranch?.parent_id == undefined) {
|
|
143
146
|
throw new Error('No branch specified. Include a base branch or add a set-context branch to continue. Your default branch has no parent, so no comparison is possible.');
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { writer } from '../writer.js';
|
|
2
|
+
import { fillSingleProject, fillSingleOrg } from '../utils/enrichers.js';
|
|
3
|
+
import { REGIONS } from './projects.js';
|
|
4
|
+
import { log } from '../log.js';
|
|
5
|
+
const VPC_ENDPOINT_FIELDS = ['vpc_endpoint_id', 'label'];
|
|
6
|
+
const VPC_ENDPOINT_DETAILS_FIELDS = [
|
|
7
|
+
'vpc_endpoint_id',
|
|
8
|
+
'label',
|
|
9
|
+
'state',
|
|
10
|
+
'num_restricted_projects',
|
|
11
|
+
'example_restricted_projects',
|
|
12
|
+
];
|
|
13
|
+
export const command = 'vpc';
|
|
14
|
+
export const describe = 'Manage VPC endpoints and project VPC restrictions';
|
|
15
|
+
export const builder = (argv) => {
|
|
16
|
+
return argv
|
|
17
|
+
.usage('$0 vpc <sub-command> [options]')
|
|
18
|
+
.command('endpoint', 'Manage VPC endpoints.\n' +
|
|
19
|
+
'See: https://neon.tech/docs/guides/neon-private-networking\n' +
|
|
20
|
+
'After adding an endpoint to an organization, client connections will be accepted\n' +
|
|
21
|
+
'from the corresponding VPC for all projects in the organization, unless overridden\n' +
|
|
22
|
+
'by a project-level VPC endpoint restriction.', (yargs) => {
|
|
23
|
+
return yargs
|
|
24
|
+
.options({
|
|
25
|
+
'org-id': {
|
|
26
|
+
describe: 'Organization ID',
|
|
27
|
+
type: 'string',
|
|
28
|
+
},
|
|
29
|
+
'region-id': {
|
|
30
|
+
describe: `The region ID. Possible values: ${REGIONS.join(', ')}`,
|
|
31
|
+
type: 'string',
|
|
32
|
+
demandOption: true,
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
.middleware(fillSingleOrg)
|
|
36
|
+
.command('list', 'List configured VPC endpoints for this organization.', (yargs) => yargs, async (args) => {
|
|
37
|
+
await listOrg(args);
|
|
38
|
+
})
|
|
39
|
+
.command({
|
|
40
|
+
command: 'assign <id>',
|
|
41
|
+
aliases: ['update <id>', 'add <id>'],
|
|
42
|
+
describe: 'Add or update a VPC endpoint for this organization.\n' +
|
|
43
|
+
'Note: Azure regions are not yet supported.',
|
|
44
|
+
builder: (yargs) => yargs.options({
|
|
45
|
+
label: {
|
|
46
|
+
describe: 'An optional descriptive label for the VPC endpoint',
|
|
47
|
+
type: 'string',
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
handler: async (args) => {
|
|
51
|
+
await assignOrg(args);
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
.command('remove <id>', 'Remove a VPC endpoint from this organization.', (yargs) => yargs, async (args) => {
|
|
55
|
+
await removeOrg(args);
|
|
56
|
+
})
|
|
57
|
+
.command('status <id>', 'Get the status of a VPC endpoint for this organization.', (yargs) => yargs, async (args) => {
|
|
58
|
+
await statusOrg(args);
|
|
59
|
+
});
|
|
60
|
+
})
|
|
61
|
+
.command('project', 'Manage project-level VPC endpoint restrictions.\n' +
|
|
62
|
+
'By default, connections are accepted from any VPC configured at the organization level.\n' +
|
|
63
|
+
'A project-level VPC endpoint restriction can be used to restrict connections to a specific VPC.', (yargs) => {
|
|
64
|
+
return yargs
|
|
65
|
+
.options({
|
|
66
|
+
'project-id': {
|
|
67
|
+
describe: 'Project ID',
|
|
68
|
+
type: 'string',
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
.middleware(fillSingleProject)
|
|
72
|
+
.command('list', 'List VPC endpoint restrictions for this project.', (yargs) => yargs, async (args) => {
|
|
73
|
+
await listProject(args);
|
|
74
|
+
})
|
|
75
|
+
.command({
|
|
76
|
+
command: 'restrict <id>',
|
|
77
|
+
aliases: ['update <id>'],
|
|
78
|
+
describe: 'Configure or update a VPC endpoint restriction for this project.',
|
|
79
|
+
builder: (yargs) => yargs.options({
|
|
80
|
+
label: {
|
|
81
|
+
describe: 'An optional descriptive label for the VPC endpoint restriction',
|
|
82
|
+
type: 'string',
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
handler: async (args) => {
|
|
86
|
+
await assignProject(args);
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
.command('remove <id>', 'Remove a VPC endpoint restriction from this project.', (yargs) => yargs, async (args) => {
|
|
90
|
+
await removeProject(args);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
const listOrg = async (props) => {
|
|
95
|
+
const { data } = await props.apiClient.listOrganizationVpcEndpoints(props.orgId, props.regionId);
|
|
96
|
+
writer(props).end(data.endpoints, {
|
|
97
|
+
fields: VPC_ENDPOINT_FIELDS,
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const assignOrg = async (props) => {
|
|
101
|
+
const vpcEndpointAssignment = {
|
|
102
|
+
label: props.label || '',
|
|
103
|
+
};
|
|
104
|
+
const { data } = await props.apiClient.assignOrganizationVpcEndpoint(props.orgId, props.regionId, props.id, vpcEndpointAssignment);
|
|
105
|
+
writer(props).end(data, { fields: [] });
|
|
106
|
+
if (props.regionId.startsWith('azure')) {
|
|
107
|
+
log.info('VPC endpoint configuration is not supported for Azure regions');
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const removeOrg = async (props) => {
|
|
111
|
+
const { data } = await props.apiClient.deleteOrganizationVpcEndpoint(props.orgId, props.regionId, props.id);
|
|
112
|
+
writer(props).end(data, { fields: [] });
|
|
113
|
+
};
|
|
114
|
+
const statusOrg = async (props) => {
|
|
115
|
+
const { data } = await props.apiClient.getOrganizationVpcEndpointDetails(props.orgId, props.regionId, props.id);
|
|
116
|
+
writer(props).end(data, { fields: VPC_ENDPOINT_DETAILS_FIELDS });
|
|
117
|
+
};
|
|
118
|
+
const listProject = async (props) => {
|
|
119
|
+
const { data } = await props.apiClient.listProjectVpcEndpoints(props.projectId);
|
|
120
|
+
writer(props).end(data.endpoints, {
|
|
121
|
+
fields: VPC_ENDPOINT_FIELDS,
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
const assignProject = async (props) => {
|
|
125
|
+
const vpcEndpointAssignment = {
|
|
126
|
+
label: props.label || '',
|
|
127
|
+
};
|
|
128
|
+
const { data } = await props.apiClient.assignProjectVpcEndpoint(props.projectId, props.id, vpcEndpointAssignment);
|
|
129
|
+
writer(props).end(data, { fields: [] });
|
|
130
|
+
};
|
|
131
|
+
const removeProject = async (props) => {
|
|
132
|
+
const { data } = await props.apiClient.deleteProjectVpcEndpoint(props.projectId, props.id);
|
|
133
|
+
writer(props).end(data, { fields: [] });
|
|
134
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe } from 'vitest';
|
|
2
|
+
import { test } from '../test_utils/fixtures';
|
|
3
|
+
describe('vpc-endpoints', () => {
|
|
4
|
+
test('list org VPC endpoints', async ({ testCliCommand }) => {
|
|
5
|
+
await testCliCommand(['vpc', 'endpoint', 'list', '--org-id', '1', '--region-id', 'test'], { mockDir: 'single_org' });
|
|
6
|
+
});
|
|
7
|
+
test('list org VPC endpoints implicit org', async ({ testCliCommand }) => {
|
|
8
|
+
await testCliCommand(['vpc', 'endpoint', 'list', '--region-id', 'test'], {
|
|
9
|
+
mockDir: 'single_org',
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
test('update org VPC endpoint', async ({ testCliCommand }) => {
|
|
13
|
+
await testCliCommand([
|
|
14
|
+
'vpc',
|
|
15
|
+
'endpoint',
|
|
16
|
+
'update',
|
|
17
|
+
'vpc-test',
|
|
18
|
+
'--label',
|
|
19
|
+
'newlabel',
|
|
20
|
+
'--region-id',
|
|
21
|
+
'test',
|
|
22
|
+
], { mockDir: 'single_org' });
|
|
23
|
+
});
|
|
24
|
+
test('delete org VPC endpoint', async ({ testCliCommand }) => {
|
|
25
|
+
await testCliCommand(['vpc', 'endpoint', 'remove', 'vpc-test', '--region-id', 'test'], { mockDir: 'single_org' });
|
|
26
|
+
});
|
|
27
|
+
test('get org VPC endpoint status', async ({ testCliCommand }) => {
|
|
28
|
+
await testCliCommand(['vpc', 'endpoint', 'status', 'vpc-test', '--region-id', 'test'], { mockDir: 'single_org' });
|
|
29
|
+
});
|
|
30
|
+
test('set org VPC endpoint in azure', async ({ testCliCommand }) => {
|
|
31
|
+
await testCliCommand([
|
|
32
|
+
'vpc',
|
|
33
|
+
'endpoint',
|
|
34
|
+
'update',
|
|
35
|
+
'vpc-test',
|
|
36
|
+
'--label',
|
|
37
|
+
'newlabel',
|
|
38
|
+
'--region-id',
|
|
39
|
+
'azure-test',
|
|
40
|
+
], {
|
|
41
|
+
mockDir: 'single_org',
|
|
42
|
+
stderr: 'INFO: VPC endpoint configuration is not supported for Azure regions',
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
test('list project VPC endpoint restrictions', async ({ testCliCommand }) => {
|
|
46
|
+
await testCliCommand([
|
|
47
|
+
'vpc',
|
|
48
|
+
'project',
|
|
49
|
+
'list',
|
|
50
|
+
'--region-id',
|
|
51
|
+
'test',
|
|
52
|
+
'--project-id',
|
|
53
|
+
'test-project-123456',
|
|
54
|
+
], { mockDir: 'single_org' });
|
|
55
|
+
});
|
|
56
|
+
test('list project VPC endpoint restrictions with implicit project', async ({ testCliCommand, }) => {
|
|
57
|
+
await testCliCommand(['vpc', 'project', 'list', '--region-id', 'test'], {
|
|
58
|
+
mockDir: 'single_org',
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
test('set project VPC endpoint restrictions', async ({ testCliCommand }) => {
|
|
62
|
+
await testCliCommand(['vpc', 'project', 'update', 'vpc-test', '--label', 'newlabel'], { mockDir: 'single_org' });
|
|
63
|
+
});
|
|
64
|
+
test('delete project VPC endpoint restrictions', async ({ testCliCommand, }) => {
|
|
65
|
+
await testCliCommand(['vpc', 'project', 'remove', 'vpc-test'], {
|
|
66
|
+
mockDir: 'single_org',
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
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.5.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": "
|
|
57
|
+
"@neondatabase/api-client": "1.11.2",
|
|
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
|
@@ -35,14 +35,34 @@ export const projectCreateRequest = {
|
|
|
35
35
|
description: "If true, the list will be applied only to protected branches.",
|
|
36
36
|
demandOption: false,
|
|
37
37
|
},
|
|
38
|
-
'project.settings.
|
|
38
|
+
'project.settings.enable_logical_replication': {
|
|
39
39
|
type: "boolean",
|
|
40
|
-
description: "
|
|
40
|
+
description: "Sets wal_level=logical for all compute endpoints in this project.\nAll active endpoints will be suspended.\nOnce enabled, logical replication cannot be disabled.\n",
|
|
41
41
|
demandOption: false,
|
|
42
42
|
},
|
|
43
|
-
'project.settings.
|
|
43
|
+
'project.settings.maintenance_window.weekdays': {
|
|
44
|
+
type: "array",
|
|
45
|
+
description: "A list of weekdays when the maintenance window is active.\nEncoded as ints, where 1 - Monday, and 7 - Sunday.\n",
|
|
46
|
+
demandOption: true,
|
|
47
|
+
},
|
|
48
|
+
'project.settings.maintenance_window.start_time': {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Start time of the maintenance window, in the format of \"HH:MM\". Uses UTC.\n",
|
|
51
|
+
demandOption: true,
|
|
52
|
+
},
|
|
53
|
+
'project.settings.maintenance_window.end_time': {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "End time of the maintenance window, in the format of \"HH:MM\". Uses UTC.\n",
|
|
56
|
+
demandOption: true,
|
|
57
|
+
},
|
|
58
|
+
'project.settings.block_public_connections': {
|
|
44
59
|
type: "boolean",
|
|
45
|
-
description: "
|
|
60
|
+
description: "When set, connections from the public internet\nare disallowed. This supersedes the AllowedIPs list.\nThis parameter is under active development and its semantics may change in the future.\n",
|
|
61
|
+
demandOption: false,
|
|
62
|
+
},
|
|
63
|
+
'project.settings.block_vpc_connections': {
|
|
64
|
+
type: "boolean",
|
|
65
|
+
description: "When set, connections using VPC endpoints are disallowed.\nThis parameter is under active development and its semantics may change in the future.\n",
|
|
46
66
|
demandOption: false,
|
|
47
67
|
},
|
|
48
68
|
'project.name': {
|
|
@@ -52,24 +72,23 @@ export const projectCreateRequest = {
|
|
|
52
72
|
},
|
|
53
73
|
'project.branch.name': {
|
|
54
74
|
type: "string",
|
|
55
|
-
description: "The branch name. If not specified, the default branch name will be used.\n",
|
|
75
|
+
description: "The default branch name. If not specified, the default branch name, `main`, will be used.\n",
|
|
56
76
|
demandOption: false,
|
|
57
77
|
},
|
|
58
78
|
'project.branch.role_name': {
|
|
59
79
|
type: "string",
|
|
60
|
-
description: "The role name. If not specified, the default role name will be used.\n",
|
|
80
|
+
description: "The role name. If not specified, the default role name, `{database_name}_owner`, will be used.\n",
|
|
61
81
|
demandOption: false,
|
|
62
82
|
},
|
|
63
83
|
'project.branch.database_name': {
|
|
64
84
|
type: "string",
|
|
65
|
-
description: "The database name. If not specified, the default database name will be used.\n",
|
|
85
|
+
description: "The database name. If not specified, the default database name, `neondb`, will be used.\n",
|
|
66
86
|
demandOption: false,
|
|
67
87
|
},
|
|
68
88
|
'project.provisioner': {
|
|
69
89
|
type: "string",
|
|
70
|
-
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n",
|
|
90
|
+
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n\nProvisioner can be one of the following values:\n* k8s-pod\n* k8s-neonvm\n\nClients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.\n",
|
|
71
91
|
demandOption: false,
|
|
72
|
-
choices: ["k8s-pod", "k8s-neonvm"],
|
|
73
92
|
},
|
|
74
93
|
'project.region_id': {
|
|
75
94
|
type: "string",
|
|
@@ -83,7 +102,7 @@ export const projectCreateRequest = {
|
|
|
83
102
|
},
|
|
84
103
|
'project.pg_version': {
|
|
85
104
|
type: "number",
|
|
86
|
-
description: "The major Postgres version number. Currently supported versions are `14`, `15`, and `
|
|
105
|
+
description: "The major Postgres version number. Currently supported versions are `14`, `15`, `16`, and `17`.",
|
|
87
106
|
demandOption: false,
|
|
88
107
|
},
|
|
89
108
|
'project.store_passwords': {
|
|
@@ -93,7 +112,7 @@ export const projectCreateRequest = {
|
|
|
93
112
|
},
|
|
94
113
|
'project.history_retention_seconds': {
|
|
95
114
|
type: "number",
|
|
96
|
-
description: "The number of seconds to retain the
|
|
115
|
+
description: "The number of seconds to retain the shared history for all branches in this project.\nThe default is 1 day (86400 seconds).\n",
|
|
97
116
|
demandOption: false,
|
|
98
117
|
},
|
|
99
118
|
'project.org_id': {
|
|
@@ -138,14 +157,34 @@ export const projectUpdateRequest = {
|
|
|
138
157
|
description: "If true, the list will be applied only to protected branches.",
|
|
139
158
|
demandOption: false,
|
|
140
159
|
},
|
|
141
|
-
'project.settings.
|
|
160
|
+
'project.settings.enable_logical_replication': {
|
|
142
161
|
type: "boolean",
|
|
143
|
-
description: "
|
|
162
|
+
description: "Sets wal_level=logical for all compute endpoints in this project.\nAll active endpoints will be suspended.\nOnce enabled, logical replication cannot be disabled.\n",
|
|
144
163
|
demandOption: false,
|
|
145
164
|
},
|
|
146
|
-
'project.settings.
|
|
165
|
+
'project.settings.maintenance_window.weekdays': {
|
|
166
|
+
type: "array",
|
|
167
|
+
description: "A list of weekdays when the maintenance window is active.\nEncoded as ints, where 1 - Monday, and 7 - Sunday.\n",
|
|
168
|
+
demandOption: true,
|
|
169
|
+
},
|
|
170
|
+
'project.settings.maintenance_window.start_time': {
|
|
171
|
+
type: "string",
|
|
172
|
+
description: "Start time of the maintenance window, in the format of \"HH:MM\". Uses UTC.\n",
|
|
173
|
+
demandOption: true,
|
|
174
|
+
},
|
|
175
|
+
'project.settings.maintenance_window.end_time': {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "End time of the maintenance window, in the format of \"HH:MM\". Uses UTC.\n",
|
|
178
|
+
demandOption: true,
|
|
179
|
+
},
|
|
180
|
+
'project.settings.block_public_connections': {
|
|
147
181
|
type: "boolean",
|
|
148
|
-
description: "
|
|
182
|
+
description: "When set, connections from the public internet\nare disallowed. This supersedes the AllowedIPs list.\nThis parameter is under active development and its semantics may change in the future.\n",
|
|
183
|
+
demandOption: false,
|
|
184
|
+
},
|
|
185
|
+
'project.settings.block_vpc_connections': {
|
|
186
|
+
type: "boolean",
|
|
187
|
+
description: "When set, connections using VPC endpoints are disallowed.\nThis parameter is under active development and its semantics may change in the future.\n",
|
|
149
188
|
demandOption: false,
|
|
150
189
|
},
|
|
151
190
|
'project.name': {
|
|
@@ -160,7 +199,7 @@ export const projectUpdateRequest = {
|
|
|
160
199
|
},
|
|
161
200
|
'project.history_retention_seconds': {
|
|
162
201
|
type: "number",
|
|
163
|
-
description: "The number of seconds to retain the
|
|
202
|
+
description: "The number of seconds to retain the shared history for all branches in this project.\nThe default is 1 day (604800 seconds).\n",
|
|
164
203
|
demandOption: false,
|
|
165
204
|
},
|
|
166
205
|
};
|
|
@@ -195,6 +234,17 @@ export const branchCreateRequest = {
|
|
|
195
234
|
description: "Whether the branch is protected\n",
|
|
196
235
|
demandOption: false,
|
|
197
236
|
},
|
|
237
|
+
'branch.archived': {
|
|
238
|
+
type: "boolean",
|
|
239
|
+
description: "Whether to create the branch as archived\n",
|
|
240
|
+
demandOption: false,
|
|
241
|
+
},
|
|
242
|
+
'branch.schema_initialization_type': {
|
|
243
|
+
type: "string",
|
|
244
|
+
description: "The type of schema initialization. Defines how the schema is initialized, currently only empty is supported. This parameter is under\nactive development and may change its semantics in the future.\n",
|
|
245
|
+
demandOption: false,
|
|
246
|
+
choices: ["empty"],
|
|
247
|
+
},
|
|
198
248
|
};
|
|
199
249
|
export const branchCreateRequestEndpointOptions = {
|
|
200
250
|
'type': {
|
|
@@ -205,9 +255,8 @@ export const branchCreateRequestEndpointOptions = {
|
|
|
205
255
|
},
|
|
206
256
|
'provisioner': {
|
|
207
257
|
type: "string",
|
|
208
|
-
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n",
|
|
258
|
+
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n\nProvisioner can be one of the following values:\n* k8s-pod\n* k8s-neonvm\n\nClients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.\n",
|
|
209
259
|
demandOption: false,
|
|
210
|
-
choices: ["k8s-pod", "k8s-neonvm"],
|
|
211
260
|
},
|
|
212
261
|
'suspend_timeout_seconds': {
|
|
213
262
|
type: "number",
|
|
@@ -246,9 +295,8 @@ export const endpointCreateRequest = {
|
|
|
246
295
|
},
|
|
247
296
|
'endpoint.provisioner': {
|
|
248
297
|
type: "string",
|
|
249
|
-
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n",
|
|
298
|
+
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n\nProvisioner can be one of the following values:\n* k8s-pod\n* k8s-neonvm\n\nClients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.\n",
|
|
250
299
|
demandOption: false,
|
|
251
|
-
choices: ["k8s-pod", "k8s-neonvm"],
|
|
252
300
|
},
|
|
253
301
|
'endpoint.pooler_enabled': {
|
|
254
302
|
type: "boolean",
|
|
@@ -280,14 +328,13 @@ export const endpointCreateRequest = {
|
|
|
280
328
|
export const endpointUpdateRequest = {
|
|
281
329
|
'endpoint.branch_id': {
|
|
282
330
|
type: "string",
|
|
283
|
-
description: "
|
|
331
|
+
description: "DEPRECATED: This field will be removed in a future release.\nThe destination branch ID. The destination branch must not have an exsiting read-write endpoint.\n",
|
|
284
332
|
demandOption: false,
|
|
285
333
|
},
|
|
286
334
|
'endpoint.provisioner': {
|
|
287
335
|
type: "string",
|
|
288
|
-
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n",
|
|
336
|
+
description: "The Neon compute provisioner.\nSpecify the `k8s-neonvm` provisioner to create a compute endpoint that supports Autoscaling.\n\nProvisioner can be one of the following values:\n* k8s-pod\n* k8s-neonvm\n\nClients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.\n",
|
|
289
337
|
demandOption: false,
|
|
290
|
-
choices: ["k8s-pod", "k8s-neonvm"],
|
|
291
338
|
},
|
|
292
339
|
'endpoint.pooler_enabled': {
|
|
293
340
|
type: "boolean",
|
package/utils/enrichers.js
CHANGED
|
@@ -4,7 +4,9 @@ export const branchIdResolve = async ({ branch, apiClient, projectId, }) => {
|
|
|
4
4
|
if (looksLikeBranchId(branch)) {
|
|
5
5
|
return branch;
|
|
6
6
|
}
|
|
7
|
-
const { data } = await apiClient.listProjectBranches(
|
|
7
|
+
const { data } = await apiClient.listProjectBranches({
|
|
8
|
+
projectId,
|
|
9
|
+
});
|
|
8
10
|
const branchData = data.branches.find((b) => b.name === branch);
|
|
9
11
|
if (!branchData) {
|
|
10
12
|
throw new Error(`Branch ${branch} not found.\nAvailable branches: ${data.branches
|
|
@@ -24,7 +26,9 @@ export const branchIdFromProps = async (props) => {
|
|
|
24
26
|
projectId: props.projectId,
|
|
25
27
|
});
|
|
26
28
|
}
|
|
27
|
-
const { data } = await props.apiClient.listProjectBranches(
|
|
29
|
+
const { data } = await props.apiClient.listProjectBranches({
|
|
30
|
+
projectId: props.projectId,
|
|
31
|
+
});
|
|
28
32
|
const defaultBranch = data.branches.find((b) => b.default);
|
|
29
33
|
if (defaultBranch) {
|
|
30
34
|
return defaultBranch.id;
|
|
@@ -47,3 +51,16 @@ export const fillSingleProject = async (props) => {
|
|
|
47
51
|
projectId: data.projects[0].id,
|
|
48
52
|
};
|
|
49
53
|
};
|
|
54
|
+
export const fillSingleOrg = async (props) => {
|
|
55
|
+
if (props.orgId) {
|
|
56
|
+
return props;
|
|
57
|
+
}
|
|
58
|
+
const { data } = await props.apiClient.getCurrentUserOrganizations();
|
|
59
|
+
if (data.organizations.length === 0) {
|
|
60
|
+
throw new Error('No organizations found');
|
|
61
|
+
}
|
|
62
|
+
if (data.organizations.length > 1) {
|
|
63
|
+
throw new Error(`Multiple organizations found, please provide one with the --org-id option`);
|
|
64
|
+
}
|
|
65
|
+
return { ...props, orgId: data.organizations[0].id };
|
|
66
|
+
};
|