Skip to content

cli: streamline autostart ux #2251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 13, 2022
Prev Previous commit
Next Next commit
fix some unit tests
  • Loading branch information
johnstcn committed Jun 10, 2022
commit 84f1a12d6c6de40720db7bac6328d7d98c715c7c
2 changes: 1 addition & 1 deletion cli/autostart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func TestAutostart(t *testing.T) {
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
)

cmd, root := clitest.New(t, "autostart", "set", "doesnotexist")
cmd, root := clitest.New(t, "autostart", "set", "doesnotexist", "09:30AM")
clitest.SetupConfig(t, client, root)

err := cmd.Execute()
Expand Down
11 changes: 6 additions & 5 deletions coderd/util/tz/tz_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

const etcLocaltime = "/etc/localtime"
const zoneInfoPath = "/var/db/timezone/zoneinfo"
const zoneInfoPath = "/var/db/timezone/zoneinfo/"

// TimezoneIANA attempts to determine the local timezone in IANA format.
// If the TZ environment variable is set, this is used.
Expand All @@ -25,20 +25,21 @@ func TimezoneIANA() (*time.Location, error) {
return time.UTC, nil
}
loc, err := time.LoadLocation(tzEnv)
if err == nil {
return loc, nil
if err != nil {
return nil, xerrors.Errorf("load location from TZ env: %w", err)
}
return loc, nil
}

lp, err := filepath.EvalSymlinks(etcLocaltime)
if err != nil {
return nil, err
return nil, xerrors.Errorf("read location of %s: %w", etcLocaltime, err)
}

stripped := strings.Replace(lp, etcLocaltime, "", -1)
loc, err := time.LoadLocation(stripped)
if err != nil {
return nil, err
return nil, xerrors.Errorf("invalid location %q guessed from %s: %w", stripped, lp, err)
}
return loc
}
15 changes: 9 additions & 6 deletions coderd/util/tz/tz_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import (
"path/filepath"
"strings"
"time"

"golang.org/x/xerrors"
)

const etcLocaltime = "/etc/localtime"
const zoneInfoPath = "/usr/share/zoneinfo"
const zoneInfoPath = "/usr/share/zoneinfo/"

// TimezoneIANA attempts to determine the local timezone in IANA format.
// If the TZ environment variable is set, this is used.
Expand All @@ -26,20 +28,21 @@ func TimezoneIANA() (*time.Location, error) {
return time.UTC, nil
}
loc, err := time.LoadLocation(tzEnv)
if err == nil {
return loc, nil
if err != nil {
return nil, xerrors.Errorf("load location from TZ env: %w", err)
}
return loc, nil
}

lp, err := filepath.EvalSymlinks(etcLocaltime)
if err != nil {
return nil, err
return nil, xerrors.Errorf("read location of %s: %w", etcLocaltime, err)
}

stripped := strings.Replace(lp, etcLocaltime, "", -1)
stripped := strings.Replace(lp, zoneInfoPath, "", -1)
loc, err := time.LoadLocation(stripped)
if err != nil {
return nil, err
return nil, xerrors.Errorf("invalid location %q guessed from %s: %w", stripped, lp, err)
}
return loc, nil
}
40 changes: 40 additions & 0 deletions coderd/util/tz/tz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package tz_test

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/coder/coder/coderd/util/tz"
)

//nolint:paralleltest // Environment variables
func Test_TimezoneIANA(t *testing.T) {
//nolint:paralleltest // t.Setenv
t.Run("Env", func(t *testing.T) {
t.Setenv("TZ", "Europe/Dublin")

zone, err := tz.TimezoneIANA()
assert.NoError(t, err)
if assert.NotNil(t, zone) {
assert.Equal(t, "Europe/Dublin", zone.String())
}
})

//nolint:paralleltest // UnsetEnv
t.Run("NoEnv", func(t *testing.T) {
oldEnv, found := os.LookupEnv("TZ")
if found {
require.NoError(t, os.Unsetenv("TZ"))
t.Cleanup(func() {
_ = os.Setenv("TZ", oldEnv)
})
}

zone, err := tz.TimezoneIANA()
assert.NoError(t, err)
assert.NotNil(t, zone)
})
}
27 changes: 17 additions & 10 deletions coderd/util/tz/tz_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
package tz

import (
"exec"
"bytes"
"fmt"
"os"
"os/exec"
"time"

"golang.org/x/xerrors"
)

const cmdTimezone = "[Windows.Globalization.Calendar,Windows.Globalization,ContentType=WindowsRuntime]::New().GetTimeZone()"
Expand All @@ -22,35 +27,37 @@ func TimezoneIANA() (*time.Location, error) {
return time.UTC, nil
}
loc, err := time.LoadLocation(tzEnv)
if err == nil {
return loc, nil
if err != nil {
return nil, xerrors.Errorf("load location from TZ env: %w", err)
}
return loc, nil
}

// https://superuser.com/a/1584968
cmd := exec.Command("powershell", "-nologo", "-noprofile")
cmd := exec.Command("powershell.exe", "-nologo", "-noprofile")
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
return nil, xerrors.Errorf("run powershell: %w", err)
}

done := make(chan struct{})
go func() {
defer stdin.Close()
defer close(done)
_, _ = fmt.Fprintln(stdin, cmdTimezone)
}
}()

<- done
<-done

out, err := cmd.CombinedOutput()
if err != nil {
return nil, err
return nil, xerrors.Errorf("execute powershell command %q: %w", cmdTimezone, err)
}

loc, err := time.LoadLocation(out)
locStr := string(bytes.TrimSpace(out))
loc, err := time.LoadLocation(locStr)
if err != nil {
return nil, err
return nil, xerrors.Errorf("invalid location %q from powershell: %w", locStr, err)
}

return loc, nil
Expand Down