Skip to content

Commit 2578b28

Browse files
Merge pull request #1181 from planetscale/token-ttl
Add --ttl flag to service token create
2 parents 9400043 + 7a3bee2 commit 2578b28

File tree

6 files changed

+131
-3
lines changed

6 files changed

+131
-3
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ require (
2525
github.com/mattn/go-shellwords v1.0.12
2626
github.com/mitchellh/go-homedir v1.1.0
2727
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
28-
github.com/planetscale/planetscale-go v0.147.0
28+
github.com/planetscale/planetscale-go v0.148.0
2929
github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4
3030
github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7
3131
github.com/spf13/cobra v1.10.2

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL
182182
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
183183
github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e h1:MZ8D+Z3m2vvqGZLvoQfpaGg/j1fNDr4j03s3PRz4rVY=
184184
github.com/planetscale/noglog v0.2.1-0.20210421230640-bea75fcd2e8e/go.mod h1:hwAsSPQdvPa3WcfKfzTXxtEq/HlqwLjQasfO6QbGo4Q=
185-
github.com/planetscale/planetscale-go v0.147.0 h1:dof3HNIlEhJPN+gAM7BJlUCiuhVsf8mX2wlGtjVbp6U=
186-
github.com/planetscale/planetscale-go v0.147.0/go.mod h1:PheYDHAwF14wfCBak1M0J64AdPW8NUeyvgPgWqe7zpI=
185+
github.com/planetscale/planetscale-go v0.148.0 h1:9tMRq4btsuOe5s/QCx6DNKDwKnGVEZYu++RX0rOaC6g=
186+
github.com/planetscale/planetscale-go v0.148.0/go.mod h1:PheYDHAwF14wfCBak1M0J64AdPW8NUeyvgPgWqe7zpI=
187187
github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4 h1:Xv5pj20Rhfty1Tv0OVcidg4ez4PvGrpKvb6rvUwQgDs=
188188
github.com/planetscale/psdb v0.0.0-20250717190954-65c6661ab6e4/go.mod h1:M52h5IWxAcbdQ1hSZrLAGQC4ZXslxEsK/Wh9nu3wdWs=
189189
github.com/planetscale/psdbproxy v0.0.0-20250728082226-3f4ea3a74ec7 h1:aRd6vdE1fyuSI4RVj7oCr8lFmgqXvpnPUmN85VbZCp8=

internal/cmd/token/create.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
func CreateCmd(ch *cmdutil.Helper) *cobra.Command {
1313
var name string
14+
var ttl int
1415

1516
cmd := &cobra.Command{
1617
Use: "create",
@@ -25,6 +26,7 @@ func CreateCmd(ch *cmdutil.Helper) *cobra.Command {
2526
req := &planetscale.CreateServiceTokenRequest{
2627
Organization: ch.Config.Organization,
2728
Name: stringPtrOrNil(name),
29+
TTL: intPtrOrNil(ttl),
2830
}
2931

3032
end := ch.Printer.PrintProgress(fmt.Sprintf("Creating service token in org %s", printer.BoldBlue(ch.Config.Organization)))
@@ -47,6 +49,7 @@ func CreateCmd(ch *cmdutil.Helper) *cobra.Command {
4749
}
4850

4951
cmd.Flags().StringVar(&name, "name", "", "optional name for the service token")
52+
cmd.Flags().IntVar(&ttl, "ttl", 0, "Time to live (in seconds) for the service token. The token will be invalid when TTL has passed")
5053

5154
return cmd
5255
}
@@ -57,3 +60,10 @@ func stringPtrOrNil(s string) *string {
5760
}
5861
return &s
5962
}
63+
64+
func intPtrOrNil(i int) *int {
65+
if i == 0 {
66+
return nil
67+
}
68+
return &i
69+
}

internal/cmd/token/create_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,54 @@ func TestServiceToken_CreateCmdWithName(t *testing.T) {
105105
res := &ServiceTokenWithSecret{orig: orig}
106106
c.Assert(buf.String(), qt.JSONEquals, res)
107107
}
108+
109+
func TestServiceToken_CreateCmdWithTTL(t *testing.T) {
110+
c := qt.New(t)
111+
112+
var buf bytes.Buffer
113+
format := printer.JSON
114+
p := printer.NewPrinter(&format)
115+
p.SetResourceOutput(&buf)
116+
117+
org := "planetscale"
118+
id := "123456"
119+
name := "my-token"
120+
ttl := 3600
121+
createdAt := time.Date(2025, 1, 15, 10, 30, 0, 0, time.UTC)
122+
expiresAt := time.Date(2025, 1, 15, 11, 30, 0, 0, time.UTC)
123+
124+
orig := &ps.ServiceToken{ID: id, Name: &name, CreatedAt: createdAt, ExpiresAt: &expiresAt}
125+
126+
svc := &mock.ServiceTokenService{
127+
CreateFn: func(ctx context.Context, req *ps.CreateServiceTokenRequest) (*ps.ServiceToken, error) {
128+
c.Assert(req.Organization, qt.Equals, org)
129+
c.Assert(req.Name, qt.IsNotNil)
130+
c.Assert(*req.Name, qt.Equals, name)
131+
c.Assert(req.TTL, qt.IsNotNil)
132+
c.Assert(*req.TTL, qt.Equals, ttl)
133+
return orig, nil
134+
},
135+
}
136+
137+
ch := &cmdutil.Helper{
138+
Printer: p,
139+
Config: &config.Config{
140+
Organization: org,
141+
},
142+
Client: func() (*ps.Client, error) {
143+
return &ps.Client{
144+
ServiceTokens: svc,
145+
}, nil
146+
},
147+
}
148+
149+
cmd := CreateCmd(ch)
150+
cmd.SetArgs([]string{"--name", name, "--ttl", "3600"})
151+
err := cmd.Execute()
152+
153+
c.Assert(err, qt.IsNil)
154+
c.Assert(svc.CreateFnInvoked, qt.IsTrue)
155+
156+
res := &ServiceTokenWithSecret{orig: orig}
157+
c.Assert(buf.String(), qt.JSONEquals, res)
158+
}

internal/cmd/token/list_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,56 @@ func TestServiceToken_ListCmd(t *testing.T) {
6464
}
6565
c.Assert(buf.String(), qt.JSONEquals, res)
6666
}
67+
68+
func TestServiceToken_ListCmdWithExpiresAt(t *testing.T) {
69+
c := qt.New(t)
70+
71+
var buf bytes.Buffer
72+
format := printer.JSON
73+
p := printer.NewPrinter(&format)
74+
p.SetResourceOutput(&buf)
75+
76+
org := "planetscale"
77+
name1 := "token-one"
78+
createdAt1 := time.Date(2025, 1, 15, 10, 30, 0, 0, time.UTC)
79+
lastUsedAt1 := time.Date(2025, 1, 20, 14, 45, 0, 0, time.UTC)
80+
expiresAt1 := time.Date(2025, 2, 15, 10, 30, 0, 0, time.UTC)
81+
createdAt2 := time.Date(2025, 1, 16, 11, 0, 0, 0, time.UTC)
82+
expiresAt2 := time.Date(2025, 2, 16, 11, 0, 0, 0, time.UTC)
83+
84+
orig := []*ps.ServiceToken{
85+
{ID: "1", Name: &name1, CreatedAt: createdAt1, LastUsedAt: &lastUsedAt1, ExpiresAt: &expiresAt1},
86+
{ID: "2", CreatedAt: createdAt2, ExpiresAt: &expiresAt2},
87+
}
88+
89+
svc := &mock.ServiceTokenService{
90+
ListFn: func(ctx context.Context, req *ps.ListServiceTokensRequest) ([]*ps.ServiceToken, error) {
91+
c.Assert(req.Organization, qt.Equals, org)
92+
return orig, nil
93+
},
94+
}
95+
96+
ch := &cmdutil.Helper{
97+
Printer: p,
98+
Config: &config.Config{
99+
Organization: org,
100+
},
101+
Client: func() (*ps.Client, error) {
102+
return &ps.Client{
103+
ServiceTokens: svc,
104+
}, nil
105+
},
106+
}
107+
108+
cmd := ListCmd(ch)
109+
err := cmd.Execute()
110+
111+
c.Assert(err, qt.IsNil)
112+
c.Assert(svc.ListFnInvoked, qt.IsTrue)
113+
114+
res := []*ServiceToken{
115+
{orig: orig[0]},
116+
{orig: orig[1]},
117+
}
118+
c.Assert(buf.String(), qt.JSONEquals, res)
119+
}

internal/cmd/token/token.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type ServiceToken struct {
5050
ID string `header:"id" json:"id"`
5151
Name string `header:"name" json:"name"`
5252
LastUsedAt int64 `header:"last_used_at,timestamp(ms|utc|human)" json:"last_used_at"`
53+
ExpiresAt int64 `header:"expires_at,timestamp(ms|utc|human)" json:"expires_at"`
5354
CreatedAt int64 `header:"created_at,timestamp(ms|utc|human)" json:"created_at"`
5455

5556
orig *ps.ServiceToken
@@ -74,10 +75,16 @@ func toServiceToken(st *ps.ServiceToken) *ServiceToken {
7475
lastUsedAt = printer.GetMilliseconds(*st.LastUsedAt)
7576
}
7677

78+
var expiresAt int64
79+
if st.ExpiresAt != nil {
80+
expiresAt = printer.GetMilliseconds(*st.ExpiresAt)
81+
}
82+
7783
return &ServiceToken{
7884
ID: st.ID,
7985
Name: name,
8086
LastUsedAt: lastUsedAt,
87+
ExpiresAt: expiresAt,
8188
CreatedAt: printer.GetMilliseconds(st.CreatedAt),
8289
orig: st,
8390
}
@@ -88,6 +95,7 @@ type ServiceTokenWithSecret struct {
8895
ID string `header:"id" json:"id"`
8996
Name string `header:"name" json:"name"`
9097
Token string `header:"token" json:"token"`
98+
ExpiresAt int64 `header:"expires_at,timestamp(ms|utc|human)" json:"expires_at"`
9199
CreatedAt int64 `header:"created_at,timestamp(ms|utc|human)" json:"created_at"`
92100

93101
orig *ps.ServiceToken
@@ -104,10 +112,16 @@ func toServiceTokenWithSecret(st *ps.ServiceToken) *ServiceTokenWithSecret {
104112
name = *st.Name
105113
}
106114

115+
var expiresAt int64
116+
if st.ExpiresAt != nil {
117+
expiresAt = printer.GetMilliseconds(*st.ExpiresAt)
118+
}
119+
107120
return &ServiceTokenWithSecret{
108121
ID: st.ID,
109122
Name: name,
110123
Token: st.Token,
124+
ExpiresAt: expiresAt,
111125
CreatedAt: printer.GetMilliseconds(st.CreatedAt),
112126
orig: st,
113127
}

0 commit comments

Comments
 (0)