github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+incompatible/command/v6/services_command.go (about)

     1  package v6
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	"code.cloudfoundry.org/cli/actor/sharedaction"
     9  	"code.cloudfoundry.org/cli/actor/v2action"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    11  	"code.cloudfoundry.org/cli/command"
    12  	"code.cloudfoundry.org/cli/command/v6/shared"
    13  	"code.cloudfoundry.org/cli/util/sorting"
    14  )
    15  
    16  //go:generate counterfeiter . ServiceInstancesActor
    17  
    18  type ServiceInstancesActor interface {
    19  	GetServiceInstancesSummaryBySpace(spaceGUID string) ([]v2action.ServiceInstanceSummary, v2action.Warnings, error)
    20  }
    21  
    22  type ServicesCommand struct {
    23  	usage           interface{} `usage:"CF_NAME services"`
    24  	relatedCommands interface{} `related_commands:"create-service, marketplace"`
    25  
    26  	UI          command.UI
    27  	Config      command.Config
    28  	SharedActor command.SharedActor
    29  	Actor       ServiceInstancesActor
    30  }
    31  
    32  func (cmd *ServicesCommand) Setup(config command.Config, ui command.UI) error {
    33  	cmd.Config = config
    34  	cmd.UI = ui
    35  	cmd.SharedActor = sharedaction.NewActor(config)
    36  	ccClient, uaaClient, err := shared.NewClients(config, ui, true)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	cmd.Actor = v2action.NewActor(ccClient, uaaClient, config)
    41  
    42  	return nil
    43  }
    44  
    45  func (cmd ServicesCommand) Execute(args []string) error {
    46  	err := cmd.SharedActor.CheckTarget(true, true)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	user, err := cmd.Config.CurrentUser()
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	cmd.UI.DisplayTextWithFlavor("Getting services in org {{.OrgName}} / space {{.SpaceName}} as {{.CurrentUser}}...",
    57  		map[string]interface{}{
    58  			"OrgName":     cmd.Config.TargetedOrganization().Name,
    59  			"SpaceName":   cmd.Config.TargetedSpace().Name,
    60  			"CurrentUser": user.Name,
    61  		})
    62  	cmd.UI.DisplayNewline()
    63  
    64  	instanceSummaries, warnings, err := cmd.Actor.GetServiceInstancesSummaryBySpace(cmd.Config.TargetedSpace().GUID)
    65  	cmd.UI.DisplayWarnings(warnings)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	if len(instanceSummaries) == 0 {
    71  		cmd.UI.DisplayText("No services found")
    72  		return nil
    73  	}
    74  
    75  	sortServiceInstances(instanceSummaries)
    76  
    77  	table := [][]string{{
    78  		cmd.UI.TranslateText("name"),
    79  		cmd.UI.TranslateText("service"),
    80  		cmd.UI.TranslateText("plan"),
    81  		cmd.UI.TranslateText("bound apps"),
    82  		cmd.UI.TranslateText("last operation"),
    83  		cmd.UI.TranslateText("broker"),
    84  	}}
    85  
    86  	var boundAppNames []string
    87  
    88  	for _, summary := range instanceSummaries {
    89  		serviceLabel := summary.Service.Label
    90  		if summary.ServiceInstance.Type == constant.UserProvidedService {
    91  			serviceLabel = "user-provided"
    92  		}
    93  
    94  		boundAppNames = []string{}
    95  		for _, boundApplication := range summary.BoundApplications {
    96  			boundAppNames = append(boundAppNames, boundApplication.AppName)
    97  		}
    98  
    99  		table = append(table, []string{
   100  			summary.Name,
   101  			serviceLabel,
   102  			summary.ServicePlan.Name,
   103  			strings.Join(boundAppNames, ", "),
   104  			fmt.Sprintf("%s %s", summary.LastOperation.Type, summary.LastOperation.State),
   105  			summary.Service.ServiceBrokerName},
   106  		)
   107  	}
   108  	cmd.UI.DisplayTableWithHeader("", table, 3)
   109  
   110  	return nil
   111  }
   112  
   113  func sortServiceInstances(instanceSummaries []v2action.ServiceInstanceSummary) {
   114  	sort.Slice(instanceSummaries, func(i, j int) bool {
   115  		return sorting.LessIgnoreCase(instanceSummaries[i].Name, instanceSummaries[j].Name)
   116  	})
   117  
   118  	for _, instance := range instanceSummaries {
   119  		sortBoundApps(instance)
   120  	}
   121  }
   122  
   123  func sortBoundApps(serviceInstance v2action.ServiceInstanceSummary) {
   124  	sort.Slice(
   125  		serviceInstance.BoundApplications,
   126  		func(i, j int) bool {
   127  			return sorting.LessIgnoreCase(serviceInstance.BoundApplications[i].AppName, serviceInstance.BoundApplications[j].AppName)
   128  		})
   129  }