github.com/jenkins-x/jx/v2@v2.1.155/pkg/pipelinescheduler/testhelpers/helpers.go (about) 1 package testhelpers 2 3 import ( 4 "io/ioutil" 5 "math/rand" 6 "path/filepath" 7 "testing" 8 "time" 9 10 v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1" 11 12 "github.com/ghodss/yaml" 13 14 "github.com/jenkins-x/jx/v2/pkg/pipelinescheduler" 15 "github.com/jenkins-x/lighthouse/pkg/config" 16 "github.com/jenkins-x/lighthouse/pkg/plugins" 17 18 "github.com/stretchr/testify/assert" 19 20 "github.com/google/uuid" 21 ) 22 23 // CompleteScheduler returns a SchedulerSpec completely filled with dummy data 24 func CompleteScheduler() *v1.SchedulerSpec { 25 return &v1.SchedulerSpec{ 26 Policy: pointerToGlobalProtectionPolicy(), 27 Merger: &v1.Merger{ 28 ContextPolicy: &v1.ContextPolicy{ 29 OptionalContexts: PointerToReplaceableSliceOfStrings(), 30 RequiredContexts: PointerToReplaceableSliceOfStrings(), 31 RequiredIfPresentContexts: PointerToReplaceableSliceOfStrings(), 32 }, 33 MergeType: pointerToUUID(), 34 TargetURL: pointerToUUID(), 35 PRStatusBaseURL: pointerToUUID(), 36 BlockerLabel: pointerToUUID(), 37 SquashLabel: pointerToUUID(), 38 MaxGoroutines: pointerToRandomNumber(), 39 StatusUpdatePeriod: pointerToRandomDuration(), 40 SyncPeriod: pointerToRandomDuration(), 41 }, 42 Presubmits: &v1.Presubmits{ 43 Items: []*v1.Presubmit{ 44 { 45 MergeType: pointerToUUID(), 46 Context: pointerToUUID(), 47 Report: pointerToTrue(), 48 AlwaysRun: pointerToTrue(), 49 Optional: pointerToTrue(), 50 ContextPolicy: &v1.RepoContextPolicy{ 51 ContextPolicy: pointerToContextPolicy(), 52 Branches: &v1.ReplaceableMapOfStringContextPolicy{ 53 Items: map[string]*v1.ContextPolicy{ 54 uuid.New().String(): pointerToContextPolicy(), 55 }, 56 }, 57 }, 58 Queries: []*v1.Query{{ 59 Labels: PointerToReplaceableSliceOfStrings(), 60 ExcludedBranches: PointerToReplaceableSliceOfStrings(), 61 IncludedBranches: PointerToReplaceableSliceOfStrings(), 62 MissingLabels: PointerToReplaceableSliceOfStrings(), 63 Milestone: pointerToUUID(), 64 ReviewApprovedRequired: pointerToTrue(), 65 }}, 66 Brancher: pointerToBrancher(), 67 RerunCommand: pointerToUUID(), 68 Trigger: pointerToUUID(), 69 Policy: &v1.ProtectionPolicies{ 70 Items: map[string]*v1.ProtectionPolicy{ 71 uuid.New().String(): pointerToProtectionPolicy(), 72 }, 73 }, 74 RegexpChangeMatcher: pointerToRegexpChangeMatcher(), 75 JobBase: pointerToJobBase(), 76 }, 77 }, 78 }, 79 Postsubmits: &v1.Postsubmits{ 80 Items: []*v1.Postsubmit{ 81 { 82 Report: pointerToTrue(), 83 Context: pointerToUUID(), 84 JobBase: pointerToJobBase(), 85 RegexpChangeMatcher: pointerToRegexpChangeMatcher(), 86 Brancher: pointerToBrancher(), 87 }, 88 }, 89 }, 90 Trigger: &v1.Trigger{ 91 IgnoreOkToTest: pointerToTrue(), 92 JoinOrgURL: pointerToUUID(), 93 OnlyOrgMembers: pointerToTrue(), 94 TrustedOrg: pointerToUUID(), 95 }, 96 ScehdulerAgent: &v1.SchedulerAgent{ 97 Agent: pointerToUUID(), 98 }, 99 Approve: &v1.Approve{ 100 RequireSelfApproval: pointerToTrue(), 101 LgtmActsAsApprove: pointerToTrue(), 102 IssueRequired: pointerToTrue(), 103 IgnoreReviewState: pointerToTrue(), 104 }, 105 ExternalPlugins: &v1.ReplaceableSliceOfExternalPlugins{ 106 Items: []*v1.ExternalPlugin{ 107 { 108 Name: pointerToUUID(), 109 Events: PointerToReplaceableSliceOfStrings(), 110 Endpoint: pointerToUUID(), 111 }, 112 }, 113 }, 114 LGTM: &v1.Lgtm{ 115 StoreTreeHash: pointerToTrue(), 116 ReviewActsAsLgtm: pointerToTrue(), 117 StickyLgtmTeam: pointerToUUID(), 118 }, 119 Plugins: PointerToReplaceableSliceOfStrings(), 120 } 121 } 122 123 func pointerToTrue() *bool { 124 b := true 125 return &b 126 } 127 128 func pointerToUUID() *string { 129 s := uuid.New().String() 130 return &s 131 } 132 133 func pointerToRandomNumber() *int { 134 i := rand.Int() // #nosec 135 return &i 136 } 137 138 func pointerToRandomDuration() *time.Duration { 139 i := rand.Int63() 140 duration := time.Duration(i) 141 return &duration 142 } 143 144 // PointerToReplaceableSliceOfStrings creaters a ReplaceableSliceOfStrings and returns its pointer 145 func PointerToReplaceableSliceOfStrings() *v1.ReplaceableSliceOfStrings { 146 return &v1.ReplaceableSliceOfStrings{ 147 Items: []string{ 148 uuid.New().String(), 149 }, 150 } 151 } 152 153 // PointerToReplaceableMapOfStringString returns a ReplaceableMapOfStringString pointer 154 func PointerToReplaceableMapOfStringString() *v1.ReplaceableMapOfStringString { 155 return &v1.ReplaceableMapOfStringString{ 156 Items: map[string]string{ 157 uuid.New().String(): uuid.New().String(), 158 }, 159 } 160 } 161 162 func pointerToContextPolicy() *v1.ContextPolicy { 163 return &v1.ContextPolicy{ 164 SkipUnknownContexts: pointerToTrue(), 165 FromBranchProtection: pointerToTrue(), 166 RequiredIfPresentContexts: PointerToReplaceableSliceOfStrings(), 167 RequiredContexts: PointerToReplaceableSliceOfStrings(), 168 OptionalContexts: PointerToReplaceableSliceOfStrings(), 169 } 170 } 171 172 func pointerToGlobalProtectionPolicy() *v1.GlobalProtectionPolicy { 173 return &v1.GlobalProtectionPolicy{ 174 ProtectTested: pointerToTrue(), 175 ProtectionPolicy: pointerToProtectionPolicy(), 176 } 177 } 178 179 func pointerToProtectionPolicy() *v1.ProtectionPolicy { 180 return &v1.ProtectionPolicy{ 181 Restrictions: &v1.Restrictions{ 182 Users: PointerToReplaceableSliceOfStrings(), 183 Teams: PointerToReplaceableSliceOfStrings(), 184 }, 185 Admins: pointerToTrue(), 186 RequiredPullRequestReviews: &v1.ReviewPolicy{ 187 DismissalRestrictions: &v1.Restrictions{ 188 Users: PointerToReplaceableSliceOfStrings(), 189 Teams: PointerToReplaceableSliceOfStrings(), 190 }, 191 }, 192 RequiredStatusChecks: &v1.BranchProtectionContextPolicy{ 193 Strict: pointerToTrue(), 194 Contexts: PointerToReplaceableSliceOfStrings(), 195 }, 196 Protect: pointerToTrue(), 197 } 198 } 199 200 func pointerToJobBase() *v1.JobBase { 201 return &v1.JobBase{ 202 Labels: PointerToReplaceableMapOfStringString(), 203 Namespace: pointerToUUID(), 204 Cluster: pointerToUUID(), 205 MaxConcurrency: pointerToRandomNumber(), 206 Agent: pointerToUUID(), 207 Name: pointerToUUID(), 208 } 209 } 210 211 func pointerToRegexpChangeMatcher() *v1.RegexpChangeMatcher { 212 return &v1.RegexpChangeMatcher{ 213 RunIfChanged: pointerToUUID(), 214 } 215 } 216 217 func pointerToBrancher() *v1.Brancher { 218 return &v1.Brancher{ 219 Branches: PointerToReplaceableSliceOfStrings(), 220 SkipBranches: PointerToReplaceableSliceOfStrings(), 221 } 222 } 223 224 // SchedulerFile contains a list of leaf files to build the scheduler from 225 type SchedulerFile struct { 226 // Filenames is the hierarchy with the leaf at the right 227 Filenames []string 228 Org string 229 Repo string 230 } 231 232 // BuildAndValidateProwConfig takes a list of schedulerFiles and builds them to a Prow config, 233 // and validates them against the expectedConfigFilename and expectedPluginsFilename that make up the prow config. 234 // Filepaths are relative to the baseDir 235 func BuildAndValidateProwConfig(t *testing.T, baseDir string, expectedConfigFilename string, 236 expectedPluginsFilename string, schedulerFiles []SchedulerFile) { 237 var expectedConfig config.Config 238 if expectedConfigFilename != "" { 239 cfgBytes, err := ioutil.ReadFile(filepath.Join(baseDir, expectedConfigFilename)) 240 assert.NoError(t, err) 241 err = yaml.Unmarshal(cfgBytes, &expectedConfig) 242 assert.NoError(t, err) 243 } 244 245 var expectedPlugins plugins.Configuration 246 if expectedPluginsFilename != "" { 247 bytes, err := ioutil.ReadFile(filepath.Join(baseDir, expectedPluginsFilename)) 248 assert.NoError(t, err) 249 err = yaml.Unmarshal(bytes, &expectedPlugins) 250 assert.NoError(t, err) 251 } 252 253 schedulerLeaves := make([]*pipelinescheduler.SchedulerLeaf, 0) 254 for _, sfs := range schedulerFiles { 255 schedulers := make([]*v1.SchedulerSpec, 0) 256 for _, f := range sfs.Filenames { 257 bytes, err := ioutil.ReadFile(filepath.Join(baseDir, f)) 258 assert.NoError(t, err) 259 s := v1.SchedulerSpec{} 260 err = yaml.Unmarshal(bytes, &s) 261 assert.NoError(t, err) 262 schedulers = append(schedulers, &s) 263 } 264 s, err := pipelinescheduler.Build(schedulers) 265 assert.NoError(t, err) 266 schedulerLeaves = append(schedulerLeaves, &pipelinescheduler.SchedulerLeaf{ 267 Repo: sfs.Repo, 268 Org: sfs.Org, 269 SchedulerSpec: s, 270 }) 271 } 272 273 cfg, plugs, err := pipelinescheduler.BuildProwConfig(schedulerLeaves) 274 assert.NoError(t, err) 275 if expectedConfigFilename != "" { 276 expected, err := yaml.Marshal(&expectedConfig) 277 assert.NoError(t, err) 278 actual, err := yaml.Marshal(cfg) 279 assert.NoError(t, err) 280 assert.NotNil(t, expected) 281 assert.Equal(t, string(expected), string(actual)) 282 } 283 if expectedPluginsFilename != "" { 284 expected, err := yaml.Marshal(&expectedPlugins) 285 assert.NoError(t, err) 286 actual, err := yaml.Marshal(plugs) 287 assert.NoError(t, err) 288 assert.Equal(t, string(expected), string(actual)) 289 } 290 }