Perform validation of boot command.
This commit is contained in:
parent
7d43324359
commit
aa69bdf74e
|
@ -42,13 +42,22 @@ func (k KeyAction) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type expression interface {
|
type expression interface {
|
||||||
|
// Do executes the expression
|
||||||
Do(context.Context, BCDriver) error
|
Do(context.Context, BCDriver) error
|
||||||
|
// Validate validates the expression without executing it
|
||||||
|
Validate() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type expressionSequence []expression
|
type expressionSequence []expression
|
||||||
|
|
||||||
// Do executes every expression in the sequence and then finalizes the driver.
|
// Do executes every expression in the sequence and then finalizes the driver.
|
||||||
func (s expressionSequence) Do(ctx context.Context, b BCDriver) error {
|
func (s expressionSequence) Do(ctx context.Context, b BCDriver) error {
|
||||||
|
// validate should never fail here, since it should be called before
|
||||||
|
// expressionSequence.Do. Only reason we don't panic is so we can clean up.
|
||||||
|
if errs := s.Validate(); errs != nil {
|
||||||
|
return fmt.Errorf("Found an invalid boot command. This is likely an error in Packer, so please open a ticket.")
|
||||||
|
}
|
||||||
|
|
||||||
for _, exp := range s {
|
for _, exp := range s {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -60,6 +69,16 @@ func (s expressionSequence) Do(ctx context.Context, b BCDriver) error {
|
||||||
return b.Finalize()
|
return b.Finalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do executes every expression in the sequence and then finalizes the driver.
|
||||||
|
func (s expressionSequence) Validate() (errs []error) {
|
||||||
|
for _, exp := range s {
|
||||||
|
if err := exp.Validate(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateExpressionSequence generates a sequence of expressions from the
|
// GenerateExpressionSequence generates a sequence of expressions from the
|
||||||
// given command. This is the primary entry point to the boot command parser.
|
// given command. This is the primary entry point to the boot command parser.
|
||||||
func GenerateExpressionSequence(command string) (expressionSequence, error) {
|
func GenerateExpressionSequence(command string) (expressionSequence, error) {
|
||||||
|
@ -67,9 +86,6 @@ func GenerateExpressionSequence(command string) (expressionSequence, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if got == nil {
|
|
||||||
return nil, fmt.Errorf("No expressions found.")
|
|
||||||
}
|
|
||||||
seq := expressionSequence{}
|
seq := expressionSequence{}
|
||||||
for _, exp := range got.([]interface{}) {
|
for _, exp := range got.([]interface{}) {
|
||||||
seq = append(seq, exp.(expression))
|
seq = append(seq, exp.(expression))
|
||||||
|
@ -93,6 +109,14 @@ func (w *waitExpression) Do(ctx context.Context, _ BCDriver) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate returns an error if the time is <= 0
|
||||||
|
func (w *waitExpression) Validate() error {
|
||||||
|
if w.d <= 0 {
|
||||||
|
return fmt.Errorf("Expecting a positive wait value. Got %s", w.d)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w *waitExpression) String() string {
|
func (w *waitExpression) String() string {
|
||||||
return fmt.Sprintf("Wait<%s>", w.d)
|
return fmt.Sprintf("Wait<%s>", w.d)
|
||||||
}
|
}
|
||||||
|
@ -107,6 +131,11 @@ func (s *specialExpression) Do(ctx context.Context, driver BCDriver) error {
|
||||||
return driver.SendSpecial(s.s, s.action)
|
return driver.SendSpecial(s.s, s.action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate always passes
|
||||||
|
func (s *specialExpression) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *specialExpression) String() string {
|
func (s *specialExpression) String() string {
|
||||||
return fmt.Sprintf("Spec-%s(%s)", s.action, s.s)
|
return fmt.Sprintf("Spec-%s(%s)", s.action, s.s)
|
||||||
}
|
}
|
||||||
|
@ -121,6 +150,11 @@ func (l *literal) Do(ctx context.Context, driver BCDriver) error {
|
||||||
return driver.SendKey(l.s, l.action)
|
return driver.SendKey(l.s, l.action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate always passes
|
||||||
|
func (l *literal) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (l *literal) String() string {
|
func (l *literal) String() string {
|
||||||
return fmt.Sprintf("LIT-%s(%s)", l.action, string(l.s))
|
return fmt.Sprintf("LIT-%s(%s)", l.action, string(l.s))
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,17 +100,41 @@ func Test_special(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_negativeWait(t *testing.T) {
|
func Test_validation(t *testing.T) {
|
||||||
in := "<wait-1m>"
|
var expressions = []struct {
|
||||||
_, err := ParseReader("", strings.NewReader(in))
|
in string
|
||||||
if err != nil {
|
valid bool
|
||||||
log.Fatal(err)
|
}{
|
||||||
|
{
|
||||||
|
"<wait1m>",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<wait-1m>",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<f1>",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"<",
|
||||||
|
true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
for _, tt := range expressions {
|
||||||
|
got, err := ParseReader("", strings.NewReader(tt.in))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
gL := toIfaceSlice(got)
|
gL := toIfaceSlice(got)
|
||||||
for _, g := range gL {
|
assert.Len(t, gL, 1)
|
||||||
assert.Equal(t, tt.out, g.(*specialExpression).String())
|
err = gL[0].(expression).Validate()
|
||||||
}
|
if tt.valid {
|
||||||
*/
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,16 @@ func (c *BootConfig) Prepare(ctx *interpolate.Context) (errs []error) {
|
||||||
c.BootWait = bw
|
c.BootWait = bw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.BootCommand != nil {
|
||||||
|
expSeq, err := GenerateExpressionSequence(c.FlatBootCommand())
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
} else if vErrs := expSeq.Validate(); vErrs != nil {
|
||||||
|
errs = append(errs, vErrs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue