11package codefresh
22
33import (
4+ "context"
45 "fmt"
56 "regexp"
67 "strings"
78
89 cfClient "github.com/codefresh-io/terraform-provider-codefresh/client"
10+ "github.com/hashicorp/go-cty/cty"
11+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
12+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
913 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
14+ "github.com/robfig/cron"
1015)
1116
1217func resourcePipelineCronTrigger () * schema.Resource {
@@ -20,7 +25,7 @@ func resourcePipelineCronTrigger() *schema.Resource {
2025 idParts := strings .Split (d .Id (), "," )
2126
2227 if len (idParts ) != 2 || idParts [0 ] == "" || idParts [1 ] == "" {
23- return nil , fmt .Errorf ("Unexpected format of ID (%q), expected EVENT,PIPELINE_ID" , d .Id ())
28+ return nil , fmt .Errorf ("unexpected format of ID (%q), expected EVENT,PIPELINE_ID" , d .Id ())
2429 }
2530
2631 event := idParts [0 ]
@@ -39,12 +44,55 @@ func resourcePipelineCronTrigger() *schema.Resource {
3944 "expression" : {
4045 Type : schema .TypeString ,
4146 Required : true ,
47+ ValidateDiagFunc : func (v interface {}, path cty.Path ) (diags diag.Diagnostics ) {
48+ expression := v .(string )
49+
50+ // Cron expression requirements: 6 fields, with ability to use descriptors (e.g. @yearly)
51+ parser := cron .NewParser (cron .Second | cron .Minute | cron .Hour | cron .Dom | cron .Month | cron .Dow | cron .Descriptor )
52+ if _ , err := parser .Parse (expression ); err != nil {
53+ diags = append (diags , diag.Diagnostic {
54+ Severity : diag .Error ,
55+ Summary : "Invalid cron expression." ,
56+ Detail : fmt .Sprintf ("The cron expression %q is invalid: %s" , expression , err ),
57+ })
58+ }
59+
60+ return
61+ },
4262 },
4363 "message" : {
4464 Type : schema .TypeString ,
4565 Required : true ,
66+ ValidateDiagFunc : func (v interface {}, path cty.Path ) (diags diag.Diagnostics ) {
67+ message := v .(string )
68+
69+ // https://github.com/codefresh-io/hermes/blob/6d75b347cb8ff471ce970a766b2285788e5e19fe/pkg/backend/dev_compose_types.json#L226
70+ re := regexp .MustCompile (`^[a-zA-Z0-9_+\s-#?.:]{2,128}$` )
71+
72+ if ! re .MatchString (message ) {
73+ diags = append (diags , diag.Diagnostic {
74+ Severity : diag .Error ,
75+ Summary : "Invalid message." ,
76+ Detail : fmt .Sprintf ("The message %q is invalid (must match %q)." , message , re .String ()),
77+ })
78+ }
79+
80+ return
81+ },
4682 },
4783 },
84+ // Force new resource if any field changes. This is because the Codefresh API does not support updating cron triggers.
85+ CustomizeDiff : customdiff .All (
86+ customdiff .ForceNewIfChange ("pipeline_id" , func (ctx context.Context , old , new , meta interface {}) bool {
87+ return true
88+ }),
89+ customdiff .ForceNewIfChange ("expression" , func (ctx context.Context , old , new , meta interface {}) bool {
90+ return true
91+ }),
92+ customdiff .ForceNewIfChange ("message" , func (ctx context.Context , old , new , meta interface {}) bool {
93+ return true
94+ }),
95+ ),
4896 }
4997}
5098
@@ -97,7 +145,8 @@ func resourcePipelineCronTriggerRead(d *schema.ResourceData, meta interface{}) e
97145}
98146
99147func resourcePipelineCronTriggerUpdate (d * schema.ResourceData , meta interface {}) error {
100- return resourcePipelineCronTriggerCreate (d , meta )
148+ // see notes in resourcePipelineCronTrigger()
149+ return fmt .Errorf ("cron triggers cannot be updated" )
101150}
102151
103152func resourcePipelineCronTriggerDelete (d * schema.ResourceData , meta interface {}) error {
@@ -107,7 +156,7 @@ func resourcePipelineCronTriggerDelete(d *schema.ResourceData, meta interface{})
107156
108157 err := client .DeleteHermesTriggerByEventAndPipeline (hermesTrigger .Event , hermesTrigger .PipelineID )
109158 if err != nil {
110- return fmt .Errorf ("Failed to delete cron trigger: %s " , err )
159+ return fmt .Errorf ("failed to delete cron trigger: %v " , err )
111160 }
112161
113162 return nil
@@ -122,7 +171,7 @@ func mapPipelineCronTriggerToResource(hermesTrigger *cfClient.HermesTrigger, d *
122171 r := regexp .MustCompile ("[^:]+:[^:]+:[^:]+:[^:]+" )
123172 eventStringAttributes := strings .Split (hermesTrigger .Event , ":" )
124173 if ! r .MatchString (hermesTrigger .Event ) {
125- return fmt .Errorf ("Event string must be in format 'cron:codefresh:[expression]:[message]:[uid]': %s" , hermesTrigger .Event )
174+ return fmt .Errorf ("event string must be in format 'cron:codefresh:[expression]:[message]:[uid]': %s" , hermesTrigger .Event )
126175 }
127176 d .Set ("expression" , eventStringAttributes [2 ])
128177 d .Set ("message" , eventStringAttributes [3 ])
0 commit comments