Compare commits

..

9 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
Jeff McCune
810a7c6649 version 0.105.0 with kubectl-slice 2025-09-24 20:58:09 -07:00
Jeff McCune
b24e35f46d add kubectl-slice subcommand
It's really good at filtering resources like Namespace, Secret, and
CustomResourceDefinition.  It's excellent at breaking up files into an
easy to navigate, clear structure that integrates well with tools.  fzf
for example.
2025-09-24 20:46:49 -07:00
46 changed files with 759 additions and 107 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.104.3
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.104.3
0.106.0

View File

@@ -1 +1 @@
0.104.3
0.105.1

View File

@@ -1,3 +1,3 @@
[main 70107f8] 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 dc787e2] 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 aaf64bb] 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 111.222667ms
rendered prometheus in 139.292917ms
rendered platform in 139.350708ms
rendered blackbox in 112.795875ms
rendered prometheus in 144.441042ms
rendered platform in 144.505625ms

View File

@@ -1,4 +1,4 @@
[main 688da56] 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 778.713375ms
rendered prometheus in 839.024292ms
rendered platform in 839.07325ms
rendered blackbox in 877.548833ms
rendered prometheus in 882.902333ms
rendered platform in 883.561541ms

View File

@@ -1,2 +1,2 @@
[main 2d46297] 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.104.3
0.106.0

View File

@@ -1 +1 @@
0.104.3
0.105.1

View File

@@ -1,4 +1,4 @@
[main f621828] 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 0cccd8c] 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 77.754459ms
rendered platform in 77.832042ms
rendered httpbin in 82.637042ms
rendered platform in 82.702458ms

View File

@@ -1,2 +1,2 @@
rendered httpbin in 77.095625ms
rendered platform in 77.190416ms
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.104.3
0.106.0

View File

@@ -1,2 +1,2 @@
rendered podinfo in 159.277916ms
rendered platform in 159.380625ms
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.104.3
0.106.0

View File

@@ -1,3 +1,3 @@
[main 7761ac1] 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 8c81fed] 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 18c7aad] 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 110.354458ms
rendered prometheus in 138.13225ms
rendered platform in 138.168958ms
rendered blackbox in 120.236ms
rendered prometheus in 147.333125ms
rendered platform in 147.385208ms

View File

@@ -1,4 +1,4 @@
[main ff5bfaa] 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 693.763959ms
rendered prometheus in 788.544209ms
rendered platform in 788.618792ms
rendered blackbox in 1.023009333s
rendered prometheus in 1.1285565s
rendered platform in 1.128658458s

View File

@@ -1,2 +1,2 @@
[main 4033953] 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.104.3
0.106.0

View File

@@ -1,4 +1,4 @@
[main 1b332f8] 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 e37f8ce] 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 77.710709ms
rendered platform in 77.792958ms
rendered httpbin in 79.923ms
rendered platform in 79.99475ms

View File

@@ -1,2 +1,2 @@
rendered httpbin in 76.942666ms
rendered platform in 77.014958ms
rendered httpbin in 81.503708ms
rendered platform in 81.573166ms

37
go.mod
View File

@@ -1,29 +1,29 @@
module github.com/holos-run/holos
go 1.23.0
toolchain go1.23.6
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
@@ -110,6 +110,7 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/mitchellh/copystructure v1.2.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.18.2 // 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

68
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=
@@ -308,6 +308,8 @@ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4 h1:NK3O7S5FRD/wj7ORQ5C3Mx1STpyEMuFe+/F0Lakd1Nk=
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4/go.mod h1:FqD3ES5hx6zpzDainDaHgkTIqrPaI9uX4CVWqYZoQjY=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
@@ -364,6 +366,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/patrickdappollonio/kubectl-slice v1.4.2 h1:U1Jrma4BRK9D1Mbly8oP6uA06/gmOif6KjVQFrPUBzI=
github.com/patrickdappollonio/kubectl-slice v1.4.2/go.mod h1:gt3IidcTPeCcazqcMuXF51VWU5mGsQv6YlNpXxQvPsE=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
@@ -404,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=
@@ -437,13 +441,13 @@ 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=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
@@ -496,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=
@@ -518,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=
@@ -559,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=
@@ -576,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

