Skip to content

Commit

Permalink
feat(CLI): envd env describe expose info (#801)
Browse files Browse the repository at this point in the history
* feat(CLI): envd env describe expose info

Signed-off-by: Keming <kemingyang@tensorchord.ai>

* done

Signed-off-by: Keming <kemingyang@tensorchord.ai>

* keep writer interface

Signed-off-by: Keming <kemingyang@tensorchord.ai>

Signed-off-by: Keming <kemingyang@tensorchord.ai>
  • Loading branch information
kemingy authored Aug 22, 2022
1 parent c85766c commit 5c4971b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 14 deletions.
52 changes: 39 additions & 13 deletions pkg/app/env_describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,20 @@ import (
var CommandDescribeEnvironment = &cli.Command{
Name: "describe",
Aliases: []string{"d"},
Usage: "Show details about environments, including dependencies",
Usage: "Show details about environments, including dependencies and port binding",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "env",
Usage: "Specify the envd environment to use",
Aliases: []string{"e"},
Name: "env",
Usage: "Specify the envd environment to use",
Aliases: []string{"e"},
Required: true,
},
},
Action: getEnvironmentDependency,
Action: getEnvironmentDescriptions,
}

func getEnvironmentDependency(clicontext *cli.Context) error {
func getEnvironmentDescriptions(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")
Expand All @@ -54,13 +52,20 @@ func getEnvironmentDependency(clicontext *cli.Context) error {
if err != nil {
return errors.Wrap(err, "failed to list dependencies")
}
renderDependencies(dep, os.Stdout)

ports, err := envdEngine.ListEnvPortBinding(clicontext.Context, envName)
if err != nil {
return errors.Wrap(err, "failed to list port bindings")
}

renderDependencies(os.Stdout, dep)
renderPortBindings(os.Stdout, ports)
return nil
}

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

table.SetAutoWrapText(false)
table.SetAutoFormatHeaders(true)
Expand All @@ -70,13 +75,34 @@ func renderDependencies(dep *types.Dependency, w io.Writer) {
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetBorder(true)
table.SetTablePadding("\t") // pad with tabs
table.SetNoWhiteSpace(true)

return table
}

func renderPortBindings(w io.Writer, ports []types.PortBinding) {
if ports == nil {
return
}
table := createTable(w, []string{"Container Port", "Protocol", "Host IP", "Host Port"})
for _, port := range ports {
row := make([]string, 4)
row[0] = port.Port
row[1] = port.Protocol
row[2] = port.HostIP
row[3] = port.HostPort
table.Append(row)
}
table.Render()
}

func renderDependencies(w io.Writer, dep *types.Dependency) {
if dep == nil {
return
}
table := createTable(w, []string{"Dependencies", "Type"})
for _, p := range dep.PyPIPackages {
envRow := make([]string, 2)
envRow[0] = p
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/image_describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ func getImageDependency(clicontext *cli.Context) error {
if err != nil {
return errors.Wrap(err, "failed to list dependencies")
}
renderDependencies(dep, os.Stdout)
renderDependencies(os.Stdout, dep)
return nil
}
11 changes: 11 additions & 0 deletions pkg/envd/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Engine interface {
ResumeEnvironment(ctx context.Context, env string) (string, error)
ListEnvironment(ctx context.Context) ([]types.EnvdEnvironment, error)
ListEnvDependency(ctx context.Context, env string) (*types.Dependency, error)
ListEnvPortBinding(ctx context.Context, env string) ([]types.PortBinding, error)
GetInfo(ctx context.Context) (*types.EnvdInfo, error)
}

Expand Down Expand Up @@ -142,6 +143,16 @@ func (e generalEngine) ListEnvDependency(
return dep, nil
}

func (e generalEngine) ListEnvPortBinding(ctx context.Context, env string) ([]types.PortBinding, error) {
logrus.WithField("env", env).Debug("getting env port bindings")
ctr, err := e.dockerCli.GetContainer(ctx, env)
if err != nil {
return nil, errors.Wrap(err, "failed to get container")
}
ports := types.NewPortBindingFromContainerJSON(ctr)
return ports, nil
}

func (e generalEngine) GetInfo(ctx context.Context) (*types.EnvdInfo, error) {
info, err := e.dockerCli.GetInfo(ctx)
if err != nil {
Expand Down
25 changes: 25 additions & 0 deletions pkg/types/envd.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ type Dependency struct {
PyPIPackages []string `json:"pypi_packages,omitempty"`
}

type PortBinding struct {
Port string
Protocol string
HostIP string
HostPort string
}

func NewImage(image types.ImageSummary) (*EnvdImage, error) {
img := EnvdImage{
ImageSummary: image,
Expand Down Expand Up @@ -135,6 +142,24 @@ func NewDependencyFromImage(img types.ImageSummary) (*Dependency, error) {
return newDependencyFromLabels(img.Labels)
}

func NewPortBindingFromContainerJSON(ctr types.ContainerJSON) []PortBinding {
config := ctr.HostConfig.PortBindings
var ports []PortBinding
for port, bindings := range config {
if len(bindings) <= 0 {
continue
}
binding := bindings[len(bindings)-1]
ports = append(ports, PortBinding{
Port: port.Port(),
Protocol: port.Proto(),
HostIP: binding.HostIP,
HostPort: binding.HostPort,
})
}
return ports
}

func GetImageName(image EnvdImage) string {
if len(image.ImageSummary.RepoTags) != 0 {
return image.ImageSummary.RepoTags[0]
Expand Down

0 comments on commit 5c4971b

Please sign in to comment.