Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions tool/tsh/common/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -4855,19 +4855,26 @@ func onShow(cf *CLIConf) error {
return nil
}

func humanFriendlyValidUntilDuration(validUntil time.Time, clock clockwork.Clock) string {
duration := validUntil.Sub(clock.Now())
switch {
case duration <= 0:
return "EXPIRED"
case duration < time.Minute:
return "valid for <1m"
default:
return fmt.Sprintf("valid for %s",
// Since duration is truncated to minute, duration.String() always
// ends with 0s.
strings.TrimRight(duration.Truncate(time.Minute).String(), "0s"),
)
}
}

// printStatus prints the status of the profile.
func printStatus(debug bool, p *profileInfo, env map[string]string, isActive bool) {
clock := clockwork.NewRealClock()
var prefix string
humanDuration := "EXPIRED"
duration := time.Until(p.ValidUntil)
if duration.Nanoseconds() > 0 {
humanDuration = fmt.Sprintf("valid for %v", duration.Round(time.Minute))
// If certificate is valid for less than a minute, display "<1m" instead of "0s".
if duration < time.Minute {
humanDuration = "valid for <1m"
}
}

proxyURL := p.getProxyURLLine(isActive, env)
cluster := p.getClusterLine(isActive, env)
kubeCluster := p.getKubeClusterLine(isActive, env)
Expand Down Expand Up @@ -4926,7 +4933,7 @@ func printStatus(debug bool, p *profileInfo, env map[string]string, isActive boo
fmt.Printf(" Allowed Resources: %s\n", allowedResourcesStr)
}
}
fmt.Printf(" Valid until: %v [%v]\n", p.ValidUntil, humanDuration)
fmt.Printf(" Valid until: %v [%v]\n", p.ValidUntil, humanFriendlyValidUntilDuration(p.ValidUntil, clock))
fmt.Printf(" Extensions: %v\n", strings.Join(p.Extensions, ", "))

if debug {
Expand Down
38 changes: 38 additions & 0 deletions tool/tsh/common/tsh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import (
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/google/uuid"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
otlp "go.opentelemetry.io/proto/otlp/trace/v1"
Expand Down Expand Up @@ -7209,3 +7210,40 @@ func TestSetEnvVariables(t *testing.T) {
})
}
}

func Test_humanFriendlyValidUntilDuration(t *testing.T) {
clock := clockwork.NewFakeClock()
tests := []struct {
name string
input time.Time
expect string
}{
{
name: "expired",
input: clock.Now().Add(-time.Minute),
expect: "EXPIRED",
},
{
name: "less than one minute",
input: clock.Now().Add(time.Second * 30),
expect: "valid for <1m",
},
{
name: "truncate",
input: clock.Now().Add(time.Minute*5 + time.Second*50),
expect: "valid for 5m",
},
{
name: "hours",
input: clock.Now().Add(time.Hour*12 + time.Minute*34 + time.Second*10),
expect: "valid for 12h34m",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := humanFriendlyValidUntilDuration(test.input, clock)
require.Equal(t, test.expect, actual)
})
}
}
Loading