Skip to content

Commit 39b358f

Browse files
fix: support direct rofl set-admin
1 parent e663fe8 commit 39b358f

File tree

6 files changed

+104
-55
lines changed

6 files changed

+104
-55
lines changed

cmd/rofl/set_admin.go

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66

77
"github.com/spf13/cobra"
88

9+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"
910
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
1011
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rofl"
12+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"
1113

1214
buildRofl "github.com/oasisprotocol/cli/build/rofl"
1315
"github.com/oasisprotocol/cli/cmd/common"
@@ -16,45 +18,49 @@ import (
1618
)
1719

1820
var setAdminCmd = &cobra.Command{
19-
Use: "set-admin <new-admin>",
20-
Short: "Change the administrator of the application in ROFL",
21+
Use: "set-admin [<app-id>] <new-admin>",
22+
Short: "Change the administrator of a ROFL",
2123
Aliases: []string{"change-admin"},
22-
Args: cobra.ExactArgs(1),
24+
Args: cobra.RangeArgs(1, 2),
2325
Run: func(_ *cobra.Command, args []string) {
26+
cfg := cliConfig.Global()
27+
npa := common.GetNPASelection(cfg)
2428
txCfg := common.GetTransactionConfig()
2529

26-
manifest, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{
27-
NeedAppID: true,
28-
NeedAdmin: true,
29-
})
30+
var (
31+
rawAppID string
32+
newAdminArg string
33+
manifest *buildRofl.Manifest
34+
deployment *buildRofl.Deployment
35+
)
36+
switch len(args) {
37+
case 2:
38+
// Direct mode: oasis rofl set-admin <app-id> <new-admin>
39+
rawAppID = args[0]
40+
newAdminArg = args[1]
41+
case 1:
42+
// Manifest mode: oasis rofl set-admin <new-admin>
43+
newAdminArg = args[0]
44+
manifest, deployment, npa = roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{
45+
NeedAppID: true,
46+
NeedAdmin: true,
47+
})
48+
rawAppID = deployment.AppID
49+
}
3050

3151
var appID rofl.AppID
32-
if err := appID.UnmarshalText([]byte(deployment.AppID)); err != nil {
52+
if err := appID.UnmarshalText([]byte(rawAppID)); err != nil {
3353
cobra.CheckErr(fmt.Errorf("malformed ROFL app ID: %w", err))
3454
}
3555

3656
npa.MustHaveAccount()
3757
npa.MustHaveParaTime()
3858

39-
if deployment.Policy == nil {
40-
cobra.CheckErr("no policy configured in the manifest")
41-
}
42-
43-
oldAdminAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, deployment.Admin)
44-
if err != nil {
45-
cobra.CheckErr(fmt.Errorf("bad current administrator address: %w", err))
46-
}
47-
48-
newAdminAddr, newAdminEthAddr, err := common.ResolveLocalAccountOrAddress(npa.Network, args[0])
59+
newAdminAddr, newAdminEthAddr, err := common.ResolveLocalAccountOrAddress(npa.Network, newAdminArg)
4960
if err != nil {
5061
cobra.CheckErr(fmt.Errorf("invalid new admin address: %w", err))
5162
}
5263

53-
if *oldAdminAddr == *newAdminAddr {
54-
fmt.Println("New admin is the same as the current admin, nothing to do.")
55-
return
56-
}
57-
5864
// When not in offline mode, connect to the given network endpoint.
5965
ctx := context.Background()
6066
var conn connection.Connection
@@ -63,45 +69,82 @@ var setAdminCmd = &cobra.Command{
6369
cobra.CheckErr(err)
6470
}
6571

72+
fmt.Printf("App ID: %s\n", appID)
73+
74+
updateBody := rofl.Update{
75+
ID: appID,
76+
Admin: newAdminAddr,
77+
}
78+
79+
var oldAdminAddr *types.Address
80+
if manifest != nil {
81+
// Manifest mode: use local policy, metadata, secrets.
82+
if deployment.Policy == nil {
83+
cobra.CheckErr("no policy configured in the manifest")
84+
}
85+
86+
oldAdminAddr, _, err = common.ResolveLocalAccountOrAddress(npa.Network, deployment.Admin)
87+
if err != nil {
88+
cobra.CheckErr(fmt.Errorf("bad current administrator address: %w", err))
89+
}
90+
91+
updateBody.Policy = *deployment.Policy.AsDescriptor()
92+
updateBody.Metadata = manifest.GetMetadata(roflCommon.DeploymentName)
93+
updateBody.Secrets = buildRofl.PrepareSecrets(deployment.Secrets)
94+
} else {
95+
// Direct mode: reuse current policy, metadata, secrets from chain.
96+
if txCfg.Offline {
97+
cobra.CheckErr("direct mode requires network access")
98+
}
99+
100+
appCfg, err := conn.Runtime(npa.ParaTime).ROFL.App(ctx, client.RoundLatest, appID)
101+
cobra.CheckErr(err)
102+
103+
oldAdminAddr = appCfg.Admin
104+
updateBody.Policy = appCfg.Policy
105+
updateBody.Metadata = appCfg.Metadata
106+
updateBody.Secrets = appCfg.Secrets
107+
}
108+
109+
if oldAdminAddr != nil {
110+
if *oldAdminAddr == *newAdminAddr {
111+
fmt.Println("New admin is the same as the current admin, nothing to do.")
112+
return
113+
}
114+
fmt.Printf("Old admin: %s\n", common.PrettyAddress(oldAdminAddr.String()))
115+
}
116+
66117
newAdminStr := newAdminAddr.String()
67118
if newAdminEthAddr != nil {
68119
newAdminStr = newAdminEthAddr.Hex()
69120
}
70121

