From 887901fd9a9b51cfc643dd633bacbc73ba9573f6 Mon Sep 17 00:00:00 2001 From: Oleksandr Saulyak Date: Fri, 18 Aug 2023 08:58:14 +0300 Subject: [PATCH] Add inline cron triggers to `codefresh_pipeline` (#122) ## What `[codefresh_pipeline]`: add `spec.cron_trigger` ## Why New feature that supersedes [pipeline_cron_trigger](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline_cron_trigger) added in #90 (the API used by `pipeline_cron_trigger` is limited; additional cron trigger options were recently added to the pipelines API, currently behind a feature flag) ## Notes Will be first released as part of `0.6.0-beta-1` (pre-release) ## Checklist * [x] _I have read [CONTRIBUTING.md](https://github.com/codefresh-io/terraform-provider-codefresh/blob/master/CONTRIBUTING.md)._ * [x] _I have [allowed changes to my fork to be made](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)._ * [x] _I have added tests, assuming new tests are warranted_. * [x] _I understand that the `/test` comment will be ignored by the CI trigger [unless it is made by a repo admin or collaborator](https://codefresh.io/docs/docs/pipelines/triggers/git-triggers/#support-for-building-pull-requests-from-forks)._ --------- Co-authored-by: Yonatan Koren <10080107+korenyoni@users.noreply.github.com> --- client/pipeline.go | 20 ++ codefresh/resource_pipeline.go | 323 +++++++++++++++--- codefresh/resource_pipeline_cron_trigger.go | 1 + codefresh/resource_pipeline_test.go | 229 +++++++++++++ docs/resources/pipeline.md | 46 +++ docs/resources/pipeline_cron_trigger.md | 2 + templates/resources/pipeline.md.tmpl | 2 + .../resources/pipeline_cron_trigger.md.tmpl | 2 + 8 files changed, 579 insertions(+), 46 deletions(-) diff --git a/client/pipeline.go b/client/pipeline.go index defb352..459a746 100644 --- a/client/pipeline.go +++ b/client/pipeline.go @@ -62,6 +62,19 @@ type Trigger struct { Variables []Variable `json:"variables,omitempty"` } +type CronTrigger struct { + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Expression string `json:"expression,omitempty"` + Message string `json:"message,omitempty"` + GitTriggerId string `json:"gitTriggerId,omitempty"` + Branch string `json:"branch,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Options *TriggerOptions `json:"options,omitempty"` + RuntimeEnvironment *RuntimeEnvironment `json:"runtimeEnvironment,omitempty"` + Variables []Variable `json:"variables,omitempty"` +} + type TriggerOptions struct { NoCache bool `json:"noCache,omitempty"` NoCfCache bool `json:"noCfCache,omitempty"` @@ -83,10 +96,17 @@ func (t *Trigger) SetVariables(variables map[string]interface{}) { } } +func (t *CronTrigger) SetVariables(variables map[string]interface{}) { + for key, value := range variables { + t.Variables = append(t.Variables, Variable{Key: key, Value: value.(string)}) + } +} + type Spec struct { Variables []Variable `json:"variables,omitempty"` SpecTemplate *SpecTemplate `json:"specTemplate,omitempty"` Triggers []Trigger `json:"triggers,omitempty"` + CronTriggers []CronTrigger `json:"cronTriggers,omitempty"` Priority int `json:"priority,omitempty"` Concurrency int `json:"concurrency,omitempty"` BranchConcurrency int `json:"branchConcurrency,omitempty"` diff --git a/codefresh/resource_pipeline.go b/codefresh/resource_pipeline.go index ebab792..db595b3 100644 --- a/codefresh/resource_pipeline.go +++ b/codefresh/resource_pipeline.go @@ -2,6 +2,7 @@ package codefresh import ( "fmt" + "github.com/robfig/cron" "log" "regexp" "strconv" @@ -341,6 +342,170 @@ Or: original_yaml_string = file("/path/to/my/codefresh.yml") }, }, }, + "cron_trigger": { + Description: "The pipeline's cron triggers. Conflicts with the deprecated [codefresh_pipeline_cron_trigger](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline_cron_trigger) resource.", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Description: "The name of the cron trigger.", + Type: schema.TypeString, + Required: true, + }, + "type": { + Description: "The type of the trigger (default: `cron`; see notes above).", + Type: schema.TypeString, + Optional: true, + Default: "cron", + ValidateDiagFunc: func(v any, p cty.Path) diag.Diagnostics { + value := v.(string) + expected := "cron" + var diags diag.Diagnostics + if value != expected { + diag := diag.Diagnostic{ + Severity: diag.Error, + Summary: "Only triggers of type cron are supported for cron triggers. For other trigger types, use the codefresh_pipeline_*_trigger resources.", + Detail: fmt.Sprintf("%q is not %q", value, expected), + } + diags = append(diags, diag) + } + return diags + }, + }, + "disabled": { + Description: "Flag to disable the trigger.", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "expression": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: func(v interface{}, path cty.Path) (diags diag.Diagnostics) { + expression := v.(string) + + // Cron expression requirements: 6 fields, with ability to use descriptors (e.g. @yearly) + parser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor) + if _, err := parser.Parse(expression); err != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid cron expression.", + Detail: fmt.Sprintf("The cron expression %q is invalid: %s", expression, err), + }) + } + + return + }, + }, + "message": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: func(v interface{}, path cty.Path) (diags diag.Diagnostics) { + message := v.(string) + + // https://github.com/codefresh-io/hermes/blob/6d75b347cb8ff471ce970a766b2285788e5e19fe/pkg/backend/dev_compose_types.json#L226 + re := regexp.MustCompile(`^[a-zA-Z0-9_+\s-#?.:]{2,128}$`) + + if !re.MatchString(message) { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid message.", + Detail: fmt.Sprintf("The message %q is invalid (must match %q).", message, re.String()), + }) + } + + return + }, + }, + "git_trigger_id": { + Description: "Related git-trigger id. Will by used to take all possible git information by branch.", + Type: schema.TypeString, + Optional: true, + }, + "branch": { + Description: "Branch that should be passed for build triggered by this cron trigger.", + Type: schema.TypeString, + Optional: true, + }, + "options": { + Description: "The trigger's options.", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "no_cache": { + Description: "If true, docker layer cache is disabled.", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "no_cf_cache": { + Description: "If true, extra Codefresh caching is disabled.", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "reset_volume": { + Description: "If true, all files on volume will be deleted before each execution.", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "enable_notifications": { + Description: "If false the pipeline will not send notifications to Slack and status updates back to the Git provider.", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, + "runtime_environment": { + Description: "The runtime environment for the trigger.", + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Description: "The name of the runtime environment.", + Type: schema.TypeString, + Optional: true, + }, + "memory": { + Description: "The memory allocated to the runtime environment.", + Type: schema.TypeString, + Optional: true, + }, + "cpu": { + Description: "The CPU allocated to the runtime environment.", + Type: schema.TypeString, + Optional: true, + }, + "dind_storage": { + Description: "The storage allocated to the runtime environment.", + Type: schema.TypeString, + Optional: true, + }, + "required_available_storage": { + Description: "Minimum disk space required for build filesystem ( unit Gi is required).", + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "variables": { + Description: "Trigger variables.", + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, "contexts": { Description: "A list of strings representing the contexts ([shared_configuration](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/shared-configuration/)) to be configured for the pipeline.", Type: schema.TypeList, @@ -610,6 +775,10 @@ func flattenSpec(spec cfClient.Spec) []interface{} { m["trigger"] = flattenTriggers(spec.Triggers) } + if len(spec.CronTriggers) > 0 { + m["cron_trigger"] = flattenCronTriggers(spec.CronTriggers) + } + if spec.SpecTemplate != nil { m["spec_template"] = flattenSpecTemplate(*spec.SpecTemplate) } @@ -752,6 +921,29 @@ func flattenTriggers(triggers []cfClient.Trigger) []map[string]interface{} { return res } +func flattenCronTriggers(cronTriggers []cfClient.CronTrigger) []map[string]interface{} { + var res = make([]map[string]interface{}, len(cronTriggers)) + for i, trigger := range cronTriggers { + m := make(map[string]interface{}) + m["name"] = trigger.Name + m["type"] = trigger.Type + m["expression"] = trigger.Expression + m["message"] = trigger.Message + m["disabled"] = trigger.Disabled + m["git_trigger_id"] = trigger.GitTriggerId + m["branch"] = trigger.Branch + m["variables"] = convertVariables(trigger.Variables) + if trigger.Options != nil { + m["options"] = flattenTriggerOptions(*trigger.Options) + } + if trigger.RuntimeEnvironment != nil { + m["runtime_environment"] = flattenSpecRuntimeEnvironment(*trigger.RuntimeEnvironment) + } + res[i] = m + } + return res +} + func mapResourceToPipeline(d *schema.ResourceData) (*cfClient.Pipeline, error) { tags := d.Get("tags").(*schema.Set).List() @@ -807,56 +999,95 @@ func mapResourceToPipeline(d *schema.ResourceData) (*cfClient.Pipeline, error) { } } - contexts := d.Get("spec.0.contexts").([]interface{}) - pipeline.Spec.Contexts = contexts - - variables := d.Get("spec.0.variables").(map[string]interface{}) - pipeline.SetVariables(variables) - - triggers := d.Get("spec.0.trigger").([]interface{}) - for idx := range triggers { - events := d.Get(fmt.Sprintf("spec.0.trigger.%v.events", idx)).([]interface{}) - contexts := d.Get(fmt.Sprintf("spec.0.trigger.%v.contexts", idx)).([]interface{}) - codefreshTrigger := cfClient.Trigger{ - Name: d.Get(fmt.Sprintf("spec.0.trigger.%v.name", idx)).(string), - Description: d.Get(fmt.Sprintf("spec.0.trigger.%v.description", idx)).(string), - Type: d.Get(fmt.Sprintf("spec.0.trigger.%v.type", idx)).(string), - Repo: d.Get(fmt.Sprintf("spec.0.trigger.%v.repo", idx)).(string), - BranchRegex: d.Get(fmt.Sprintf("spec.0.trigger.%v.branch_regex", idx)).(string), - BranchRegexInput: d.Get(fmt.Sprintf("spec.0.trigger.%v.branch_regex_input", idx)).(string), - PullRequestTargetBranchRegex: d.Get(fmt.Sprintf("spec.0.trigger.%v.pull_request_target_branch_regex", idx)).(string), - CommentRegex: d.Get(fmt.Sprintf("spec.0.trigger.%v.comment_regex", idx)).(string), - ModifiedFilesGlob: d.Get(fmt.Sprintf("spec.0.trigger.%v.modified_files_glob", idx)).(string), - Provider: d.Get(fmt.Sprintf("spec.0.trigger.%v.provider", idx)).(string), - Disabled: d.Get(fmt.Sprintf("spec.0.trigger.%v.disabled", idx)).(bool), - PullRequestAllowForkEvents: d.Get(fmt.Sprintf("spec.0.trigger.%v.pull_request_allow_fork_events", idx)).(bool), - CommitStatusTitle: d.Get(fmt.Sprintf("spec.0.trigger.%v.commit_status_title", idx)).(string), - Context: d.Get(fmt.Sprintf("spec.0.trigger.%v.context", idx)).(string), - Contexts: convertStringArr(contexts), - Events: convertStringArr(events), - } - variables := d.Get(fmt.Sprintf("spec.0.trigger.%v.variables", idx)).(map[string]interface{}) - codefreshTrigger.SetVariables(variables) - if _, ok := d.GetOk(fmt.Sprintf("spec.0.trigger.%v.options", idx)); ok { - options := cfClient.TriggerOptions{ - NoCache: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.no_cache", idx)).(bool), - NoCfCache: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.no_cf_cache", idx)).(bool), - ResetVolume: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.reset_volume", idx)).(bool), - EnableNotifications: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.enable_notifications", idx)).(bool), + if contexts, ok := d.GetOk("spec.0.contexts"); ok { + pipeline.Spec.Contexts = contexts.([]interface{}) + } + + if variables, ok := d.GetOk("spec.0.variables"); ok { + pipeline.SetVariables(variables.(map[string]interface{})) + } + + if triggers, ok := d.GetOk("spec.0.trigger"); ok { + for idx := range triggers.([]interface{}) { + events := d.Get(fmt.Sprintf("spec.0.trigger.%v.events", idx)).([]interface{}) + contexts := d.Get(fmt.Sprintf("spec.0.trigger.%v.contexts", idx)).([]interface{}) + codefreshTrigger := cfClient.Trigger{ + Name: d.Get(fmt.Sprintf("spec.0.trigger.%v.name", idx)).(string), + Description: d.Get(fmt.Sprintf("spec.0.trigger.%v.description", idx)).(string), + Type: d.Get(fmt.Sprintf("spec.0.trigger.%v.type", idx)).(string), + Repo: d.Get(fmt.Sprintf("spec.0.trigger.%v.repo", idx)).(string), + BranchRegex: d.Get(fmt.Sprintf("spec.0.trigger.%v.branch_regex", idx)).(string), + BranchRegexInput: d.Get(fmt.Sprintf("spec.0.trigger.%v.branch_regex_input", idx)).(string), + PullRequestTargetBranchRegex: d.Get(fmt.Sprintf("spec.0.trigger.%v.pull_request_target_branch_regex", idx)).(string), + CommentRegex: d.Get(fmt.Sprintf("spec.0.trigger.%v.comment_regex", idx)).(string), + ModifiedFilesGlob: d.Get(fmt.Sprintf("spec.0.trigger.%v.modified_files_glob", idx)).(string), + Provider: d.Get(fmt.Sprintf("spec.0.trigger.%v.provider", idx)).(string), + Disabled: d.Get(fmt.Sprintf("spec.0.trigger.%v.disabled", idx)).(bool), + PullRequestAllowForkEvents: d.Get(fmt.Sprintf("spec.0.trigger.%v.pull_request_allow_fork_events", idx)).(bool), + CommitStatusTitle: d.Get(fmt.Sprintf("spec.0.trigger.%v.commit_status_title", idx)).(string), + Context: d.Get(fmt.Sprintf("spec.0.trigger.%v.context", idx)).(string), + Contexts: convertStringArr(contexts), + Events: convertStringArr(events), } - codefreshTrigger.Options = &options + variables := d.Get(fmt.Sprintf("spec.0.trigger.%v.variables", idx)).(map[string]interface{}) + codefreshTrigger.SetVariables(variables) + if _, ok := d.GetOk(fmt.Sprintf("spec.0.trigger.%v.options", idx)); ok { + options := cfClient.TriggerOptions{ + NoCache: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.no_cache", idx)).(bool), + NoCfCache: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.no_cf_cache", idx)).(bool), + ResetVolume: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.reset_volume", idx)).(bool), + EnableNotifications: d.Get(fmt.Sprintf("spec.0.trigger.%v.options.0.enable_notifications", idx)).(bool), + } + codefreshTrigger.Options = &options + } + if _, ok := d.GetOk(fmt.Sprintf("spec.0.trigger.%v.runtime_environment", idx)); ok { + triggerRuntime := cfClient.RuntimeEnvironment{ + Name: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.name", idx)).(string), + Memory: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.memory", idx)).(string), + CPU: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.cpu", idx)).(string), + DindStorage: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.dind_storage", idx)).(string), + RequiredAvailableStorage: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.required_available_storage", idx)).(string), + } + codefreshTrigger.RuntimeEnvironment = &triggerRuntime + } + pipeline.Spec.Triggers = append(pipeline.Spec.Triggers, codefreshTrigger) } - if _, ok := d.GetOk(fmt.Sprintf("spec.0.trigger.%v.runtime_environment", idx)); ok { - triggerRuntime := cfClient.RuntimeEnvironment{ - Name: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.name", idx)).(string), - Memory: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.memory", idx)).(string), - CPU: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.cpu", idx)).(string), - DindStorage: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.dind_storage", idx)).(string), - RequiredAvailableStorage: d.Get(fmt.Sprintf("spec.0.trigger.%v.runtime_environment.0.required_available_storage", idx)).(string), + } + + if cronTriggers, ok := d.GetOk("spec.0.cron_trigger"); ok { + for idx := range cronTriggers.([]interface{}) { + codefreshCronTrigger := cfClient.CronTrigger{ + Name: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.name", idx)).(string), + Type: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.type", idx)).(string), + Expression: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.expression", idx)).(string), + Message: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.message", idx)).(string), + Disabled: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.disabled", idx)).(bool), + GitTriggerId: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.git_trigger_id", idx)).(string), + Branch: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.branch", idx)).(string), + } + variables := d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.variables", idx)).(map[string]interface{}) + codefreshCronTrigger.SetVariables(variables) + if _, ok := d.GetOk(fmt.Sprintf("spec.0.cron_trigger.%v.options", idx)); ok { + options := cfClient.TriggerOptions{ + NoCache: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.options.0.no_cache", idx)).(bool), + NoCfCache: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.options.0.no_cf_cache", idx)).(bool), + ResetVolume: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.options.0.reset_volume", idx)).(bool), + EnableNotifications: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.options.0.enable_notifications", idx)).(bool), + } + codefreshCronTrigger.Options = &options + } + if _, ok := d.GetOk(fmt.Sprintf("spec.0.cron_trigger.%v.runtime_environment", idx)); ok { + triggerRuntime := cfClient.RuntimeEnvironment{ + Name: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.runtime_environment.0.name", idx)).(string), + Memory: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.runtime_environment.0.memory", idx)).(string), + CPU: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.runtime_environment.0.cpu", idx)).(string), + DindStorage: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.runtime_environment.0.dind_storage", idx)).(string), + RequiredAvailableStorage: d.Get(fmt.Sprintf("spec.0.cron_trigger.%v.runtime_environment.0.required_available_storage", idx)).(string), + } + codefreshCronTrigger.RuntimeEnvironment = &triggerRuntime } - codefreshTrigger.RuntimeEnvironment = &triggerRuntime + pipeline.Spec.CronTriggers = append(pipeline.Spec.CronTriggers, codefreshCronTrigger) } - pipeline.Spec.Triggers = append(pipeline.Spec.Triggers, codefreshTrigger) } var codefreshTerminationPolicy []map[string]interface{} diff --git a/codefresh/resource_pipeline_cron_trigger.go b/codefresh/resource_pipeline_cron_trigger.go index 1340a15..6e5933b 100644 --- a/codefresh/resource_pipeline_cron_trigger.go +++ b/codefresh/resource_pipeline_cron_trigger.go @@ -16,6 +16,7 @@ import ( func resourcePipelineCronTrigger() *schema.Resource { return &schema.Resource{ + DeprecationMessage: "This resource is deprecated and will be removed in a future version of the Codefresh Terraform provider. Please use the cron_triggers attribute of the codefresh_pipeline resource instead.", Description: "This resource is used to create cron-based triggers for pipeilnes.", Create: resourcePipelineCronTriggerCreate, Read: resourcePipelineCronTriggerRead, diff --git a/codefresh/resource_pipeline_test.go b/codefresh/resource_pipeline_test.go index 440f4fe..cb14c20 100644 --- a/codefresh/resource_pipeline_test.go +++ b/codefresh/resource_pipeline_test.go @@ -406,6 +406,125 @@ func TestAccCodefreshPipeline_Triggers(t *testing.T) { }) } +func TestAccCodefreshPipeline_CronTriggers(t *testing.T) { + name := pipelineNamePrefix + acctest.RandString(10) + resourceName := "codefresh_pipeline.test" + var pipeline cfClient.Pipeline + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCodefreshPipelineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCodefreshPipelineBasicConfigCronTriggers( + name, + "codefresh-contrib/react-sample-app", + "./codefresh.yml", + "master", + "git", + "cT1", + "first", + "0 0/1 * 1/1 * *", + "64abd1550f02a62699b10df7", + "runtime1", + "100mb", + "1cpu", + "1gb", + "1gb", + "cT2", + "second", + "0 0/1 * 1/1 * *", + "64abd1550f02a62699b10df7", + true, + true, + true, + true, + "MY_VAR", + "test", + ), + Check: resource.ComposeTestCheckFunc( + testAccCheckCodefreshPipelineExists(resourceName, &pipeline), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.name", "cT1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.message", "first"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.expression", "0 0/1 * 1/1 * *"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.name", "runtime1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.memory", "100mb"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.cpu", "1cpu"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.dind_storage", "1gb"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.required_available_storage", "1gb"), + + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.name", "cT2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.message", "second"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.expression", "0 0/1 * 1/1 * *"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.git_trigger_id", "64abd1550f02a62699b10df7"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.no_cache", "true"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.no_cf_cache", "true"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.reset_volume", "true"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.enable_notifications", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccCodefreshPipelineBasicConfigCronTriggers( + name, + "codefresh-contrib/react-sample-app", + "./codefresh.yml", + "master", + "git", + "cT1", + "first-1", + "0 0/1 * 1/1 * *", + "00abd1550f02a62699b10df7", + "runtime2", + "500mb", + "2cpu", + "2gb", + "3gb", + "cT2", + "second", + "0 1/1 * 1/1 * *", + "00abd1550f02a62699b10df7", + true, + true, + false, + false, + "MY_VAR", + "test", + ), + Check: resource.ComposeTestCheckFunc( + testAccCheckCodefreshPipelineExists(resourceName, &pipeline), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.name", "cT1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.message", "first-1"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.expression", "0 0/1 * 1/1 * *"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.name", "runtime2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.memory", "500mb"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.cpu", "2cpu"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.dind_storage", "2gb"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.0.runtime_environment.0.required_available_storage", "3gb"), + + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.#", "2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.name", "cT2"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.message", "second"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.expression", "0 1/1 * 1/1 * *"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.git_trigger_id", "00abd1550f02a62699b10df7"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.no_cache", "true"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.no_cf_cache", "true"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.reset_volume", "false"), + resource.TestCheckResourceAttr(resourceName, "spec.0.cron_trigger.1.options.0.enable_notifications", "false"), + ), + }, + }, + }) +} + func TestAccCodefreshPipeline_Revision(t *testing.T) { name := pipelineNamePrefix + acctest.RandString(10) resourceName := "codefresh_pipeline.test" @@ -901,6 +1020,116 @@ resource "codefresh_pipeline" "test" { trigger2CommitStatusTitle) } +func testAccCodefreshPipelineBasicConfigCronTriggers( + rName, + repo, + path, + revision, + context, + cronTrigger1Name string, + cronTrigger1Message string, + cronTrigger1Expression string, + cronTrigger1GitTriggerId string, + cronTrigger1REName string, + cronTrigger1REMemory string, + cronTrigger1RECpu string, + cronTrigger1REDindStorage string, + cronTrigger1RERequiredAvailableStorage string, + cronTrigger2Name string, + cronTrigger2Message string, + cronTrigger2Expression string, + cronTrigger2GitTriggerId string, + cronTrigger2NoCache bool, + cronTrigger2NoCfCache bool, + cronTrigger2ResetVolume bool, + cronTrigger2EnableNotifications bool, + cronTrigger2VarName string, + cronTrigger2VarValue string, +) string { + return fmt.Sprintf(` +resource "codefresh_pipeline" "test" { + + lifecycle { + ignore_changes = [ + revision + ] + } + + name = "%s" + + spec { + spec_template { + repo = %q + path = %q + revision = %q + context = %q + } + + cron_trigger { + name = %q + type = "cron" + branch = "main" + message = %q + expression = %q + git_trigger_id = %q + disabled = true + runtime_environment { + name = %q + memory = %q + cpu = %q + dind_storage = %q + required_available_storage = %q + } + } + + cron_trigger { + name = %q + type = "cron" + branch = "master" + message = %q + expression = %q + git_trigger_id = %q + disabled = false + options { + no_cache = %t + no_cf_cache = %t + reset_volume = %t + enable_notifications = %t + } + variables = { + %q = %q + } + } + } +} +`, + rName, + repo, + path, + revision, + context, + cronTrigger1Name, + cronTrigger1Message, + cronTrigger1Expression, + cronTrigger1GitTriggerId, + cronTrigger1REName, + cronTrigger1REMemory, + cronTrigger1RECpu, + cronTrigger1REDindStorage, + cronTrigger1RERequiredAvailableStorage, + cronTrigger2Name, + cronTrigger2Message, + cronTrigger2Expression, + cronTrigger2GitTriggerId, + cronTrigger2NoCache, + cronTrigger2NoCfCache, + cronTrigger2ResetVolume, + cronTrigger2EnableNotifications, + cronTrigger2VarName, + cronTrigger2VarValue, + ) +} + func testAccCodefreshPipelineBasicConfigRuntimeEnvironment(rName, repo, path, revision, context, runtimeName string) string { return fmt.Sprintf(` resource "codefresh_pipeline" "test" { diff --git a/docs/resources/pipeline.md b/docs/resources/pipeline.md index dca0922..d4468aa 100644 --- a/docs/resources/pipeline.md +++ b/docs/resources/pipeline.md @@ -11,6 +11,8 @@ The central component of the Codefresh Platform. Pipelines are workflows that co See the [documentation](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for the details. +~> **NOTE:** `cron_trigger` conflicts with the deprecated [codefresh_pipeline_cron_trigger](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline_cron_trigger) resource. + ## Example Usage ```hcl @@ -125,6 +127,7 @@ Optional: - `branch_concurrency` (Number) The maximum amount of concurrent builds that may run for each branch. Zero is unlimited (default: `0`). - `concurrency` (Number) The maximum amount of concurrent builds. Zero is unlimited (default: `0`). - `contexts` (List of String) A list of strings representing the contexts ([shared_configuration](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/shared-configuration/)) to be configured for the pipeline. +- `cron_trigger` (Block List) The pipeline's cron triggers. Conflicts with the deprecated [codefresh_pipeline_cron_trigger](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline_cron_trigger) resource. (see [below for nested schema](#nestedblock--spec--cron_trigger)) - `options` (Block List, Max: 1) The options for the pipeline. (see [below for nested schema](#nestedblock--spec--options)) - `pack_id` (String) SAAS pack (`5cd1746617313f468d669013` for Small; `5cd1746717313f468d669014` for Medium; `5cd1746817313f468d669015` for Large; `5cd1746817313f468d669017` for XL; `5cd1746817313f468d669018` for XXL). - `priority` (Number) Helps to organize the order of builds execution in case of reaching the concurrency limit (default: `0`). @@ -136,6 +139,49 @@ Optional: - `trigger_concurrency` (Number) The maximum amount of concurrent builds that may run for each trigger (default: `0`). - `variables` (Map of String) The pipeline's variables. + +### Nested Schema for `spec.cron_trigger` + +Required: + +- `expression` (String) +- `message` (String) +- `name` (String) The name of the cron trigger. + +Optional: + +- `branch` (String) Branch that should be passed for build triggered by this cron trigger. +- `disabled` (Boolean) Flag to disable the trigger. +- `git_trigger_id` (String) Related git-trigger id. Will by used to take all possible git information by branch. +- `options` (Block List) The trigger's options. (see [below for nested schema](#nestedblock--spec--cron_trigger--options)) +- `runtime_environment` (Block List) The runtime environment for the trigger. (see [below for nested schema](#nestedblock--spec--cron_trigger--runtime_environment)) +- `type` (String) The type of the trigger (default: `cron`; see notes above). +- `variables` (Map of String) Trigger variables. + + +### Nested Schema for `spec.cron_trigger.options` + +Optional: + +- `enable_notifications` (Boolean) If false the pipeline will not send notifications to Slack and status updates back to the Git provider. +- `no_cache` (Boolean) If true, docker layer cache is disabled. +- `no_cf_cache` (Boolean) If true, extra Codefresh caching is disabled. +- `reset_volume` (Boolean) If true, all files on volume will be deleted before each execution. + + + +### Nested Schema for `spec.cron_trigger.runtime_environment` + +Optional: + +- `cpu` (String) The CPU allocated to the runtime environment. +- `dind_storage` (String) The storage allocated to the runtime environment. +- `memory` (String) The memory allocated to the runtime environment. +- `name` (String) The name of the runtime environment. +- `required_available_storage` (String) Minimum disk space required for build filesystem ( unit Gi is required). + + + ### Nested Schema for `spec.options` diff --git a/docs/resources/pipeline_cron_trigger.md b/docs/resources/pipeline_cron_trigger.md index 7002753..8e7de7c 100644 --- a/docs/resources/pipeline_cron_trigger.md +++ b/docs/resources/pipeline_cron_trigger.md @@ -11,6 +11,8 @@ This resource is used to create cron-based triggers for pipeilnes. See the [documentation](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/triggers/cron-triggers/). +~> **DEPRECATED:** This resource is being deprecated in favor of the `cron_trigger` attribute of the [codefresh_pipeline](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline) resource. + ## Example usage ```hcl diff --git a/templates/resources/pipeline.md.tmpl b/templates/resources/pipeline.md.tmpl index 055da96..0f5ed90 100644 --- a/templates/resources/pipeline.md.tmpl +++ b/templates/resources/pipeline.md.tmpl @@ -11,6 +11,8 @@ description: |- See the [documentation](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for the details. +~> **NOTE:** `cron_trigger` conflicts with the deprecated [codefresh_pipeline_cron_trigger](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline_cron_trigger) resource. + ## Example Usage ```hcl diff --git a/templates/resources/pipeline_cron_trigger.md.tmpl b/templates/resources/pipeline_cron_trigger.md.tmpl index 80a70eb..ad05ed8 100644 --- a/templates/resources/pipeline_cron_trigger.md.tmpl +++ b/templates/resources/pipeline_cron_trigger.md.tmpl @@ -11,6 +11,8 @@ description: |- See the [documentation](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/triggers/cron-triggers/). +~> **DEPRECATED:** This resource is being deprecated in favor of the `cron_trigger` attribute of the [codefresh_pipeline](https://registry.terraform.io/providers/codefresh-io/codefresh/latest/docs/resources/pipeline) resource. + ## Example usage ```hcl