github.com/saucelabs/saucectl@v0.175.1/internal/cmd/apit/vault.go (about)

     1  package apit
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/AlecAivazis/survey/v2"
     9  	"github.com/mattn/go-isatty"
    10  	"github.com/saucelabs/saucectl/internal/apitest"
    11  	"github.com/spf13/cobra"
    12  )
    13  
    14  type ResolvedProject struct {
    15  	apitest.ProjectMeta
    16  	Hooks []apitest.Hook
    17  }
    18  
    19  var (
    20  	selectedProject ResolvedProject
    21  )
    22  
    23  func VaultCommand(preRunE func(cmd *cobra.Command, args []string) error) *cobra.Command {
    24  	var projectName string
    25  	var err error
    26  	cmd := &cobra.Command{
    27  		Use:          "vault",
    28  		Short:        "Commands for interacting with API Testing project vaults",
    29  		SilenceUsage: true,
    30  		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
    31  			if preRunE != nil {
    32  				err = preRunE(cmd, args)
    33  				if err != nil {
    34  					return err
    35  				}
    36  			}
    37  			selectedProject, err = resolve(projectName)
    38  			if err != nil {
    39  				return err
    40  			}
    41  			return nil
    42  		},
    43  	}
    44  
    45  	cmd.PersistentFlags().StringVar(&projectName, "project", "", "The name of the project the vault belongs to.")
    46  
    47  	cmd.AddCommand(
    48  		GetCommand(),
    49  		SetVariableCommand(),
    50  		GetVariableCommand(),
    51  		GetSnippetCommand(),
    52  		SetSnippetCommand(),
    53  		ListFilesCommand(),
    54  		DownloadFileCommand(),
    55  		UploadFileCommand(),
    56  		DeleteFileCommand(),
    57  	)
    58  	return cmd
    59  }
    60  
    61  func projectSurvey(names []string) (string, error) {
    62  	var selection string
    63  	prompt := &survey.Select{
    64  		Help:    "Select the project the vault belongs to. Use --project to define a project in your command and skip this selection",
    65  		Message: "Select a vault by project name",
    66  		Options: names,
    67  	}
    68  
    69  	err := survey.AskOne(prompt, &selection)
    70  
    71  	return selection, err
    72  }
    73  
    74  func isTerm(fd uintptr) bool {
    75  	return isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd)
    76  }
    77  
    78  func resolve(projectName string) (ResolvedProject, error) {
    79  	projects, err := apitesterClient.GetProjects(context.Background())
    80  	if projectName == "" {
    81  		if !isTerm(os.Stdin.Fd()) || !isTerm(os.Stdout.Fd()) {
    82  			return ResolvedProject{}, fmt.Errorf("no project specified, use --project to choose a project by name")
    83  		}
    84  		var names []string
    85  		for _, p := range projects {
    86  			names = append(names, p.Name)
    87  		}
    88  		projectName, err = projectSurvey(names)
    89  	}
    90  	if err != nil {
    91  		return ResolvedProject{}, err
    92  	}
    93  	var project apitest.ProjectMeta
    94  	for _, p := range projects {
    95  		if p.Name == projectName {
    96  			project = p
    97  			break
    98  		}
    99  	}
   100  	if project.ID == "" {
   101  		return ResolvedProject{}, fmt.Errorf("could not find project named %s", projectName)
   102  	}
   103  
   104  	hooks, err := apitesterClient.GetHooks(context.Background(), project.ID)
   105  	if err != nil {
   106  		return ResolvedProject{}, err
   107  	}
   108  	if len(hooks) == 0 {
   109  		return ResolvedProject{}, fmt.Errorf("project named %s has no hooks configured", projectName)
   110  	}
   111  
   112  	return ResolvedProject{
   113  		ProjectMeta: project,
   114  		Hooks:       hooks,
   115  	}, nil
   116  }