github.com/jenkins-x/jx/v2@v2.1.155/pkg/tekton/syntax/syntax_helpers_test/test_helpers.go (about) 1 package syntax_helpers_test 2 3 import ( 4 v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1" 5 "github.com/jenkins-x/jx/v2/pkg/tekton/syntax" 6 "github.com/jenkins-x/jx/v2/pkg/util" 7 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" 8 "github.com/tektoncd/pipeline/test/builder" 9 corev1 "k8s.io/api/core/v1" 10 "k8s.io/apimachinery/pkg/api/resource" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 ) 13 14 // PipelineStructureOp is an operation used in generating a PipelineStructure 15 type PipelineStructureOp func(structure *v1.PipelineStructure) 16 17 // PipelineStructureStageOp is an operation used in generating a PipelineStructureStage 18 type PipelineStructureStageOp func(stage *v1.PipelineStructureStage) 19 20 // PipelineStructure creates a PipelineStructure 21 func PipelineStructure(name string, ops ...PipelineStructureOp) *v1.PipelineStructure { 22 s := &v1.PipelineStructure{ 23 ObjectMeta: metav1.ObjectMeta{ 24 Name: name, 25 }, 26 } 27 28 for _, op := range ops { 29 op(s) 30 } 31 32 return s 33 } 34 35 // StructurePipelineRunRef adds a run reference to the structure 36 func StructurePipelineRunRef(name string) PipelineStructureOp { 37 return func(structure *v1.PipelineStructure) { 38 structure.PipelineRunRef = &name 39 } 40 } 41 42 // StructureStage adds a stage to the structure 43 func StructureStage(name string, ops ...PipelineStructureStageOp) PipelineStructureOp { 44 return func(structure *v1.PipelineStructure) { 45 stage := v1.PipelineStructureStage{Name: name} 46 47 for _, op := range ops { 48 op(&stage) 49 } 50 51 structure.Stages = append(structure.Stages, stage) 52 } 53 } 54 55 // StructureStageTaskRef adds a task ref to the stage 56 func StructureStageTaskRef(name string) PipelineStructureStageOp { 57 return func(stage *v1.PipelineStructureStage) { 58 stage.TaskRef = &name 59 } 60 } 61 62 // StructureStageTaskRunRef adds a task run ref to the stage 63 func StructureStageTaskRunRef(name string) PipelineStructureStageOp { 64 return func(stage *v1.PipelineStructureStage) { 65 stage.TaskRunRef = &name 66 } 67 } 68 69 // StructureStageDepth sets the depth on the stage 70 func StructureStageDepth(depth int8) PipelineStructureStageOp { 71 return func(stage *v1.PipelineStructureStage) { 72 stage.Depth = depth 73 } 74 } 75 76 // StructureStageParent sets the parent stage for the stage 77 func StructureStageParent(parent string) PipelineStructureStageOp { 78 return func(stage *v1.PipelineStructureStage) { 79 stage.Parent = &parent 80 } 81 } 82 83 // StructureStagePrevious sets the previous stage for the stage 84 func StructureStagePrevious(previous string) PipelineStructureStageOp { 85 return func(stage *v1.PipelineStructureStage) { 86 stage.Previous = &previous 87 } 88 } 89 90 // StructureStageNext sets the next stage for the stage 91 func StructureStageNext(Next string) PipelineStructureStageOp { 92 return func(stage *v1.PipelineStructureStage) { 93 stage.Next = &Next 94 } 95 } 96 97 // StructureStageStages sets the nested sequential stages for the stage 98 func StructureStageStages(stages ...string) PipelineStructureStageOp { 99 return func(stage *v1.PipelineStructureStage) { 100 stage.Stages = append(stage.Stages, stages...) 101 } 102 } 103 104 // StructureStageParallel sets the nested parallel stages for the stage 105 func StructureStageParallel(stages ...string) PipelineStructureStageOp { 106 return func(stage *v1.PipelineStructureStage) { 107 stage.Parallel = append(stage.Parallel, stages...) 108 } 109 } 110 111 // PipelineOp is an operation on a ParsedPipeline 112 type PipelineOp func(*syntax.ParsedPipeline) 113 114 // PipelineOptionsOp is an operation on RootOptions 115 type PipelineOptionsOp func(*syntax.RootOptions) 116 117 // PipelinePostOp is an operation on Post 118 type PipelinePostOp func(*syntax.Post) 119 120 // StageOp is an operation on a Stage 121 type StageOp func(*syntax.Stage) 122 123 // StageOptionsOp is an operation on StageOptions 124 type StageOptionsOp func(*syntax.StageOptions) 125 126 // StepOp is an operation on a step 127 type StepOp func(*syntax.Step) 128 129 // LoopOp is an operation on a Loop 130 type LoopOp func(*syntax.Loop) 131 132 // ParsedPipeline creates a ParsedPipeline from the provided operations 133 func ParsedPipeline(ops ...PipelineOp) *syntax.ParsedPipeline { 134 s := &syntax.ParsedPipeline{} 135 136 for _, op := range ops { 137 op(s) 138 } 139 140 return s 141 } 142 143 // PipelineAgent sets the agent for the pipeline 144 func PipelineAgent(image string) PipelineOp { 145 return func(parsed *syntax.ParsedPipeline) { 146 parsed.Agent = &syntax.Agent{ 147 Image: image, 148 } 149 } 150 } 151 152 // PipelineOptions sets the RootOptions for the pipeline 153 func PipelineOptions(ops ...PipelineOptionsOp) PipelineOp { 154 return func(parsed *syntax.ParsedPipeline) { 155 parsed.Options = &syntax.RootOptions{} 156 157 for _, op := range ops { 158 op(parsed.Options) 159 } 160 } 161 } 162 163 // PipelineSidecar adds a sidecar container to the RootOptions for the pipeline 164 func PipelineSidecar(sidecar *corev1.Container) PipelineOptionsOp { 165 return func(options *syntax.RootOptions) { 166 if options.Sidecars == nil { 167 options.Sidecars = []*corev1.Container{} 168 } 169 options.Sidecars = append(options.Sidecars, sidecar) 170 } 171 } 172 173 // PipelineVolume adds a volume to the RootOptions for the pipeline 174 func PipelineVolume(volume *corev1.Volume) PipelineOptionsOp { 175 return func(options *syntax.RootOptions) { 176 if options.Volumes == nil { 177 options.Volumes = []*corev1.Volume{} 178 } 179 options.Volumes = append(options.Volumes, volume) 180 } 181 } 182 183 // StageSidecar adds a sidecar to the StageOptions for the stage 184 func StageSidecar(sidecar *corev1.Container) StageOptionsOp { 185 return func(options *syntax.StageOptions) { 186 if options.RootOptions == nil { 187 options.RootOptions = &syntax.RootOptions{} 188 } 189 if options.Sidecars == nil { 190 options.Sidecars = []*corev1.Container{} 191 } 192 options.Sidecars = append(options.Sidecars, sidecar) 193 } 194 } 195 196 // StageVolume adds a volume to the StageOptions for the stage 197 func StageVolume(volume *corev1.Volume) StageOptionsOp { 198 return func(options *syntax.StageOptions) { 199 if options.RootOptions == nil { 200 options.RootOptions = &syntax.RootOptions{} 201 } 202 if options.Volumes == nil { 203 options.Volumes = []*corev1.Volume{} 204 } 205 options.Volumes = append(options.Volumes, volume) 206 } 207 } 208 209 // PipelineContainerOptions sets the containerOptions for the pipeline 210 func PipelineContainerOptions(ops ...builder.ContainerOp) PipelineOptionsOp { 211 return func(options *syntax.RootOptions) { 212 options.ContainerOptions = &corev1.Container{} 213 214 for _, op := range ops { 215 op(options.ContainerOptions) 216 } 217 } 218 } 219 220 // PipelineTolerations sets the tolerations for the pipeline 221 func PipelineTolerations(tolerations []corev1.Toleration) PipelineOptionsOp { 222 return func(options *syntax.RootOptions) { 223 options.Tolerations = append(options.Tolerations, tolerations...) 224 } 225 } 226 227 // PipelinePodLabels sets the optional pod labels for the pipeline 228 func PipelinePodLabels(labels map[string]string) PipelineOptionsOp { 229 return func(options *syntax.RootOptions) { 230 options.PodLabels = util.MergeMaps(options.PodLabels, labels) 231 } 232 } 233 234 // StageContainerOptions sets the containerOptions for a stage 235 func StageContainerOptions(ops ...builder.ContainerOp) StageOptionsOp { 236 return func(options *syntax.StageOptions) { 237 if options.RootOptions == nil { 238 options.RootOptions = &syntax.RootOptions{} 239 } 240 options.ContainerOptions = &corev1.Container{} 241 242 for _, op := range ops { 243 op(options.ContainerOptions) 244 } 245 } 246 } 247 248 // PipelineDir sets the default working directory for the pipeline 249 func PipelineDir(dir string) PipelineOp { 250 return func(pipeline *syntax.ParsedPipeline) { 251 pipeline.WorkingDir = &dir 252 } 253 } 254 255 // StageDir sets the default working directory for the stage 256 func StageDir(dir string) StageOp { 257 return func(stage *syntax.Stage) { 258 stage.WorkingDir = &dir 259 } 260 } 261 262 // ContainerResourceLimits sets the resource limits for container options 263 func ContainerResourceLimits(cpus, memory string) builder.ContainerOp { 264 return func(container *corev1.Container) { 265 cpuQuantity, _ := resource.ParseQuantity(cpus) 266 memoryQuantity, _ := resource.ParseQuantity(memory) 267 container.Resources.Limits = corev1.ResourceList{ 268 "cpu": cpuQuantity, 269 "memory": memoryQuantity, 270 } 271 } 272 } 273 274 // ContainerResourceRequests sets the resource requests for container options 275 func ContainerResourceRequests(cpus, memory string) builder.ContainerOp { 276 return func(container *corev1.Container) { 277 cpuQuantity, _ := resource.ParseQuantity(cpus) 278 memoryQuantity, _ := resource.ParseQuantity(memory) 279 container.Resources.Requests = corev1.ResourceList{ 280 "cpu": cpuQuantity, 281 "memory": memoryQuantity, 282 } 283 } 284 } 285 286 // ContainerSecurityContext sets the security context for container options 287 func ContainerSecurityContext(privileged bool) builder.ContainerOp { 288 return func(container *corev1.Container) { 289 container.SecurityContext = &corev1.SecurityContext{ 290 Privileged: &privileged, 291 } 292 } 293 } 294 295 // ContainerVolumeMount adds a VolumeMount to the container options 296 func ContainerVolumeMount(name string, mountPath string) builder.ContainerOp { 297 return func(container *corev1.Container) { 298 container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{ 299 Name: name, 300 MountPath: mountPath, 301 }) 302 } 303 } 304 305 // StepVolumeMount adds a VolumeMount to the container options on a step 306 func StepVolumeMount(name string, mountPath string) builder.StepOp { 307 return func(step *v1alpha1.Step) { 308 step.VolumeMounts = append(step.VolumeMounts, corev1.VolumeMount{ 309 Name: name, 310 MountPath: mountPath, 311 }) 312 } 313 } 314 315 // StepResourceLimits sets the resource limits for container options on a step 316 func StepResourceLimits(cpus, memory string) builder.StepOp { 317 return func(step *v1alpha1.Step) { 318 cpuQuantity, _ := resource.ParseQuantity(cpus) 319 memoryQuantity, _ := resource.ParseQuantity(memory) 320 step.Resources.Limits = corev1.ResourceList{ 321 "cpu": cpuQuantity, 322 "memory": memoryQuantity, 323 } 324 } 325 } 326 327 // StepResourceRequests sets the resource requests for container options on a step 328 func StepResourceRequests(cpus, memory string) builder.StepOp { 329 return func(step *v1alpha1.Step) { 330 cpuQuantity, _ := resource.ParseQuantity(cpus) 331 memoryQuantity, _ := resource.ParseQuantity(memory) 332 step.Resources.Requests = corev1.ResourceList{ 333 "cpu": cpuQuantity, 334 "memory": memoryQuantity, 335 } 336 } 337 } 338 339 // StepSecurityContext sets the security context for container options on a step 340 func StepSecurityContext(privileged bool) builder.StepOp { 341 return func(step *v1alpha1.Step) { 342 step.SecurityContext = &corev1.SecurityContext{ 343 Privileged: &privileged, 344 } 345 } 346 } 347 348 // EnvVarFrom adds an environment variable using EnvVarSource to the container options 349 func EnvVarFrom(name string, source *corev1.EnvVarSource) builder.ContainerOp { 350 return func(container *corev1.Container) { 351 container.Env = append(container.Env, corev1.EnvVar{ 352 Name: name, 353 ValueFrom: source, 354 }) 355 } 356 } 357 358 // EnvVar adds an environment variable with a value to the container options 359 func EnvVar(name string, value string) builder.ContainerOp { 360 return func(container *corev1.Container) { 361 container.Env = append(container.Env, corev1.EnvVar{ 362 Name: name, 363 Value: value, 364 }) 365 } 366 } 367 368 // PipelineOptionsTimeout sets the timeout for the pipeline 369 func PipelineOptionsTimeout(time int64, unit syntax.TimeoutUnit) PipelineOptionsOp { 370 return func(options *syntax.RootOptions) { 371 options.Timeout = &syntax.Timeout{ 372 Time: time, 373 Unit: unit, 374 } 375 } 376 } 377 378 // PipelineOptionsRetry sets the retry count for the pipeline 379 func PipelineOptionsRetry(count int8) PipelineOptionsOp { 380 return func(options *syntax.RootOptions) { 381 options.Retry = count 382 } 383 } 384 385 // PipelineOptionsDistributeParallelAcrossNodes sets the value for distributeParallelAcrossNodes 386 func PipelineOptionsDistributeParallelAcrossNodes(b bool) PipelineOptionsOp { 387 return func(options *syntax.RootOptions) { 388 options.DistributeParallelAcrossNodes = b 389 } 390 } 391 392 // PipelineEnvVar add an environment variable, with specified name and value, to the pipeline. 393 func PipelineEnvVar(name, value string) PipelineOp { 394 return func(parsed *syntax.ParsedPipeline) { 395 parsed.Env = append(parsed.GetEnv(), corev1.EnvVar{ 396 Name: name, 397 Value: value, 398 }) 399 } 400 } 401 402 // PipelinePost adds a post condition to the pipeline 403 func PipelinePost(condition syntax.PostCondition, ops ...PipelinePostOp) PipelineOp { 404 return func(parsed *syntax.ParsedPipeline) { 405 post := syntax.Post{ 406 Condition: condition, 407 } 408 409 for _, op := range ops { 410 op(&post) 411 } 412 413 parsed.Post = append(parsed.Post, post) 414 } 415 } 416 417 // PipelineStage adds a stage to the pipeline 418 func PipelineStage(name string, ops ...StageOp) PipelineOp { 419 return func(parsed *syntax.ParsedPipeline) { 420 s := syntax.Stage{ 421 Name: name, 422 } 423 424 for _, op := range ops { 425 op(&s) 426 } 427 parsed.Stages = append(parsed.Stages, s) 428 } 429 } 430 431 // PostAction adds a post action to a post condition 432 func PostAction(name string, options map[string]string) PipelinePostOp { 433 return func(post *syntax.Post) { 434 post.Actions = append(post.Actions, syntax.PostAction{ 435 Name: name, 436 Options: options, 437 }) 438 } 439 } 440 441 // StageAgent sets the image/agent for a stage 442 func StageAgent(image string) StageOp { 443 return func(stage *syntax.Stage) { 444 stage.Agent = &syntax.Agent{ 445 Image: image, 446 } 447 } 448 } 449 450 // StageOptions sets the StageOptions for a stage 451 func StageOptions(ops ...StageOptionsOp) StageOp { 452 return func(stage *syntax.Stage) { 453 stage.Options = &syntax.StageOptions{} 454 455 for _, op := range ops { 456 op(stage.Options) 457 } 458 } 459 } 460 461 // StageOptionsTimeout sets the timeout for a stage 462 func StageOptionsTimeout(time int64, unit syntax.TimeoutUnit) StageOptionsOp { 463 return func(options *syntax.StageOptions) { 464 if options.RootOptions == nil { 465 options.RootOptions = &syntax.RootOptions{} 466 } 467 options.Timeout = &syntax.Timeout{ 468 Time: time, 469 Unit: unit, 470 } 471 } 472 } 473 474 // StageOptionsRetry sets the retry count for a stage 475 func StageOptionsRetry(count int8) StageOptionsOp { 476 return func(options *syntax.StageOptions) { 477 if options.RootOptions == nil { 478 options.RootOptions = &syntax.RootOptions{} 479 } 480 options.Retry = count 481 } 482 } 483 484 // StageOptionsWorkspace sets the workspace for a stage 485 func StageOptionsWorkspace(ws string) StageOptionsOp { 486 return func(options *syntax.StageOptions) { 487 options.Workspace = &ws 488 } 489 } 490 491 // StageOptionsStash adds a stash to the stage 492 func StageOptionsStash(name, files string) StageOptionsOp { 493 return func(options *syntax.StageOptions) { 494 options.Stash = &syntax.Stash{ 495 Name: name, 496 Files: files, 497 } 498 } 499 } 500 501 // StageOptionsUnstash adds an unstash to the stage 502 func StageOptionsUnstash(name, dir string) StageOptionsOp { 503 return func(options *syntax.StageOptions) { 504 options.Unstash = &syntax.Unstash{ 505 Name: name, 506 } 507 if dir != "" { 508 options.Unstash.Dir = dir 509 } 510 } 511 } 512 513 // StageEnvVar add an environment variable, with specified name and value, to the stage. 514 func StageEnvVar(name, value string) StageOp { 515 return func(stage *syntax.Stage) { 516 stage.Env = append(stage.GetEnv(), corev1.EnvVar{ 517 Name: name, 518 Value: value, 519 }) 520 } 521 } 522 523 // StagePost adds a post condition to the stage 524 func StagePost(condition syntax.PostCondition, ops ...PipelinePostOp) StageOp { 525 return func(stage *syntax.Stage) { 526 post := syntax.Post{ 527 Condition: condition, 528 } 529 530 for _, op := range ops { 531 op(&post) 532 } 533 534 stage.Post = append(stage.Post, post) 535 } 536 } 537 538 // StepAgent sets the agent for a step 539 func StepAgent(image string) StepOp { 540 return func(step *syntax.Step) { 541 step.Agent = &syntax.Agent{ 542 Image: image, 543 } 544 } 545 } 546 547 // StepImage sets the image for a step 548 func StepImage(image string) StepOp { 549 return func(step *syntax.Step) { 550 step.Image = image 551 } 552 } 553 554 // StepCmd sets the command for a step 555 func StepCmd(cmd string) StepOp { 556 return func(step *syntax.Step) { 557 step.Command = cmd 558 } 559 } 560 561 // StepName sets the name for a step 562 func StepName(name string) StepOp { 563 return func(step *syntax.Step) { 564 step.Name = name 565 } 566 } 567 568 // StepArg sets the arguments for a step 569 func StepArg(arg string) StepOp { 570 return func(step *syntax.Step) { 571 step.Arguments = append(step.Arguments, arg) 572 } 573 } 574 575 // StepStep sets the alias step for a step 576 func StepStep(s string) StepOp { 577 return func(step *syntax.Step) { 578 step.Step = s 579 } 580 } 581 582 // StepOptions sets the alias step options for a step 583 func StepOptions(options map[string]string) StepOp { 584 return func(step *syntax.Step) { 585 step.Options = options 586 } 587 } 588 589 // StepDir sets the working dir for a step 590 func StepDir(dir string) StepOp { 591 return func(step *syntax.Step) { 592 step.Dir = dir 593 } 594 } 595 596 // StepLoop adds a loop to the step 597 func StepLoop(variable string, values []string, ops ...LoopOp) StepOp { 598 return func(step *syntax.Step) { 599 loop := &syntax.Loop{ 600 Variable: variable, 601 Values: values, 602 } 603 604 for _, op := range ops { 605 op(loop) 606 } 607 608 step.Loop = loop 609 } 610 } 611 612 // StepEnvVar add an environment variable, with specified name and value, to the step. 613 func StepEnvVar(name, value string) StepOp { 614 return func(step *syntax.Step) { 615 step.Env = append(step.Env, corev1.EnvVar{ 616 Name: name, 617 Value: value, 618 }) 619 } 620 } 621 622 // LoopStep adds a step to the loop 623 func LoopStep(ops ...StepOp) LoopOp { 624 return func(loop *syntax.Loop) { 625 step := syntax.Step{} 626 627 for _, op := range ops { 628 op(&step) 629 } 630 631 loop.Steps = append(loop.Steps, step) 632 } 633 } 634 635 // StageStep adds a step to the stage 636 func StageStep(ops ...StepOp) StageOp { 637 return func(stage *syntax.Stage) { 638 step := syntax.Step{} 639 640 for _, op := range ops { 641 op(&step) 642 } 643 644 stage.Steps = append(stage.Steps, step) 645 } 646 } 647 648 // StageParallel adds a nested parallel stage to the stage 649 func StageParallel(name string, ops ...StageOp) StageOp { 650 return func(stage *syntax.Stage) { 651 n := syntax.Stage{Name: name} 652 653 for _, op := range ops { 654 op(&n) 655 } 656 657 stage.Parallel = append(stage.Parallel, n) 658 } 659 } 660 661 // StageSequential adds a nested sequential stage to the stage 662 func StageSequential(name string, ops ...StageOp) StageOp { 663 return func(stage *syntax.Stage) { 664 n := syntax.Stage{Name: name} 665 666 for _, op := range ops { 667 op(&n) 668 } 669 670 stage.Stages = append(stage.Stages, n) 671 } 672 } 673 674 // TaskStageLabel sets the stage label on the task 675 func TaskStageLabel(value string) builder.TaskOp { 676 return func(t *v1alpha1.Task) { 677 if t.ObjectMeta.Labels == nil { 678 t.ObjectMeta.Labels = map[string]string{} 679 } 680 t.ObjectMeta.Labels[syntax.LabelStageName] = syntax.MangleToRfc1035Label(value, "") 681 } 682 } 683 684 // OutputsResource adds a resource, with specified name and type, to the Outputs. 685 // Any number of TaskResource modifier can be passed to transform it. 686 func OutputsResource(name string, resourceType v1alpha1.PipelineResourceType, ops ...builder.TaskResourceOp) builder.OutputsOp { 687 return func(i *v1alpha1.Outputs) { 688 r := &v1alpha1.TaskResource{ 689 ResourceDeclaration: v1alpha1.ResourceDeclaration{ 690 Name: name, 691 Type: resourceType, 692 }} 693 for _, op := range ops { 694 op(r) 695 } 696 i.Resources = append(i.Resources, *r) 697 } 698 }