diff --git a/manifests/testpostgresql.yaml b/manifests/testpostgresql.yaml index 44f1fad78..1728f46a7 100644 --- a/manifests/testpostgresql.yaml +++ b/manifests/testpostgresql.yaml @@ -43,4 +43,4 @@ spec: maximum_lag_on_failover: 33554432 maintenanceWindows: - 01:00-06:00 #UTC - - Sat:00:00-Sat:04:00 + - Sat:00:00-04:00 diff --git a/pkg/spec/postgresql.go b/pkg/spec/postgresql.go index e00625c7d..0ff3d9ff3 100644 --- a/pkg/spec/postgresql.go +++ b/pkg/spec/postgresql.go @@ -3,7 +3,6 @@ package spec import ( "encoding/json" "fmt" - "regexp" "strings" "time" @@ -12,14 +11,11 @@ import ( "k8s.io/client-go/pkg/api/v1" ) -var alphaRegexp = regexp.MustCompile("^[a-zA-Z]*$") - type MaintenanceWindow struct { - StartTime time.Time // Start time - StartWeekday time.Weekday // Start weekday - - EndTime time.Time // End time - EndWeekday time.Weekday // End weekday + Everyday bool + Weekday time.Weekday + StartTime time.Time // Start time + EndTime time.Time // End time } type Volume struct { @@ -71,7 +67,7 @@ type Postgresql struct { Metadata v1.ObjectMeta `json:"metadata"` Spec PostgresSpec `json:"spec"` - Status PostgresStatus `json:"status"` + Status PostgresStatus `json:"status,omitempty"` Error error `json:"-"` } @@ -96,54 +92,49 @@ type PostgresqlList struct { Items []Postgresql `json:"items"` } -func parseTime(s string) (t time.Time, wd time.Weekday, wdProvided bool, err error) { - var timeLayout string +var weekdays = map[string]int{"Sun": 0, "Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6} +func parseTime(s string) (time.Time, error) { parts := strings.Split(s, ":") - if len(parts) == 3 { - if len(parts[0]) != 3 || !alphaRegexp.MatchString(parts[0]) { - err = fmt.Errorf("weekday must be 3 characters length") - return - } - timeLayout = "Mon:15:04" - wdProvided = true - } else { - wdProvided = false - timeLayout = "15:04" + if len(parts) != 2 { + return time.Time{}, fmt.Errorf("incorrect time format") } + timeLayout := "15:04" tp, err := time.Parse(timeLayout, s) if err != nil { - return + return time.Time{}, err } - wd = tp.Weekday() - t = tp.UTC() + return tp.UTC(), nil +} - return +func parseWeekday(s string) (time.Weekday, error) { + weekday, ok := weekdays[s] + if !ok { + return time.Weekday(0), fmt.Errorf("incorrect weekday") + } + + return time.Weekday(weekday), nil } func (m *MaintenanceWindow) MarshalJSON() ([]byte, error) { - var startWd, endWd string - if m.StartWeekday == time.Sunday && m.EndWeekday == time.Saturday { - startWd = "" - endWd = "" + if m.Everyday { + return []byte(fmt.Sprintf("\"%s-%s\"", + m.StartTime.Format("15:04"), + m.EndTime.Format("15:04"))), nil } else { - startWd = m.StartWeekday.String()[:3] + ":" - endWd = m.EndWeekday.String()[:3] + ":" + return []byte(fmt.Sprintf("\"%s:%s-%s\"", + m.Weekday.String()[:3], + m.StartTime.Format("15:04"), + m.EndTime.Format("15:04"))), nil } - - return []byte(fmt.Sprintf("\"%s%s-%s%s\"", - startWd, m.StartTime.Format("15:04"), - endWd, m.EndTime.Format("15:04"))), nil } func (m *MaintenanceWindow) UnmarshalJSON(data []byte) error { var ( - got MaintenanceWindow - weekdayProvidedFrom bool - weekdayProvidedTo bool - err error + got MaintenanceWindow + err error ) parts := strings.Split(string(data[1:len(data)-1]), "-") @@ -151,25 +142,35 @@ func (m *MaintenanceWindow) UnmarshalJSON(data []byte) error { return fmt.Errorf("incorrect maintenance window format") } - got.StartTime, got.StartWeekday, weekdayProvidedFrom, err = parseTime(parts[0]) + fromParts := strings.Split(parts[0], ":") + switch len(fromParts) { + case 3: + got.Everyday = false + got.Weekday, err = parseWeekday(fromParts[0]) + if err != nil { + return fmt.Errorf("could not parse weekday: %v", err) + } + + got.StartTime, err = parseTime(fromParts[1] + ":" + fromParts[2]) + case 2: + got.Everyday = true + got.StartTime, err = parseTime(fromParts[0] + ":" + fromParts[1]) + default: + return fmt.Errorf("incorrect maintenance window format") + } if err != nil { - return err + return fmt.Errorf("could not parse start time: %v", err) } - got.EndTime, got.EndWeekday, weekdayProvidedTo, err = parseTime(parts[1]) + got.EndTime, err = parseTime(parts[1]) if err != nil { - return err + return fmt.Errorf("could not parse end time: %v", err) } if got.EndTime.Before(got.StartTime) { return fmt.Errorf("'From' time must be prior to the 'To' time") } - if !weekdayProvidedFrom || !weekdayProvidedTo { - got.StartWeekday = time.Sunday - got.EndWeekday = time.Saturday - } - *m = got return nil @@ -191,11 +192,16 @@ func (pl *PostgresqlList) GetListMeta() unversioned.List { return &pl.Metadata } -func clusterName(clusterName string, teamName string) (string, error) { +func extractClusterName(clusterName string, teamName string) (string, error) { teamNameLen := len(teamName) if len(clusterName) < teamNameLen+2 { return "", fmt.Errorf("name is too short") } + + if teamNameLen == 0 { + return "", fmt.Errorf("team name is empty") + } + if strings.ToLower(clusterName[:teamNameLen+1]) != strings.ToLower(teamName)+"-" { return "", fmt.Errorf("name must match {TEAM}-{NAME} format") } @@ -211,7 +217,8 @@ type PostgresqlListCopy PostgresqlList type PostgresqlCopy Postgresql func (p *Postgresql) UnmarshalJSON(data []byte) error { - tmp := PostgresqlCopy{} + var tmp PostgresqlCopy + err := json.Unmarshal(data, &tmp) if err != nil { metaErr := json.Unmarshal(data, &tmp.Metadata) @@ -228,7 +235,7 @@ func (p *Postgresql) UnmarshalJSON(data []byte) error { } tmp2 := Postgresql(tmp) - clusterName, err := clusterName(tmp2.Metadata.Name, tmp2.Spec.TeamID) + clusterName, err := extractClusterName(tmp2.Metadata.Name, tmp2.Spec.TeamID) if err == nil { tmp2.Spec.ClusterName = clusterName } else { @@ -241,7 +248,8 @@ func (p *Postgresql) UnmarshalJSON(data []byte) error { } func (pl *PostgresqlList) UnmarshalJSON(data []byte) error { - tmp := PostgresqlListCopy{} + var tmp PostgresqlListCopy + err := json.Unmarshal(data, &tmp) if err != nil { return err