github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/step/step_wait_for_artifact.go (about)

     1  package step
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/olli-ai/jx/v2/pkg/cmd/opts/step"
    10  
    11  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    12  
    13  	"github.com/jenkins-x/jx-logging/pkg/log"
    14  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    15  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    16  	"github.com/olli-ai/jx/v2/pkg/util"
    17  	"github.com/spf13/cobra"
    18  )
    19  
    20  const (
    21  	optionRepo              = "repo"
    22  	optionGroup             = "group"
    23  	optionArtifact          = "artifact"
    24  	optionVersion           = "version"
    25  	optionPollTime          = "poll-time"
    26  	DefaultMavenCentralRepo = "https://repo1.maven.org/maven2/"
    27  )
    28  
    29  // StepWaitForArtifactOptions contains the command line flags
    30  type StepWaitForArtifactOptions struct {
    31  	step.StepOptions
    32  
    33  	ArtifactURL string
    34  	RepoURL     string
    35  	GroupId     string
    36  	ArtifactId  string
    37  	Version     string
    38  	Extension   string
    39  	Timeout     string
    40  	PollTime    string
    41  
    42  	// calculated fields
    43  	TimeoutDuration time.Duration
    44  	PollDuration    time.Duration
    45  }
    46  
    47  var (
    48  	StepWaitForArtifactLong = templates.LongDesc(`
    49  		Waits for the given artifact to be available in a maven style repository
    50  
    51  `)
    52  
    53  	StepWaitForArtifactExample = templates.Examples(`
    54  		# wait for a 
    55  		jx step gpg credentials
    56  
    57  		# generate the git credentials to a output file
    58  		jx step gpg credentials -o /tmp/mycreds
    59  
    60  `)
    61  )
    62  
    63  func NewCmdStepWaitForArtifact(commonOpts *opts.CommonOptions) *cobra.Command {
    64  	options := StepWaitForArtifactOptions{
    65  		StepOptions: step.StepOptions{
    66  			CommonOptions: commonOpts,
    67  		},
    68  	}
    69  	cmd := &cobra.Command{
    70  		Use:     "wait for artifact",
    71  		Short:   "Waits for the given artifact to be available in a maven style repository",
    72  		Long:    StepWaitForArtifactLong,
    73  		Example: StepWaitForArtifactExample,
    74  		Run: func(cmd *cobra.Command, args []string) {
    75  			options.Cmd = cmd
    76  			options.Args = args
    77  			err := options.Run()
    78  			helper.CheckErr(err)
    79  		},
    80  	}
    81  	cmd.Flags().StringVarP(&options.ArtifactURL, "artifact-url", "", "", "The full URL of the artifact to wait for. If not specified it is calculated from the repository URL, group, artifact and version")
    82  	cmd.Flags().StringVarP(&options.RepoURL, optionRepo, "r", DefaultMavenCentralRepo, "The URL of the maven style repository to query for the artifact")
    83  	cmd.Flags().StringVarP(&options.GroupId, optionGroup, "g", "", "The group ID of the artifact to search for")
    84  	cmd.Flags().StringVarP(&options.ArtifactId, optionArtifact, "a", "", "The artifact ID of the artifact to search for")
    85  	cmd.Flags().StringVarP(&options.Version, optionVersion, "v", "", "The version of the artifact to search for")
    86  	cmd.Flags().StringVarP(&options.Extension, "ext", "x", "pom", "The file extension to search for")
    87  	cmd.Flags().StringVarP(&options.Timeout, opts.OptionTimeout, "t", "1h", "The duration before we consider this operation failed")
    88  	cmd.Flags().StringVarP(&options.PollTime, optionPollTime, "", "10s", "The amount of time between polls for the artifact URL being present")
    89  	return cmd
    90  }
    91  
    92  func (o *StepWaitForArtifactOptions) getUrlStatusOK(u string) error {
    93  	client := http.Client{}
    94  	req, err := http.NewRequest(http.MethodGet, u, nil)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	res, err := client.Do(req)
    99  	if err != nil {
   100  		return err
   101  	}
   102  	if res.StatusCode < 200 || res.StatusCode >= 300 {
   103  		return fmt.Errorf("Failed in request for %s as got status %d %s", u, res.StatusCode, res.Status)
   104  	}
   105  	return nil
   106  }
   107  
   108  func (o *StepWaitForArtifactOptions) Run() error {
   109  	var err error
   110  	if o.PollTime != "" {
   111  		o.PollDuration, err = time.ParseDuration(o.PollTime)
   112  		if err != nil {
   113  			return fmt.Errorf("Invalid duration format %s for option --%s: %s", o.PollTime, optionPollTime, err)
   114  		}
   115  	}
   116  	if o.Timeout != "" {
   117  		o.TimeoutDuration, err = time.ParseDuration(o.Timeout)
   118  		if err != nil {
   119  			return fmt.Errorf("Invalid duration format %s for option --%s: %s", o.Timeout, opts.OptionTimeout, err)
   120  		}
   121  	}
   122  
   123  	if o.ArtifactURL == "" {
   124  		// lets create it from the various parts
   125  		if o.RepoURL == "" {
   126  			return util.MissingOption(optionRepo)
   127  		}
   128  		group := o.GroupId
   129  		if group == "" {
   130  			return util.MissingOption(optionGroup)
   131  		}
   132  		group = strings.Replace(group, ".", "/", -1)
   133  		artifact := o.ArtifactId
   134  		if artifact == "" {
   135  			return util.MissingOption(optionArtifact)
   136  		}
   137  		version := o.Version
   138  		if version == "" {
   139  			return util.MissingOption(optionVersion)
   140  		}
   141  		o.ArtifactURL = util.UrlJoin(o.RepoURL, group, artifact, version, artifact+"-"+version+"."+o.Extension)
   142  	}
   143  	log.Logger().Infof("Waiting for artifact at %s", util.ColorInfo(o.ArtifactURL))
   144  
   145  	fn := func() error {
   146  		return o.getUrlStatusOK(o.ArtifactURL)
   147  	}
   148  	err = o.RetryQuietlyUntilTimeout(o.TimeoutDuration, o.PollDuration, fn)
   149  	if err == nil {
   150  		log.Logger().Infof("Found artifact at %s", util.ColorInfo(o.ArtifactURL))
   151  		return nil
   152  	}
   153  	log.Logger().Warnf("Failed to find artifact at %s due to %s", o.ArtifactURL, err)
   154  	return err
   155  }