Skip to content

Commit

Permalink
feat(CLI): List deps (#223)
Browse files Browse the repository at this point in the history
* feat: Support image get and dep list

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* fix: Reorder argument

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* fix: Add a new field

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* fix: Remove default env

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* fix: Add mod

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* fix: Add license

Signed-off-by: Ce Gao <cegao@tensorchord.ai>
  • Loading branch information
gaocegege committed Jun 1, 2022
1 parent 2d8f6fb commit 6a4b7b5
Show file tree
Hide file tree
Showing 17 changed files with 644 additions and 58 deletions.
2 changes: 1 addition & 1 deletion cmd/envd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ func build(clicontext *cli.Context) error {
if err != nil {
return errors.Wrap(err, "failed to create the builder")
}
return builder.Build(clicontext.Path("public-key"), clicontext.Context)
return builder.Build(clicontext.Context, clicontext.Path("public-key"))
}
30 changes: 30 additions & 0 deletions cmd/envd/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2022 The envd 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.

package main

import (
cli "github.com/urfave/cli/v2"
)

var CommandGet = &cli.Command{
Name: "get",
Aliases: []string{"g"},
Usage: "Get images, or environments",

Subcommands: []*cli.Command{
CommandGetEnvironment,
CommandGetImage,
},
}
38 changes: 24 additions & 14 deletions cmd/envd/ls.go → cmd/envd/get_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,36 @@ import (
"github.com/tensorchord/envd/pkg/types"
)

var CommandLS = &cli.Command{
Name: "ls",
Aliases: []string{"l"},
Usage: "list envd environments",
var CommandGetEnvironment = &cli.Command{
Name: "envs",
Aliases: []string{"env", "e"},
Usage: "List envd environments",

Action: list,
Subcommands: []*cli.Command{
CommandGetEnvironmentDependency,
},
Action: getEnvironment,
}

func list(clicontext *cli.Context) error {
func getEnvironment(clicontext *cli.Context) error {
envdEngine, err := envd.New(clicontext.Context)
if err != nil {
return err
}
envs, err := envdEngine.List(clicontext.Context)
envs, err := envdEngine.ListEnvironment(clicontext.Context)
if err != nil {
return err
}
render(envs, os.Stdout)
renderEnvironments(envs, os.Stdout)
return nil
}

func render(envs []types.EnvdEnvironment, w io.Writer) {
func renderEnvironments(envs []types.EnvdEnvironment, w io.Writer) {
table := tablewriter.NewWriter(w)
table.SetHeader([]string{"Name", "jupyter", "SSH Target", "GPU", "Status", "Container ID"})
table.SetHeader([]string{
"Name", "jupyter", "SSH Target", "Context", "Image",
"GPU", "CUDA", "CUDNN", "Status", "Container ID",
})

table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
Expand All @@ -66,13 +72,17 @@ func render(envs []types.EnvdEnvironment, w io.Writer) {
table.SetNoWhiteSpace(true)

for _, env := range envs {
envRow := make([]string, 6)
envRow := make([]string, 10)
envRow[0] = env.Name
envRow[1] = env.JupyterAddr
envRow[2] = fmt.Sprintf("%s.envd", env.Name)
envRow[3] = strconv.FormatBool(env.GPU)
envRow[4] = env.State
envRow[5] = stringid.TruncateID(env.Container.ID)
envRow[3] = stringOrNone(env.BuildContext)
envRow[4] = env.Container.Image
envRow[5] = strconv.FormatBool(env.GPU)
envRow[6] = stringOrNone(env.CUDA)
envRow[7] = stringOrNone(env.CUDNN)
envRow[8] = env.State
envRow[9] = stringid.TruncateID(env.Container.ID)
table.Append(envRow)
}
table.Render()
Expand Down
113 changes: 113 additions & 0 deletions cmd/envd/get_env_dep.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2022 The envd 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.

package main

import (
"io"
"os"

"github.com/cockroachdb/errors"
"github.com/olekukonko/tablewriter"
"github.com/sirupsen/logrus"
"github.com/tensorchord/envd/pkg/envd"
sshconfig "github.com/tensorchord/envd/pkg/ssh/config"
"github.com/tensorchord/envd/pkg/types"
cli "github.com/urfave/cli/v2"
)

var CommandGetEnvironmentDependency = &cli.Command{
Name: "deps",
Aliases: []string{"dep", "d"},
Usage: "List all dependencies",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "env",
Usage: "Specify the envd environment to use",
Aliases: []string{"e"},
},
&cli.PathFlag{
Name: "private-key",
Usage: "Path to the private key",
Aliases: []string{"k"},
Value: sshconfig.GetPrivateKey(),
},
&cli.BoolFlag{
Name: "full",
Usage: "Show full dependency information",
Aliases: []string{"f"},
},
},
Action: getEnvironmentDependency,
}

func getEnvironmentDependency(clicontext *cli.Context) error {
envName := clicontext.String("env")
if envName == "" {
return errors.New("env is required")
}
envdEngine, err := envd.New(clicontext.Context)
if err != nil {
return errors.Wrap(err, "failed to create envd engine")
}
full := clicontext.Bool("full")
if full {
output, err := envdEngine.ListEnvFullDependency(clicontext.Context, envName, clicontext.Path("private-key"))
if err != nil {
return errors.Wrap(err, "failed to list dependencies")
}
logrus.Infof("%s", output)
} else {
dep, err := envdEngine.ListEnvDependency(clicontext.Context, envName)
if err != nil {
return errors.Wrap(err, "failed to list dependencies")
}
renderDependencies(dep, os.Stdout)
}
return nil
}

func renderDependencies(dep *types.Dependency, w io.Writer) {
table := tablewriter.NewWriter(w)
table.SetHeader([]string{"Dependency", "Type"})

table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetTablePadding("\t") // pad with tabs
table.SetNoWhiteSpace(true)

if dep == nil {
return
}
for _, p := range dep.PyPIPackages {
envRow := make([]string, 2)
envRow[0] = p
envRow[1] = "Python"
table.Append(envRow)
}
for _, p := range dep.APTPackages {
envRow := make([]string, 2)
envRow[0] = p
envRow[1] = "APT"
table.Append(envRow)
}
table.Render()
}
103 changes: 103 additions & 0 deletions cmd/envd/get_image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2022 The envd 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.

package main

import (
"io"
"os"
"strconv"
"time"

"github.com/docker/docker/pkg/stringid"
"github.com/docker/go-units"
"github.com/olekukonko/tablewriter"
cli "github.com/urfave/cli/v2"

"github.com/tensorchord/envd/pkg/envd"
"github.com/tensorchord/envd/pkg/types"
)

var CommandGetImage = &cli.Command{
Name: "images",
Aliases: []string{"image", "i"},
Usage: "List envd images",

Subcommands: []*cli.Command{
CommandGetImageDependency,
},

Action: getImage,
}

func getImage(clicontext *cli.Context) error {
envdEngine, err := envd.New(clicontext.Context)
if err != nil {
return err
}
envs, err := envdEngine.ListImage(clicontext.Context)
if err != nil {
return err
}
renderImages(envs, os.Stdout)
return nil
}

func renderImages(imgs []types.EnvdImage, w io.Writer) {
table := tablewriter.NewWriter(w)
table.SetHeader([]string{"Name", "Context", "GPU", "CUDA", "CUDNN", "Image ID", "Created", "Size"})

table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetTablePadding("\t") // pad with tabs
table.SetNoWhiteSpace(true)

for _, img := range imgs {
envRow := make([]string, 8)
envRow[0] = types.GetImageName(img)
envRow[1] = stringOrNone(img.BuildContext)
envRow[2] = strconv.FormatBool(img.GPU)
envRow[3] = stringOrNone(img.CUDA)
envRow[4] = stringOrNone(img.CUDNN)
envRow[5] = stringid.TruncateID(img.ImageSummary.ID)
envRow[6] = createdSinceString(img.ImageSummary.Created)
envRow[7] = units.HumanSizeWithPrecision(float64(img.ImageSummary.Size), 3)
table.Append(envRow)
}
table.Render()
}

func stringOrNone(cuda string) string {
if cuda == "" {
return "<none>"
}
return cuda
}

func createdSinceString(created int64) string {
createdAt := time.Unix(created, 0)

if createdAt.IsZero() {
return ""
}

return units.HumanDuration(time.Now().UTC().Sub(createdAt)) + " ago"
}
54 changes: 54 additions & 0 deletions cmd/envd/get_image_dep.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2022 The envd 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.

package main

import (
"os"

"github.com/cockroachdb/errors"
"github.com/tensorchord/envd/pkg/envd"
cli "github.com/urfave/cli/v2"
)

var CommandGetImageDependency = &cli.Command{
Name: "deps",
Aliases: []string{"dep", "d"},
Usage: "List all dependencies in the image",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "image",
Usage: "Specify the image to use",
Aliases: []string{"i"},
},
},
Action: getImageDependency,
}

func getImageDependency(clicontext *cli.Context) error {
envName := clicontext.String("image")
if envName == "" {
return errors.New("image is required")
}
envdEngine, err := envd.New(clicontext.Context)
if err != nil {
return errors.Wrap(err, "failed to create envd engine")
}
dep, err := envdEngine.ListImageDependency(clicontext.Context, envName)
if err != nil {
return errors.Wrap(err, "failed to list dependencies")
}
renderDependencies(dep, os.Stdout)
return nil
}
2 changes: 1 addition & 1 deletion cmd/envd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func run(args []string) (bool, error) {
CommandBootstrap,
CommandBuild,
CommandDestroy,
CommandLS,
CommandGet,
CommandUp,
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/envd/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func up(clicontext *cli.Context) error {
return errors.Wrap(err, "failed to create the builder")
}

if err := builder.Build(clicontext.Path("public-key"), clicontext.Context); err != nil {
if err := builder.Build(clicontext.Context, clicontext.Path("public-key")); err != nil {
return err
}
gpu := builder.GPUEnabled()
Expand Down

0 comments on commit 6a4b7b5

Please sign in to comment.