github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/inline/render.go (about) 1 package inline 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 8 "github.com/go-kit/kit/log" 9 "github.com/go-kit/kit/log/level" 10 "github.com/pkg/errors" 11 "github.com/replicatedhq/libyaml" 12 "github.com/replicatedhq/ship/pkg/api" 13 "github.com/replicatedhq/ship/pkg/lifecycle/render/root" 14 "github.com/replicatedhq/ship/pkg/templates" 15 "github.com/replicatedhq/ship/pkg/util" 16 "github.com/spf13/viper" 17 ) 18 19 // Renderer is something that can render a helm asset as part of a planner.Plan 20 type Renderer interface { 21 Execute( 22 rootFs root.Fs, 23 asset api.InlineAsset, 24 meta api.ReleaseMetadata, 25 templateContext map[string]interface{}, 26 configGroups []libyaml.ConfigGroup, 27 ) func(ctx context.Context) error 28 } 29 30 var _ Renderer = &LocalRenderer{} 31 32 // LocalRenderer can add a helm step to the plan, the step will fetch the 33 // chart to a temporary location and then run a local operation to run the helm templating 34 type LocalRenderer struct { 35 Logger log.Logger 36 BuilderBuilder *templates.BuilderBuilder 37 Viper *viper.Viper 38 } 39 40 func NewRenderer( 41 logger log.Logger, 42 bb *templates.BuilderBuilder, 43 v *viper.Viper, 44 ) Renderer { 45 return &LocalRenderer{ 46 Logger: logger, 47 BuilderBuilder: bb, 48 Viper: v, 49 } 50 } 51 52 func (r *LocalRenderer) Execute( 53 rootFs root.Fs, 54 asset api.InlineAsset, 55 meta api.ReleaseMetadata, 56 templateContext map[string]interface{}, 57 configGroups []libyaml.ConfigGroup, 58 ) func(ctx context.Context) error { 59 debug := level.Debug(log.With(r.Logger, "step.type", "render", "render.phase", "execute", "asset.type", "inline", "dest", asset.Dest, "description", asset.Description)) 60 61 return func(ctx context.Context) error { 62 debug.Log("event", "execute") 63 64 builder, err := r.BuilderBuilder.FullBuilder(meta, configGroups, templateContext) 65 if err != nil { 66 return errors.Wrap(err, "init builder") 67 } 68 69 builtAsset, err := templateInline(builder, asset) 70 if err != nil { 71 return errors.Wrap(err, "building contents") 72 } 73 74 err = util.IsLegalPath(builtAsset.Dest) 75 if err != nil { 76 return errors.Wrap(err, "write inline asset") 77 } 78 79 basePath := filepath.Dir(asset.Dest) 80 debug.Log("event", "mkdirall.attempt", "dest", builtAsset.Dest, "basePath", basePath) 81 if err := rootFs.MkdirAll(basePath, 0755); err != nil { 82 debug.Log("event", "mkdirall.fail", "err", err, "dest", builtAsset.Dest, "basePath", basePath) 83 return errors.Wrapf(err, "write directory to %s", builtAsset.Dest) 84 } 85 86 mode := os.FileMode(0644) 87 if builtAsset.Mode != os.FileMode(0) { 88 debug.Log("event", "applying override permissions", "override.filemode", builtAsset.Mode, "override.filemode.int", int(builtAsset.Mode)) 89 mode = builtAsset.Mode 90 } 91 92 if err := rootFs.WriteFile(builtAsset.Dest, []byte(builtAsset.Contents), mode); err != nil { 93 debug.Log("event", "execute.fail", "err", err) 94 return errors.Wrapf(err, "Write inline asset to %s", builtAsset.Dest) 95 } 96 if err := rootFs.Chmod(builtAsset.Dest, mode); err != nil { 97 debug.Log("event", "chmod.fail", "err", err) 98 return errors.Wrapf(err, "Set inline asset %s filemode to %s", builtAsset.Dest, mode) 99 } 100 return nil 101 102 } 103 } 104 105 func templateInline(builder *templates.Builder, asset api.InlineAsset) (api.InlineAsset, error) { 106 builtAsset := asset 107 var err error 108 109 builtAsset.Contents, err = builder.String(asset.Contents) 110 if err != nil { 111 return builtAsset, errors.Wrap(err, "building contents") 112 } 113 114 builtAsset.Dest, err = builder.String(asset.Dest) 115 if err != nil { 116 return builtAsset, errors.Wrap(err, "building dest") 117 } 118 119 return builtAsset, nil 120 }