Skip to content
Open
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
4 changes: 2 additions & 2 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import (
type CronHorizontalPodAutoscalerSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
ExcludeDates []string `json:"excludeDates"`
ScaleTargetRef ScaleTargetRef `json:"scaleTargetRef"`
Jobs []Job `json:"jobs"`
ExcludeDates []string `json:"excludeDates" validate:"excludeDatesValidator"`
ScaleTargetRef ScaleTargetRef `json:"scaleTargetRef"`
Jobs []Job `json:"jobs"`
}

type Job struct {
Expand Down
90 changes: 90 additions & 0 deletions pkg/apis/autoscaling/v1beta1/validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package v1beta1

import (
"fmt"
"github.com/ringtail/go-cron"
"reflect"
"strings"
)

const tagName = "validate"

type Validator interface {
Validate(interface{}) (bool, error)
}

type DefaultValidator struct {
}

type NumberValidator struct {
Min int
Max int
}

type StringValidator struct {
Min int
Max int
}

func (v StringValidator) Validate(val interface{}) (bool, error) {
return true, nil
}

type ExcludeDatesValidator struct {
}

func (v ExcludeDatesValidator) Validate(val interface{}) (bool, error) {
switch i := val.(type) {
case []string:
parser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
for _, item := range i {
_, err := parser.Parse(item)
if err != nil {
return false, err
}
}
}
return true, nil
}

func (v DefaultValidator) Validate(val interface{}) (bool,error) {
return true, nil
}

// get Validator struct corresponding to validate tag
func getValidatorFromTag(tag string) Validator {
args := strings.Split(tag, ",")
switch args[0] {
case "excludeDatesValidator":
validator := ExcludeDatesValidator{}
return validator
}
return DefaultValidator{}
}

func Validate(s interface{}) (bool, []error){
errs := []error{}
pass := true
v := reflect.ValueOf(s)
for i := 0; i < v.NumField(); i++ {
// Get the field tag value
tag := strings.TrimSpace(v.Type().Field(i).Tag.Get(tagName))

if tag == "" || tag=="-" {
continue
}
// Get a validator
validator := getValidatorFromTag(tag)

// Perform validation
valid, err := validator.Validate(v.Field(i).Interface())

if !valid && err != nil {
pass = false
errs = append(errs, fmt.Errorf("%s %s", v.Type().Field(i).Name, err.Error()))
}
}
return pass, errs
}


Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (r *ReconcileCronHorizontalPodAutoscaler) Reconcile(request reconcile.Reque

leftConditions := make([]v1beta1.Condition, 0)
// check scaleTargetRef and excludeDates
if checkGlobalParamsChanges(instance.Status, instance.Spec) {
if !validateParams(instance) || checkGlobalParamsChanges(instance.Status, instance.Spec) {
for _, cJob := range conditions {
r.CronManager.delete(cJob.JobId)
}
Expand Down Expand Up @@ -237,6 +237,18 @@ func updateConditions(conditions []v1beta1.Condition, condition v1beta1.Conditio
return r
}

func validateParams(instance *v1beta1.CronHorizontalPodAutoscaler) (bool) {
pass := true
var errs []error
// verify spec params - ExcludeDates
validRes,errs:= autoscalingv1beta1.Validate(instance.Spec.ExcludeDates)
if !validRes || errs != nil {
log.Errorf("Failed to validate spec.ExcludeDates: %s Errors are: %s ", instance.Spec.ExcludeDates, errs)
pass = false
}
return pass
}

// if global params changed then all jobs need to be recreated.
func checkGlobalParamsChanges(status v1beta1.CronHorizontalPodAutoscalerStatus, spec v1beta1.CronHorizontalPodAutoscalerSpec) bool {
if &status.ScaleTargetRef != nil && (status.ScaleTargetRef.Kind != spec.ScaleTargetRef.Kind || status.ScaleTargetRef.ApiVersion != spec.ScaleTargetRef.ApiVersion ||
Expand Down