Compare commits

..

7 Commits

Author SHA1 Message Date
Jeff McCune
5680049650 docs: add v1alpha6 executor implementation plan
Plan to wire the compiler pool to holos render platform, build a
unified task DAG from all BuildPlans, execute with topological sort,
and deduplicate Helm chart fetches across components.

Related: #435 #389 #452

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 17:13:29 -08:00
Jeff McCune
f4484ffb21 Merge pull request #451 from holos-run/feat/cue-0.15.1
cue: update to 0.15.1 from 0.14.1 for embed allowEmptyGlob
2025-11-24 09:19:49 -08:00
Jeff McCune
8512ca01d1 docs: bump minor version to 0.105.0 with cue 0.15.1 2025-11-24 09:13:13 -08:00
Jeff McCune
e6f3a6d8d9 cue: update to 0.15.1 from 0.14.1 for allowEmptyGlob 2025-11-24 09:11:02 -08:00
Jeff McCune
3d696b958b version 0.105.1 fixes oci chart auth (#447) 2025-09-25 07:12:41 -07:00
Jeff McCune
1bf627b5e1 Merge pull request #447 from manrueda/feat-oci-chart-authentication
Allows authentication of OCI charts
2025-09-25 07:08:13 -07:00
Manuel Rueda
df69198cef allows authentication of OCI charts 2025-09-25 09:52:38 -04:00
42 changed files with 512 additions and 104 deletions

View File

@@ -274,8 +274,8 @@ type Chart struct {
// repository. Holos gets the username and password from the environment
// variables represented by the Auth field.
type Repository struct {
Name string `json:"name" yaml:"name"`
URL string `json:"url" yaml:"url"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
URL string `json:"url,omitempty" yaml:"url,omitempty"`
Auth Auth `json:"auth,omitempty" yaml:"auth,omitempty"`
}

View File

@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
-- command.sh --
holos --version
-- output.txt --
0.105.0
0.106.0

View File

@@ -1 +1 @@
0.104.3
0.105.1

View File

@@ -1,2 +1,2 @@
rendered podinfo in 160.977334ms
rendered platform in 161.101292ms
rendered podinfo in 169.504ms
rendered platform in 169.609583ms

View File

@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
-- command.sh --
holos --version
-- output.txt --
0.105.0
0.106.0

View File

@@ -1 +1 @@
0.104.3
0.105.1

View File

@@ -1,3 +1,3 @@
[main 11e8f96] add blackbox configuration
[main 67f5363] add blackbox configuration
1 file changed, 15 insertions(+)
create mode 100644 config/prometheus/blackbox.cue

View File

@@ -1,3 +1,3 @@
[main 1ea1005] integrate blackbox and prometheus together
3 files changed, 1348 insertions(+), 2 deletions(-)
[main bef876c] integrate blackbox and prometheus together
3 files changed, 1359 insertions(+), 2 deletions(-)
create mode 100644 components/prometheus/values.cue.orig

View File

@@ -1,4 +1,4 @@
[main a2e337a] import values
2 files changed, 1815 insertions(+)
[main 9dd00f3] import values
2 files changed, 1826 insertions(+)
create mode 100644 components/blackbox/values.cue
create mode 100644 components/prometheus/values.cue

View File

@@ -1,3 +1,3 @@
rendered blackbox in 143.36875ms
rendered prometheus in 170.982208ms
rendered platform in 171.067125ms
rendered blackbox in 112.795875ms
rendered prometheus in 144.441042ms
rendered platform in 144.505625ms

View File

@@ -1,4 +1,4 @@
[main 58e925d] add blackbox and prometheus
[main c523ef0] add blackbox and prometheus
5 files changed, 1550 insertions(+)
create mode 100644 components/blackbox/blackbox.cue
create mode 100644 components/prometheus/prometheus.cue

View File

@@ -1,3 +1,3 @@
rendered blackbox in 5.63152525s
rendered prometheus in 9.53072125s
rendered platform in 9.530793625s
rendered blackbox in 877.548833ms
rendered prometheus in 882.902333ms
rendered platform in 883.561541ms

View File

@@ -1,2 +1,2 @@
[main f4371e4] render integrated blackbox and prometheus manifests
[main 3aa63f4] render integrated blackbox and prometheus manifests
2 files changed, 7 insertions(+), 7 deletions(-)

View File

@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
-- command.sh --
holos --version
-- output.txt --
0.105.0
0.106.0

View File

@@ -1 +1 @@
0.104.3
0.105.1

View File

@@ -1,4 +1,4 @@
[main da03e4a] add httpbin
[main 2fc33ea] add httpbin
4 files changed, 113 insertions(+)
create mode 100644 components/httpbin/httpbin.cue
create mode 100644 components/httpbin/httpbin.yaml

View File

@@ -1,3 +1,3 @@
[main 2d3c3cb] annotate httpbin for prometheus probes
[main 6d5bbc3] annotate httpbin for prometheus probes
2 files changed, 18 insertions(+)
create mode 100644 components/httpbin/patches.cue

View File

@@ -1,2 +1,2 @@
rendered httpbin in 99.597583ms
rendered platform in 99.678042ms
rendered httpbin in 82.637042ms
rendered platform in 82.702458ms

View File

@@ -1,2 +1,2 @@
rendered httpbin in 2.595108833s
rendered platform in 2.595221s
rendered httpbin in 80.916166ms
rendered platform in 80.992958ms

View File

@@ -0,0 +1,391 @@
# v1alpha6 Build Plan Executor
This document outlines the plan to finalize the v1alpha6 build plan executor for `holos render platform`. The goal is to use the compiler pool to produce a complete set of BuildPlans, then combine them into a topologically sorted DAG for efficient concurrent execution.
## Related Issues
- [#435 v1alpha6 Design](https://github.com/holos-run/holos/issues/435)
- [#389 Concurrent Component Compiler](https://github.com/holos-run/holos/issues/389)
- [#452 Fix concurrent helm invocations](https://github.com/holos-run/holos/issues/452)
## Current State Analysis
### What's Implemented
1. **Compiler Pool** (`internal/compile/compile.go`):
- `compile.Compile()` function spawns a pool of `holos compile` subprocesses
- Producer-consumer pattern with task queue using channels
- Each worker maintains a persistent subprocess with stdin/stdout pipes
- JSON streaming protocol for BuildPlanRequest/BuildPlanResponse
2. **`holos show buildplans`** (`internal/cli/show.go`):
- Uses `compile.Compile()` to produce BuildPlans concurrently
- Displays BuildPlans without executing them
- Validates the compiler pool works correctly
3. **`holos render platform`** (`internal/cli/render/render.go`):
- Spawns individual `holos render component` subprocesses
- Each subprocess independently compiles AND executes its BuildPlan
- Does NOT use the compiler pool
4. **BuildPlan Execution** (`internal/component/v1alpha6/v1alpha6.go`):
- `BuildPlan.Build()` processes artifacts concurrently
- Within each artifact: generators run concurrently, transformers sequentially, validators concurrently
- Worker pool for task execution within a single BuildPlan
### What's Missing
1. **Compiler Pool in `holos render platform`**: The render command still spawns individual subprocesses instead of using the compiler pool.
2. **Unified DAG Execution**: BuildPlans execute independently. No cross-BuildPlan task deduplication or optimization.
3. **Helm Chart Deduplication**: Each component fetches Helm charts independently. Multiple components using the same chart/version fetch redundantly.
4. **Topological Sort**: No dependency analysis or task ordering across BuildPlans.
## Architecture Design
### Phase 1: Compile All BuildPlans
Use the existing compiler pool to compile all BuildPlans before executing any.
```
holos render platform
├─> Platform.Build()
│ └─> Collect all Components
├─> compile.Compile(ctx, concurrency, requests)
│ ├─> Producer: sends BuildPlanRequest per component
│ ├─> N Workers: each runs holos compile subprocess
│ └─> Returns: []BuildPlanResponse with all BuildPlans
└─> Phase 2: Execute BuildPlans
```
### Phase 2: Build Unified Task DAG
Transform all BuildPlans into a single DAG of executable tasks.
```go
// Task represents a single executable unit of work
type Task struct {
ID string // Unique identifier
Kind string // helm-fetch, generator, transformer, validator, write-artifact
BuildPlan string // Which BuildPlan this task belongs to
Artifact string // Which Artifact within the BuildPlan
Inputs []string // Task IDs this depends on
Outputs []string // Output keys this produces
Run func(ctx) error // Execution function
}
// TaskDAG represents the complete dependency graph
type TaskDAG struct {
Tasks map[string]*Task // All tasks by ID
Adjacency map[string][]string // task -> tasks that depend on it
InDegree map[string]int // task -> number of dependencies
}
```
#### Task Types
1. **helm-fetch**: Download a Helm chart to local cache
- Key: `helm-fetch:{repo}:{chart}:{version}`
- Deduplicated across all BuildPlans
2. **generator**: Execute a Generator (Resources, Helm template, File, Command)
- Key: `{buildplan}:{artifact}:gen:{output}`
- helm-fetch tasks depend on generators that use Helm
3. **transformer**: Execute a Transformer (Kustomize, Join, Command)
- Key: `{buildplan}:{artifact}:transform:{output}`
- Sequential within artifact, depends on generators or prior transformers
4. **validator**: Execute a Validator (Command)
- Key: `{buildplan}:{artifact}:validate:{idx}`
- Depends on final transformer output
5. **write-artifact**: Write artifact to filesystem
- Key: `{buildplan}:{artifact}:write`
- Depends on validators completing
### Phase 3: Topological Sort and Execution
Execute tasks using Kahn's algorithm for topological ordering with concurrent execution.
```go
func ExecuteDAG(ctx context.Context, dag *TaskDAG, workers int) error {
g, ctx := errgroup.WithContext(ctx)
ready := make(chan *Task, len(dag.Tasks))
completed := make(chan string, len(dag.Tasks))
// Initialize with tasks that have no dependencies
for id, task := range dag.Tasks {
if dag.InDegree[id] == 0 {
ready <- task
}
}
// Coordinator goroutine
g.Go(func() error {
remaining := len(dag.Tasks)
for remaining > 0 {
select {
case <-ctx.Done():
return ctx.Err()
case id := <-completed:
remaining--
// Decrement in-degree of dependent tasks
for _, depID := range dag.Adjacency[id] {
dag.InDegree[depID]--
if dag.InDegree[depID] == 0 {
ready <- dag.Tasks[depID]
}
}
}
}
close(ready)
return nil
})
// Worker goroutines
for i := 0; i < workers; i++ {
g.Go(func() error {
for task := range ready {
if err := task.Run(ctx); err != nil {
return err
}
completed <- task.ID
}
return nil
})
}
return g.Wait()
}
```
### Helm Chart Deduplication
Extract all Helm chart references, deduplicate, and create fetch tasks.
```go
type ChartKey struct {
Repository string
Name string
Version string
}
func ExtractHelmCharts(plans []BuildPlan) map[ChartKey][]TaskRef {
charts := make(map[ChartKey][]TaskRef)
for _, plan := range plans {
for _, artifact := range plan.Spec.Artifacts {
for _, gen := range artifact.Generators {
if gen.Kind == "Helm" {
key := ChartKey{
Repository: gen.Helm.Chart.Repository.URL,
Name: gen.Helm.Chart.Name,
Version: gen.Helm.Chart.Version,
}
charts[key] = append(charts[key], TaskRef{
BuildPlan: plan.Metadata.Name,
Artifact: artifact.Artifact,
Generator: gen.Output,
})
}
}
}
}
return charts
}
```
## Implementation Plan
### Step 1: Wire Compiler Pool to Render Platform
Modify `internal/cli/render/render.go` to:
1. Collect all components from the Platform
2. Build `[]BuildPlanRequest` for each component
3. Call `compile.Compile()` to get all BuildPlans
4. Execute BuildPlans (initially using existing per-BuildPlan execution)
**Files to modify:**
- `internal/cli/render/render.go`
**Validation:**
- `holos render platform` produces identical output to before
- Compilation is faster due to concurrent pool
### Step 2: Create Task DAG Package
Create new package `internal/dag/` with:
1. Task and TaskDAG types
2. DAG construction from BuildPlans
3. Topological sort execution
4. Shared artifact store across BuildPlans
**Files to create:**
- `internal/dag/dag.go` - Core types and construction
- `internal/dag/execute.go` - DAG execution with worker pool
- `internal/dag/dag_test.go` - Unit tests
### Step 3: Implement Helm Chart Deduplication
1. Extract all Helm chart references before execution
2. Create single fetch task per unique chart
3. Helm generator tasks depend on corresponding fetch task
4. Use file system locking for concurrent safety
**Files to modify:**
- `internal/dag/dag.go` - Add chart extraction and fetch task creation
- `internal/component/v1alpha6/v1alpha6.go` - Refactor helm fetch logic
### Step 4: Integrate DAG Execution into Render Platform
Replace per-BuildPlan execution with unified DAG execution.
**Files to modify:**
- `internal/cli/render/render.go`
- `internal/platform/platform.go`
### Step 5: Update Build Plan Execution to Use Shared Store
Modify BuildPlan execution to:
1. Accept a shared artifact store
2. Support external Helm chart cache
3. Report task completion to coordinator
**Files to modify:**
- `internal/component/v1alpha6/v1alpha6.go`
- `internal/artifact/artifact.go`
## Testing Strategy
### Unit Tests
1. DAG construction from BuildPlans
2. Topological sort correctness
3. Cycle detection
4. Helm chart deduplication
### Integration Tests
1. Render platform with multiple components sharing Helm charts
2. Verify deduplication reduces Helm fetches
3. Verify output matches non-DAG execution
4. Use `holos compare buildplans` to validate equivalence
### Performance Tests
1. Measure compilation time improvement
2. Measure execution time with chart deduplication
3. Benchmark with varying concurrency levels
## Migration Path
1. **v0.106.0**: Wire compiler pool to render platform (Step 1)
2. **v0.107.0**: Introduce DAG package, optional via flag (Steps 2-3)
3. **v0.108.0**: Make DAG execution default, deprecate old path (Steps 4-5)
## Future Considerations
### TaskSet Schema (v1alpha6 Design Goal)
The DAG implementation provides a foundation for the TaskSet schema:
```cue
TaskSet: {
tasks: [string]: Task
}
Task: {
kind: "HelmFetch" | "Generator" | "Transformer" | "Validator" | "Write"
inputs: [...string] // Task IDs
outputs: [...string] // Output keys
// Kind-specific fields
}
```
### Cross-Component Dependencies
Future enhancement to support:
```cue
Component: {
dependsOn: [...string] // Other component names
}
```
### Caching
Consider caching:
1. Compiled BuildPlans (CUE evaluation cache)
2. Generator outputs (content-addressed)
3. Transformer outputs (input-hash based)
## Appendix: Current Code Flow
### `holos show buildplans` (Uses Compiler Pool)
```
show.go:84 showBuildPlans.Run()
├─> p.Select() - Get components matching selectors
├─> Build []BuildPlanRequest from components
├─> compile.Compile(ctx, concurrency, reqs)
│ compile.go:155
│ ├─> Producer goroutine sends requests to channel
│ ├─> N Consumer goroutines run holos compile
│ └─> Returns []BuildPlanResponse
└─> Encode and output BuildPlans
```
### `holos render platform` (Current: Per-Component Subprocess)
```
render.go:49 renderPlatform.Run()
├─> platform.Platform.Build()
│ platform.go
│ └─> For each component (concurrent, limited):
│ └─> PerComponentFunc()
└─> PerComponentFunc() spawns subprocess:
holos render component [path]
└─> component.go
├─> Compile CUE to BuildPlan
└─> BuildPlan.Build() - Execute artifact pipeline
```
### Proposed: `holos render platform` (With Compiler Pool + DAG)
```
render.go renderPlatform.Run()
├─> Collect all components from Platform
├─> compile.Compile(ctx, concurrency, reqs)
│ └─> Returns []BuildPlanResponse
├─> dag.Build(buildPlans)
│ ├─> Extract and deduplicate Helm charts
│ ├─> Create fetch tasks
│ ├─> Create generator tasks (depend on fetch)
│ ├─> Create transformer tasks (depend on generators)
│ ├─> Create validator tasks (depend on transformers)
│ └─> Create write tasks (depend on validators)
└─> dag.Execute(ctx, workers)
├─> Topological sort execution
├─> Fixed worker pool with errgroup
└─> Write artifacts to filesystem
```

View File

@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
-- command.sh --
holos --version
-- output.txt --
0.105.0
0.106.0

View File

@@ -1,2 +1,2 @@
rendered podinfo in 4.155374125s
rendered platform in 4.155477334s
rendered podinfo in 290.020792ms
rendered platform in 290.155667ms

View File

@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
-- command.sh --
holos --version
-- output.txt --
0.105.0
0.106.0

View File

@@ -1,3 +1,3 @@
[main d448299] add blackbox configuration
[main fd30368] add blackbox configuration
1 file changed, 15 insertions(+)
create mode 100644 config/prometheus/blackbox.cue

View File

@@ -1,3 +1,3 @@
[main 2ce5a78] integrate blackbox and prometheus together
3 files changed, 1348 insertions(+), 2 deletions(-)
[main e9a22bd] integrate blackbox and prometheus together
3 files changed, 1359 insertions(+), 2 deletions(-)
create mode 100644 components/prometheus/values.cue.orig

View File

@@ -1,4 +1,4 @@
[main 2f0cd50] import values
2 files changed, 1815 insertions(+)
[main dbaf504] import values
2 files changed, 1826 insertions(+)
create mode 100644 components/blackbox/values.cue
create mode 100644 components/prometheus/values.cue

View File

@@ -1,3 +1,3 @@
rendered blackbox in 143.137333ms
rendered prometheus in 167.300583ms
rendered platform in 167.341209ms
rendered blackbox in 120.236ms
rendered prometheus in 147.333125ms
rendered platform in 147.385208ms

View File

@@ -1,4 +1,4 @@
[main b7e507c] add blackbox and prometheus
[main c523ef0] add blackbox and prometheus
5 files changed, 1550 insertions(+)
create mode 100644 components/blackbox/blackbox.cue
create mode 100644 components/prometheus/prometheus.cue

View File

@@ -1,3 +1,3 @@
rendered blackbox in 5.595935416s
rendered prometheus in 5.602449167s
rendered platform in 5.602527541s
rendered blackbox in 1.023009333s
rendered prometheus in 1.1285565s
rendered platform in 1.128658458s

View File

@@ -1,2 +1,2 @@
[main 137f66a] render integrated blackbox and prometheus manifests
[main ed5ce22] render integrated blackbox and prometheus manifests
2 files changed, 7 insertions(+), 7 deletions(-)

View File

@@ -4,4 +4,4 @@ cmp stdout $WORK/output.txt
-- command.sh --
holos --version
-- output.txt --
0.105.0
0.106.0

View File

@@ -1,4 +1,4 @@
[main 2c843b8] add httpbin
[main bdb182b] add httpbin
4 files changed, 113 insertions(+)
create mode 100644 components/httpbin/httpbin.cue
create mode 100644 components/httpbin/httpbin.yaml

View File

@@ -1,3 +1,3 @@
[main a324ab5] annotate httpbin for prometheus probes
[main d557fa2] annotate httpbin for prometheus probes
2 files changed, 18 insertions(+)
create mode 100644 components/httpbin/patches.cue

View File

@@ -1,2 +1,2 @@
rendered httpbin in 113.981791ms
rendered platform in 114.0585ms
rendered httpbin in 79.923ms
rendered platform in 79.99475ms

View File

@@ -1,2 +1,2 @@
rendered httpbin in 2.546013s
rendered platform in 2.546090458s
rendered httpbin in 81.503708ms
rendered platform in 81.573166ms

33
go.mod
View File

@@ -3,25 +3,27 @@ module github.com/holos-run/holos
go 1.24.0
require (
cuelang.org/go v0.14.1
cuelang.org/go v0.15.1
github.com/google/go-cmp v0.7.0
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-runewidth v0.0.15
github.com/olekukonko/tablewriter v0.0.5
github.com/patrickdappollonio/kubectl-slice v1.4.2
github.com/princjef/gomarkdoc v1.1.0
github.com/rogpeppe/go-internal v1.14.1
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.7
github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
golang.org/x/sync v0.16.0
golang.org/x/tools v0.35.0
golang.org/x/sync v0.17.0
golang.org/x/tools v0.38.0
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.16.3
sigs.k8s.io/kustomize/kustomize/v5 v5.5.0
)
require (
cuelabs.dev/go/oci/ociregistry v0.0.0-20250715075730-49cab49c8e9d // indirect
cuelabs.dev/go/oci/ociregistry v0.0.0-20250722084951-074d06050084 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
@@ -128,7 +130,6 @@ require (
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/patrickdappollonio/kubectl-slice v1.4.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
@@ -140,7 +141,7 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/protocolbuffers/txtpbfmt v0.0.0-20250627152318-f293424e46b5 // indirect
github.com/protocolbuffers/txtpbfmt v0.0.0-20251016062345-16587c79cd91 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rubenv/sql-migrate v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
@@ -153,7 +154,6 @@ require (
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/viper v1.19.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
@@ -168,14 +168,15 @@ require (
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/mod v0.26.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/term v0.33.0 // indirect
golang.org/x/text v0.27.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/term v0.36.0 // indirect
golang.org/x/text v0.30.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/grpc v1.65.0 // indirect

62
go.sum
View File

@@ -1,7 +1,7 @@
cuelabs.dev/go/oci/ociregistry v0.0.0-20250715075730-49cab49c8e9d h1:lX0EawyoAu4kgMJJfy7MmNkIHioBcdBGFRSKDZ+CWo0=
cuelabs.dev/go/oci/ociregistry v0.0.0-20250715075730-49cab49c8e9d/go.mod h1:4WWeZNxUO1vRoZWAHIG0KZOd6dA25ypyWuwD3ti0Tdc=
cuelang.org/go v0.14.1 h1:kxFAHr7bvrCikbtVps2chPIARazVdnRmlz65dAzKyWg=
cuelang.org/go v0.14.1/go.mod h1:aSP9UZUM5m2izHAHUvqtq0wTlWn5oLjuv2iBMQZBLLs=
cuelabs.dev/go/oci/ociregistry v0.0.0-20250722084951-074d06050084 h1:4k1yAtPvZJZQTu8DRY8muBo0LHv6TqtrE0AO5n6IPYs=
cuelabs.dev/go/oci/ociregistry v0.0.0-20250722084951-074d06050084/go.mod h1:4WWeZNxUO1vRoZWAHIG0KZOd6dA25ypyWuwD3ti0Tdc=
cuelang.org/go v0.15.1 h1:MRnjc/KJE+K42rnJ3a+425f1jqXeOOgq9SK4tYRTtWw=
cuelang.org/go v0.15.1/go.mod h1:NYw6n4akZcTjA7QQwJ1/gqWrrhsN4aZwhcAL0jv9rZE=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
@@ -408,8 +408,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/protocolbuffers/txtpbfmt v0.0.0-20250627152318-f293424e46b5 h1:WWs1ZFnGobK5ZXNu+N9If+8PDNVB9xAqrib/stUXsV4=
github.com/protocolbuffers/txtpbfmt v0.0.0-20250627152318-f293424e46b5/go.mod h1:BnHogPTyzYAReeQLZrOxyxzS739DaTNtTvohVdbENmA=
github.com/protocolbuffers/txtpbfmt v0.0.0-20251016062345-16587c79cd91 h1:s1LvMaU6mVwoFtbxv/rCZKE7/fwDmDY684FfUe4c1Io=
github.com/protocolbuffers/txtpbfmt v0.0.0-20251016062345-16587c79cd91/go.mod h1:JSbkp0BviKovYYt9XunS95M3mLPibE9bGg+Y95DsEEY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
@@ -441,13 +441,11 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -502,19 +500,21 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -524,18 +524,18 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -565,16 +565,16 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -582,8 +582,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -3,11 +3,13 @@ package helm
import (
"context"
"fmt"
"net/url"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/registry"
)
// PullChart downloads and caches a Helm chart locally. It handles both OCI and
@@ -32,6 +34,20 @@ func PullChart(ctx context.Context, settings *cli.EnvSettings, chartRef, chartVe
}
actionConfig.RegistryClient = registryClient
chartRefURL, err := url.Parse(chartRef)
if err != nil {
return errors.Format("Failed to parse the Chart: %w", err)
}
// If the chart been pulled is an OCI chart, the repo authentication has to be done ahead of the pull.
if chartRefURL.Scheme == "oci" && username != "" && password != "" {
loginOption := registry.LoginOptBasicAuth(username, password)
err = registryClient.Login(chartRefURL.Host, loginOption)
if err != nil {
return errors.Format("failed to login to registry: %w", err)
}
}
pullClient := action.NewPullWithOpts(action.WithConfig(actionConfig))
pullClient.Untar = true
pullClient.RepoURL = repoURL

View File

@@ -1 +1 @@
105
106