github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/commands/suggest_builders.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"sync"
     7  	"text/tabwriter"
     8  
     9  	"github.com/spf13/cobra"
    10  
    11  	bldr "github.com/buildpacks/pack/internal/builder"
    12  	"github.com/buildpacks/pack/internal/style"
    13  	"github.com/buildpacks/pack/pkg/logging"
    14  )
    15  
    16  // Deprecated: Use `builder suggest` instead.
    17  func SuggestBuilders(logger logging.Logger, inspector BuilderInspector) *cobra.Command {
    18  	cmd := &cobra.Command{
    19  		Use:     "suggest-builders",
    20  		Hidden:  true,
    21  		Args:    cobra.NoArgs,
    22  		Short:   "Display list of recommended builders",
    23  		Example: "pack suggest-builders",
    24  		Run: func(cmd *cobra.Command, s []string) {
    25  			deprecationWarning(logger, "suggest-builder", "builder suggest")
    26  			suggestBuilders(logger, inspector)
    27  		},
    28  	}
    29  
    30  	return cmd
    31  }
    32  
    33  func suggestSettingBuilder(logger logging.Logger, inspector BuilderInspector) {
    34  	logger.Info("Please select a default builder with:")
    35  	logger.Info("")
    36  	logger.Info("\tpack config default-builder <builder-image>")
    37  	logger.Info("")
    38  	suggestBuilders(logger, inspector)
    39  }
    40  
    41  func suggestBuilders(logger logging.Logger, client BuilderInspector) {
    42  	suggestedBuilders := []bldr.KnownBuilder{}
    43  	for _, knownBuilder := range bldr.KnownBuilders {
    44  		if knownBuilder.Suggested {
    45  			suggestedBuilders = append(suggestedBuilders, knownBuilder)
    46  		}
    47  	}
    48  	WriteSuggestedBuilder(logger, client, suggestedBuilders)
    49  }
    50  
    51  func WriteSuggestedBuilder(logger logging.Logger, inspector BuilderInspector, builders []bldr.KnownBuilder) {
    52  	sort.Slice(builders, func(i, j int) bool {
    53  		if builders[i].Vendor == builders[j].Vendor {
    54  			return builders[i].Image < builders[j].Image
    55  		}
    56  
    57  		return builders[i].Vendor < builders[j].Vendor
    58  	})
    59  
    60  	logger.Info("Suggested builders:")
    61  
    62  	// Fetch descriptions concurrently.
    63  	descriptions := make([]string, len(builders))
    64  
    65  	var wg sync.WaitGroup
    66  	wg.Add(len(builders))
    67  
    68  	for i, builder := range builders {
    69  		go func(w *sync.WaitGroup, i int, builder bldr.KnownBuilder) {
    70  			descriptions[i] = getBuilderDescription(builder, inspector)
    71  			w.Done()
    72  		}(&wg, i, builder)
    73  	}
    74  
    75  	wg.Wait()
    76  
    77  	tw := tabwriter.NewWriter(logger.Writer(), 10, 10, 5, ' ', tabwriter.TabIndent)
    78  	for i, builder := range builders {
    79  		fmt.Fprintf(tw, "\t%s:\t%s\t%s\t\n", builder.Vendor, style.Symbol(builder.Image), descriptions[i])
    80  	}
    81  	fmt.Fprintln(tw)
    82  
    83  	logging.Tip(logger, "Learn more about a specific builder with:")
    84  	logger.Info("\tpack builder inspect <builder-image>")
    85  }
    86  
    87  func getBuilderDescription(builder bldr.KnownBuilder, inspector BuilderInspector) string {
    88  	info, err := inspector.InspectBuilder(builder.Image, false)
    89  	if err == nil && info != nil && info.Description != "" {
    90  		return info.Description
    91  	}
    92  
    93  	return builder.DefaultDescription
    94  }
    95  
    96  func isSuggestedBuilder(builder string) bool {
    97  	for _, knownBuilder := range bldr.KnownBuilders {
    98  		if builder == knownBuilder.Image && knownBuilder.Suggested {
    99  			return true
   100  		}
   101  	}
   102  
   103  	return false
   104  }