Skip to content

Commit c3ee7b2

Browse files
authored
Allow to pass chart values directly
2 parents f75f6be + 82e48e7 commit c3ee7b2

File tree

8 files changed

+74
-49
lines changed

8 files changed

+74
-49
lines changed

internal/bootstrap/helm.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ type ChartSetupper interface {
2020

2121
// Add Helm repos to user's local helm configuration file, Optionupdate all existing repos and pulls charts
2222
func SetupHelm(settings *cli.EnvSettings, charts ChartSetupper, setters ...helm.Option) (*helm.ChartCollection, error) {
23-
2423
// Default Options
2524
args := &helm.Options{
2625
Verbose: false,
@@ -34,7 +33,7 @@ func SetupHelm(settings *cli.EnvSettings, charts ChartSetupper, setters ...helm.
3433

3534
// Set up Helm action configuration
3635
if err := setEnv("HELM_EXPERIMENTAL_OCI", "1"); err != nil {
37-
slog.Error("Error setting OCI environment variable: %v", err)
36+
slog.Error("Error setting OCI environment variable", slog.Any("error", err))
3837
os.Exit(1)
3938
}
4039

internal/bootstrap/viper.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/spf13/viper"
1212
"go.uber.org/fx"
1313
"golang.org/x/xerrors"
14+
"gopkg.in/yaml.v3"
1415
"helm.sh/helm/v3/pkg/repo"
1516

1617
"github.com/ChristofferNissen/helmper/pkg/helm"
@@ -107,7 +108,7 @@ type config struct {
107108
}
108109

109110
// Reads flags from user and sets state accordingly
110-
func LoadViperConfiguration(rc helm.RegistryClient) (*viper.Viper, error) {
111+
func LoadViperConfiguration() (*viper.Viper, error) {
111112
viper := viper.New()
112113

113114
pflag.String("f", "unused", "path to configuration file")
@@ -155,7 +156,7 @@ func LoadViperConfiguration(rc helm.RegistryClient) (*viper.Viper, error) {
155156
}
156157

157158
for _, c := range inputConf.Charts {
158-
rc, _ = helm.NewRegistryClient(c.PlainHTTP, false)
159+
rc, _ := helm.NewRegistryClient(c.PlainHTTP, false)
159160
if strings.HasPrefix(c.Repo.URL, "oci://") {
160161
rc = helm.NewOCIRegistryClient(rc, c.PlainHTTP)
161162
}
@@ -165,6 +166,31 @@ func LoadViperConfiguration(rc helm.RegistryClient) (*viper.Viper, error) {
165166
LoadFunc: repo.LoadIndexFile,
166167
}
167168

169+
if c.ValuesFilePath != "" && len(c.Values) > 0 {
170+
return nil, xerrors.Errorf("invalid chart configuration: cannot have both ValuesFilePath and Values defined at the same time")
171+
}
172+
173+
if c.ValuesFilePath == "" && len(c.Values) > 0 {
174+
// write c.Values into a temp file and set c.ValuesFilePath to its path
175+
176+
yamlBytes, err := yaml.Marshal(c.Values)
177+
if err != nil {
178+
return nil, xerrors.Errorf("failed to marshal values to YAML: %w", err)
179+
}
180+
181+
tmpValuesFile, err := os.CreateTemp("", "chart_values_*.yaml")
182+
if err != nil {
183+
return nil, xerrors.Errorf("failed to create temp file: %w", err)
184+
}
185+
defer tmpValuesFile.Close()
186+
187+
if _, err := tmpValuesFile.Write(yamlBytes); err != nil {
188+
return nil, xerrors.Errorf("failed to write YAML to temp file: %w", err)
189+
}
190+
191+
c.ValuesFilePath = tmpValuesFile.Name()
192+
}
193+
168194
if conf.Parser.FailOnMissingValues {
169195
if c.ValuesFilePath == "" {
170196
continue

pkg/helm/chart.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func DependencyToChart(d *chart.Dependency, p *Chart) *Chart {
4646
Version: d.Version,
4747
Parent: p,
4848
ValuesFilePath: p.ValuesFilePath,
49+
Values: p.Values,
4950
DepsCount: 0,
5051
PlainHTTP: p.PlainHTTP,
5152
RegistryClient: p.RegistryClient,
@@ -57,7 +58,6 @@ func DependencyToChart(d *chart.Dependency, p *Chart) *Chart {
5758

5859
// addToHelmRepositoryFile adds repository to Helm repository.yml to enable querying/pull
5960
func (c Chart) addToHelmRepositoryFile(settings *cli.EnvSettings) (bool, error) {
60-
6161
var f *repo.File = repo.NewFile()
6262
if file.Exists(settings.RepositoryConfig) {
6363
file, err := repo.LoadFile(settings.RepositoryConfig)
@@ -66,12 +66,12 @@ func (c Chart) addToHelmRepositoryFile(settings *cli.EnvSettings) (bool, error)
6666
}
6767
f = file
6868
} else {
69-
f.WriteFile(settings.RepositoryConfig, 0644)
69+
f.WriteFile(settings.RepositoryConfig, 0o644)
7070
}
7171

7272
if !f.Has(c.Repo.Name) {
7373
f.Update(&c.Repo)
74-
return true, f.WriteFile(settings.RepositoryConfig, 0644)
74+
return true, f.WriteFile(settings.RepositoryConfig, 0o644)
7575
}
7676

7777
return false, nil
@@ -226,7 +226,7 @@ func (c *Chart) modifyRegistryReferences(settings *cli.EnvSettings, newRegistry
226226

227227
// Write the lock file to the chart path
228228
lockFilePath := filepath.Join(dir, c.Name, "Chart.lock")
229-
if err := os.WriteFile(lockFilePath, data, 0644); err != nil {
229+
if err := os.WriteFile(lockFilePath, data, 0o644); err != nil {
230230
return "", fmt.Errorf("failed to write lock file: %w", err)
231231
}
232232

@@ -410,7 +410,6 @@ func (c Chart) Pull(settings *cli.EnvSettings) (string, error) {
410410
}
411411

412412
func (c Chart) Locate(settings *cli.EnvSettings) (string, error) {
413-
414413
// Check if the repository URL is an OCI URL
415414
if strings.HasPrefix(c.Repo.URL, "oci://") {
416415
// Pull the chart from OCI
@@ -440,23 +439,21 @@ func (c Chart) Locate(settings *cli.EnvSettings) (string, error) {
440439
return chartPath, nil
441440
}
442441

443-
func (c Chart) Values(settings *cli.EnvSettings) (map[string]any, error) {
442+
func (c Chart) GetValues(settings *cli.EnvSettings) (map[string]any, error) {
444443
// Get detailed information about the chart
445444
chartRef, err := c.ChartRef(settings)
446445
if err != nil {
447446
return nil, err
448447
}
449448

450449
// Check if file exists, or use default values
451-
var values chartutil.Values
450+
var values chartutil.Values = chartRef.Values
452451
if file.Exists(c.ValuesFilePath) {
453452
valuesFromFile, err := chartutil.ReadValuesFile(c.ValuesFilePath)
454453
if err != nil {
455454
return nil, err
456455
}
457456
values = valuesFromFile.AsMap()
458-
} else {
459-
values = chartRef.Values
460457
}
461458

462459
vs, err := chartutil.CoalesceValues(chartRef, values)
@@ -465,7 +462,7 @@ func (c Chart) Values(settings *cli.EnvSettings) (map[string]any, error) {
465462
}
466463

467464
if c.Parent != nil {
468-
pv, err := c.Parent.Values(settings)
465+
pv, err := c.Parent.GetValues(settings)
469466
if err != nil {
470467
return nil, err
471468
}
@@ -510,7 +507,7 @@ func (c *Chart) Read(settings *cli.EnvSettings, update bool) (string, *chart.Cha
510507
}
511508

512509
// Get custom Helm values
513-
values, err := c.Values(settings)
510+
values, err := c.GetValues(settings)
514511
if err != nil {
515512
return "", nil, nil, err
516513
}

pkg/helm/chartImportOption.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func (io *IdentifyImportOption) Run(_ context.Context) (RegistryChartStatus, Reg
7474

7575
existsInRegistry := registry.Exists(context.TODO(), n, v, []*registry.Registry{r})[r.URL]
7676
b := io.All || !existsInRegistry
77-
elem[&c] = b
77+
elem[c] = b
7878
if b {
7979
sc.Inc(r.URL + "charts")
8080
}

pkg/helm/chartOption.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ func (co *ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, e
322322
chartImageHelmValuesMap := make(ChartData)
323323

324324
for c := range charts {
325-
chartImageHelmValuesMap[*c.Chart] = nil
325+
chartImageHelmValuesMap[c.Chart] = nil
326326
}
327327

328328
return chartImageHelmValuesMap
@@ -341,7 +341,7 @@ func (co *ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, e
341341
c, chart := chart.Chart, chart.chartRef
342342

343343
// Get custom Helm values
344-
values, err := c.Values(co.Settings)
344+
values, err := c.GetValues(co.Settings)
345345
if err != nil {
346346
return err
347347
}
@@ -448,10 +448,10 @@ func (co *ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, e
448448

449449
// Add image map to chart map
450450
switch {
451-
case chartImageHelmValuesMap[*i.chart] == nil:
452-
chartImageHelmValuesMap[*i.chart] = imageHelmValuesPathMap
453-
case chartImageHelmValuesMap[*i.chart][i.image] == nil:
454-
chartImageHelmValuesMap[*i.chart][i.image] = imageHelmValuesPathMap[i.image]
451+
case chartImageHelmValuesMap[i.chart] == nil:
452+
chartImageHelmValuesMap[i.chart] = imageHelmValuesPathMap
453+
case chartImageHelmValuesMap[i.chart][i.image] == nil:
454+
chartImageHelmValuesMap[i.chart][i.image] = imageHelmValuesPathMap[i.image]
455455
}
456456

457457
id = id + 1
@@ -488,7 +488,7 @@ func (co *ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, e
488488

489489
if len(co.Images) > 0 {
490490
// Add in images from config
491-
placeHolder := Chart{Name: "images", Version: "0.0.0"}
491+
placeHolder := &Chart{Name: "images", Version: "0.0.0"}
492492
m := map[*image.Image][]string{}
493493
for _, i := range co.Images {
494494
m[&i] = []string{}
@@ -498,8 +498,8 @@ func (co *ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, e
498498

499499
// Make sure we parse Charts with no images as well
500500
for _, c := range co.ChartCollection.Charts {
501-
if cd[*c] == nil {
502-
cd[*c] = make(map[*image.Image][]string)
501+
if cd[c] == nil {
502+
cd[c] = make(map[*image.Image][]string)
503503
}
504504
}
505505

pkg/helm/types.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ type Images struct {
2222
}
2323

2424
type Chart struct {
25-
Name string `json:"name"`
26-
Version string `json:"version"`
27-
ValuesFilePath string `json:"valuesFilePath"`
28-
Repo repo.Entry `json:"repo"`
25+
Name string `json:"name"`
26+
Version string `json:"version"`
27+
ValuesFilePath string `json:"valuesFilePath"`
28+
Values map[string]any `json:"values,omitempty"`
29+
Repo repo.Entry `json:"repo"`
2930
Parent *Chart
3031
Images *Images `json:"images"`
3132
PlainHTTP bool `json:"plainHTTP"`
@@ -51,7 +52,7 @@ type imageInfo struct {
5152
collection *[]string
5253
}
5354

54-
type ChartData map[Chart]map[*image.Image][]string
55+
type ChartData map[*Chart]map[*image.Image][]string
5556

5657
type RegistryChartStatus map[*registry.Registry]map[*Chart]bool
5758

pkg/trivy/main.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ type ScanOption struct {
3232
}
3333

3434
func (opts ScanOption) Scan(reference string) (types.Report, error) {
35-
3635
platform := ftypes.Platform{}
3736
if opts.Architecture != nil {
3837
p, _ := v1.ParsePlatform(*opts.Architecture)
@@ -57,7 +56,7 @@ func (opts ScanOption) Scan(reference string) (types.Report, error) {
5756
ImageSources: []ftypes.ImageSource{ftypes.RemoteImageSource},
5857
})
5958
if err != nil {
60-
slog.Error("NewContainerImage failed: %v", err)
59+
slog.Error("NewContainerImage failed", slog.Any("error", err))
6160
return types.Report{}, err
6261
}
6362
defer cleanup()
@@ -94,7 +93,7 @@ func (opts ScanOption) Scan(reference string) (types.Report, error) {
9493
},
9594
})
9695
if err != nil {
97-
slog.Error("NewArtifact failed: %v", err)
96+
slog.Error("NewArtifact failed: %v", slog.Any("error", err))
9897
return types.Report{}, err
9998
}
10099

@@ -134,5 +133,4 @@ func (opts ScanOption) Scan(reference string) (types.Report, error) {
134133
}
135134

136135
return report, nil
137-
138136
}

website/docs/config.md

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ sidebar_position: 4
77

88
## Location
99

10-
The configuration file `helmper.yaml` can be placed in:
10+
The configuration file `helmper.yaml` can be placed in:
1111

1212
- Current directory (`.`)
1313
- `$HOME/.config/helmper/`
@@ -70,7 +70,9 @@ charts:
7070
pass_credentials_all: false
7171
- name: kyverno
7272
version: 3.1.1
73-
valuesFilePath: /workspace/.in/values/kyverno/values.yaml
73+
values:
74+
namespaceOverride: system
75+
registry: customer-registry.io/
7476
repo:
7577
name: kyverno
7678
url: https://kyverno.github.io/kyverno/
@@ -94,7 +96,7 @@ charts:
9496
- ref: quay.io/cilium/cilium-envoy
9597
excludeCopacetic:
9698
- ref: quay.io/cilium/startup-script
97-
modify:
99+
modify:
98100
- fromValuePath: operator.image.repository
99101
to: quay.io/cilium/operator-generic
100102
- name: prometheus
@@ -152,6 +154,7 @@ registries:
152154
| `charts[].version` | string | | true | Desired version of chart. Supports semver literal or semver ranges (semantic version spec 2.0) |
153155
| `charts[].plainHTTP` | bool | false | false | Use HTTP instead of HTTPS for repository protocol |
154156
| `charts[].valuesFilePath` | string | "" | false | Path to custom values.yaml to customize importing |
157+
| `charts[].values` | object | nil | false | Inline values to customize importing (cannot be used together with `charts[].valuesFilePath`) |
155158
| `charts[].images` | object | nil | false | Customization options for images in chart |
156159
| `charts[].images.exclude` | list(object) | [] | false | Defines which images to exclude from processing |
157160
| `charts[].images.exclude[].ref` | string | "" | false | Container Image reference |
@@ -193,6 +196,7 @@ The `charts` configuration option defines which charts to import.
193196
| `charts[].name` | string | | true | Chart name |
194197
| `charts[].version` | string | | true | Desired version of chart. Supports semver literal or semver ranges (semantic version spec 2.0) |
195198
| `charts[].valuesFilePath` | string | "" | false | Path to custom values.yaml to customize importing |
199+
| `charts[].values` | object | nil | false | Inline values to customize importing (cannot be used together with `charts[].valuesFilePath`) |
196200
| `charts[].images` | object | nil | false | Customization options for images in chart |
197201
| `charts[].images.exclude` | list(object) | [] | false | Defines which images to exclude from processing |
198202
| `charts[].images.exclude.ref` | string | "" | false | Container Image reference |
@@ -240,25 +244,25 @@ Simply define the additional images in the `images` configuration option.
240244

241245
Here are the supported formats for `import.copacetic.buildkit.addr` configuration option:
242246

243-
* `unix:///path/to/buildkit.sock` - Connect to buildkit over unix socket.
244-
* `tcp://$BUILDKIT_ADDR:$PORT` - Connect to buildkit over TCP. (not recommended for security reasons)
245-
* `docker://<docker connection spec>` - Connect to docker, currently only unix sockets are supported, e.g. `docker://unix:///var/run/docker.sock` (or just `docker://`).
246-
* `docker-container://my-buildkit-container` - Connect to a buildkitd running in a docker container.
247-
* `buildx://my-builder` - Connect to a buildx builder (or `buildx://` for the currently selected builder). *Note: only container-backed buildx instances are currently supported*
248-
* `nerdctl-container://my-container-name` - Similar to `docker-container` but uses `nerdctl`.
249-
* `podman-container://my-container-name` - Similar to `docker-container` but uses `podman`.
250-
* `ssh://myhost` - Connect to a buildkit instance over SSH. Format of the host spec should mimic the SSH command.
251-
* `kubepod://mypod` - Connect to buildkit running in a Kubernetes pod. Can also specify kubectl context and pod namespace (`kubepod://mypod?context=foo&namespace=notdefault`).
247+
- `unix:///path/to/buildkit.sock` - Connect to buildkit over unix socket.
248+
- `tcp://$BUILDKIT_ADDR:$PORT` - Connect to buildkit over TCP. (not recommended for security reasons)
249+
- `docker://<docker connection spec>` - Connect to docker, currently only unix sockets are supported, e.g. `docker://unix:///var/run/docker.sock` (or just `docker://`).
250+
- `docker-container://my-buildkit-container` - Connect to a buildkitd running in a docker container.
251+
- `buildx://my-builder` - Connect to a buildx builder (or `buildx://` for the currently selected builder). *Note: only container-backed buildx instances are currently supported*
252+
- `nerdctl-container://my-container-name` - Similar to `docker-container` but uses `nerdctl`.
253+
- `podman-container://my-container-name` - Similar to `docker-container` but uses `podman`.
254+
- `ssh://myhost` - Connect to a buildkit instance over SSH. Format of the host spec should mimic the SSH command.
255+
- `kubepod://mypod` - Connect to buildkit running in a Kubernetes pod. Can also specify kubectl context and pod namespace (`kubepod://mypod?context=foo&namespace=notdefault`).
252256

253257
See more details in the [Copacetic Documentation](https://project-copacetic.github.io/copacetic/website/custom-address)
254258

255259
### mTLS
256260

257261
Helmper supports setting required configuration options for enabling mTLS with an expose Buildkit instance over TCP, although the following configuration options:
258262

259-
* `import.copacetic.buildkitd.CACertPath`
260-
* `import.copacetic.buildkitd.certPath`
261-
* `import.copacetic.buildkitd.keyPath`
263+
- `import.copacetic.buildkitd.CACertPath`
264+
- `import.copacetic.buildkitd.certPath`
265+
- `import.copacetic.buildkitd.keyPath`
262266

263267
Read more in the official docs by [moby/buildkit](https://github.com/moby/buildkit?tab=readme-ov-file#expose-buildkit-as-a-tcp-service).
264268

0 commit comments

Comments
 (0)