github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/step/verify/step_verify_url.go (about)

     1  package verify
     2  
     3  import (
     4  	"crypto/tls"
     5  	"fmt"
     6  	"net/http"
     7  	"time"
     8  
     9  	"github.com/jenkins-x/jx-logging/pkg/log"
    10  	"github.com/jenkins-x/jx/v2/pkg/cmd/helper"
    11  	"github.com/jenkins-x/jx/v2/pkg/cmd/opts"
    12  	"github.com/jenkins-x/jx/v2/pkg/cmd/opts/step"
    13  	"github.com/jenkins-x/jx/v2/pkg/cmd/templates"
    14  	"github.com/jenkins-x/jx/v2/pkg/util"
    15  	"github.com/pkg/errors"
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  const (
    20  	optionEndpoint           = "endpoint"
    21  	optionCode               = "code"
    22  	optionTimeout            = "timeout"
    23  	optionInsecureSkipVerify = "insecureSkipVerify"
    24  )
    25  
    26  var (
    27  	stepVerifyURLLong = templates.LongDesc(`
    28  		This step checks the status of a URL
    29  	`)
    30  
    31  	stepVerifyURLExample = templates.Examples(`
    32          jx step verify url --endpoint https://jenkins-x.io
    33  	`)
    34  )
    35  
    36  // StepVerifyURLOptions options for step verify url command
    37  type StepVerifyURLOptions struct {
    38  	step.StepOptions
    39  
    40  	Endpoint           string
    41  	Code               int
    42  	Timeout            time.Duration
    43  	InsecureSkipVerify bool
    44  }
    45  
    46  // NewCmdStepVerifyURL creates a new verify url command
    47  func NewCmdStepVerifyURL(commonOpts *opts.CommonOptions) *cobra.Command {
    48  	options := StepVerifyURLOptions{
    49  		StepOptions: step.StepOptions{
    50  			CommonOptions: commonOpts,
    51  		},
    52  	}
    53  
    54  	cmd := &cobra.Command{
    55  		Use:     "url",
    56  		Short:   "Verifies a URL returns an expected HTTP code",
    57  		Long:    stepVerifyURLLong,
    58  		Example: stepVerifyURLExample,
    59  		Run: func(cmd *cobra.Command, args []string) {
    60  			options.Cmd = cmd
    61  			options.Args = args
    62  			err := options.Run()
    63  			helper.CheckErr(err)
    64  		},
    65  	}
    66  
    67  	cmd.Flags().StringVarP(&options.Endpoint, optionEndpoint, "e", "", "The endpoint on which to wait for expected HTTP code")
    68  	cmd.Flags().IntVarP(&options.Code, optionCode, "c", http.StatusOK, "The HTTP code which should be returned by the endpoint")
    69  	cmd.Flags().DurationVarP(&options.Timeout, optionTimeout, "t", 10*time.Minute, "The default timeout for the endpoint to return the expected HTTP code")
    70  	cmd.Flags().BoolVarP(&options.InsecureSkipVerify, optionInsecureSkipVerify, "i", false, "If the URL requires an insucure request")
    71  	return cmd
    72  }
    73  
    74  func (o *StepVerifyURLOptions) checkFlags() error {
    75  	if o.Endpoint == "" {
    76  		return util.MissingOption(optionEndpoint)
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (o *StepVerifyURLOptions) logError(err error) error {
    83  	log.Logger().Infof("Retrying due to: %s", err)
    84  	return err
    85  }
    86  
    87  // Run waits with exponential backoff for an endpoint to return an expected HTTP status code
    88  func (o *StepVerifyURLOptions) Run() error {
    89  	if err := o.checkFlags(); err != nil {
    90  		return errors.Wrap(err, "checking flags")
    91  	}
    92  
    93  	tr := &http.Transport{}
    94  	if o.InsecureSkipVerify {
    95  		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // #nosec
    96  	}
    97  	client := &http.Client{Transport: tr}
    98  
    99  	log.Logger().Infof("Waiting for %q endpoint to return %d HTTP code", o.Endpoint, o.Code)
   100  
   101  	start := time.Now()
   102  
   103  	err := util.Retry(o.Timeout, func() error {
   104  		resp, err := client.Get(o.Endpoint)
   105  		if err != nil {
   106  			return o.logError(err)
   107  		}
   108  		if resp.StatusCode != o.Code {
   109  			err := fmt.Errorf("invalid status code %d expecting %d", resp.StatusCode, o.Code)
   110  			return o.logError(err)
   111  		}
   112  		return nil
   113  	})
   114  	if err != nil {
   115  		return errors.Wrapf(err, "waiting for %q", o.Endpoint)
   116  	}
   117  
   118  	elapsed := time.Since(start)
   119  	log.Logger().Infof("Endpoint %q returns expected status code %d in %s", o.Endpoint, o.Code, elapsed)
   120  	return nil
   121  }