@@ -2,10 +2,13 @@ package codefresh
2
2
3
3
import (
4
4
"fmt"
5
+ "log"
5
6
"strings"
6
7
7
8
cfClient "github.com/codefresh-io/terraform-provider-codefresh/client"
9
+ ghodss "github.com/ghodss/yaml"
8
10
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11
+ "gopkg.in/yaml.v2"
9
12
)
10
13
11
14
func resourcePipeline () * schema.Resource {
@@ -383,6 +386,11 @@ func mapResourceToPipeline(d *schema.ResourceData) *cfClient.Pipeline {
383
386
384
387
tags := d .Get ("tags" ).(* schema.Set ).List ()
385
388
389
+ originalYamlString := strings .Replace (
390
+ d .Get ("original_yaml_string" ).(string ),
391
+ "\n " ,
392
+ "\n " ,
393
+ - 1 )
386
394
pipeline := & cfClient.Pipeline {
387
395
Metadata : cfClient.Metadata {
388
396
Name : d .Get ("name" ).(string ),
@@ -391,11 +399,7 @@ func mapResourceToPipeline(d *schema.ResourceData) *cfClient.Pipeline {
391
399
Labels : cfClient.Labels {
392
400
Tags : convertStringArr (tags ),
393
401
},
394
- OriginalYamlString : strings .Replace (
395
- d .Get ("original_yaml_string" ).(string ),
396
- "\n " ,
397
- "\n " ,
398
- - 1 ),
402
+ OriginalYamlString : originalYamlString ,
399
403
},
400
404
Spec : cfClient.Spec {
401
405
Priority : d .Get ("spec.0.priority" ).(int ),
@@ -411,6 +415,14 @@ func mapResourceToPipeline(d *schema.ResourceData) *cfClient.Pipeline {
411
415
Revision : d .Get ("spec.0.spec_template.0.revision" ).(string ),
412
416
Context : d .Get ("spec.0.spec_template.0.context" ).(string ),
413
417
}
418
+ } else {
419
+ stages , steps := extractStagesAndSteps (originalYamlString )
420
+ pipeline .Spec .Steps = & cfClient.Steps {
421
+ Steps : steps ,
422
+ }
423
+ pipeline .Spec .Stages = & cfClient.Stages {
424
+ Stages : stages ,
425
+ }
414
426
}
415
427
416
428
if _ , ok := d .GetOk ("spec.0.runtime_environment" ); ok {
@@ -452,3 +464,51 @@ func mapResourceToPipeline(d *schema.ResourceData) *cfClient.Pipeline {
452
464
}
453
465
return pipeline
454
466
}
467
+
468
+ // extractStagesAndSteps extracts the steps and stages from the original yaml string to enable propagation in the `Spec` attribute of the pipeline
469
+ // We cannot leverage on the standard marshal/unmarshal because the steps attribute needs to maintain the order of elements
470
+ // while by default the standard function doesn't do it because in JSON maps are unordered
471
+ func extractStagesAndSteps (originalYamlString string ) (stages , steps string ) {
472
+ // Use mapSlice to preserve order of items from the YAML string
473
+ m := yaml.MapSlice {}
474
+ err := yaml .Unmarshal ([]byte (originalYamlString ), & m )
475
+ if err != nil {
476
+ log .Fatal ("Unable to unmarshall original_yaml_string" )
477
+ }
478
+
479
+ stages = "[]"
480
+ // Dynamically build JSON object for steps using String builder
481
+ stepsBuilder := strings.Builder {}
482
+ stepsBuilder .WriteString ("{" )
483
+ // Parse elements of the YAML string to extract Steps and Stages if defined
484
+ for _ , item := range m {
485
+ if item .Key == "steps" {
486
+ switch x := item .Value .(type ) {
487
+ default :
488
+ log .Fatalf ("unsupported value type: %T" , item .Value )
489
+
490
+ case yaml.MapSlice :
491
+ numberOfSteps := len (x )
492
+ for index , item := range x {
493
+ // We only need to preserve order at the first level to guarantee order of the steps, hence the child nodes can be marshalled
494
+ // with the standard library
495
+ y , _ := yaml .Marshal (item .Value )
496
+ j2 , _ := ghodss .YAMLToJSON (y )
497
+ stepsBuilder .WriteString ("\" " + item .Key .(string ) + "\" : " + string (j2 ))
498
+ if index < numberOfSteps - 1 {
499
+ stepsBuilder .WriteString ("," )
500
+ }
501
+ }
502
+ }
503
+ }
504
+ if item .Key == "stages" {
505
+ // For Stages we don't have ordering issue because it's a list
506
+ y , _ := yaml .Marshal (item .Value )
507
+ j2 , _ := ghodss .YAMLToJSON (y )
508
+ stages = string (j2 )
509
+ }
510
+ }
511
+ stepsBuilder .WriteString ("}" )
512
+ steps = stepsBuilder .String ()
513
+ return
514
+ }
0 commit comments