Skip to content

Commit

Permalink
command/flag: add timezone flag to common task flags
Browse files Browse the repository at this point in the history
- Add Timezone type
- Resolve timezone name from /etc/localtime
  • Loading branch information
mmatczuk committed Dec 30, 2021
1 parent e7ed469 commit e544523
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 0 deletions.
4 changes: 4 additions & 0 deletions pkg/command/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ func (w Wrapper) window(p *[]string) {
w.fs.StringSliceVar(p, "window", nil, usage["window"])
}

func (w Wrapper) timezone(p *Timezone) {
w.fs.Var(p, "timezone", usage["timezone"])
}

func (w Wrapper) interval(p *Duration) {
w.fs.VarP(p, "interval", "i", usage["interval"])
w.MustMarkDeprecated("interval", "use cron instead")
Expand Down
9 changes: 9 additions & 0 deletions pkg/command/flag/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/scylladb/scylla-manager/pkg/managerclient"
"github.com/scylladb/scylla-manager/pkg/util/timeutc"
"github.com/spf13/cobra"
)

Expand All @@ -18,6 +19,7 @@ type TaskBase struct {
name string
cron Cron
window []string
timezone Timezone
interval Duration
startDate Time
numRetries int
Expand All @@ -26,6 +28,7 @@ type TaskBase struct {

func MakeTaskBase() TaskBase {
return TaskBase{
timezone: Timezone{timeutc.LocalName},
retryWait: DurationWithDefault(10 * time.Minute),
}
}
Expand All @@ -43,6 +46,7 @@ func (cmd *TaskBase) Init() {
w.name(&cmd.name)
w.cron(&cmd.cron)
w.window(&cmd.window)
w.timezone(&cmd.timezone)
w.interval(&cmd.interval)
w.startDate(&cmd.startDate)
w.numRetries(&cmd.numRetries, cmd.numRetries)
Expand All @@ -63,6 +67,7 @@ func (cmd *TaskBase) CreateTask(taskType string) *managerclient.Task {
Schedule: &managerclient.Schedule{
Cron: cmd.cron.Value(),
Window: cmd.window,
Timezone: cmd.timezone.Value(),
Interval: cmd.interval.String(),
StartDate: cmd.startDate.DateTimePtr(),
NumRetries: int64(cmd.numRetries),
Expand Down Expand Up @@ -91,6 +96,10 @@ func (cmd *TaskBase) UpdateTask(task *managerclient.Task) bool {
task.Schedule.Window = cmd.window
ok = true
}
if cmd.Flag("timezone").Changed {
task.Schedule.Timezone = cmd.timezone.Value()
ok = true
}
if cmd.Flag("interval").Changed {
task.Schedule.Interval = cmd.interval.String()
ok = true
Expand Down
4 changes: 4 additions & 0 deletions pkg/command/flag/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ window: |
* '23:00,06:00' - can be executed every night from 11PM to 6AM
* '23:00,06:00,SAT-00:00,SUN-23:59' - can be executed every night from 11PM to 6AM and all day during the weekend
timezone: |
Timezone of --cron and --window flag values.
The default value is taken from this system, namely 'TZ' envvar or '/etc/localtime' file.
interval: |
Time after which a successfully completed task would be run again, supported units are:
Expand Down
30 changes: 30 additions & 0 deletions pkg/command/flag/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,36 @@ func (c *Cron) Type() string {
return "string"
}

// Timezone wraps string for early validation.
type Timezone struct {
v string
}

var _ flag.Value = (*Timezone)(nil)

func (c *Timezone) String() string {
return c.v
}

// Set implements pflag.Value.
func (c *Timezone) Set(s string) error {
if _, err := time.LoadLocation(s); err != nil {
return err
}

c.v = s
return nil
}

func (c *Timezone) Value() string {
return c.v
}

// Type implements pflag.Value.
func (c *Timezone) Type() string {
return "string"
}

// Time wraps time.Time and add support for now+duration syntax.
type Time struct {
v time.Time
Expand Down
34 changes: 34 additions & 0 deletions pkg/util/timeutc/zoneinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (C) 2021 ScyllaDB

package timeutc

import (
"os"
"strings"
"time"
)

// LocalName is name of the local time zone conforming to the IANA Time Zone database, such as "America/New_York".
// Using time.Local if timezone is read from /etc/localtime its name is overwritten by "Local".
// LocalName provides the name as read from /etc/localtime static link.
var LocalName string

func init() {
tz := time.Local.String()
if tz == "Local" {
p, err := os.Readlink("/etc/localtime")
if err != nil {
return
}
i := strings.LastIndex(p, "/zoneinfo/")
if i < 0 {
return
}
tz = p[i+len("/zoneinfo/"):]
if _, err := time.LoadLocation(tz); err != nil {
return
}
}

LocalName = tz
}

0 comments on commit e544523

Please sign in to comment.