Skip to content

Commit

Permalink
feat(bundles): allow usage of bundles with included secret-values as …
Browse files Browse the repository at this point in the history
…oci chart dependencies

Decode secret-values.yaml included into the bundle when converging a werf project with bundle enabled as a chart dependency.

Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
  • Loading branch information
distorhead committed Mar 2, 2023
1 parent e1dcbea commit 469678c
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 86 deletions.
13 changes: 11 additions & 2 deletions cmd/werf/bundle/export/export.go
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/werf/werf/pkg/deploy/helm/chart_extender"
"github.com/werf/werf/pkg/deploy/helm/chart_extender/helpers"
"github.com/werf/werf/pkg/deploy/helm/command_helpers"
"github.com/werf/werf/pkg/deploy/secrets_manager"
"github.com/werf/werf/pkg/git_repo"
"github.com/werf/werf/pkg/git_repo/gitdata"
"github.com/werf/werf/pkg/image"
Expand Down Expand Up @@ -123,7 +124,9 @@ func NewCmd(ctx context.Context) *cobra.Command {
common.SetupValues(&commonCmdData, cmd)

commonCmdData.SetupDisableDefaultValues(cmd)
commonCmdData.SetupDisableDefaultSecretValues(cmd)
commonCmdData.SetupSkipDependenciesRepoRefresh(cmd)
common.SetupIgnoreSecretKey(&commonCmdData, cmd)

common.SetupSaveBuildReport(&commonCmdData, cmd)
common.SetupBuildReportPath(&commonCmdData, cmd)
Expand Down Expand Up @@ -361,9 +364,15 @@ func runExport(ctx context.Context, imagesToProcess build.ImagesToProcess) error

helm_v3.Settings.Debug = *commonCmdData.LogDebug

secretsManager := secrets_manager.NewSecretsManager(secrets_manager.SecretsManagerOptions{DisableSecretsDecryption: *commonCmdData.IgnoreSecretKey})

loader.GlobalLoadOptions = &loader.LoadOptions{
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender { return chart_extender.NewWerfSubchart() },
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender {
return chart_extender.NewWerfSubchart(ctx, secretsManager, chart_extender.WerfSubchartOptions{
DisableDefaultSecretValues: *commonCmdData.DisableDefaultSecretValues,
})
},
}

chartVersion := fmt.Sprintf("0.0.0-%d", time.Now().Unix())
Expand Down
8 changes: 6 additions & 2 deletions cmd/werf/bundle/publish/publish.go
Expand Up @@ -386,8 +386,12 @@ func runPublish(ctx context.Context, imagesToProcess build.ImagesToProcess) erro
helm_v3.Settings.Debug = *commonCmdData.LogDebug

loader.GlobalLoadOptions = &loader.LoadOptions{
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender { return chart_extender.NewWerfSubchart() },
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender {
return chart_extender.NewWerfSubchart(ctx, secretsManager, chart_extender.WerfSubchartOptions{
DisableDefaultSecretValues: *commonCmdData.DisableDefaultSecretValues,
})
},
}

sv, err := bundles.BundleTagToChartVersion(ctx, cmdData.Tag, time.Now())
Expand Down
9 changes: 7 additions & 2 deletions cmd/werf/bundle/render/render.go
Expand Up @@ -88,6 +88,7 @@ func NewCmd(ctx context.Context) *cobra.Command {
common.SetupValues(&commonCmdData, cmd)
common.SetupSecretValues(&commonCmdData, cmd)
common.SetupIgnoreSecretKey(&commonCmdData, cmd)
commonCmdData.SetupDisableDefaultSecretValues(cmd)

common.SetupRelease(&commonCmdData, cmd)
common.SetupNamespace(&commonCmdData, cmd)
Expand Down Expand Up @@ -212,8 +213,12 @@ func runRender(ctx context.Context) error {
}

loader.GlobalLoadOptions = &loader.LoadOptions{
ChartExtender: bundle,
SubchartExtenderFactoryFunc: func() chart.ChartExtender { return chart_extender.NewWerfSubchart() },
ChartExtender: bundle,
SubchartExtenderFactoryFunc: func() chart.ChartExtender {
return chart_extender.NewWerfSubchart(ctx, secretsManager, chart_extender.WerfSubchartOptions{
DisableDefaultSecretValues: *commonCmdData.DisableDefaultSecretValues,
})
},
}

var output io.Writer
Expand Down
8 changes: 6 additions & 2 deletions cmd/werf/converge/converge.go
Expand Up @@ -450,8 +450,12 @@ func run(ctx context.Context, containerBackend container_backend.ContainerBacken
}

loader.GlobalLoadOptions = &loader.LoadOptions{
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender { return chart_extender.NewWerfSubchart() },
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender {
return chart_extender.NewWerfSubchart(ctx, secretsManager, chart_extender.WerfSubchartOptions{
DisableDefaultSecretValues: *commonCmdData.DisableDefaultSecretValues,
})
},
}

valueOpts := &values.Options{
Expand Down
8 changes: 6 additions & 2 deletions cmd/werf/render/render.go
Expand Up @@ -439,8 +439,12 @@ func runRender(ctx context.Context, imagesToProcess build.ImagesToProcess) error
helm_v3.Settings.Debug = *commonCmdData.LogDebug

loader.GlobalLoadOptions = &loader.LoadOptions{
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender { return chart_extender.NewWerfSubchart() },
ChartExtender: wc,
SubchartExtenderFactoryFunc: func() chart.ChartExtender {
return chart_extender.NewWerfSubchart(ctx, secretsManager, chart_extender.WerfSubchartOptions{
DisableDefaultSecretValues: *commonCmdData.DisableDefaultSecretValues,
})
},
}

templateOpts := helm_v3.TemplateCmdOptions{
Expand Down
26 changes: 2 additions & 24 deletions pkg/deploy/helm/chart_extender/bundle.go
Expand Up @@ -11,11 +11,9 @@ import (

"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/postrender"
"helm.sh/helm/v3/pkg/registry"
"sigs.k8s.io/yaml"

"github.com/werf/logboek"
"github.com/werf/werf/pkg/deploy/helm"
Expand Down Expand Up @@ -87,6 +85,7 @@ type Bundle struct {
*secrets.SecretsRuntimeData
*helpers.ChartExtenderServiceValuesData
*helpers.ChartExtenderContextData
*helpers.ChartExtenderValuesMerger
}

func (bundle *Bundle) ChainPostRenderer(postRenderer postrender.PostRenderer) postrender.PostRenderer {
Expand Down Expand Up @@ -140,28 +139,7 @@ func (bundle *Bundle) ChartDependenciesLoaded() error {

// MakeValues method for the chart.Extender interface
func (bundle *Bundle) MakeValues(inputVals map[string]interface{}) (map[string]interface{}, error) {
vals := make(map[string]interface{})

debugPrintValues(bundle.ChartExtenderContext, "service", bundle.ServiceValues)
chartutil.CoalesceTables(vals, bundle.ServiceValues)

if debugSecretValues() {
debugPrintValues(bundle.ChartExtenderContext, "secret", bundle.SecretsRuntimeData.DecryptedSecretValues)
}
chartutil.CoalesceTables(vals, bundle.SecretsRuntimeData.DecryptedSecretValues)

debugPrintValues(bundle.ChartExtenderContext, "input", inputVals)
chartutil.CoalesceTables(vals, inputVals)

if debugSecretValues() {
// Only print all values with secrets when secret values debug enabled
debugPrintValues(bundle.ChartExtenderContext, "all", vals)
}

data, err := yaml.Marshal(vals)
logboek.Context(bundle.ChartExtenderContext).Debug().LogF("-- Bundle.MakeValues result (err=%v):\n%s\n---\n", err, data)

return vals, nil
return bundle.MergeValues(bundle.ChartExtenderContext, inputVals, bundle.ServiceValues, bundle.SecretsRuntimeData)
}

// SetupTemplateFuncs method for the chart.Extender interface
Expand Down
@@ -0,0 +1,35 @@
package helpers

import (
"context"

"helm.sh/helm/v3/pkg/chartutil"

"github.com/werf/werf/pkg/deploy/helm/chart_extender/helpers/secrets"
)

type ChartExtenderValuesMerger struct{}

func (m *ChartExtenderValuesMerger) MergeValues(ctx context.Context, inputVals, serviceVals map[string]interface{}, secretsRuntimeData *secrets.SecretsRuntimeData) (map[string]interface{}, error) {
vals := make(map[string]interface{})

DebugPrintValues(ctx, "service", serviceVals)
chartutil.CoalesceTables(vals, serviceVals) // NOTE: service values will not be saved into the marshalled release

if secretsRuntimeData != nil {
if DebugSecretValues() {
DebugPrintValues(ctx, "secret", secretsRuntimeData.DecryptedSecretValues)
}
chartutil.CoalesceTables(vals, secretsRuntimeData.DecryptedSecretValues)
}

DebugPrintValues(ctx, "input", inputVals)
chartutil.CoalesceTables(vals, inputVals)

if DebugSecretValues() {
// Only print all values with secrets when secret values debug enabled
DebugPrintValues(ctx, "all", vals)
}

return vals, nil
}
Expand Up @@ -19,7 +19,7 @@ const (
SecretDirName = "secret"
)

func GetDefaultSecretValuesFile(chartDir string, loadedChartFiles []*chart.ChartExtenderBufferedFile) *chart.ChartExtenderBufferedFile {
func GetDefaultSecretValuesFile(loadedChartFiles []*chart.ChartExtenderBufferedFile) *chart.ChartExtenderBufferedFile {
for _, file := range loadedChartFiles {
if file.Name == DefaultSecretValuesFileName {
return file
Expand Down
Expand Up @@ -39,7 +39,7 @@ func (secretsRuntimeData *SecretsRuntimeData) DecodeAndLoadSecrets(ctx context.C
var loadedSecretValuesFiles []*chart.ChartExtenderBufferedFile

if !opts.WithoutDefaultSecretValues {
if defaultSecretValues := GetDefaultSecretValuesFile(chartDir, loadedChartFiles); defaultSecretValues != nil {
if defaultSecretValues := GetDefaultSecretValuesFile(loadedChartFiles); defaultSecretValues != nil {
loadedSecretValuesFiles = append(loadedSecretValuesFiles, defaultSecretValues)
}
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/deploy/helm/chart_extender/helpers/util.go
@@ -0,0 +1,23 @@
package helpers

import (
"context"
"os"

"sigs.k8s.io/yaml"

"github.com/werf/logboek"
)

func DebugPrintValues(ctx context.Context, name string, vals map[string]interface{}) {
data, err := yaml.Marshal(vals)
if err != nil {
logboek.Context(ctx).Debug().LogF("Unable to marshal %q values: %s\n", err)
} else {
logboek.Context(ctx).Debug().LogF("%q values:\n%s---\n", name, data)
}
}

func DebugSecretValues() bool {
return os.Getenv("WERF_DEBUG_SECRET_VALUES") == "1"
}
50 changes: 7 additions & 43 deletions pkg/deploy/helm/chart_extender/werf_chart.go
Expand Up @@ -94,6 +94,7 @@ type WerfChart struct {
*secrets.SecretsRuntimeData
*helpers.ChartExtenderServiceValuesData
*helpers.ChartExtenderContextData
*helpers.ChartExtenderValuesMerger
}

// ChartCreated method for the chart.Extender interface
Expand Down Expand Up @@ -144,52 +145,15 @@ func (wc *WerfChart) ChartDependenciesLoaded() error {
return nil
}

func debugSecretValues() bool {
return os.Getenv("WERF_DEBUG_SECRET_VALUES") == "1"
}

func debugPrintValues(ctx context.Context, name string, vals map[string]interface{}) {
data, err := yaml.Marshal(vals)
if err != nil {
logboek.Context(ctx).Debug().LogF("Unable to marshal %q values: %s\n", err)
} else {
logboek.Context(ctx).Debug().LogF("%q values:\n%s---\n", name, data)
}
}

func (wc *WerfChart) makeValues(inputVals map[string]interface{}, withSecrets bool) (map[string]interface{}, error) {
vals := make(map[string]interface{})

debugPrintValues(wc.ChartExtenderContext, "service", wc.ServiceValues)
chartutil.CoalesceTables(vals, wc.ServiceValues) // NOTE: service values will not be saved into the marshalled release

if withSecrets {
if debugSecretValues() {
debugPrintValues(wc.ChartExtenderContext, "secret", wc.SecretsRuntimeData.DecryptedSecretValues)
}
chartutil.CoalesceTables(vals, wc.SecretsRuntimeData.DecryptedSecretValues)
}

debugPrintValues(wc.ChartExtenderContext, "input", inputVals)
chartutil.CoalesceTables(vals, inputVals)

if debugSecretValues() {
// Only print all values with secrets when secret values debug enabled
debugPrintValues(wc.ChartExtenderContext, "all", vals)
}

return vals, nil
}

// MakeValues method for the chart.Extender interface
func (wc *WerfChart) MakeValues(inputVals map[string]interface{}) (map[string]interface{}, error) {
return wc.makeValues(inputVals, true)
return wc.MergeValues(wc.ChartExtenderContext, inputVals, wc.ServiceValues, wc.SecretsRuntimeData)
}

func (wc *WerfChart) MakeBundleValues(chrt *chart.Chart, inputVals map[string]interface{}) (map[string]interface{}, error) {
debugPrintValues(wc.ChartExtenderContext, "input", inputVals)
helpers.DebugPrintValues(wc.ChartExtenderContext, "input", inputVals)

vals, err := wc.makeValues(inputVals, false)
vals, err := wc.MergeValues(wc.ChartExtenderContext, inputVals, wc.ServiceValues, nil)
if err != nil {
return nil, fmt.Errorf("failed to coalesce werf chart values: %w", err)
}
Expand All @@ -207,14 +171,14 @@ func (wc *WerfChart) MakeBundleValues(chrt *chart.Chart, inputVals map[string]in

chartutil.CoalesceChartValues(chrt, valsCopy)

debugPrintValues(wc.ChartExtenderContext, "all", valsCopy)
helpers.DebugPrintValues(wc.ChartExtenderContext, "all", valsCopy)

return valsCopy, nil
}

func (wc *WerfChart) MakeBundleSecretValues(ctx context.Context, secretsRuntimeData *secrets.SecretsRuntimeData) (map[string]interface{}, error) {
if debugSecretValues() {
debugPrintValues(wc.ChartExtenderContext, "secret", wc.SecretsRuntimeData.DecryptedSecretValues)
if helpers.DebugSecretValues() {
helpers.DebugPrintValues(wc.ChartExtenderContext, "secret", wc.SecretsRuntimeData.DecryptedSecretValues)
}
return secretsRuntimeData.GetEncodedSecretValues(ctx, wc.SecretsManager, wc.GiterminismManager.ProjectDir())
}
Expand Down
46 changes: 39 additions & 7 deletions pkg/deploy/helm/chart_extender/werf_subchart.go
@@ -1,32 +1,66 @@
package chart_extender

import (
"context"
"fmt"
"text/template"

"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"

"github.com/werf/logboek"
"github.com/werf/werf/pkg/deploy/helm/chart_extender/helpers"
"github.com/werf/werf/pkg/deploy/helm/chart_extender/helpers/secrets"
"github.com/werf/werf/pkg/deploy/secrets_manager"
)

// NOTE: maybe in the future we will need a support for the werf project to be used as a chart.
// NOTE: This extender allows to define this behaviour.

func NewWerfSubchart() *WerfSubchart {
return &WerfSubchart{}
type WerfSubchartOptions struct {
DisableDefaultSecretValues bool
}

func NewWerfSubchart(ctx context.Context, secretsManager *secrets_manager.SecretsManager, opts WerfSubchartOptions) *WerfSubchart {
return &WerfSubchart{
SecretsManager: secretsManager,
ChartExtenderContextData: helpers.NewChartExtenderContextData(ctx),
DisableDefaultSecretValues: opts.DisableDefaultSecretValues,
}
}

type WerfSubchart struct {
HelmChart *chart.Chart
HelmChart *chart.Chart
SecretsManager *secrets_manager.SecretsManager

DisableDefaultSecretValues bool

*secrets.SecretsRuntimeData
*helpers.ChartExtenderContextData
*helpers.ChartExtenderValuesMerger
}

// ChartCreated method for the chart.Extender interface
func (wc *WerfSubchart) ChartCreated(c *chart.Chart) error {
wc.HelmChart = c
wc.SecretsRuntimeData = secrets.NewSecretsRuntimeData()
return nil
}

// ChartLoaded method for the chart.Extender interface
func (wc *WerfSubchart) ChartLoaded(files []*chart.ChartExtenderBufferedFile) error {
if wc.SecretsManager != nil {
if wc.DisableDefaultSecretValues {
logboek.Context(wc.ChartExtenderContext).Info().LogF("Disabled subchart secret values\n")
}

if err := wc.SecretsRuntimeData.DecodeAndLoadSecrets(wc.ChartExtenderContext, files, "", "", wc.SecretsManager, secrets.DecodeAndLoadSecretsOptions{
WithoutDefaultSecretValues: wc.DisableDefaultSecretValues,
}); err != nil {
return fmt.Errorf("error decoding secrets: %w", err)
}
}

return nil
}

Expand All @@ -37,9 +71,7 @@ func (wc *WerfSubchart) ChartDependenciesLoaded() error {

// MakeValues method for the chart.Extender interface
func (wc *WerfSubchart) MakeValues(inputVals map[string]interface{}) (map[string]interface{}, error) {
vals := make(map[string]interface{})
chartutil.CoalesceTables(vals, inputVals)
return vals, nil
return wc.MergeValues(wc.ChartExtenderContext, inputVals, nil, wc.SecretsRuntimeData)
}

// SetupTemplateFuncs method for the chart.Extender interface
Expand Down

0 comments on commit 469678c

Please sign in to comment.