From f8d51a3a2404e8711cfe88394114b24b724f2dbc Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 1 Apr 2026 15:45:03 +0200 Subject: [PATCH 1/2] refactor: extract manifest getter Signed-off-by: Mark Sagi-Kazar --- cmd/playground/manifest.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/cmd/playground/manifest.go b/cmd/playground/manifest.go index e63e03f..e28064c 100644 --- a/cmd/playground/manifest.go +++ b/cmd/playground/manifest.go @@ -32,14 +32,29 @@ func newManifestCommand(cli labcli.CLI) *cobra.Command { } func runManifest(ctx context.Context, cli labcli.CLI, opts *manifestOptions) error { - playground, err := cli.Client().GetPlayground(ctx, opts.name, &api.GetPlaygroundOptions{ + manifest, err := getManifest(ctx, cli, opts.name) + if err != nil { + return err + } + + bytes, err := yaml.Marshal(manifest) + if err != nil { + return fmt.Errorf("couldn't marshal manifest: %w", err) + } + + cli.PrintOut("%s", string(bytes)) + return nil +} + +func getManifest(ctx context.Context, cli labcli.CLI, name string) (*api.PlaygroundManifest, error) { + playground, err := cli.Client().GetPlayground(ctx, name, &api.GetPlaygroundOptions{ Format: "extended", }) if err != nil { - return fmt.Errorf("couldn't get playground: %w", err) + return nil, fmt.Errorf("couldn't get playground: %w", err) } - manifest := api.PlaygroundManifest{ + return &api.PlaygroundManifest{ Kind: "playground", Name: playground.Name, Base: playground.Base, @@ -58,13 +73,5 @@ func runManifest(ctx context.Context, cli labcli.CLI, opts *manifestOptions) err PortForwards: playground.PortForwards, AccessControl: playground.AccessControl, }, - } - - bytes, err := yaml.Marshal(manifest) - if err != nil { - return fmt.Errorf("couldn't marshal manifest: %w", err) - } - - cli.PrintOut("%s", string(bytes)) - return nil + }, nil } From 54e8ee060ee181fc312025e8a48777ca6c830951 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 1 Apr 2026 15:45:29 +0200 Subject: [PATCH 2/2] feat: allow creating a playground without a manifest Signed-off-by: Mark Sagi-Kazar --- cmd/playground/create.go | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/cmd/playground/create.go b/cmd/playground/create.go index e5abe8d..3d30c13 100644 --- a/cmd/playground/create.go +++ b/cmd/playground/create.go @@ -40,9 +40,6 @@ func newCreateCommand(cli labcli.CLI) *cobra.Command { if opts.base == "" { return labcli.NewStatusError(1, "--base flag is required\n\nHint: List all possible base playgrounds with `labctl playgrounds catalog --filter base`.") } - if opts.file == "" { - return labcli.NewStatusError(1, "--file flag is required\n\nHint: You can get some inspiration from `labctl playgrounds manifest k8s-omni` output.") - } return labcli.WrapStatusError(runCreate(cmd.Context(), cli, &opts)) }, } @@ -74,19 +71,33 @@ func newCreateCommand(cli labcli.CLI) *cobra.Command { } func runCreate(ctx context.Context, cli labcli.CLI, opts *createOptions) error { - if opts.file != "-" { - absFile, err := filepath.Abs(opts.file) + var manifest *api.PlaygroundManifest + var err error + if opts.file == "" { + cli.PrintAux("Creating playground from default manifest\n") + + manifest, err = getManifest(ctx, cli, opts.base) if err != nil { - return fmt.Errorf("couldn't get the absolute path of %s: %w", opts.file, err) + return err } - cli.PrintAux("Creating playground from %s\n", absFile) + + manifest.Name = opts.name } else { - cli.PrintAux("Creating playground from stdin\n") - } - manifest, err := readManifestFile(opts.file) - if err != nil { - return fmt.Errorf("couldn't read manifest: %w", err) + if opts.file != "-" { + absFile, err := filepath.Abs(opts.file) + if err != nil { + return fmt.Errorf("couldn't get the absolute path of %s: %w", opts.file, err) + } + cli.PrintAux("Creating playground from %s\n", absFile) + } else { + cli.PrintAux("Creating playground from stdin\n") + } + + manifest, err = readManifestFile(opts.file) + if err != nil { + return fmt.Errorf("couldn't read manifest: %w", err) + } } if manifest.Name != "" && manifest.Name != opts.name {