@@ -17,6 +17,7 @@ import (
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/render"
"github.com/holos-run/holos/internal/cli/slice"
"github.com/holos-run/holos/internal/cli/txtar"
cueCmd "cuelang.org/go/cmd/cue/cmd"
@@ -82,6 +83,9 @@ func New(cfg *holos.Config) *cobra.Command {
// Compile
rootCmd.AddCommand(NewCompileCmd())
// Slice - https://github.com/patrickdappollonio/kubectl-slice
rootCmd.AddCommand(slice.NewKubectlSliceCmd())
return rootCmd
}

22
internal/cli/slice/doc.go Normal file
View File

@@ -0,0 +1,22 @@
// MIT License
// Copyright (c) 2021 Patrick D'appollonio
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package slice

212
internal/cli/slice/slice.go Normal file
View File

@@ -0,0 +1,212 @@
package slice
import (
"bytes"
"fmt"
"os"
"strings"
"github.com/patrickdappollonio/kubectl-slice/slice"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
var version = "development"
const (
helpShort = "kubectl-slice allows you to split a YAML into multiple subfiles using a pattern."
helpLong = `kubectl-slice allows you to split a YAML into multiple subfiles using a pattern.
For documentation, available functions, and more, visit: https://github.com/patrickdappollonio/kubectl-slice.`
)
var examples = []string{
"kubectl-slice -f foo.yaml -o ./ --include-kind Pod,Namespace",
"kubectl-slice -f foo.yaml -o ./ --exclude-kind Pod",
"kubectl-slice -f foo.yaml -o ./ --exclude-name *-svc",
"kubectl-slice -f foo.yaml --exclude-name *-svc --stdout",
"kubectl-slice -f foo.yaml --include Pod/* --stdout",
"kubectl-slice -f foo.yaml --exclude deployment/kube* --stdout",
"kubectl-slice -d ./ --recurse -o ./ --include-kind Pod,Namespace",
"kubectl-slice -d ./ --recurse --stdout --include Pod/*",
"kubectl-slice --config config.yaml",
}
func generateExamples([]string) string {
var s bytes.Buffer
for pos, v := range examples {
s.WriteString(fmt.Sprintf(" %s", v))
if pos != len(examples)-1 {
s.WriteString("\n")
}
}
return s.String()
}
func NewKubectlSliceCmd() *cobra.Command {
opts := slice.Options{}
var configFile string
rootCommand := &cobra.Command{
Use: "kubectl-slice",
Short: helpShort,
Long: helpLong,
Version: version,
SilenceUsage: true,
SilenceErrors: true,
Example: generateExamples(examples),
PreRunE: func(cmd *cobra.Command, args []string) error {
return bindCobraAndViper(cmd, configFile)
},
RunE: func(cmd *cobra.Command, args []string) error {
// Bind to the appropriate stdout/stderr
opts.Stdout = cmd.OutOrStdout()
opts.Stderr = cmd.ErrOrStderr()
// If no input file has been provided or it's "-", then
// point the app to stdin
if (opts.InputFile == "" || opts.InputFile == "-") && opts.InputFolder == "" {
opts.InputFile = os.Stdin.Name()
// Check if we're receiving data from the terminal
// or from piped content. Users from piped content
// won't see this message. Users that might have forgotten
// setting the flags correctly will see this message.
if !opts.Quiet {
if fi, err := os.Stdin.Stat(); err == nil && fi.Mode()&os.ModeNamedPipe == 0 {
fmt.Fprintln(opts.Stderr, "Receiving data from the terminal. Press CTRL+D when you're done typing or CTRL+C")
fmt.Fprintln(opts.Stderr, "to exit without processing the content. If you're seeing this by mistake, make")
fmt.Fprintln(opts.Stderr, "sure the command line flags, environment variables or config file are correct.")
}
}
}
// Create a new instance. This will also perform a basic validation.
instance, err := slice.New(opts)
if err != nil {
return fmt.Errorf("validation failed: %w", err)
}
return instance.Execute()
},
}
rootCommand.Flags().StringVarP(&opts.InputFile, "input-file", "f", "", "the input file used to read the initial macro YAML file; if empty or \"-\", stdin is used (exclusive with --input-folder)")
rootCommand.Flags().StringVarP(&opts.InputFolder, "input-folder", "d", "", "the input folder used to read the initial macro YAML files (exclusive with --input-file)")
rootCommand.Flags().StringSliceVar(&opts.InputFolderExt, "extensions", []string{".yaml", ".yml"}, "the extensions to look for in the input folder")
rootCommand.Flags().BoolVarP(&opts.Recurse, "recurse", "r", false, "if true, the input folder will be read recursively (has no effect unless used with --input-folder)")
rootCommand.Flags().StringVarP(&opts.OutputDirectory, "output-dir", "o", "", "the output directory used to output the splitted files")
rootCommand.Flags().StringVarP(&opts.GoTemplate, "template", "t", slice.DefaultTemplateName, "go template used to generate the file name when creating the resource files in the output directory")
rootCommand.Flags().BoolVar(&opts.DryRun, "dry-run", false, "if true, no files are created, but the potentially generated files will be printed as the command output")
rootCommand.Flags().BoolVar(&opts.DebugMode, "debug", false, "enable debug mode")
rootCommand.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "if true, no output is written to stdout/err")
rootCommand.Flags().StringSliceVar(&opts.IncludedKinds, "include-kind", nil, "resource kind to include in the output (singular, case insensitive, glob supported)")
rootCommand.Flags().StringSliceVar(&opts.ExcludedKinds, "exclude-kind", nil, "resource kind to exclude in the output (singular, case insensitive, glob supported)")
rootCommand.Flags().StringSliceVar(&opts.IncludedNames, "include-name", nil, "resource name to include in the output (singular, case insensitive, glob supported)")
rootCommand.Flags().StringSliceVar(&opts.ExcludedNames, "exclude-name", nil, "resource name to exclude in the output (singular, case insensitive, glob supported)")
rootCommand.Flags().StringSliceVar(&opts.Included, "include", nil, "resource name to include in the output (format <kind>/<name>, case insensitive, glob supported)")
rootCommand.Flags().StringSliceVar(&opts.Excluded, "exclude", nil, "resource name to exclude in the output (format <kind>/<name>, case insensitive, glob supported)")
rootCommand.Flags().BoolVarP(&opts.StrictKubernetes, "skip-non-k8s", "s", false, "if enabled, any YAMLs that don't contain at least an \"apiVersion\", \"kind\" and \"metadata.name\" will be excluded from the split")
rootCommand.Flags().BoolVar(&opts.SortByKind, "sort-by-kind", false, "if enabled, resources are sorted by Kind, a la Helm, before saving them to disk")
rootCommand.Flags().BoolVar(&opts.OutputToStdout, "stdout", false, "if enabled, no resource is written to disk and all resources are printed to stdout instead")
rootCommand.Flags().StringVarP(&configFile, "config", "c", "", "path to the config file")
rootCommand.Flags().BoolVar(&opts.AllowEmptyKinds, "allow-empty-kinds", false, "if enabled, resources with empty kinds don't produce an error when filtering")
rootCommand.Flags().BoolVar(&opts.AllowEmptyNames, "allow-empty-names", false, "if enabled, resources with empty names don't produce an error when filtering")
rootCommand.Flags().BoolVar(&opts.IncludeTripleDash, "include-triple-dash", false, "if enabled, the typical \"---\" YAML separator is included at the beginning of resources sliced")
rootCommand.Flags().BoolVar(&opts.PruneOutputDir, "prune", false, "if enabled, the output directory will be pruned before writing the files")
rootCommand.Flags().BoolVar(&opts.RemoveFileComments, "remove-comments", false, "if enabled, comments generated by the app are removed from the sliced files (but keep comments from the original file)")
rootCommand.Flags().StringSliceVar(&opts.IncludedGroups, "include-group", nil, "resource kind to include in the output (singular, case insensitive, glob supported)")
rootCommand.Flags().StringSliceVar(&opts.ExcludedGroups, "exclude-group", nil, "resource kind to exclude in the output (singular, case insensitive, glob supported)")
_ = rootCommand.Flags().MarkHidden("debug")
return rootCommand
}
// envVarPrefix is the prefix used for environment variables.
// Using underscores to ensure compatibility with the shell.
const envVarPrefix = "KUBECTL_SLICE"
// skippedFlags is a list of flags that are not bound through
// Viper. These include things like "help", "version", and of
// course, "config", since it doesn't make sense to say where
// the config file is located in the config file itself.
var skippedFlags = [...]string{
"help",
"version",
"config",
}
// bindCobraAndViper binds the settings loaded by Viper
// to the flags defined in Cobra.
func bindCobraAndViper(cmd *cobra.Command, configFileLocation string) error {
v := viper.New()
// If a configuration file has been passed...
if cmd.Flags().Lookup("config").Changed {
// ... then set it as the configuration file
v.SetConfigFile(configFileLocation)
// then read the configuration file
if err := v.ReadInConfig(); err != nil {
return fmt.Errorf("failed to read configuration file: %w", err)
}
}
// Handler for potential error
var err error
// Recurse through all the variables
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
// Skip the flags that are not bound through Viper
for _, v := range skippedFlags {
if v == flag.Name {
return
}
}
// Normalize key names with underscores instead of dashes
nameUnderscored := strings.ReplaceAll(flag.Name, "-", "_")
envVarName := strings.ToUpper(fmt.Sprintf("%s_%s", envVarPrefix, nameUnderscored))
// Bind the flag to the environment variable
if val, found := os.LookupEnv(envVarName); found {
v.Set(nameUnderscored, val)
}
// If the CLI flag hasn't been changed, but the value is set in
// the configuration file, then set the CLI flag to the value
// from the configuration file
if !flag.Changed && v.IsSet(nameUnderscored) {
// Type check for all the supported types
switch val := v.Get(nameUnderscored).(type) {
case string:
_ = cmd.Flags().Set(flag.Name, val)
case []interface{}:
var stringified []string
for _, v := range val {
stringified = append(stringified, fmt.Sprintf("%v", v))
}
_ = cmd.Flags().Set(flag.Name, strings.Join(stringified, ","))
case bool:
_ = cmd.Flags().Set(flag.Name, fmt.Sprintf("%t", val))
case int:
_ = cmd.Flags().Set(flag.Name, fmt.Sprintf("%d", val))
default:
err = fmt.Errorf("unsupported type %T for flag %q", val, nameUnderscored)
return
}
}
})
// If an error occurred, return it
return err
}

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 @@
104
106

View File

@@ -1 +1 @@
3
0