From 099dd3e7b33fa9a7e6c8c77440fed45cbc1cc8ea Mon Sep 17 00:00:00 2001 From: Gennady Lipenkov Date: Thu, 9 Jul 2020 01:52:08 +0300 Subject: [PATCH] Validate and render 'paths' config value --- .../yandex-export/post-processor.go | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/post-processor/yandex-export/post-processor.go b/post-processor/yandex-export/post-processor.go index bc0fe48da..e09e031ea 100644 --- a/post-processor/yandex-export/post-processor.go +++ b/post-processor/yandex-export/post-processor.go @@ -6,6 +6,7 @@ package yandexexport import ( "context" "fmt" + "log" "os" "strings" "time" @@ -67,6 +68,11 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "paths", + }, + }, }, raws...) if err != nil { return err @@ -79,6 +85,14 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { errs, fmt.Errorf("paths must be specified")) } + // Validate templates in 'paths' + for _, path := range p.config.Paths { + if err = interpolate.Validate(path, &p.config.ctx); err != nil { + errs = packer.MultiErrorAppend( + errs, fmt.Errorf("Error parsing one of 'paths' template: %s", err)) + } + } + // provision config by OS environment variables if p.config.Token == "" { p.config.Token = os.Getenv("YC_TOKEN") @@ -143,14 +157,38 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact return nil, false, false, err } - builderID := artifact.State("ImageID").(string) + // prepare and render values + var generatedData map[interface{}]interface{} + stateData := artifact.State("generated_data") + if stateData != nil { + // Make sure it's not a nil map so we can assign to it later. + generatedData = stateData.(map[interface{}]interface{}) + } + // If stateData has a nil map generatedData will be nil + // and we need to make sure it's not + if generatedData == nil { + generatedData = make(map[interface{}]interface{}) + } + p.config.ctx.Data = generatedData + + var err error + // Render this key since we didn't in the configure phase + for i, path := range p.config.Paths { + p.config.Paths[i], err = interpolate.Render(path, &p.config.ctx) + if err != nil { + return nil, false, false, fmt.Errorf("Error rendering one of 'path' template: %s", err) + } + } + + log.Printf("Rendered path items: %v", p.config.Paths) - ui.Say(fmt.Sprintf("Exporting image %v to destination: %v", builderID, p.config.Paths)) + imageID := artifact.State("ImageID").(string) + ui.Say(fmt.Sprintf("Exporting image %v to destination: %v", imageID, p.config.Paths)) // Set up exporter instance configuration. exporterName := fmt.Sprintf("%s-exporter", artifact.Id()) exporterMetadata := map[string]string{ - "image_id": builderID, + "image_id": imageID, "name": exporterName, "paths": strings.Join(p.config.Paths, " "), "user-data": CloudInitScript,