Files
holos/internal/cli/render/render.go
Jeff McCune b78e862d09 maint: cleanup unused functions and code
ExtractYAML is no longer used, also cleans up connectrpc packages, error
handling, tracing, and memory profiling.
2025-04-03 15:33:42 -07:00

98 lines
3.0 KiB
Go

package render
import (
"context"
"os"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/component"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/platform"
"github.com/holos-run/holos/internal/util"
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("render")
cmd.Args = cobra.NoArgs
cmd.Short = "render platforms and components to manifest files"
cmd.AddCommand(NewRenderPlatformCommand(cfg, platform.NewConfig()))
cmd.AddCommand(component.NewCommand(component.NewConfig()))
return cmd
}
func NewRenderPlatformCommand(cfg *holos.Config, pcfg *platform.Config) (cmd *cobra.Command) {
rp := &renderPlatform{cfg: cfg, pcfg: pcfg}
cmd = platform.NewCommand(pcfg, rp.Run)
cmd.Short = "render an entire platform"
cmd.Flags().AddFlagSet(pcfg.FlagSet())
return cmd
}
// renderPlatform implements the holos render platform command.
type renderPlatform struct {
cfg *holos.Config
pcfg *platform.Config
}
// Run executes the holos render component command concurrently for each
// platform component. The overall approach is to marshal the component into
// cue tags, pass the log level and format, then execute the command as a sub
// process.
//
// Note that the marshalling of component fields through the argument vector has
// been quite awkward to maintain. Consider refactoring to an approach of
// marshaling the entire component structure via stdin to a sub process that
// returns a build plan on stdout. The purpose of using a sub process is to
// execute cue concurrently. Cue is not safe for concurrent use within the same
// process.
func (r *renderPlatform) Run(ctx context.Context, p *platform.Platform) error {
prefixArgs := []string{
"--log-level", r.cfg.LogConfig().Level(),
"--log-format", r.cfg.LogConfig().Format(),
}
opts := platform.BuildOpts{
PerComponentFunc: func(ctx context.Context, i int, c holos.Component) error {
select {
case <-ctx.Done():
return errors.Wrap(ctx.Err())
default:
args := make([]string, 0, 100)
args = append(args, prefixArgs...)
args = append(args, "render", "component")
// holos render platform --inject tags
for _, tag := range r.pcfg.TagMap.Tags() {
args = append(args, "--inject", tag)
}
// component tags (name, labels, annotations)
if tags, err := c.Tags(); err != nil {
return errors.Wrap(err)
} else {
for _, tag := range tags {
args = append(args, "--inject", tag)
}
}
// component path
args = append(args, c.Path())
// Get current executable path.
holosPath, err := os.Executable()
if err != nil {
return errors.Wrap(err)
}
// Run holos render component ...
if _, err := util.RunCmdA(ctx, r.pcfg.Stderr, holosPath, args...); err != nil {
return errors.Format("could not render component: %w", err)
}
}
return nil
},
InfoEnabled: true,
}
return errors.Wrap(p.Build(ctx, opts))
}