mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 16:54:58 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a60b613ff | ||
|
|
5862725bab | ||
|
|
8660826b05 |
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
@@ -19,11 +20,15 @@ import (
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
)
|
||||
|
||||
// cue context and loading is not safe for concurrent use.
|
||||
var cueMutex sync.Mutex
|
||||
|
||||
// ExtractYAML extracts yaml encoded data from file paths. The data is unified
|
||||
// into one [cue.Value]. If a path element is a directory, all files in the
|
||||
// directory are loaded non-recursively.
|
||||
//
|
||||
// Attribution: https://github.com/cue-lang/cue/issues/3504
|
||||
// Deprecated: Use cue embed instead.
|
||||
func ExtractYAML(ctxt *cue.Context, filepaths []string) (cue.Value, error) {
|
||||
value := ctxt.CompileString("")
|
||||
files := make([]string, 0, 10*len(filepaths))
|
||||
@@ -67,6 +72,8 @@ func ExtractYAML(ctxt *cue.Context, filepaths []string) (cue.Value, error) {
|
||||
// extracted data values are unified with the platform configuration [cue.Value]
|
||||
// in the returned [Instance].
|
||||
func LoadInstance(path string, filepaths []string, tags []string) (*Instance, error) {
|
||||
cueMutex.Lock()
|
||||
defer cueMutex.Unlock()
|
||||
root, leaf, err := util.FindRootLeaf(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
@@ -89,7 +96,6 @@ func LoadInstance(path string, filepaths []string, tags []string) (*Instance, er
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
// TODO: https://cuelang.org/docs/howto/place-data-go-api/
|
||||
value = value.Unify(values[0])
|
||||
|
||||
inst := &Instance{
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// platform.
|
||||
type PlatformOpts struct {
|
||||
Fn func(context.Context, int, holos.Component) error
|
||||
Selector holos.Selector
|
||||
Selectors holos.Selectors
|
||||
Concurrency int
|
||||
InfoEnabled bool
|
||||
}
|
||||
@@ -31,7 +31,7 @@ type Platform struct {
|
||||
func (p *Platform) Build(ctx context.Context, opts PlatformOpts) error {
|
||||
limit := max(opts.Concurrency, 1)
|
||||
parentStart := time.Now()
|
||||
components := p.Select(opts.Selector)
|
||||
components := p.Select(opts.Selectors...)
|
||||
total := len(components)
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
@@ -45,8 +45,8 @@ func newPlatform(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
|
||||
cmd.Flags().StringVar(&platform, "platform", "./platform", "platform directory path")
|
||||
var extractYAMLs holos.StringSlice
|
||||
cmd.Flags().Var(&extractYAMLs, "extract-yaml", "data file paths to extract and unify with the platform config")
|
||||
var selector holos.Selector
|
||||
cmd.Flags().VarP(&selector, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
var selectors holos.Selectors
|
||||
cmd.Flags().VarP(&selectors, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
tagMap := make(holos.TagMap)
|
||||
cmd.Flags().VarP(&tagMap, "inject", "t", tagHelp)
|
||||
|
||||
@@ -75,7 +75,7 @@ func newPlatform(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
|
||||
}
|
||||
opts := builder.PlatformOpts{
|
||||
Fn: makeComponentRenderFunc(cmd.ErrOrStderr(), prefixArgs, tagMap.Tags()),
|
||||
Selector: selector,
|
||||
Selectors: selectors,
|
||||
Concurrency: concurrency,
|
||||
InfoEnabled: true,
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ func newShowBuildPlanCmd() (cmd *cobra.Command) {
|
||||
cmd.Flags().Var(&extractYAMLs, "extract-yaml", "data file paths to extract and unify with the platform config")
|
||||
var format string
|
||||
cmd.Flags().StringVar(&format, "format", "yaml", "yaml or json format")
|
||||
var selector holos.Selector
|
||||
cmd.Flags().VarP(&selector, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
var selectors holos.Selectors
|
||||
cmd.Flags().VarP(&selectors, "selector", "l", "label selector (e.g. label==string,label!=string)")
|
||||
tagMap := make(holos.TagMap)
|
||||
cmd.Flags().VarP(&tagMap, "inject", "t", "set the value of a cue @tag field from a key=value pair")
|
||||
var concurrency int
|
||||
@@ -102,7 +102,7 @@ func newShowBuildPlanCmd() (cmd *cobra.Command) {
|
||||
|
||||
platformOpts := builder.PlatformOpts{
|
||||
Fn: makeBuildFunc(encoder, buildPlanOpts),
|
||||
Selector: selector,
|
||||
Selectors: selectors,
|
||||
Concurrency: concurrency,
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,28 @@ func (e *EnvFlagger) Flag(name feature) bool {
|
||||
|
||||
type Labels map[string]string
|
||||
|
||||
type Selectors []Selector
|
||||
|
||||
// String implements the flag.Value interface.
|
||||
func (s *Selectors) String() string {
|
||||
return fmt.Sprint(*s)
|
||||
}
|
||||
|
||||
// Type implements the pflag.Value interface and describes the type.
|
||||
func (s *Selectors) Type() string {
|
||||
return "selectors"
|
||||
}
|
||||
|
||||
// Set implements the flag.Value interface.
|
||||
func (s *Selectors) Set(value string) error {
|
||||
selector := Selector{}
|
||||
if err := selector.Set(value); err != nil {
|
||||
return err
|
||||
}
|
||||
*s = append(*s, selector)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Selector struct {
|
||||
Positive map[string]string
|
||||
Negative map[string]string
|
||||
@@ -118,14 +140,9 @@ func (s *Selector) IsSelected(labels Labels) bool {
|
||||
return true // Nil selector selects everything
|
||||
}
|
||||
|
||||
if len(s.Positive) == 0 && len(s.Negative) == 0 {
|
||||
return true // Empty selector selects everything
|
||||
}
|
||||
|
||||
// Check positive matches
|
||||
for k, v := range s.Positive {
|
||||
val, ok := labels[k]
|
||||
if !ok || v != val {
|
||||
if val, ok := labels[k]; !ok || v != val {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -251,15 +268,18 @@ func (y *yamlEncoder) Close() error {
|
||||
return errors.Wrap(y.enc.Close())
|
||||
}
|
||||
|
||||
// IsSelected returns true if all selectors select the given labels or no
|
||||
// IsSelected returns true if any one selector selects the given labels or no
|
||||
// selectors are given.
|
||||
func IsSelected(labels Labels, selectors ...Selector) bool {
|
||||
if len(selectors) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, selector := range selectors {
|
||||
if !selector.IsSelected(labels) {
|
||||
return false
|
||||
if selector.IsSelected(labels) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
type orderedEncoder struct {
|
||||
|
||||
@@ -1 +1 @@
|
||||
2
|
||||
4
|
||||
|
||||
Reference in New Issue
Block a user