Skip to content

Commit 45dddba

Browse files
authored
Merge pull request #582 from oasisprotocol/kostko/feature/rofl-machine-change-admin
feat(cmd/rofl): Add machine change-admin subcommand
2 parents fa0535f + 04cff6d commit 45dddba

File tree

6 files changed

+139
-26
lines changed

6 files changed

+139
-26
lines changed

cmd/common/selector.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ type NPASelection struct {
4343
ParaTimeName string
4444
ParaTime *config.ParaTime
4545

46-
AccountName string
47-
Account *cliConfig.Account
46+
AccountName string
47+
Account *cliConfig.Account
48+
AccountSetExplicitly bool
4849
}
4950

5051
// GetNPASelection returns the user-selected network/ParaTime/account combination.
@@ -78,6 +79,7 @@ func GetNPASelection(cfg *cliConfig.Config) *NPASelection {
7879
s.AccountName = cfg.Wallet.Default
7980
if selectedAccount != "" {
8081
s.AccountName = selectedAccount
82+
s.AccountSetExplicitly = true
8183
}
8284
if s.AccountName != "" {
8385
accCfg, err := LoadAccountConfig(cfg, s.AccountName)

cmd/rofl/common/manifest.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package common
22

33
import (
44
"fmt"
5+
"regexp"
6+
"strings"
57

68
"github.com/spf13/cobra"
79

@@ -10,6 +12,14 @@ import (
1012
cliConfig "github.com/oasisprotocol/cli/config"
1113
)
1214

15+
var (
16+
// orcFilenameDisallowedChars is a regexp matching characters that are not allowed in filenames.
17+
orcFilenameDisallowedChars = regexp.MustCompile("[^a-zA-Z0-9-]")
18+
19+
// orcFilenameRepeatedChars is a regexp matching repeats of dash characters in filenames.
20+
orcFilenameRepeatedChars = regexp.MustCompile("(-){2,}")
21+
)
22+
1323
// ManifestOptions configures the manifest options.
1424
type ManifestOptions struct {
1525
// NeedAppID specifies whether a configured app ID is required in the manifest.
@@ -76,8 +86,11 @@ func MaybeLoadManifestAndSetNPA(cfg *cliConfig.Config, npa *common.NPASelection,
7686
}
7787
npa.ParaTimeName = d.ParaTime
7888
}
79-
switch d.Admin {
80-
case "":
89+
switch {
90+
case d.Admin == "":
91+
// No admin in manifest, leave unchanged.
92+
case npa.AccountSetExplicitly:
93+
// Account explicitly overridden on the command line, leave unchanged.
8194
default:
8295
accCfg, err := common.LoadAccountConfig(cfg, d.Admin)
8396
switch {
@@ -95,5 +108,9 @@ func MaybeLoadManifestAndSetNPA(cfg *cliConfig.Config, npa *common.NPASelection,
95108

96109
// GetOrcFilename generates a filename based on the project name and deployment.
97110
func GetOrcFilename(manifest *rofl.Manifest, deploymentName string) string {
98-
return fmt.Sprintf("%s.%s.orc", manifest.Name, deploymentName)
111+
normalizedName := strings.ToLower(manifest.Name)
112+
normalizedName = strings.TrimSpace(normalizedName)
113+
normalizedName = orcFilenameDisallowedChars.ReplaceAllString(normalizedName, "-")
114+
normalizedName = orcFilenameRepeatedChars.ReplaceAllString(normalizedName, "$1")
115+
return fmt.Sprintf("%s.%s.orc", normalizedName, deploymentName)
99116
}

cmd/rofl/common/manifest_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package common
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
8+
"github.com/oasisprotocol/cli/build/rofl"
9+
)
10+
11+
func TestGetOrcFilename(t *testing.T) {
12+
require := require.New(t)
13+
14+
for _, tc := range []struct {
15+
name string
16+
deployment string
17+
expected string
18+
}{
19+
{"rofl-scheduler", "mainnet", "rofl-scheduler.mainnet.orc"},
20+
{"ROFL Scheduler", "mainnet", "rofl-scheduler.mainnet.orc"},
21+
{" This is a test ", "mainnet", "this-is-a-test.mainnet.orc"},
22+
} {
23+
manifest := &rofl.Manifest{Name: tc.name}
24+
fn := GetOrcFilename(manifest, "mainnet")
25+
require.Equal(tc.expected, fn)
26+
}
27+
}

cmd/rofl/machine/machine.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func init() {
1515
Cmd.AddCommand(restartCmd)
1616
Cmd.AddCommand(stopCmd)
1717
Cmd.AddCommand(removeCmd)
18+
Cmd.AddCommand(changeAdminCmd)
1819
Cmd.AddCommand(topUpCmd)
1920
Cmd.AddCommand(logsCmd)
2021
}

cmd/rofl/machine/mgmt.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/spf13/cobra"
88

99
"github.com/oasisprotocol/oasis-core/go/common/cbor"
10+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"
1011
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
1112
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rofl"
1213
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/roflmarket"
@@ -110,6 +111,84 @@ var (
110111
},
111112
}
112113

114+
changeAdminCmd = &cobra.Command{
115+
Use: "change-admin [<machine-name>] <new-admin>",
116+
Short: "Change the machine administrator",
117+
Args: cobra.RangeArgs(1, 2),
118+
Run: func(_ *cobra.Command, args []string) {
119+
txCfg := common.GetTransactionConfig()
120+
121+
_, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{
122+
NeedAppID: true,
123+
NeedAdmin: false,
124+
})
125+
126+
var newAdminAddress string
127+
switch len(args) {
128+
case 1:
129+
// Just admin address.
130+
newAdminAddress = args[0]
131+
args = nil
132+
case 2:
133+
// Machine and admin address.
134+
newAdminAddress = args[1]
135+
args = args[:1]
136+
}
137+
138+
machine, machineName, machineID := resolveMachine(args, deployment)
139+
140+
// Resolve provider address.
141+
providerAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, machine.Provider)
142+
if err != nil {
143+
cobra.CheckErr(fmt.Sprintf("Invalid provider address: %s", err))
144+
}
145+
146+
// Resolve new admin address.
147+
newAdminAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, newAdminAddress)
148+
if err != nil {
149+
cobra.CheckErr(fmt.Sprintf("Invalid admin address: %s", err))
150+
}
151+
152+
// When not in offline mode, connect to the given network endpoint.
153+
ctx := context.Background()
154+
var conn connection.Connection
155+
if !txCfg.Offline {
156+
conn, err = connection.Connect(ctx, npa.Network)
157+
cobra.CheckErr(err)
158+
}
159+
160+
fmt.Printf("Provider: %s (%s)\n", machine.Provider, providerAddr)
161+
fmt.Printf("Machine: %s [%s]\n", machineName, machine.ID)
162+
163+
// Resolve old admin in online mode.
164+
if !txCfg.Offline {
165+
insDsc, err := conn.Runtime(npa.ParaTime).ROFLMarket.Instance(ctx, client.RoundLatest, *providerAddr, machineID)
166+
cobra.CheckErr(err)
167+
168+
fmt.Printf("Old admin: %s\n", insDsc.Admin)
169+
}
170+
171+
fmt.Printf("New admin: %s\n", newAdminAddr)
172+
173+
// Prepare transaction.
174+
tx := roflmarket.NewInstanceChangeAdmin(nil, &roflmarket.InstanceChangeAdmin{
175+
Provider: *providerAddr,
176+
ID: machineID,
177+
Admin: *newAdminAddr,
178+
})
179+
180+
acc := common.LoadAccount(cliConfig.Global(), npa.AccountName)
181+
sigTx, meta, err := common.SignParaTimeTransaction(ctx, npa, acc, conn, tx, nil)
182+
cobra.CheckErr(err)
183+
184+
if !common.BroadcastOrExportTransaction(ctx, npa, conn, sigTx, meta, nil) {
185+
return
186+
}
187+
188+
fmt.Printf("Machine admin address changed.\n")
189+
},
190+
}
191+
113192
topUpCmd = &cobra.Command{
114193
Use: "top-up [<machine-name>]",
115194
Short: "Top-up payment for a machine",
@@ -284,6 +363,10 @@ func init() {
284363
removeCmd.Flags().AddFlagSet(common.RuntimeTxFlags)
285364
removeCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
286365

366+
changeAdminCmd.Flags().AddFlagSet(common.AccountFlag)
367+
changeAdminCmd.Flags().AddFlagSet(common.RuntimeTxFlags)
368+
changeAdminCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
369+
287370
topUpCmd.Flags().AddFlagSet(common.SelectorFlags)
288371
topUpCmd.Flags().AddFlagSet(common.RuntimeTxFlags)
289372
topUpCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)

cmd/rofl/mgmt.go

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"sort"
1414

1515
"github.com/spf13/cobra"
16-
flag "github.com/spf13/pflag"
1716

1817
"github.com/oasisprotocol/oasis-core/go/common/sgx/pcs"
1918
"github.com/oasisprotocol/oasis-core/go/common/sgx/quote"
@@ -37,9 +36,8 @@ var (
3736
"cn": rofl.CreatorNonce,
3837
}
3938

40-
scheme string
41-
adminAddress string
42-
pubName string
39+
scheme string
40+
pubName string
4341

4442
appTEE string
4543
appKind string
@@ -302,9 +300,6 @@ var (
302300
NeedAdmin: true,
303301
})
304302

305-
if adminAddress == "" && deployment.Admin != "" {
306-
adminAddress = "self"
307-
}
308303
secrets := buildRofl.PrepareSecrets(deployment.Secrets)
309304

310305
var appID rofl.AppID
@@ -315,10 +310,6 @@ var (
315310
npa.MustHaveAccount()
316311
npa.MustHaveParaTime()
317312

318-
if adminAddress == "" {
319-
fmt.Println("You must specify --admin or configure an admin in the manifest.")
320-
return
321-
}
322313
if deployment.Policy == nil {
323314
fmt.Println("You must configure policy in the manifest.")
324315
return
@@ -341,11 +332,8 @@ var (
341332
}
342333

343334
// Update administrator address.
344-
if adminAddress == "self" {
345-
adminAddress = npa.AccountName
346-
}
347335
var err error
348-
updateBody.Admin, _, err = common.ResolveLocalAccountOrAddress(npa.Network, adminAddress)
336+
updateBody.Admin, _, err = common.ResolveLocalAccountOrAddress(npa.Network, deployment.Admin)
349337
if err != nil {
350338
cobra.CheckErr(fmt.Errorf("bad administrator address: %w", err))
351339
}
@@ -819,10 +807,6 @@ func detectOrCreateComposeFile() string {
819807
}
820808

821809
func init() {
822-
updateFlags := flag.NewFlagSet("", flag.ContinueOnError)
823-
updateFlags.StringVar(&adminAddress, "admin", "", "set the administrator address")
824-
updateCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
825-
826810
initCmd.Flags().StringVar(&appTEE, "tee", "tdx", "TEE kind [tdx, sgx]")
827811
initCmd.Flags().StringVar(&appKind, "kind", "container", "ROFL app kind [container, raw]")
828812

@@ -832,10 +816,9 @@ func init() {
832816
createCmd.Flags().AddFlagSet(roflCommon.NoUpdateFlag)
833817
createCmd.Flags().StringVar(&scheme, "scheme", "cn", "app ID generation scheme: creator+round+index [cri] or creator+nonce [cn]")
834818

835-
updateCmd.Flags().AddFlagSet(common.SelectorFlags)
819+
updateCmd.Flags().AddFlagSet(common.AccountFlag)
836820
updateCmd.Flags().AddFlagSet(common.RuntimeTxFlags)
837821
updateCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
838-
updateCmd.Flags().AddFlagSet(updateFlags)
839822

840823
removeCmd.Flags().AddFlagSet(common.SelectorFlags)
841824
removeCmd.Flags().AddFlagSet(common.RuntimeTxFlags)

0 commit comments

Comments
 (0)