1- import { defineCommand , detectOutputFormat , BailianError , ExitCode } from "bailian-cli-core" ;
1+ import {
2+ defineCommand ,
3+ detectOutputFormat ,
4+ BailianError ,
5+ ExitCode ,
6+ generateCLIAccessToken ,
7+ callConsoleGateway ,
8+ effectiveConsoleGatewayConfig ,
9+ createBailianControlUser ,
10+ listBailianControlWorkspaces ,
11+ resetBailianControlPolicies4Agent ,
12+ type ConsoleGatewayTarget ,
13+ type FlagsDef ,
14+ } from "bailian-cli-core" ;
215import { emitResult , emitBare } from "bailian-cli-runtime" ;
316
417const API = {
518 loginInfo : "zeldaEasy.cornerstone-portal.cs-console.loginInfo" ,
619 initSpace : "zeldaEasy.bailian-dash-workspace.space.initSpace" ,
7- createUser : "zeldaEasy.bailian-dash-workspace.account.createUser" ,
820 queryBuyResult : "zeldaEasy.bailian-commerce.bill.queryBuyPostpaidResult" ,
921 commodityOrderInfo : "zeldaEasy.bailian-commerce.bill.postpaidCommodityOrderInfo" ,
1022 buyCommodity : "zeldaEasy.bailian-commerce.bill.buyPostpaidCommodity" ,
1123} as const ;
1224
25+ const FLAGS = {
26+ accessKeyId : {
27+ type : "string" ,
28+ valueHint : "<id>" ,
29+ description : "Alibaba Cloud Access Key ID" ,
30+ } ,
31+ accessKeySecret : {
32+ type : "string" ,
33+ valueHint : "<secret>" ,
34+ description : "Alibaba Cloud Access Key Secret" ,
35+ } ,
36+ securityToken : {
37+ type : "string" ,
38+ valueHint : "<token>" ,
39+ description : "Alibaba Cloud STS Security Token (optional)" ,
40+ } ,
41+ } satisfies FlagsDef ;
42+
1343const POLL_INTERVAL_MS = 1000 ;
14- const MAX_POLL_ATTEMPTS = 120 ;
44+ const MAX_POLL_ATTEMPTS = 20 ;
1545
1646function sleep ( ms : number ) : Promise < void > {
1747 return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
@@ -21,25 +51,44 @@ function extractData(resp: any): any {
2151 return resp ?. data ?. DataV2 ?. data ?. data ;
2252}
2353
54+ /**
55+ * Resolve the agent id from a ListWorkspaces response. Workspaces live under
56+ * `data.data`; the agent id is the workspace's `tenantId`. Prefer the default
57+ * workspace (`defaultAgent`), else fall back to the first one.
58+ */
59+ function extractAgentId ( resp : any ) : number | undefined {
60+ const workspaces = resp ?. data ?. data ;
61+ if ( ! Array . isArray ( workspaces ) || workspaces . length === 0 ) return undefined ;
62+ const chosen = workspaces . find ( ( workspace ) => workspace ?. defaultAgent === true ) ?? workspaces [ 0 ] ;
63+ const tenantId = chosen ?. tenantId ;
64+ const agentId = typeof tenantId === "string" ? Number ( tenantId ) : tenantId ;
65+ return typeof agentId === "number" && Number . isFinite ( agentId ) ? agentId : undefined ;
66+ }
67+
2468interface CommodityItem {
2569 commodityCode ?: string ;
2670 status ?: number ;
2771}
2872
2973export default defineCommand ( {
3074 description : "Initialize Bailian workspace and activate postpaid services" ,
31- auth : "console " ,
32- usageArgs : "" ,
33- flags : { } ,
34- exampleArgs : [ ] ,
75+ auth : "none " ,
76+ usageArgs : "--access-key-id <id> --access-key-secret <secret> [--security-token <token>] " ,
77+ flags : FLAGS ,
78+ exampleArgs : [ "--access-key-id LTAIxxxxx --access-key-secret xxxxx" ] ,
3579 async run ( ctx ) {
36- const { settings } = ctx ;
80+ const { settings, flags } = ctx ;
3781 const format = detectOutputFormat ( settings . output ) ;
3882
3983 if ( settings . dryRun ) {
4084 emitResult (
4185 {
4286 apis : [
87+ {
88+ step : 0 ,
89+ api : "GenerateCLIAccessToken" ,
90+ description : "Generate CLI access token from AK/SK" ,
91+ } ,
4392 {
4493 step : 1 ,
4594 api : API . loginInfo ,
@@ -52,21 +101,31 @@ export default defineCommand({
52101 } ,
53102 {
54103 step : 3 ,
55- api : API . createUser ,
56- description : "Create console account user" ,
104+ api : "CreateUser" ,
105+ description : "Create console user via BailianControl OpenAPI (CreateUser) " ,
57106 } ,
58107 {
59108 step : 4 ,
109+ api : "ListWorkspaces" ,
110+ description : "List workspaces to resolve agentId" ,
111+ } ,
112+ {
113+ step : 5 ,
114+ api : "ResetPolicies4Agent" ,
115+ description : "Authorize user permissions" ,
116+ } ,
117+ {
118+ step : 6 ,
60119 api : API . queryBuyResult ,
61120 description : "Query postpaid order status" ,
62121 } ,
63122 {
64- step : 5 ,
123+ step : 7 ,
65124 api : API . commodityOrderInfo ,
66125 description : "Query commodity activation status" ,
67126 } ,
68127 {
69- step : 6 ,
128+ step : 8 ,
70129 api : API . buyCommodity ,
71130 description : "Activate postpaid commodities (if needed)" ,
72131 } ,
@@ -77,11 +136,42 @@ export default defineCommand({
77136 return ;
78137 }
79138
139+ const { accessKeyId, accessKeySecret } = flags ;
140+ if ( ! accessKeyId || ! accessKeySecret ) {
141+ throw new BailianError (
142+ "bootstrap requires --access-key-id and --access-key-secret." ,
143+ ExitCode . USAGE ,
144+ ) ;
145+ }
146+ const securityToken = flags . securityToken || undefined ;
147+
148+ // Step 0: Exchange AK/SK for a temporary CLI access token used by console calls.
149+ const tokenResp = await generateCLIAccessToken ( {
150+ identity : ctx . identity ,
151+ settings,
152+ baseUrl : ctx . client . baseUrl ,
153+ accessKeyId,
154+ accessKeySecret,
155+ securityToken,
156+ } ) ;
157+ const accessToken : string | undefined = tokenResp . cliAccessToken ;
158+ if ( ! accessToken ) {
159+ throw new BailianError ( "Failed to generate CLI access token from AK/SK." , ExitCode . GENERAL ) ;
160+ }
161+
162+ const gateway = effectiveConsoleGatewayConfig ( settings ) ;
163+ const target : ConsoleGatewayTarget = {
164+ region : gateway . consoleRegion ,
165+ site : gateway . consoleSite ,
166+ ...( gateway . consoleSwitchAgent != null ? { switchAgent : gateway . consoleSwitchAgent } : { } ) ,
167+ token : accessToken ,
168+ } ;
169+
80170 const verbose = settings . verbose ;
81171 const callApi = async ( api : string , data : Record < string , unknown > = { } ) => {
82172 if ( verbose ) process . stderr . write ( `> ${ api } \n` ) ;
83173 try {
84- const resp = await ctx . client . console < any > ( api , data ) ;
174+ const resp = await callConsoleGateway ( target , settings . timeout , { api, data } , settings ) ;
85175 if ( verbose ) process . stderr . write ( `< ${ JSON . stringify ( resp ) } \n` ) ;
86176 return resp ;
87177 } catch ( err ) {
@@ -109,20 +199,60 @@ export default defineCommand({
109199 emitBare ( "Workspace already initialized." ) ;
110200 }
111201
112- // Step 3: Create console user
202+ // Step 3: Create console user via BailianControl OpenAPI (AK/SK signed)
113203 const uid = loginData ?. aliyun ?. uid ;
114204 if ( typeof uid !== "string" || uid . length === 0 ) {
115205 throw new BailianError ( "Console login info did not include aliyun.uid." , ExitCode . GENERAL ) ;
116206 }
117- await callApi ( API . createUser , {
118- reqDTO : {
119- outerKey : uid ,
120- nickName : uid ,
121- userName : uid ,
122- } ,
207+ const bailianControlAuth = {
208+ identity : ctx . identity ,
209+ settings,
210+ baseUrl : ctx . client . baseUrl ,
211+ regionId : gateway . consoleRegion ,
212+ accessKeyId,
213+ accessKeySecret,
214+ securityToken,
215+ } ;
216+
217+ try {
218+ await createBailianControlUser ( {
219+ ...bailianControlAuth ,
220+ reqDTO : {
221+ outerKey : uid ,
222+ nickName : uid ,
223+ userName : uid ,
224+ } ,
225+ } ) ;
226+ } catch ( err ) {
227+ // Re-running bootstrap is idempotent: an already-existing user is not
228+ // fatal, so swallow it and continue with the remaining steps.
229+ if ( ! ( err instanceof BailianError ) || ! / a l r e a d y e x i s t s / i. test ( err . message ) ) {
230+ throw err ;
231+ }
232+ emitBare ( "Console user already exists, continuing." ) ;
233+ }
234+
235+ // Step 4-5: Resolve the workspace agent id, then authorize user permissions.
236+ emitBare ( "Resolving workspace agent..." ) ;
237+ const workspacesResp = await listBailianControlWorkspaces ( bailianControlAuth ) ;
238+ const agentId = extractAgentId ( workspacesResp ) ;
239+ if ( agentId == null ) {
240+ throw new BailianError (
241+ "Could not resolve agentId from ListWorkspaces response." ,
242+ ExitCode . GENERAL ,
243+ "Re-run with --verbose to inspect the ListWorkspaces response body." ,
244+ ) ;
245+ }
246+
247+ emitBare ( "Authorizing user permissions..." ) ;
248+ await resetBailianControlPolicies4Agent ( {
249+ ...bailianControlAuth ,
250+ outerKey : uid ,
251+ agentId,
252+ policyIndexList : [ 1 ] ,
123253 } ) ;
124254
125- // Step 4-6 : Order & commodity flow
255+ // Step 6-8 : Order & commodity flow
126256 await ensureCommoditiesActive ( callApi , format ) ;
127257 } ,
128258} ) ;
0 commit comments