github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/validator/distro_validator.go (about) 1 package validator 2 3 import ( 4 "fmt" 5 6 "github.com/evergreen-ci/evergreen" 7 "github.com/evergreen-ci/evergreen/cloud/providers" 8 "github.com/evergreen-ci/evergreen/cloud/providers/static" 9 "github.com/evergreen-ci/evergreen/model/distro" 10 "github.com/evergreen-ci/evergreen/util" 11 "github.com/mitchellh/mapstructure" 12 ) 13 14 type distroValidator func(*distro.Distro, *evergreen.Settings) []ValidationError 15 16 // Functions used to validate the syntax of a distro object. 17 var distroSyntaxValidators = []distroValidator{ 18 ensureHasRequiredFields, 19 ensureValidSSHOptions, 20 ensureValidExpansions, 21 ensureStaticHostsAreNotSpawnable, 22 } 23 24 // CheckDistro checks if the distro configuration syntax is valid. Returns 25 // a slice of any validation errors found. 26 func CheckDistro(d *distro.Distro, s *evergreen.Settings, newDistro bool) ([]ValidationError, error) { 27 validationErrs := []ValidationError{} 28 distroIds := []string{} 29 var err error 30 if newDistro { 31 // check ensureUniqueId separately and pass in distroIds list 32 distroIds, err = getDistroIds() 33 if err != nil { 34 return nil, err 35 } 36 } 37 validationErrs = append(validationErrs, ensureUniqueId(d, distroIds)...) 38 39 for _, v := range distroSyntaxValidators { 40 validationErrs = append(validationErrs, v(d, s)...) 41 } 42 return validationErrs, nil 43 } 44 45 // ensureStaticHostsAreNotSpawnable makes sure that any static distro cannot also be spawnable. 46 func ensureStaticHostsAreNotSpawnable(d *distro.Distro, s *evergreen.Settings) []ValidationError { 47 if d.SpawnAllowed && d.Provider == static.ProviderName { 48 return []ValidationError{ 49 { 50 Message: fmt.Sprintf("static distro %s cannot be spawnable", d.Id), 51 Level: Error, 52 }, 53 } 54 } 55 56 return nil 57 } 58 59 // ensureHasRequiredFields check that the distro configuration has all the required fields 60 func ensureHasRequiredFields(d *distro.Distro, s *evergreen.Settings) []ValidationError { 61 errs := []ValidationError{} 62 63 if d.Id == "" { 64 errs = append(errs, ValidationError{ 65 Message: fmt.Sprintf("distro '%v' cannot be blank", distro.IdKey), 66 Level: Error, 67 }) 68 } 69 70 if d.Arch == "" { 71 errs = append(errs, ValidationError{ 72 Message: fmt.Sprintf("distro '%v' cannot be blank", distro.ArchKey), 73 Level: Error, 74 }) 75 } 76 77 if d.User == "" { 78 errs = append(errs, ValidationError{ 79 Message: fmt.Sprintf("distro '%v' cannot be blank", distro.UserKey), 80 Level: Error, 81 }) 82 } 83 84 if d.WorkDir == "" { 85 errs = append(errs, ValidationError{ 86 Message: fmt.Sprintf("distro '%v' cannot be blank", distro.WorkDirKey), 87 Level: Error, 88 }) 89 } 90 91 if d.SSHKey == "" && d.Provider != static.ProviderName { 92 errs = append(errs, ValidationError{ 93 Message: fmt.Sprintf("distro '%v' cannot be blank", distro.SSHKeyKey), 94 Level: Error, 95 }) 96 } 97 98 if d.Provider == "" { 99 errs = append(errs, ValidationError{ 100 Message: fmt.Sprintf("distro '%v' cannot be blank", distro.ProviderKey), 101 Level: Error, 102 }) 103 return errs 104 } 105 106 mgr, err := providers.GetCloudManager(d.Provider, s) 107 if err != nil { 108 errs = append(errs, ValidationError{ 109 Message: err.Error(), 110 Level: Error, 111 }) 112 return errs 113 } 114 115 settings := mgr.GetSettings() 116 117 if err = mapstructure.Decode(d.ProviderSettings, settings); err != nil { 118 errs = append(errs, ValidationError{ 119 Message: fmt.Sprintf("distro '%v' decode error: %v", distro.ProviderSettingsKey, err), 120 Level: Error, 121 }) 122 return errs 123 } 124 125 if err := settings.Validate(); err != nil { 126 errs = append(errs, ValidationError{Error, err.Error()}) 127 } 128 129 return errs 130 } 131 132 // ensureUniqueId checks that the distro's id does not collide with an existing id. 133 func ensureUniqueId(d *distro.Distro, distroIds []string) []ValidationError { 134 if util.SliceContains(distroIds, d.Id) { 135 return []ValidationError{{Error, fmt.Sprintf("distro '%v' uses an existing identifier", d.Id)}} 136 } 137 return nil 138 } 139 140 // ensureValidExpansions checks that no expansion option key is blank. 141 func ensureValidExpansions(d *distro.Distro, s *evergreen.Settings) []ValidationError { 142 for _, e := range d.Expansions { 143 if e.Key == "" { 144 return []ValidationError{{Error, fmt.Sprintf("distro cannot be blank expansion key")}} 145 } 146 } 147 return nil 148 } 149 150 // ensureValidSSHOptions checks that no SSH option key is blank. 151 func ensureValidSSHOptions(d *distro.Distro, s *evergreen.Settings) []ValidationError { 152 for _, o := range d.SSHOptions { 153 if o == "" { 154 return []ValidationError{{Error, fmt.Sprintf("distro cannot be blank SSH option")}} 155 } 156 } 157 return nil 158 }