sealos-cli 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/LICENSE +191 -0
- package/README.md +234 -0
- package/dist/bin/cli.cjs +2066 -0
- package/dist/bin/cli.d.cts +1 -0
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.mjs +2044 -0
- package/dist/main.cjs +2079 -0
- package/dist/main.d.cts +7 -0
- package/dist/main.d.ts +7 -0
- package/dist/main.mjs +2045 -0
- package/package.json +112 -0
- package/src/bin/cli.ts +4 -0
- package/src/commands/app/index.ts +22 -0
- package/src/commands/auth/index.ts +124 -0
- package/src/commands/auth/login.ts +35 -0
- package/src/commands/auth/logout.ts +23 -0
- package/src/commands/auth/whoami.ts +38 -0
- package/src/commands/config/index.ts +54 -0
- package/src/commands/database/index.ts +881 -0
- package/src/commands/devbox/index.ts +224 -0
- package/src/commands/quota/index.ts +22 -0
- package/src/commands/s3/index.ts +35 -0
- package/src/commands/template/index.ts +314 -0
- package/src/commands/workspace/index.ts +84 -0
- package/src/docs/database_openapi.json +8297 -0
- package/src/docs/template_openapi.json +1 -0
- package/src/generated/database.ts +3969 -0
- package/src/generated/template.ts +1007 -0
- package/src/lib/api-client.ts +64 -0
- package/src/lib/api.ts +83 -0
- package/src/lib/auth.ts +570 -0
- package/src/lib/config.ts +134 -0
- package/src/lib/constants.ts +1 -0
- package/src/lib/errors.ts +105 -0
- package/src/lib/oauth.ts +197 -0
- package/src/lib/output.ts +93 -0
- package/src/lib/with-auth.ts +56 -0
- package/src/main.ts +51 -0
- package/src/types/index.ts +56 -0
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sealos-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official CLI tool for Sealos Cloud - Manage devbox, applications, databases, and object storage",
|
|
5
|
+
"types": "dist/main.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"sealos-cli": "dist/bin/cli.cjs"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/main.d.ts",
|
|
14
|
+
"default": "./dist/main.mjs"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/main.d.cts",
|
|
18
|
+
"default": "./dist/main.cjs"
|
|
19
|
+
},
|
|
20
|
+
"default": "./dist/main.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./dist/*": {
|
|
23
|
+
"types": "./dist/*.d.ts",
|
|
24
|
+
"import": "./dist/*.mjs",
|
|
25
|
+
"require": "./dist/*.cjs"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22.0.0"
|
|
30
|
+
},
|
|
31
|
+
"packageManager": "npm@8.4.0",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"src",
|
|
35
|
+
"bin"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"start": "node --import tsx src/bin/cli.ts",
|
|
39
|
+
"generate:api": "openapi-typescript src/docs/template_openapi.json -o src/generated/template.ts && openapi-typescript src/docs/database_openapi.json -o src/generated/database.ts",
|
|
40
|
+
"build": "npm run generate:api && tsc && tsup",
|
|
41
|
+
"lint": "eslint . && npm run lint:lockfile && npm run lint:markdown",
|
|
42
|
+
"lint:markdown": "npx -y markdownlint-cli@0.45.0 -c .github/.markdownlint.yml -i '.git' -i '__tests__' -i '.github' -i '.changeset' -i 'CODE_OF_CONDUCT.md' -i 'CHANGELOG.md' -i 'docs/**' -i 'node_modules' -i 'dist' '**/**.md' --fix",
|
|
43
|
+
"lint:fix": "eslint . --fix",
|
|
44
|
+
"lint:lockfile": "lockfile-lint --path package-lock.json --validate-https --allowed-hosts npm yarn",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"test:coverage": "vitest run --coverage",
|
|
48
|
+
"coverage:view": "open coverage/lcov-report/index.html",
|
|
49
|
+
"version": "changeset version",
|
|
50
|
+
"release": "changeset publish"
|
|
51
|
+
},
|
|
52
|
+
"author": {
|
|
53
|
+
"name": "zjy365",
|
|
54
|
+
"email": "3161362058@qq.com",
|
|
55
|
+
"url": "https://github.com/zjy365"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"provenance": true,
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"license": "Apache-2.0",
|
|
62
|
+
"keywords": [
|
|
63
|
+
"sealos",
|
|
64
|
+
"cli",
|
|
65
|
+
"cloud",
|
|
66
|
+
"devbox",
|
|
67
|
+
"s3",
|
|
68
|
+
"database",
|
|
69
|
+
"kubernetes",
|
|
70
|
+
"deployment"
|
|
71
|
+
],
|
|
72
|
+
"homepage": "https://github.com/zjy365/sealos-cli.git",
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/zjy365/sealos-cli.git/issues"
|
|
75
|
+
},
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "git+https://github.com/zjy365/sealos-cli.git"
|
|
79
|
+
},
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"axios": "^1.15.0",
|
|
82
|
+
"chalk": "^5.2.0",
|
|
83
|
+
"commander": "^14.0.3",
|
|
84
|
+
"openapi-fetch": "^0.17.0",
|
|
85
|
+
"ora": "^9.3.0",
|
|
86
|
+
"table": "^6.8.1"
|
|
87
|
+
},
|
|
88
|
+
"devDependencies": {
|
|
89
|
+
"@changesets/changelog-github": "^0.5.0",
|
|
90
|
+
"@changesets/cli": "^2.27.7",
|
|
91
|
+
"@types/node": "^20.14.10",
|
|
92
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
93
|
+
"eslint": "^9.6.0",
|
|
94
|
+
"eslint-plugin-security": "^3.0.1",
|
|
95
|
+
"husky": "^9.0.11",
|
|
96
|
+
"lint-staged": "^15.2.7",
|
|
97
|
+
"lockfile-lint": "^4.14.0",
|
|
98
|
+
"neostandard": "^0.11.0",
|
|
99
|
+
"openapi-typescript": "^7.13.0",
|
|
100
|
+
"ts-node": "^10.9.2",
|
|
101
|
+
"tsup": "^8.1.0",
|
|
102
|
+
"tsx": "^4.19.4",
|
|
103
|
+
"typescript": "^5.5.3",
|
|
104
|
+
"validate-conventional-commit": "^1.0.4",
|
|
105
|
+
"vitest": "^4.1.6"
|
|
106
|
+
},
|
|
107
|
+
"lint-staged": {
|
|
108
|
+
"**/*.{js,json}": [
|
|
109
|
+
"npm run lint:fix"
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/bin/cli.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { handleError } from '../../lib/errors.ts'
|
|
3
|
+
|
|
4
|
+
export function createAppCommand (): Command {
|
|
5
|
+
const appCmd = new Command('app')
|
|
6
|
+
.description('Manage applications')
|
|
7
|
+
|
|
8
|
+
// TODO: 实现应用相关命令
|
|
9
|
+
|
|
10
|
+
appCmd
|
|
11
|
+
.command('list')
|
|
12
|
+
.description('List all applications')
|
|
13
|
+
.action(async () => {
|
|
14
|
+
try {
|
|
15
|
+
console.log('TODO: Implement app list')
|
|
16
|
+
} catch (error) {
|
|
17
|
+
handleError(error)
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
return appCmd
|
|
22
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { createLoginCommand } from './login.ts'
|
|
3
|
+
import { createLogoutCommand } from './logout.ts'
|
|
4
|
+
import { createWhoamiCommand } from './whoami.ts'
|
|
5
|
+
import { checkAuth, getAuthInfo, listWorkspaces, switchWorkspace } from '../../lib/auth.ts'
|
|
6
|
+
import { handleError, AuthError } from '../../lib/errors.ts'
|
|
7
|
+
import { outputJson, outputTable, success } from '../../lib/output.ts'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Register all authentication related commands
|
|
11
|
+
*/
|
|
12
|
+
export function registerAuthCommands (program: Command): void {
|
|
13
|
+
program.addCommand(createLoginCommand())
|
|
14
|
+
program.addCommand(createLogoutCommand())
|
|
15
|
+
program.addCommand(createWhoamiCommand())
|
|
16
|
+
program.addCommand(createAuthCommand())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createAuthCommand (): Command {
|
|
20
|
+
const authCmd = new Command('auth')
|
|
21
|
+
.description('Manage Sealos authentication')
|
|
22
|
+
|
|
23
|
+
authCmd
|
|
24
|
+
.command('check')
|
|
25
|
+
.description('Check authentication status')
|
|
26
|
+
.option('-o, --output <format>', 'Output format: json, table', 'json')
|
|
27
|
+
.action(async (options) => {
|
|
28
|
+
try {
|
|
29
|
+
const status = checkAuth()
|
|
30
|
+
if (options.output === 'table') {
|
|
31
|
+
outputTable([
|
|
32
|
+
['Field', 'Value'],
|
|
33
|
+
['Authenticated', String(status.authenticated)],
|
|
34
|
+
['Region', status.region || 'unknown'],
|
|
35
|
+
['Workspace', status.workspace || 'unknown'],
|
|
36
|
+
['Kubeconfig', status.kubeconfig_path || 'unknown']
|
|
37
|
+
])
|
|
38
|
+
} else {
|
|
39
|
+
outputJson(status)
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
handleError(error)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
authCmd
|
|
47
|
+
.command('info')
|
|
48
|
+
.description('Show current auth details')
|
|
49
|
+
.option('-o, --output <format>', 'Output format: json, table', 'json')
|
|
50
|
+
.action(async (options) => {
|
|
51
|
+
try {
|
|
52
|
+
const info = getAuthInfo()
|
|
53
|
+
if (!info.authenticated) {
|
|
54
|
+
throw new AuthError()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (options.output === 'table') {
|
|
58
|
+
outputTable([
|
|
59
|
+
['Field', 'Value'],
|
|
60
|
+
['Authenticated', String(info.authenticated)],
|
|
61
|
+
['Region', info.region || 'unknown'],
|
|
62
|
+
['Auth Method', info.auth_method || 'unknown'],
|
|
63
|
+
['Workspace', info.current_workspace?.id || info.workspace || 'unknown'],
|
|
64
|
+
['Team', info.current_workspace?.teamName || 'unknown'],
|
|
65
|
+
['Kubeconfig', info.kubeconfig_path || 'unknown'],
|
|
66
|
+
['Authenticated At', info.authenticated_at || 'unknown']
|
|
67
|
+
])
|
|
68
|
+
} else {
|
|
69
|
+
outputJson(info)
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
handleError(error)
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
authCmd
|
|
77
|
+
.command('list')
|
|
78
|
+
.description('List all workspaces')
|
|
79
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
80
|
+
.action(async (options) => {
|
|
81
|
+
try {
|
|
82
|
+
const result = await listWorkspaces()
|
|
83
|
+
if (options.output === 'json') {
|
|
84
|
+
outputJson(result)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
outputTable([
|
|
89
|
+
['UID', 'ID', 'TEAM', 'ROLE', 'TYPE', 'CURRENT'],
|
|
90
|
+
...result.workspaces.map(workspace => [
|
|
91
|
+
workspace.uid || '',
|
|
92
|
+
workspace.id || '',
|
|
93
|
+
workspace.teamName || '',
|
|
94
|
+
workspace.role || '',
|
|
95
|
+
workspace.nstype || '',
|
|
96
|
+
workspace.id === result.current ? '*' : ''
|
|
97
|
+
])
|
|
98
|
+
])
|
|
99
|
+
} catch (error) {
|
|
100
|
+
handleError(error)
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
authCmd
|
|
105
|
+
.command('switch')
|
|
106
|
+
.description('Switch workspace')
|
|
107
|
+
.argument('<namespace>', 'Workspace id, uid, or team name')
|
|
108
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
109
|
+
.action(async (namespace, options) => {
|
|
110
|
+
try {
|
|
111
|
+
const result = await switchWorkspace(namespace)
|
|
112
|
+
if (options.output === 'json') {
|
|
113
|
+
outputJson(result)
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
success(`Switched to workspace: ${result.workspace.id || result.workspace.uid || namespace}`)
|
|
118
|
+
} catch (error) {
|
|
119
|
+
handleError(error)
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return authCmd
|
|
124
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { loginWithDeviceFlow, loginWithToken } from '../../lib/auth.ts'
|
|
3
|
+
import { info, outputJson, success, warn } from '../../lib/output.ts'
|
|
4
|
+
import { handleError } from '../../lib/errors.ts'
|
|
5
|
+
|
|
6
|
+
export function createLoginCommand (): Command {
|
|
7
|
+
return new Command('login')
|
|
8
|
+
.description('Login to Sealos Cloud')
|
|
9
|
+
.argument('[region]', 'Sealos region URL (e.g., https://usw-1.sealos.io)')
|
|
10
|
+
.option('-t, --token <token>', 'Store a regional token without OAuth device login')
|
|
11
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
12
|
+
.action(async (region, options) => {
|
|
13
|
+
try {
|
|
14
|
+
const result = options.token
|
|
15
|
+
? await loginWithToken(region, options.token)
|
|
16
|
+
: await loginWithDeviceFlow(region)
|
|
17
|
+
|
|
18
|
+
if (options.token) {
|
|
19
|
+
warn('Token login is limited: kubeconfig is not generated. Use device login for full auth.')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (options.output === 'json') {
|
|
23
|
+
outputJson(result)
|
|
24
|
+
} else {
|
|
25
|
+
success(`Logged in to ${result.region}`)
|
|
26
|
+
info(`Workspace: ${result.workspace}`)
|
|
27
|
+
if (result.kubeconfig_path) {
|
|
28
|
+
info(`Kubeconfig: ${result.kubeconfig_path}`)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} catch (error) {
|
|
32
|
+
handleError(error)
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { checkAuth, clearAuth } from '../../lib/auth.ts'
|
|
3
|
+
import { success, warn } from '../../lib/output.ts'
|
|
4
|
+
import { handleError } from '../../lib/errors.ts'
|
|
5
|
+
|
|
6
|
+
export function createLogoutCommand (): Command {
|
|
7
|
+
return new Command('logout')
|
|
8
|
+
.description('Logout from Sealos Cloud')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
try {
|
|
11
|
+
const status = checkAuth()
|
|
12
|
+
if (!status.authenticated) {
|
|
13
|
+
warn('You are not logged in')
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
clearAuth()
|
|
18
|
+
success('Logged out from Sealos Cloud')
|
|
19
|
+
} catch (error) {
|
|
20
|
+
handleError(error)
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { getAuthInfo } from '../../lib/auth.ts'
|
|
3
|
+
import { outputJson, outputTable } from '../../lib/output.ts'
|
|
4
|
+
import { handleError, AuthError } from '../../lib/errors.ts'
|
|
5
|
+
|
|
6
|
+
export function createWhoamiCommand (): Command {
|
|
7
|
+
return new Command('whoami')
|
|
8
|
+
.description('Display current user information')
|
|
9
|
+
.option('-o, --output <format>', 'Output format: json, table', 'table')
|
|
10
|
+
.action(async (options) => {
|
|
11
|
+
try {
|
|
12
|
+
const authInfo = getAuthInfo()
|
|
13
|
+
if (!authInfo.authenticated) {
|
|
14
|
+
throw new AuthError()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (options.output === 'json') {
|
|
18
|
+
outputJson(authInfo)
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const data = [
|
|
23
|
+
['Field', 'Value'],
|
|
24
|
+
['Authenticated', 'true'],
|
|
25
|
+
['Region', authInfo.region || 'unknown'],
|
|
26
|
+
['Auth Method', authInfo.auth_method || 'unknown'],
|
|
27
|
+
['Workspace', authInfo.current_workspace?.id || authInfo.workspace || 'unknown'],
|
|
28
|
+
['Team', authInfo.current_workspace?.teamName || 'unknown'],
|
|
29
|
+
['Kubeconfig', authInfo.kubeconfig_path || 'unknown'],
|
|
30
|
+
['Authenticated At', authInfo.authenticated_at || 'unknown']
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
outputTable(data)
|
|
34
|
+
} catch (error) {
|
|
35
|
+
handleError(error)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } from 'commander'
|
|
2
|
+
import { readConfig, setConfigValue, getConfigValue } from '../../lib/config.ts'
|
|
3
|
+
import { success, outputJson } from '../../lib/output.ts'
|
|
4
|
+
import { handleError } from '../../lib/errors.ts'
|
|
5
|
+
|
|
6
|
+
export function createConfigCommand (): Command {
|
|
7
|
+
const configCmd = new Command('config')
|
|
8
|
+
.description('Manage CLI configuration')
|
|
9
|
+
|
|
10
|
+
configCmd
|
|
11
|
+
.command('set')
|
|
12
|
+
.description('Set a config value')
|
|
13
|
+
.argument('<key>', 'Config key')
|
|
14
|
+
.argument('<value>', 'Config value')
|
|
15
|
+
.action(async (key, value) => {
|
|
16
|
+
try {
|
|
17
|
+
setConfigValue(key, value)
|
|
18
|
+
success(`Config ${key} set to ${value}`)
|
|
19
|
+
} catch (error) {
|
|
20
|
+
handleError(error)
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
configCmd
|
|
25
|
+
.command('get')
|
|
26
|
+
.description('Get a config value')
|
|
27
|
+
.argument('<key>', 'Config key')
|
|
28
|
+
.action(async (key) => {
|
|
29
|
+
try {
|
|
30
|
+
const value = getConfigValue(key)
|
|
31
|
+
if (value) {
|
|
32
|
+
console.log(value)
|
|
33
|
+
} else {
|
|
34
|
+
console.log(`Config key "${key}" not found`)
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
handleError(error)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
configCmd
|
|
42
|
+
.command('list')
|
|
43
|
+
.description('List all config values')
|
|
44
|
+
.action(async () => {
|
|
45
|
+
try {
|
|
46
|
+
const config = readConfig()
|
|
47
|
+
outputJson(config)
|
|
48
|
+
} catch (error) {
|
|
49
|
+
handleError(error)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
return configCmd
|
|
54
|
+
}
|