Skip to content

Commit

Permalink
Allow to pass chart values directly
Browse files Browse the repository at this point in the history
  • Loading branch information
kuznero authored Feb 20, 2025
2 parents f75f6be + 82e48e7 commit c3ee7b2
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 49 deletions.
3 changes: 1 addition & 2 deletions internal/bootstrap/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ type ChartSetupper interface {

// Add Helm repos to user's local helm configuration file, Optionupdate all existing repos and pulls charts
func SetupHelm(settings *cli.EnvSettings, charts ChartSetupper, setters ...helm.Option) (*helm.ChartCollection, error) {

// Default Options
args := &helm.Options{
Verbose: false,
Expand All @@ -34,7 +33,7 @@ func SetupHelm(settings *cli.EnvSettings, charts ChartSetupper, setters ...helm.

// Set up Helm action configuration
if err := setEnv("HELM_EXPERIMENTAL_OCI", "1"); err != nil {
slog.Error("Error setting OCI environment variable: %v", err)
slog.Error("Error setting OCI environment variable", slog.Any("error", err))
os.Exit(1)
}

Expand Down
30 changes: 28 additions & 2 deletions internal/bootstrap/viper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/spf13/viper"
"go.uber.org/fx"
"golang.org/x/xerrors"
"gopkg.in/yaml.v3"
"helm.sh/helm/v3/pkg/repo"

"github.com/ChristofferNissen/helmper/pkg/helm"
Expand Down Expand Up @@ -107,7 +108,7 @@ type config struct {
}

// Reads flags from user and sets state accordingly
func LoadViperConfiguration(rc helm.RegistryClient) (*viper.Viper, error) {
func LoadViperConfiguration() (*viper.Viper, error) {
viper := viper.New()

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

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

if c.ValuesFilePath != "" && len(c.Values) > 0 {
return nil, xerrors.Errorf("invalid chart configuration: cannot have both ValuesFilePath and Values defined at the same time")
}

if c.ValuesFilePath == "" && len(c.Values) > 0 {
// write c.Values into a temp file and set c.ValuesFilePath to its path

yamlBytes, err := yaml.Marshal(c.Values)
if err != nil {
return nil, xerrors.Errorf("failed to marshal values to YAML: %w", err)
}

tmpValuesFile, err := os.CreateTemp("", "chart_values_*.yaml")
if err != nil {
return nil, xerrors.Errorf("failed to create temp file: %w", err)
}
defer tmpValuesFile.Close()

if _, err := tmpValuesFile.Write(yamlBytes); err != nil {
return nil, xerrors.Errorf("failed to write YAML to temp file: %w", err)
}

c.ValuesFilePath = tmpValuesFile.Name()
}

if conf.Parser.FailOnMissingValues {
if c.ValuesFilePath == "" {
continue
Expand Down
19 changes: 8 additions & 11 deletions pkg/helm/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func DependencyToChart(d *chart.Dependency, p *Chart) *Chart {
Version: d.Version,
Parent: p,
ValuesFilePath: p.ValuesFilePath,
Values: p.Values,
DepsCount: 0,
PlainHTTP: p.PlainHTTP,
RegistryClient: p.RegistryClient,
Expand All @@ -57,7 +58,6 @@ func DependencyToChart(d *chart.Dependency, p *Chart) *Chart {

// addToHelmRepositoryFile adds repository to Helm repository.yml to enable querying/pull
func (c Chart) addToHelmRepositoryFile(settings *cli.EnvSettings) (bool, error) {

var f *repo.File = repo.NewFile()
if file.Exists(settings.RepositoryConfig) {
file, err := repo.LoadFile(settings.RepositoryConfig)
Expand All @@ -66,12 +66,12 @@ func (c Chart) addToHelmRepositoryFile(settings *cli.EnvSettings) (bool, error)
}
f = file
} else {
f.WriteFile(settings.RepositoryConfig, 0644)
f.WriteFile(settings.RepositoryConfig, 0o644)
}

if !f.Has(c.Repo.Name) {
f.Update(&c.Repo)
return true, f.WriteFile(settings.RepositoryConfig, 0644)
return true, f.WriteFile(settings.RepositoryConfig, 0o644)
}

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

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

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

func (c Chart) Locate(settings *cli.EnvSettings) (string, error) {

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

func (c Chart) Values(settings *cli.EnvSettings) (map[string]any, error) {
func (c Chart) GetValues(settings *cli.EnvSettings) (map[string]any, error) {
// Get detailed information about the chart
chartRef, err := c.ChartRef(settings)
if err != nil {
return nil, err
}

// Check if file exists, or use default values
var values chartutil.Values
var values chartutil.Values = chartRef.Values
if file.Exists(c.ValuesFilePath) {
valuesFromFile, err := chartutil.ReadValuesFile(c.ValuesFilePath)
if err != nil {
return nil, err
}
values = valuesFromFile.AsMap()
} else {
values = chartRef.Values
}

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

if c.Parent != nil {
pv, err := c.Parent.Values(settings)
pv, err := c.Parent.GetValues(settings)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -510,7 +507,7 @@ func (c *Chart) Read(settings *cli.EnvSettings, update bool) (string, *chart.Cha
}

// Get custom Helm values
values, err := c.Values(settings)
values, err := c.GetValues(settings)
if err != nil {
return "", nil, nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/helm/chartImportOption.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (io *IdentifyImportOption) Run(_ context.Context) (RegistryChartStatus, Reg

existsInRegistry := registry.Exists(context.TODO(), n, v, []*registry.Registry{r})[r.URL]
b := io.All || !existsInRegistry
elem[&c] = b
elem[c] = b
if b {
sc.Inc(r.URL + "charts")
}
Expand Down
18 changes: 9 additions & 9 deletions pkg/helm/chartOption.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ func (co *ChartOption) Run(ctx context.Context, setters ...Option) (ChartData, e
chartImageHelmValuesMap := make(ChartData)

for c := range charts {
chartImageHelmValuesMap[*c.Chart] = nil
chartImageHelmValuesMap[c.Chart] = nil
}

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

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

// Add image map to chart map
switch {
case chartImageHelmValuesMap[*i.chart] == nil:
chartImageHelmValuesMap[*i.chart] = imageHelmValuesPathMap
case chartImageHelmValuesMap[*i.chart][i.image] == nil:
chartImageHelmValuesMap[*i.chart][i.image] = imageHelmValuesPathMap[i.image]
case chartImageHelmValuesMap[i.chart] == nil:
chartImageHelmValuesMap[i.chart] = imageHelmValuesPathMap
case chartImageHelmValuesMap[i.chart][i.image] == nil:
chartImageHelmValuesMap[i.chart][i.image] = imageHelmValuesPathMap[i.image]
}

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

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

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

Expand Down
11 changes: 6 additions & 5 deletions pkg/helm/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ type Images struct {
}

type Chart struct {
Name string `json:"name"`
Version string `json:"version"`
ValuesFilePath string `json:"valuesFilePath"`
Repo repo.Entry `json:"repo"`
Name string `json:"name"`
Version string `json:"version"`
ValuesFilePath string `json:"valuesFilePath"`
Values map[string]any `json:"values,omitempty"`
Repo repo.Entry `json:"repo"`
Parent *Chart
Images *Images `json:"images"`
PlainHTTP bool `json:"plainHTTP"`
Expand All @@ -51,7 +52,7 @@ type imageInfo struct {
collection *[]string
}

type ChartData map[Chart]map[*image.Image][]string
type ChartData map[*Chart]map[*image.Image][]string

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

Expand Down
6 changes: 2 additions & 4 deletions pkg/trivy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ type ScanOption struct {
}

func (opts ScanOption) Scan(reference string) (types.Report, error) {

platform := ftypes.Platform{}
if opts.Architecture != nil {
p, _ := v1.ParsePlatform(*opts.Architecture)
Expand All @@ -57,7 +56,7 @@ func (opts ScanOption) Scan(reference string) (types.Report, error) {
ImageSources: []ftypes.ImageSource{ftypes.RemoteImageSource},
})
if err != nil {
slog.Error("NewContainerImage failed: %v", err)
slog.Error("NewContainerImage failed", slog.Any("error", err))
return types.Report{}, err
}
defer cleanup()
Expand Down Expand Up @@ -94,7 +93,7 @@ func (opts ScanOption) Scan(reference string) (types.Report, error) {
},
})
if err != nil {
slog.Error("NewArtifact failed: %v", err)
slog.Error("NewArtifact failed: %v", slog.Any("error", err))
return types.Report{}, err
}

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

return report, nil

}
34 changes: 19 additions & 15 deletions website/docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ sidebar_position: 4

## Location

The configuration file `helmper.yaml` can be placed in:
The configuration file `helmper.yaml` can be placed in:

- Current directory (`.`)
- `$HOME/.config/helmper/`
Expand Down Expand Up @@ -70,7 +70,9 @@ charts:
pass_credentials_all: false
- name: kyverno
version: 3.1.1
valuesFilePath: /workspace/.in/values/kyverno/values.yaml
values:
namespaceOverride: system
registry: customer-registry.io/
repo:
name: kyverno
url: https://kyverno.github.io/kyverno/
Expand All @@ -94,7 +96,7 @@ charts:
- ref: quay.io/cilium/cilium-envoy
excludeCopacetic:
- ref: quay.io/cilium/startup-script
modify:
modify:
- fromValuePath: operator.image.repository
to: quay.io/cilium/operator-generic
- name: prometheus
Expand Down Expand Up @@ -152,6 +154,7 @@ registries:
| `charts[].version` | string | | true | Desired version of chart. Supports semver literal or semver ranges (semantic version spec 2.0) |
| `charts[].plainHTTP` | bool | false | false | Use HTTP instead of HTTPS for repository protocol |
| `charts[].valuesFilePath` | string | "" | false | Path to custom values.yaml to customize importing |
| `charts[].values` | object | nil | false | Inline values to customize importing (cannot be used together with `charts[].valuesFilePath`) |
| `charts[].images` | object | nil | false | Customization options for images in chart |
| `charts[].images.exclude` | list(object) | [] | false | Defines which images to exclude from processing |
| `charts[].images.exclude[].ref` | string | "" | false | Container Image reference |
Expand Down Expand Up @@ -193,6 +196,7 @@ The `charts` configuration option defines which charts to import.
| `charts[].name` | string | | true | Chart name |
| `charts[].version` | string | | true | Desired version of chart. Supports semver literal or semver ranges (semantic version spec 2.0) |
| `charts[].valuesFilePath` | string | "" | false | Path to custom values.yaml to customize importing |
| `charts[].values` | object | nil | false | Inline values to customize importing (cannot be used together with `charts[].valuesFilePath`) |
| `charts[].images` | object | nil | false | Customization options for images in chart |
| `charts[].images.exclude` | list(object) | [] | false | Defines which images to exclude from processing |
| `charts[].images.exclude.ref` | string | "" | false | Container Image reference |
Expand Down Expand Up @@ -240,25 +244,25 @@ Simply define the additional images in the `images` configuration option.

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

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

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

### mTLS

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

* `import.copacetic.buildkitd.CACertPath`
* `import.copacetic.buildkitd.certPath`
* `import.copacetic.buildkitd.keyPath`
- `import.copacetic.buildkitd.CACertPath`
- `import.copacetic.buildkitd.certPath`
- `import.copacetic.buildkitd.keyPath`

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

Expand Down

0 comments on commit c3ee7b2

Please sign in to comment.