github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/step/step_validate.go (about) 1 package step 2 3 import ( 4 "fmt" 5 6 "github.com/jenkins-x/jx/v2/pkg/cmd/opts/step" 7 8 "github.com/jenkins-x/jx/v2/pkg/cmd/helper" 9 10 "github.com/jenkins-x/jx/v2/pkg/helm" 11 12 "github.com/blang/semver" 13 "github.com/jenkins-x/jx-logging/pkg/log" 14 "github.com/jenkins-x/jx/v2/pkg/cmd/opts" 15 "github.com/jenkins-x/jx/v2/pkg/cmd/templates" 16 "github.com/jenkins-x/jx/v2/pkg/config" 17 "github.com/jenkins-x/jx/v2/pkg/kube" 18 "github.com/jenkins-x/jx/v2/pkg/util" 19 "github.com/jenkins-x/jx/v2/pkg/version" 20 "github.com/spf13/cobra" 21 "k8s.io/apimachinery/pkg/util/errors" 22 ) 23 24 const ( 25 optionMinJxVersion = "min-jx-version" 26 ) 27 28 var ( 29 stepValidateLong = templates.LongDesc(` 30 Validates the command line tools, container and platform to ensure a pipeline can run properly. 31 32 This helps ensure that your platform installation, 'addons, builder images and Jenkinsfile' are all on compatible versions. 33 `) 34 35 stepValidateExample = templates.Examples(` 36 # Validates that the jx version is new enough 37 jx step validate --min-jx-version ` + version.StringDefault(version.ExampleVersion) + ` 38 `) 39 ) 40 41 // StepValidateOptions contains the command line flags 42 type StepValidateOptions struct { 43 step.StepOptions 44 45 MinimumJxVersion string 46 Dir string 47 } 48 49 // NewCmdStepValidate Creates a new Command object 50 func NewCmdStepValidate(commonOpts *opts.CommonOptions) *cobra.Command { 51 options := &StepValidateOptions{ 52 StepOptions: step.StepOptions{ 53 CommonOptions: commonOpts, 54 }, 55 } 56 57 cmd := &cobra.Command{ 58 Use: "validate", 59 Short: "Validates the command line tools, container and platform to ensure a pipeline can run properly", 60 Long: stepValidateLong, 61 Example: stepValidateExample, 62 Run: func(cmd *cobra.Command, args []string) { 63 options.Cmd = cmd 64 options.Args = args 65 err := options.Run() 66 helper.CheckErr(err) 67 }, 68 } 69 cmd.Flags().StringVarP(&options.MinimumJxVersion, optionMinJxVersion, "v", "", "The minimum version of the 'jx' command line tool required") 70 cmd.Flags().StringVarP(&options.Dir, "dir", "d", "", "The project directory to look inside for the Project configuration for things like required addons") 71 return cmd 72 } 73 74 // Run implements this command 75 func (o *StepValidateOptions) Run() error { 76 errs := []error{} 77 if o.MinimumJxVersion != "" { 78 err := o.verifyJxVersion(o.MinimumJxVersion) 79 if err != nil { 80 errs = append(errs, err) 81 } 82 } 83 errs = append(errs, o.verifyAddons()...) 84 return errors.NewAggregate(errs) 85 } 86 87 func (o *StepValidateOptions) verifyJxVersion(minJxVersion string) error { 88 require, err := semver.Parse(minJxVersion) 89 if err != nil { 90 return fmt.Errorf("Given jx version '%s' is not a valid semantic version: %s", minJxVersion, err) 91 } 92 current, err := version.GetSemverVersion() 93 if err != nil { 94 return fmt.Errorf("Could not find current jx version: %s", err) 95 } 96 if require.GT(current) { 97 info := util.ColorInfo 98 log.Logger().Infof("\nThe current installation of the %s CLI is too old: %s.\nWe require an installation of %s or later.\n", info("jx"), info(current.String()), info(require.String())) 99 log.Logger().Infof(`To upgrade try these commands: 100 * to upgrade the CLI locally: %s 101 `, info("jx upgrade cli")) 102 103 return fmt.Errorf("The current jx install is too old: %s. We require: %s or later", current.String(), require.String()) 104 } 105 return nil 106 } 107 108 func (o *StepValidateOptions) verifyAddons() []error { 109 errs := []error{} 110 config, fileName, err := config.LoadProjectConfig(o.Dir) 111 if err != nil { 112 errs = append(errs, fmt.Errorf("Failed to load project config: %s", err)) 113 return errs 114 } 115 if len(config.Addons) == 0 { 116 return errs 117 } 118 _, ns, err := o.KubeClientAndNamespace() 119 if err != nil { 120 errs = append(errs, err) 121 return errs 122 } 123 releases, _, err := o.Helm().ListReleases(ns) 124 if err != nil { 125 errs = append(errs, fmt.Errorf("Failed to load addons statuses: %s", err)) 126 return errs 127 } 128 129 for _, addonConfig := range config.Addons { 130 if addonConfig != nil { 131 err := o.verifyAddon(addonConfig, fileName, releases) 132 if err != nil { 133 errs = append(errs, err) 134 } 135 } 136 } 137 return errs 138 } 139 140 func (o *StepValidateOptions) verifyAddon(addonConfig *config.AddonConfig, fileName string, 141 releases map[string]helm.ReleaseSummary) error { 142 name := addonConfig.Name 143 if name == "" { 144 log.Logger().Warnf("Ignoring addon with no name inside the projects configuration file %s", fileName) 145 return nil 146 } 147 ch := kube.AddonCharts[name] 148 if ch == "" { 149 return fmt.Errorf("No such addon name %s in %s: %s", name, fileName, util.InvalidArg(name, util.SortedMapKeys(kube.AddonCharts))) 150 } 151 status := releases[name].Status 152 if status == "DEPLOYED" { 153 return nil 154 } 155 info := util.ColorInfo 156 157 log.Logger().Infof(` 158 The Project Configuration %s requires the %s addon to be installed. To fix this please type: 159 160 %s 161 162 `, fileName, info(name), info(fmt.Sprintf("jx create addon %s", name))) 163 164 return fmt.Errorf("The addon %s is required. Please install with: jx create addon %s", name, name) 165 }