Skip to content

Commit

Permalink
Refactor kit dev flags to subcommands
Browse files Browse the repository at this point in the history
Replace --stop and --logs flags for kit dev with subcommands:

* kit dev start -> start the server
* kit dev stop  -> stop a running server
* kit dev logs  -> print logs from last run
  • Loading branch information
amisevsk committed May 10, 2024
1 parent d91345e commit 76ec9bc
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 87 deletions.
164 changes: 79 additions & 85 deletions pkg/cmd/dev/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
package dev

import (
"context"
"fmt"
"kitops/pkg/lib/constants"
"kitops/pkg/lib/filesystem"
"kitops/pkg/lib/harness"
"kitops/pkg/output"
"net"
Expand All @@ -30,76 +26,58 @@ import (
"github.com/spf13/cobra"
)

const (
shortDesc = `Start development server (experimental)`
longDesc = `Start development server (experimental) with the specified context directory and kitfile`
example = `kit dev ./my-model --port 8080`
)

type DevOptions struct {
host string
port int
modelFile string
contextDir string
configHome string
stop bool
printLogs bool
}

func (opts *DevOptions) complete(ctx context.Context, args []string) error {

configHome, ok := ctx.Value(constants.ConfigKey{}).(string)
if !ok {
return fmt.Errorf("default config path not set on command context")
}
opts.configHome = configHome
if !opts.stop && !opts.printLogs {
opts.contextDir = ""
if len(args) == 1 {
opts.contextDir = args[0]
}
if opts.modelFile == "" {
foundKitfile, err := filesystem.FindKitfileInPath(opts.contextDir)
if err != nil {
return err
}
opts.modelFile = foundKitfile
}
if opts.host == "" {
opts.host = "127.0.0.1"
}

if opts.port == 0 {
availPort, err := findAvailablePort()
if err != nil {
output.Fatalf("Invalid arguments: %s", err)
return err
}
opts.port = availPort
}
func DevCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "dev <directory> [flags]",
Short: devShortDesc,
Long: devLongDesc,
Example: devExample,
}
return nil
cmd.AddCommand(DevStartCommand())
cmd.AddCommand(DevStopCommand())
cmd.AddCommand(DevLogsCommand())
return cmd
}

func DevCommand() *cobra.Command {
opts := &DevOptions{}
func DevStartCommand() *cobra.Command {
opts := &DevStartOptions{}
cmd := &cobra.Command{
Use: "dev <directory> [flags]",
Short: shortDesc,
Long: longDesc,
Example: example,
Run: runCommand(opts),
Use: "start <directory> [flags]",
Short: devStartShortDesc,
Long: devStartLongDesc,
Example: devStartExample,
Run: runStartCommand(opts),
}
cmd.Args = cobra.MaximumNArgs(1)
cmd.Flags().StringVarP(&opts.modelFile, "file", "f", "", "Path to the kitfile")
cmd.Flags().StringVar(&opts.host, "host", "127.0.0.1", "Host for the development server")
cmd.Flags().IntVar(&opts.port, "port", 0, "Port for development server to listen on")
cmd.Flags().BoolVar(&opts.stop, "stop", false, "Stop the development server")
cmd.Flags().BoolVar(&opts.printLogs, "logs", false, "Print logs for the running development server")
return cmd
}

func runCommand(opts *DevOptions) func(cmd *cobra.Command, args []string) {
func DevStopCommand() *cobra.Command {
opts := &DevBaseOptions{}
cmd := &cobra.Command{
Use: "stop",
Short: devStopShortDesc,
Long: devStopLongDesc,
Run: runStopCommand(opts),
}
return cmd
}

func DevLogsCommand() *cobra.Command {
opts := &DevBaseOptions{}
cmd := &cobra.Command{
Use: "logs",
Short: devLogsShortDesc,
Long: devLogsLongDesc,
Run: runLogsCommand(opts),
}
return cmd
}

func runStartCommand(opts *DevStartOptions) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
if runtime.GOOS == "windows" || runtime.GOOS == "linux" {
output.Infoln("Development server is not yet supported in this platform")
Expand All @@ -111,29 +89,45 @@ func runCommand(opts *DevOptions) func(cmd *cobra.Command, args []string) {
output.Errorf("failed to complete options: %s", err)
return
}
switch {
case opts.stop:
output.Infoln("Stopping development server...")
err := stopDev(cmd.Context(), opts)
if err != nil {
output.Errorf("Failed to stop dev server: %s", err)
os.Exit(1)
}
output.Infoln("Development server stopped")
case opts.printLogs:
err := harness.PrintLogs(opts.configHome, cmd.OutOrStdout())
if err != nil {
output.Errorln(err)
os.Exit(1)
}
default:
err := runDev(cmd.Context(), opts)
if err != nil {
output.Errorf("Failed to start dev server: %s", err)
os.Exit(1)
}
output.Infof("Development server started at http://%s:%d", opts.host, opts.port)
output.Infof("Use \"kit dev --stop\" to stop the development server")

err := runDev(cmd.Context(), opts)
if err != nil {
output.Errorf("Failed to start dev server: %s", err)
os.Exit(1)
}
output.Infof("Development server started at http://%s:%d", opts.host, opts.port)
output.Infof("Use \"kit dev stop\" to stop the development server")
}
}

func runStopCommand(opts *DevBaseOptions) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
if err := opts.complete(cmd.Context(), args); err != nil {
output.Errorf("failed to complete options: %s", err)
return
}

output.Infoln("Stopping development server...")
err := stopDev(cmd.Context(), opts)
if err != nil {
output.Errorf("Failed to stop dev server: %s", err)
os.Exit(1)
}
output.Infoln("Development server stopped")
}
}

func runLogsCommand(opts *DevBaseOptions) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
if err := opts.complete(cmd.Context(), args); err != nil {
output.Errorf("failed to complete options: %s", err)
return
}

err := harness.PrintLogs(opts.configHome, cmd.OutOrStdout())
if err != nil {
output.Errorln(err)
os.Exit(1)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"os"
)

func runDev(ctx context.Context, options *DevOptions) error {
func runDev(ctx context.Context, options *DevStartOptions) error {

kitfile := &artifact.KitFile{}

Expand Down Expand Up @@ -67,7 +67,7 @@ func runDev(ctx context.Context, options *DevOptions) error {
return nil
}

func stopDev(ctx context.Context, options *DevOptions) error {
func stopDev(_ context.Context, options *DevBaseOptions) error {

llmHarness := &harness.LLMHarness{}
llmHarness.ConfigHome = options.configHome
Expand Down
77 changes: 77 additions & 0 deletions pkg/cmd/dev/opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2024 The KitOps Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package dev

import (
"context"
"fmt"
"kitops/pkg/lib/constants"
"kitops/pkg/lib/filesystem"
"kitops/pkg/output"
)

type DevBaseOptions struct {
configHome string
}

func (opts *DevBaseOptions) complete(ctx context.Context, args []string) error {
configHome, ok := ctx.Value(constants.ConfigKey{}).(string)
if !ok {
return fmt.Errorf("default config path not set on command context")
}
opts.configHome = configHome
return nil
}

type DevStartOptions struct {
DevBaseOptions
host string
port int
modelFile string
contextDir string
}

func (opts *DevStartOptions) complete(ctx context.Context, args []string) error {
if err := opts.DevBaseOptions.complete(ctx, args); err != nil {
return err
}

opts.contextDir = ""
if len(args) == 1 {
opts.contextDir = args[0]
}
if opts.modelFile == "" {
foundKitfile, err := filesystem.FindKitfileInPath(opts.contextDir)
if err != nil {
return err
}
opts.modelFile = foundKitfile
}
if opts.host == "" {
opts.host = "127.0.0.1"
}

if opts.port == 0 {
availPort, err := findAvailablePort()
if err != nil {
output.Fatalf("Invalid arguments: %s", err)
return err
}
opts.port = availPort
}
return nil
}
47 changes: 47 additions & 0 deletions pkg/cmd/dev/usage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2024 The KitOps Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package dev

const (
devShortDesc = "Run models locally (experimental)"
devLongDesc = "Start a local server and interact with a model in the browser"
devExample = "kit dev start"

devStartShortDesc = "Start development server (experimental)"
devStartLongDesc = `Start development server (experimental) from a modelkit
Start a development server for an unpacked modelkit, using a context directory
that includes the model and a kitfile.
`
devStartExample = `# Serve the model located in the current directory
kit dev start
# Serve the modelkit in ./my-model on port 8080
kit dev start ./my-model --port 8080
`

devStopShortDesc = "Stop development server"
devStopLongDesc = "Stop the development server if it is running"

devLogsShortDesc = "View logs for development server"
devLogsLongDesc = `Print any logs output by the development server.
If the development server is currently running, the logs for this server will
be printed. If it is stopped, the logs for the previous run of the server, if
available, will be printed instead.
`
)

0 comments on commit 76ec9bc

Please sign in to comment.