From 8543cbdfa3397cd04f3a0d196caeda105b9a298d Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 14 Jun 2022 16:11:37 -0700 Subject: [PATCH] Stop showing persistent vs ephemeral for resources Signed-off-by: Spike Curtis --- cli/cliui/resources.go | 83 +++++++++++++++----------------------- cli/create_test.go | 25 ++++++++---- cli/show_test.go | 61 ++++++++++++++++++++++++++++ cli/templatecreate.go | 9 ++++- cli/templatecreate_test.go | 30 +++++++++++++- 5 files changed, 147 insertions(+), 61 deletions(-) create mode 100644 cli/show_test.go diff --git a/cli/cliui/resources.go b/cli/cliui/resources.go index d6d047dc33af8..b9ce239e454af 100644 --- a/cli/cliui/resources.go +++ b/cli/cliui/resources.go @@ -9,6 +9,7 @@ import ( "github.com/jedib0t/go-pretty/v6/table" "github.com/coder/coder/coderd/database" + "github.com/coder/coder/codersdk" ) @@ -23,12 +24,12 @@ type WorkspaceResourcesOptions struct { // ┌────────────────────────────────────────────────────────────────────────────┐ // │ RESOURCE STATUS ACCESS │ // ├────────────────────────────────────────────────────────────────────────────┤ -// │ google_compute_disk.root persistent │ +// │ google_compute_disk.root │ // ├────────────────────────────────────────────────────────────────────────────┤ -// │ google_compute_instance.dev ephemeral │ +// │ google_compute_instance.dev │ // │ └─ dev (linux, amd64) ⦾ connecting [10s] coder ssh dev.dev │ // ├────────────────────────────────────────────────────────────────────────────┤ -// │ kubernetes_pod.dev ephemeral │ +// │ kubernetes_pod.dev │ // │ ├─ go (linux, amd64) ⦿ connected coder ssh dev.go │ // │ └─ postgres (linux, amd64) ⦾ disconnected [4s] coder ssh dev.postgres │ // └────────────────────────────────────────────────────────────────────────────┘ @@ -38,26 +39,16 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource return resources[i].Type < resources[j].Type }) - // Address on stop indexes whether a resource still exists when in the stopped transition. - addressOnStop := map[string]codersdk.WorkspaceResource{} - for _, resource := range resources { - if resource.Transition != codersdk.WorkspaceTransitionStop { - continue - } - addressOnStop[resource.Type+"."+resource.Name] = resource - } - // Displayed stores whether a resource has already been shown. - // Resources can be stored with numerous states, which we - // process prior to display. - displayed := map[string]struct{}{} - tableWriter := table.NewWriter() if options.Title != "" { tableWriter.SetTitle(options.Title) } tableWriter.SetStyle(table.StyleLight) tableWriter.Style().Options.SeparateColumns = false - row := table.Row{"Resource", "Status"} + row := table.Row{"Resource"} + if !options.HideAgentState { + row = append(row, "Status") + } if !options.HideAccess { row = append(row, "Access") } @@ -76,50 +67,20 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource continue } resourceAddress := resource.Type + "." + resource.Name - if _, shown := displayed[resourceAddress]; shown { - // The same resource can have multiple transitions. - continue - } - displayed[resourceAddress] = struct{}{} // Sort agents by name for consistent output. sort.Slice(resource.Agents, func(i, j int) bool { return resource.Agents[i].Name < resource.Agents[j].Name }) - _, existsOnStop := addressOnStop[resourceAddress] - resourceState := "ephemeral" - if existsOnStop { - resourceState = "persistent" - } + // Display a line for the resource. tableWriter.AppendRow(table.Row{ Styles.Bold.Render(resourceAddress), - Styles.Placeholder.Render(resourceState), + "", "", }) // Display all agents associated with the resource. for index, agent := range resource.Agents { - sshCommand := "coder ssh " + options.WorkspaceName - if totalAgents > 1 { - sshCommand += "." + agent.Name - } - sshCommand = Styles.Code.Render(sshCommand) - var agentStatus string - if !options.HideAgentState { - switch agent.Status { - case codersdk.WorkspaceAgentConnecting: - since := database.Now().Sub(agent.CreatedAt) - agentStatus = Styles.Warn.Render("⦾ connecting") + " " + - Styles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]") - case codersdk.WorkspaceAgentDisconnected: - since := database.Now().Sub(*agent.DisconnectedAt) - agentStatus = Styles.Error.Render("⦾ disconnected") + " " + - Styles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]") - case codersdk.WorkspaceAgentConnected: - agentStatus = Styles.Keyword.Render("⦿ connected") - } - } - pipe := "├" if index == len(resource.Agents)-1 { pipe = "└" @@ -127,9 +88,31 @@ func WorkspaceResources(writer io.Writer, resources []codersdk.WorkspaceResource row := table.Row{ // These tree from a resource! fmt.Sprintf("%s─ %s (%s, %s)", pipe, agent.Name, agent.OperatingSystem, agent.Architecture), - agentStatus, + } + if !options.HideAgentState { + var agentStatus string + if !options.HideAgentState { + switch agent.Status { + case codersdk.WorkspaceAgentConnecting: + since := database.Now().Sub(agent.CreatedAt) + agentStatus = Styles.Warn.Render("⦾ connecting") + " " + + Styles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]") + case codersdk.WorkspaceAgentDisconnected: + since := database.Now().Sub(*agent.DisconnectedAt) + agentStatus = Styles.Error.Render("⦾ disconnected") + " " + + Styles.Placeholder.Render("["+strconv.Itoa(int(since.Seconds()))+"s]") + case codersdk.WorkspaceAgentConnected: + agentStatus = Styles.Keyword.Render("⦿ connected") + } + } + row = append(row, agentStatus) } if !options.HideAccess { + sshCommand := "coder ssh " + options.WorkspaceName + if totalAgents > 1 { + sshCommand += "." + agent.Name + } + sshCommand = Styles.Code.Render(sshCommand) row = append(row, sshCommand) } tableWriter.AppendRow(row) diff --git a/cli/create_test.go b/cli/create_test.go index 1352ee18b0291..63654df7378b6 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -27,7 +27,11 @@ func TestCreate(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ + Parse: echo.ParseComplete, + Provision: provisionCompleteWithAgent, + ProvisionDryRun: provisionCompleteWithAgent, + }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) args := []string{ @@ -51,14 +55,19 @@ func TestCreate(t *testing.T) { err := cmd.Execute() assert.NoError(t, err) }() - matches := []string{ - "Confirm create", "yes", + matches := []struct { + match string + write string + }{ + {match: "compute.main"}, + {match: "smith (linux, i386)"}, + {match: "Confirm create", write: "yes"}, } - for i := 0; i < len(matches); i += 2 { - match := matches[i] - value := matches[i+1] - pty.ExpectMatch(match) - pty.WriteLine(value) + for _, m := range matches { + pty.ExpectMatch(m.match) + if len(m.write) > 0 { + pty.WriteLine(m.write) + } } <-doneChan }) diff --git a/cli/show_test.go b/cli/show_test.go new file mode 100644 index 0000000000000..491579a9c6ce6 --- /dev/null +++ b/cli/show_test.go @@ -0,0 +1,61 @@ +package cli_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/coder/coder/cli/clitest" + "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/provisioner/echo" + "github.com/coder/coder/pty/ptytest" +) + +func TestShow(t *testing.T) { + t.Parallel() + t.Run("Exists", func(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + user := coderdtest.CreateFirstUser(t, client) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ + Parse: echo.ParseComplete, + Provision: provisionCompleteWithAgent, + ProvisionDryRun: provisionCompleteWithAgent, + }) + coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) + workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) + coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) + + args := []string{ + "show", + workspace.Name, + } + cmd, root := clitest.New(t, args...) + clitest.SetupConfig(t, client, root) + doneChan := make(chan struct{}) + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + go func() { + defer close(doneChan) + err := cmd.Execute() + assert.NoError(t, err) + }() + matches := []struct { + match string + write string + }{ + {match: "compute.main"}, + {match: "smith (linux, i386)"}, + {match: "coder ssh " + workspace.Name}, + } + for _, m := range matches { + pty.ExpectMatch(m.match) + if len(m.write) > 0 { + pty.WriteLine(m.write) + } + } + <-doneChan + }) +} diff --git a/cli/templatecreate.go b/cli/templatecreate.go index 936c574b57396..457bf5cca784b 100644 --- a/cli/templatecreate.go +++ b/cli/templatecreate.go @@ -230,7 +230,14 @@ func createValidTemplateVersion(cmd *cobra.Command, client *codersdk.Client, org return nil, nil, err } - err = cliui.WorkspaceResources(cmd.OutOrStdout(), resources, cliui.WorkspaceResourcesOptions{ + // Only display the resources on the start transition, to avoid listing them more than once. + var startResources []codersdk.WorkspaceResource + for _, r := range resources { + if r.Transition == codersdk.WorkspaceTransitionStart { + startResources = append(startResources, r) + } + } + err = cliui.WorkspaceResources(cmd.OutOrStdout(), startResources, cliui.WorkspaceResourcesOptions{ HideAgentState: true, HideAccess: true, Title: "Template Preview", diff --git a/cli/templatecreate_test.go b/cli/templatecreate_test.go index e3d619ccdf629..bbafcbecb32b1 100644 --- a/cli/templatecreate_test.go +++ b/cli/templatecreate_test.go @@ -14,6 +14,28 @@ import ( "github.com/coder/coder/pty/ptytest" ) +var provisionCompleteWithAgent = []*proto.Provision_Response{ + { + Type: &proto.Provision_Response_Complete{ + Complete: &proto.Provision_Complete{ + Resources: []*proto.Resource{ + { + Type: "compute", + Name: "main", + Agents: []*proto.Agent{ + { + Name: "smith", + OperatingSystem: "linux", + Architecture: "i386", + }, + }, + }, + }, + }, + }, + }, +} + func TestTemplateCreate(t *testing.T) { t.Parallel() t.Run("Create", func(t *testing.T) { @@ -22,7 +44,7 @@ func TestTemplateCreate(t *testing.T) { coderdtest.CreateFirstUser(t, client) source := clitest.CreateTemplateVersionSource(t, &echo.Responses{ Parse: echo.ParseComplete, - Provision: echo.ProvisionComplete, + Provision: provisionCompleteWithAgent, }) args := []string{ "templates", @@ -49,11 +71,15 @@ func TestTemplateCreate(t *testing.T) { write string }{ {match: "Create and upload", write: "yes"}, + {match: "compute.main"}, + {match: "smith (linux, i386)"}, {match: "Confirm create?", write: "yes"}, } for _, m := range matches { pty.ExpectMatch(m.match) - pty.WriteLine(m.write) + if len(m.write) > 0 { + pty.WriteLine(m.write) + } } require.NoError(t, <-execDone) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy