Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions pkg/cmd/environment/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package delete

import (
"fmt"

"github.com/MakeNowJust/heredoc/v2"
"github.com/OctopusDeploy/cli/pkg/apiclient"
"github.com/OctopusDeploy/cli/pkg/cmd/environment/helper"
"github.com/OctopusDeploy/cli/pkg/constants"
"github.com/OctopusDeploy/cli/pkg/factory"
"github.com/OctopusDeploy/cli/pkg/question"
Expand Down Expand Up @@ -36,22 +38,7 @@ func NewCmdDelete(f factory.Factory) *cobra.Command {
return err
}

// SDK doesn't have accounts.GetByIDOrName so we emulate it here
foundEnvironments, err := client.Environments.Get(environments.EnvironmentsQuery{
// TODO we can't lookup by ID here because the server will AND it with the ItemName and produce no results
PartialName: itemIDOrName,
})
if err != nil {
return err
}
// need exact match
var itemToDelete *environments.Environment
for _, item := range foundEnvironments.Items {
if item.Name == itemIDOrName {
itemToDelete = item
break
}
}
itemToDelete, err := helper.GetByIDOrName(client.Environments, itemIDOrName)
if itemToDelete == nil {
return fmt.Errorf("cannot find an environment with name or ID of '%s'", itemIDOrName)
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/cmd/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
cmdCreate "github.com/OctopusDeploy/cli/pkg/cmd/environment/create"
cmdDelete "github.com/OctopusDeploy/cli/pkg/cmd/environment/delete"
cmdList "github.com/OctopusDeploy/cli/pkg/cmd/environment/list"
cmdView "github.com/OctopusDeploy/cli/pkg/cmd/environment/view"
"github.com/OctopusDeploy/cli/pkg/constants"
"github.com/OctopusDeploy/cli/pkg/constants/annotations"
"github.com/OctopusDeploy/cli/pkg/factory"
Expand All @@ -28,5 +29,7 @@ func NewCmdEnvironment(f factory.Factory) *cobra.Command {
cmd.AddCommand(cmdList.NewCmdList(f))
cmd.AddCommand(cmdDelete.NewCmdDelete(f))
cmd.AddCommand(cmdCreate.NewCmdCreate(f))
cmd.AddCommand(cmdView.NewCmdView(f))

return cmd
}
24 changes: 24 additions & 0 deletions pkg/cmd/environment/helper/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package helper

import "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/environments"

func GetByIDOrName(service *environments.EnvironmentService, idOrName string) (*environments.Environment, error) {
// SDK doesn't have accounts.GetByIDOrName so we emulate it here
foundEnvironments, err := service.Get(environments.EnvironmentsQuery{
// TODO we can't lookup by ID here because the server will AND it with the ItemName and produce no results
PartialName: idOrName,
})
if err != nil {
return nil, err
}
// need exact match
var matchedItem *environments.Environment
for _, item := range foundEnvironments.Items {
if item.Name == idOrName {
matchedItem = item
break
}
}

return matchedItem, nil
}
161 changes: 161 additions & 0 deletions pkg/cmd/environment/view/view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package view

import (
"fmt"
"strings"

"github.com/MakeNowJust/heredoc/v2"
"github.com/OctopusDeploy/cli/pkg/apiclient"
"github.com/OctopusDeploy/cli/pkg/cmd/environment/helper"
"github.com/OctopusDeploy/cli/pkg/constants"
"github.com/OctopusDeploy/cli/pkg/factory"
"github.com/OctopusDeploy/cli/pkg/output"
"github.com/OctopusDeploy/cli/pkg/usage"
"github.com/OctopusDeploy/cli/pkg/util"
"github.com/OctopusDeploy/cli/pkg/util/flag"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/environments"
"github.com/pkg/browser"
"github.com/spf13/cobra"
)

const (
FlagWeb = "web"
)

type ViewFlags struct {
Web *flag.Flag[bool]
}

func NewViewFlags() *ViewFlags {
return &ViewFlags{
Web: flag.New[bool](FlagWeb, false),
}
}

type ViewOptions struct {
Client *client.Client
Host string
idOrName string
flags *ViewFlags
Command *cobra.Command
}

func NewCmdView(f factory.Factory) *cobra.Command {
viewFlags := NewViewFlags()

cmd := &cobra.Command{
Args: usage.ExactArgs(1),
Use: "view {<name> | <id>}",
Short: "View an environment",
Long: "View an environment in Octopus Deploy",
Example: heredoc.Docf(`
$ %[1]s environment view 'Production'
$ %[1]s environment view Environments-102
`, constants.ExecutableName),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := f.GetSystemClient(apiclient.NewRequester(cmd))
if err != nil {
return err
}

opts := &ViewOptions{
client,
f.GetCurrentHost(),
args[0],
viewFlags,
cmd,
}

return viewRun(opts)
},
}

flags := cmd.Flags()
flags.BoolVarP(&viewFlags.Web.Value, viewFlags.Web.Name, "w", false, "Open in web browser")

return cmd
}

func viewRun(opts *ViewOptions) error {
environment, err := helper.GetByIDOrName(opts.Client.Environments, opts.idOrName)
if err != nil {
return err
}

return output.PrintResource(environment, opts.Command, output.Mappers[*environments.Environment]{
Json: func(env *environments.Environment) any {
return EnvironmentAsJson{
Id: env.GetID(),
Slug: env.Slug,
Name: env.Name,
Description: env.Description,
UseGuidedFailure: env.UseGuidedFailure,
AllowDynamicInfrastructure: env.AllowDynamicInfrastructure,
WebUrl: generateWebUrl(opts.Host, env),
}
},
Table: output.TableDefinition[*environments.Environment]{
Header: []string{"NAME", "SLUG", "DESCRIPTION", "GUIDED FAILURE", "DYNAMIC INFRASTRUCTURE", "WEB URL"},
Row: func(env *environments.Environment) []string {
description := env.Description
if description == "" {
description = constants.NoDescription
}

return []string{
output.Bold(env.Name),
env.Slug,
description,
getBoolToString(env.UseGuidedFailure, "Enabled", "Disabled"),
getBoolToString(env.UseGuidedFailure, "Allowed", "Disallowed"),
output.Blue(generateWebUrl(opts.Host, env)),
}
},
},
Basic: func(env *environments.Environment) string {
var result strings.Builder

// header
result.WriteString(fmt.Sprintf("%s %s\n", output.Bold(env.Name), output.Dimf("(%s)", env.GetID())))

// metadata
if len(env.Description) == 0 {
result.WriteString(fmt.Sprintf("%s\n", output.Dim(constants.NoDescription)))
} else {
result.WriteString(fmt.Sprintf("%s\n", output.Dim(env.Description)))
}

url := generateWebUrl(opts.Host, env)
result.WriteString(fmt.Sprintf("View this environment in Octopus Deploy: %s\n", output.Blue(url)))

if opts.flags.Web.Value {
browser.OpenURL(url)
}

return result.String()
},
})
}

type EnvironmentAsJson struct {
Id string `json:"Id"`
Slug string `json:"Slug"`
Name string `json:"Name"`
Description string `json:"Description"`
UseGuidedFailure bool `json:"UseGuidedFailure"`
AllowDynamicInfrastructure bool `json:"AllowDynamicInfrastructure"`
WebUrl string `json:"WebUrl"`
}

func generateWebUrl(host string, env *environments.Environment) string {
return util.GenerateWebURL(host, env.SpaceID, fmt.Sprintf("infrastructure/environments/%s", env.GetID()))
}

func getBoolToString(value bool, trueString string, falseString string) string {
if value {
return trueString
} else {
return falseString
}
}