Skip to content

Commit

Permalink
Launch Flyte cluster in the single binary mode (#306)
Browse files Browse the repository at this point in the history
* Using sandbox-lite

Signed-off-by: Kevin Su <[email protected]>

* Add demo command

Signed-off-by: Kevin Su <[email protected]>

* wip

Signed-off-by: Kevin Su <[email protected]>

* wip

Signed-off-by: Kevin Su <[email protected]>
  • Loading branch information
pingsutw authored Apr 12, 2022
1 parent e22bce6 commit f103848
Show file tree
Hide file tree
Showing 15 changed files with 1,485 additions and 11 deletions.
64 changes: 64 additions & 0 deletions flytectl/cmd/demo/demo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package demo

import (
sandboxConfig "github.com/flyteorg/flytectl/cmd/config/subcommand/sandbox"
cmdcore "github.com/flyteorg/flytectl/cmd/core"
"github.com/spf13/cobra"
)

// Long descriptions are whitespace sensitive when generating docs using sphinx.
const (
demoShort = `Helps with demo interactions like start, teardown, status, and exec.`
demoLong = `
Flyte Demo is a fully standalone minimal environment for running Flyte.
It provides a simplified way of running Flyte demo as a single Docker container locally.
To create a demo cluster, run:
::
flytectl demo start
To remove a demo cluster, run:
::
flytectl demo teardown
To check the status of the demo container, run:
::
flytectl demo status
To execute commands inside the demo container, use exec:
::
flytectl demo exec -- pwd
`
)

// CreateDemoCommand will return demo command
func CreateDemoCommand() *cobra.Command {
demo := &cobra.Command{
Use: "demo",
Short: demoShort,
Long: demoLong,
}

demoResourcesFuncs := map[string]cmdcore.CommandEntry{
"start": {CmdFunc: startDemoCluster, Aliases: []string{}, ProjectDomainNotRequired: true,
Short: startShort,
Long: startLong, PFlagProvider: sandboxConfig.DefaultConfig},
"teardown": {CmdFunc: teardownDemoCluster, Aliases: []string{}, ProjectDomainNotRequired: true,
Short: teardownShort,
Long: teardownLong},
"status": {CmdFunc: demoClusterStatus, Aliases: []string{}, ProjectDomainNotRequired: true,
Short: statusShort,
Long: statusLong},
"exec": {CmdFunc: demoClusterExec, Aliases: []string{}, ProjectDomainNotRequired: true,
Short: execShort,
Long: execLong},
}

cmdcore.AddCommands(demo, demoResourcesFuncs)

return demo
}
39 changes: 39 additions & 0 deletions flytectl/cmd/demo/demo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package demo

import (
"fmt"
"sort"
"testing"

"gotest.tools/assert"
)

func TestCreateDemoCommand(t *testing.T) {
demoCommand := CreateDemoCommand()
assert.Equal(t, demoCommand.Use, "demo")
assert.Equal(t, demoCommand.Short, "Helps with demo interactions like start, teardown, status, and exec.")
fmt.Println(demoCommand.Commands())
assert.Equal(t, len(demoCommand.Commands()), 4)
cmdNouns := demoCommand.Commands()
// Sort by Use value.
sort.Slice(cmdNouns, func(i, j int) bool {
return cmdNouns[i].Use < cmdNouns[j].Use
})

assert.Equal(t, cmdNouns[0].Use, "exec")
assert.Equal(t, cmdNouns[0].Short, execShort)
assert.Equal(t, cmdNouns[0].Long, execLong)

assert.Equal(t, cmdNouns[1].Use, "start")
assert.Equal(t, cmdNouns[1].Short, startShort)
assert.Equal(t, cmdNouns[1].Long, startLong)

assert.Equal(t, cmdNouns[2].Use, "status")
assert.Equal(t, cmdNouns[2].Short, statusShort)
assert.Equal(t, cmdNouns[2].Long, statusLong)

assert.Equal(t, cmdNouns[3].Use, "teardown")
assert.Equal(t, cmdNouns[3].Short, teardownShort)
assert.Equal(t, cmdNouns[3].Long, teardownLong)

}
47 changes: 47 additions & 0 deletions flytectl/cmd/demo/exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package demo

import (
"context"
"fmt"

cmdCore "github.com/flyteorg/flytectl/cmd/core"
"github.com/flyteorg/flytectl/pkg/docker"
)

const (
execShort = "Executes non-interactive command inside the demo container"
execLong = `
Run non-interactive commands inside the demo container and immediately return the output.
By default, "flytectl exec" is present in the /root directory inside the demo container.
::
flytectl demo exec -- ls -al
Usage`
)

func demoClusterExec(ctx context.Context, args []string, cmdCtx cmdCore.CommandContext) error {
cli, err := docker.GetDockerClient()
if err != nil {
return err
}
if len(args) > 0 {
return execute(ctx, cli, args)
}
return fmt.Errorf("missing argument. Please check usage examples by running flytectl demo exec --help")
}

func execute(ctx context.Context, cli docker.Docker, args []string) error {
c := docker.GetSandbox(ctx, cli)
if c != nil {
exec, err := docker.ExecCommend(ctx, cli, c.ID, args)
if err != nil {
return err
}
if err := docker.InspectExecResp(ctx, cli, exec.ID); err != nil {
return err
}
}
return nil
}
76 changes: 76 additions & 0 deletions flytectl/cmd/demo/exec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package demo

import (
"bufio"
"context"
"fmt"
"io"
"strings"
"testing"

"github.com/flyteorg/flytectl/cmd/testutils"

admin2 "github.com/flyteorg/flyteidl/clients/go/admin"

cmdCore "github.com/flyteorg/flytectl/cmd/core"
"github.com/stretchr/testify/assert"

"github.com/docker/docker/api/types"
"github.com/flyteorg/flytectl/pkg/docker"
"github.com/flyteorg/flytectl/pkg/docker/mocks"
"github.com/stretchr/testify/mock"
)

func TestDemoClusterExec(t *testing.T) {
mockDocker := &mocks.Docker{}
mockOutStream := new(io.Writer)
ctx := context.Background()
mockClient := admin2.InitializeMockClientset()
cmdCtx := cmdCore.NewCommandContext(mockClient, *mockOutStream)
reader := bufio.NewReader(strings.NewReader("test"))

mockDocker.OnContainerList(ctx, types.ContainerListOptions{All: true}).Return([]types.Container{
{
ID: docker.FlyteSandboxClusterName,
Names: []string{
docker.FlyteSandboxClusterName,
},
},
}, nil)
docker.ExecConfig.Cmd = []string{"ls -al"}
mockDocker.OnContainerExecCreateMatch(ctx, mock.Anything, docker.ExecConfig).Return(types.IDResponse{}, nil)
mockDocker.OnContainerExecInspectMatch(ctx, mock.Anything).Return(types.ContainerExecInspect{}, nil)
mockDocker.OnContainerExecAttachMatch(ctx, mock.Anything, types.ExecStartCheck{}).Return(types.HijackedResponse{
Reader: reader,
}, fmt.Errorf("Test"))
docker.Client = mockDocker
err := demoClusterExec(ctx, []string{"ls -al"}, cmdCtx)

assert.NotNil(t, err)
}

func TestSandboxClusterExecWithoutCmd(t *testing.T) {
mockDocker := &mocks.Docker{}
reader := bufio.NewReader(strings.NewReader("test"))
s := testutils.Setup()
ctx := s.Ctx

mockDocker.OnContainerList(ctx, types.ContainerListOptions{All: true}).Return([]types.Container{
{
ID: docker.FlyteSandboxClusterName,
Names: []string{
docker.FlyteSandboxClusterName,
},
},
}, nil)
docker.ExecConfig.Cmd = []string{}
mockDocker.OnContainerExecCreateMatch(ctx, mock.Anything, docker.ExecConfig).Return(types.IDResponse{}, nil)
mockDocker.OnContainerExecInspectMatch(ctx, mock.Anything).Return(types.ContainerExecInspect{}, nil)
mockDocker.OnContainerExecAttachMatch(ctx, mock.Anything, types.ExecStartCheck{}).Return(types.HijackedResponse{
Reader: reader,
}, fmt.Errorf("Test"))
docker.Client = mockDocker
err := demoClusterExec(ctx, []string{}, s.CmdCtx)

assert.NotNil(t, err)
}
Loading

0 comments on commit f103848

Please sign in to comment.