71-
fmt.Printf("App ID: %s\n", deployment.AppID)
72-
fmt.Printf("Old admin: %s\n", common.PrettyAddress(oldAdminAddr.String()))
73122
fmt.Printf("New admin: %s\n", common.PrettyAddress(newAdminStr))
74123

75-
secrets := buildRofl.PrepareSecrets(deployment.Secrets)
76-
77-
tx := rofl.NewUpdateTx(nil, &rofl.Update{
78-
ID: appID,
79-
Policy: *deployment.Policy.AsDescriptor(),
80-
Admin: newAdminAddr,
81-
Metadata: manifest.GetMetadata(roflCommon.DeploymentName),
82-
Secrets: secrets,
83-
})
124+
tx := rofl.NewUpdateTx(nil, &updateBody)
84125

85-
acc := common.LoadAccount(cliConfig.Global(), npa.AccountName)
126+
acc := common.LoadAccount(cfg, npa.AccountName)
86127
sigTx, meta, err := common.SignParaTimeTransaction(ctx, npa, acc, conn, tx, nil)
87128
cobra.CheckErr(err)
88129

89130
if !common.BroadcastOrExportTransaction(ctx, npa, conn, sigTx, meta, nil) {
90131
return
91132
}
92133

93-
// Transaction succeeded — update the manifest with the new admin.
94-
deployment.Admin = args[0]
95-
if err = manifest.Save(); err != nil {
96-
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
134+
// Transaction succeeded — update the manifest if available.
135+
if manifest != nil {
136+
deployment.Admin = newAdminArg
137+
if err = manifest.Save(); err != nil {
138+
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
139+
}
97140
}
98141

99142
fmt.Printf("ROFL admin changed to %s.\n", common.PrettyAddress(newAdminStr))
100143
},
101144
}
102145

103146
func init() {
104-
common.AddAccountFlag(setAdminCmd)
147+
common.AddSelectorFlags(setAdminCmd)
105148
setAdminCmd.Flags().AddFlagSet(common.RuntimeTxFlags)
106149
setAdminCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
107150
}

docs/rofl.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -328,29 +328,33 @@ their latest versions. This includes:
328328
### Change ROFL app administrator {#set-admin}
329329

330330
Run `rofl set-admin` to transfer ownership of a ROFL app to a new
331-
administrator. The transaction is signed by the current admin and, on success,
332-
the manifest is updated with the new admin.
331+
administrator. The ROFL app administrator owns the application, including
332+
upgrades, policy changes and removal. The transaction must be signed by the
333+
current admin.
334+
335+
If the current directory contains a ROFL manifest, the manifest is updated with
336+
the new admin after a successful transaction.
333337

334338
![code shell](../examples/rofl/set-admin.in.static)
335339

336-
### Change ROFL machine administrator {#machine-set-admin}
340+
To change the administrator directly on an existing app without a local
341+
manifest, run:
337342

338-
Run `rofl machine set-admin` to change the administrator of an individual
339-
machine instance.
343+
![code shell](../examples/rofl/set-admin-address.in.static)
340344

341-
![code shell](../examples/rofl/machine-set-admin.in.static)
345+
This mode requires network access and does not modify the manifest.
342346

343-
:::info ROFL admin vs machine admin
347+
### Change ROFL machine administrator {#machine-set-admin}
344348

345-
The **ROFL admin** (changed via `oasis rofl set-admin`) owns the
346-
application — transfer ownership, upgrades, policy changes, removal.
349+
Run `rofl machine set-admin` to change the administrator of an individual
350+
machine instance. This is independent of the ROFL app administrator and only
351+
affects management of the specific machine instance.
347352

348-
The **machine admin** (changed via `oasis rofl machine set-admin`) manages
349-
an individual machine instance — execution, restarts, stops.
353+
![code shell](../examples/rofl/machine-set-admin.in.static)
350354

351-
These are independent roles.
355+
To change the administrator of the machine without a local manifest, run:
352356

353-
:::
357+
![code shell](../examples/rofl/machine-set-admin-address.in.static)
354358

355359
### Remove ROFL app from the network {#remove}
356360

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
oasis rofl machine set-admin oasis1qp2ens0hsp7gh23wajxa4hpetkdek3swyyulyrmz:000000000000055c bob
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
oasis rofl machine set-admin [<machine-name> | <provider-address>:<machine-id>] <new-admin>
1+
oasis rofl machine set-admin bob
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
oasis rofl set-admin rofl1qpw7gxp7dqq72sdtpv4jrmdfys9nsp73wysglhue bob

examples/rofl/set-admin.in.static

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
oasis rofl set-admin <new-admin>
1+
oasis rofl set-admin bob

0 commit comments

Comments
 (0)