Skip to content

Commit 6ccdeee

Browse files
feat(rofl): machine rental expiration check and tests
1 parent 1150e8d commit 6ccdeee

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

cmd/rofl/machine/expiry.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package machine
2+
3+
import "time"
4+
5+
func isMachineRentalExpired(paidUntil time.Time, now time.Time) bool {
6+
// Treat the rental as expired at the exact paid-until timestamp.
7+
return !now.Before(paidUntil)
8+
}

cmd/rofl/machine/expiry_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package machine
2+
3+
import (
4+
"testing"
5+
"time"
6+
)
7+
8+
func TestIsMachineRentalExpired(t *testing.T) {
9+
now := time.Date(2025, 1, 14, 12, 0, 0, 0, time.UTC)
10+
11+
for _, tc := range []struct {
12+
name string
13+
paidUntil time.Time
14+
want bool
15+
}{
16+
{
17+
name: "active",
18+
paidUntil: now.Add(time.Second),
19+
want: false,
20+
},
21+
{
22+
name: "boundary",
23+
paidUntil: now,
24+
want: true,
25+
},
26+
{
27+
name: "expired",
28+
paidUntil: now.Add(-time.Second),
29+
want: true,
30+
},
31+
} {
32+
tc := tc
33+
t.Run(tc.name, func(t *testing.T) {
34+
if got := isMachineRentalExpired(tc.paidUntil, now); got != tc.want {
35+
t.Fatalf("isMachineRentalExpired() = %v, want %v", got, tc.want)
36+
}
37+
})
38+
}
39+
}

cmd/rofl/machine/show.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/binary"
66
"fmt"
77
"net"
8+
"strings"
89
"time"
910

1011
"github.com/spf13/cobra"
@@ -59,7 +60,13 @@ var showCmd = &cobra.Command{
5960
}
6061

6162
insDsc, err := conn.Runtime(npa.ParaTime).ROFLMarket.Instance(ctx, client.RoundLatest, *providerAddr, machineID)
62-
cobra.CheckErr(err)
63+
if err != nil {
64+
// The "instance not found" error originates from Rust code, so we can't compare it nicely here.
65+
if strings.Contains(err.Error(), "instance not found") {
66+
cobra.CheckErr("Machine instance not found.\nTip: This often happens when instances expire. Run `oasis rofl deploy --replace-machine` to rent a new one.")
67+
}
68+
cobra.CheckErr(err)
69+
}
6370

6471
insCmds, err := conn.Runtime(npa.ParaTime).ROFLMarket.InstanceCommands(ctx, client.RoundLatest, *providerAddr, machineID)
6572
cobra.CheckErr(err)
@@ -80,11 +87,18 @@ var showCmd = &cobra.Command{
8087
default:
8188
}
8289

90+
paidUntil := time.Unix(int64(insDsc.PaidUntil), 0)
91+
expired := isMachineRentalExpired(paidUntil, time.Now())
92+
8393
fmt.Printf("Name: %s\n", machineName)
8494
fmt.Printf("Provider: %s\n", insDsc.Provider)
8595
fmt.Printf("ID: %s\n", insDsc.ID)
8696
fmt.Printf("Offer: %s\n", insDsc.Offer)
87-
fmt.Printf("Status: %s\n", insDsc.Status)
97+
fmt.Printf("Status: %s", insDsc.Status)
98+
if expired {
99+
fmt.Printf(" (EXPIRED)")
100+
}
101+
fmt.Println()
88102
fmt.Printf("Creator: %s\n", insDsc.Creator)
89103
fmt.Printf("Admin: %s\n", insDsc.Admin)
90104
switch insDsc.NodeID {
@@ -96,7 +110,7 @@ var showCmd = &cobra.Command{
96110

97111
fmt.Printf("Created at: %s\n", time.Unix(int64(insDsc.CreatedAt), 0))
98112
fmt.Printf("Updated at: %s\n", time.Unix(int64(insDsc.UpdatedAt), 0))
99-
fmt.Printf("Paid until: %s\n", time.Unix(int64(insDsc.PaidUntil), 0))
113+
fmt.Printf("Paid until: %s\n", paidUntil)
100114

101115
if schedulerDsc != nil {
102116
if proxyDomain, ok := schedulerDsc.Metadata[scheduler.MetadataKeyProxyDomain]; ok {

0 commit comments

Comments
 (0)