From 2fcca2fd30098d3ef43cf5993c34dbd3c5dd5d8e Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Mon, 1 Feb 2021 11:28:57 +1100 Subject: [PATCH] resource/cloudflare_worker_cron_trigger: Add support Introduces support for Worker Cron Triggers API: https://api.cloudflare.com/#worker-cron-trigger-properties Documentation: https://developers.cloudflare.com/workers/platform/cron-triggers Closes #853 --- cloudflare/provider.go | 1 + ...resource_cloudflare_worker_cron_trigger.go | 109 ++++++++++++++++++ ...rce_cloudflare_worker_cron_trigger_test.go | 46 ++++++++ website/cloudflare.erb | 3 + .../docs/r/worker_cron_trigger.html.markdown | 56 +++++++++ 5 files changed, 215 insertions(+) create mode 100644 cloudflare/resource_cloudflare_worker_cron_trigger.go create mode 100644 cloudflare/resource_cloudflare_worker_cron_trigger_test.go create mode 100644 website/docs/r/worker_cron_trigger.html.markdown diff --git a/cloudflare/provider.go b/cloudflare/provider.go index 1ab68863c9..6b41ab0315 100644 --- a/cloudflare/provider.go +++ b/cloudflare/provider.go @@ -142,6 +142,7 @@ func Provider() terraform.ResourceProvider { "cloudflare_waf_package": resourceCloudflareWAFPackage(), "cloudflare_waf_rule": resourceCloudflareWAFRule(), "cloudflare_waf_override": resourceCloudflareWAFOverride(), + "cloudflare_worker_cron_trigger": resourceCloudflareWorkerCronTrigger(), "cloudflare_worker_route": resourceCloudflareWorkerRoute(), "cloudflare_worker_script": resourceCloudflareWorkerScript(), "cloudflare_workers_kv": resourceCloudflareWorkerKV(), diff --git a/cloudflare/resource_cloudflare_worker_cron_trigger.go b/cloudflare/resource_cloudflare_worker_cron_trigger.go new file mode 100644 index 0000000000..8662535714 --- /dev/null +++ b/cloudflare/resource_cloudflare_worker_cron_trigger.go @@ -0,0 +1,109 @@ +package cloudflare + +import ( + "context" + "fmt" + + "github.com/cloudflare/cloudflare-go" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func resourceCloudflareWorkerCronTrigger() *schema.Resource { + return &schema.Resource{ + Create: resourceCloudflareWorkerCronTriggerUpdate, + Read: resourceCloudflareWorkerCronTriggerRead, + Update: resourceCloudflareWorkerCronTriggerUpdate, + Delete: resourceCloudflareWorkerCronTriggerDelete, + Importer: &schema.ResourceImporter{ + State: resourceCloudflareWorkerCronTriggerImport, + }, + + Schema: map[string]*schema.Schema{ + "script_name": { + Type: schema.TypeString, + Required: true, + }, + "schedules": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +// resourceCloudflareWorkerCronTriggerUpdate is used for creation and updates of +// Worker Cron Triggers as the remote API endpoint is shared uses HTTP PUT. +func resourceCloudflareWorkerCronTriggerUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*cloudflare.API) + + scriptName := d.Get("script_name").(string) + + _, err := client.UpdateWorkerCronTriggers(context.Background(), scriptName, transformSchemaToWorkerCronTriggerStruct(d)) + if err != nil { + return fmt.Errorf("failed to update Worker Cron Trigger: %s", err) + } + + d.SetId(stringChecksum(scriptName)) + + return nil +} + +func resourceCloudflareWorkerCronTriggerRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*cloudflare.API) + scriptName := d.Get("script_name").(string) + + s, err := client.ListWorkerCronTriggers(context.Background(), scriptName) + if err != nil { + return fmt.Errorf("failed to read Worker Cron Trigger: %s", err) + } + + if err := d.Set("schedules", transformWorkerCronTriggerStructToSet(s)); err != nil { + return fmt.Errorf("failed to set schedules attribute: %s", err) + } + + return nil +} + +func resourceCloudflareWorkerCronTriggerDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*cloudflare.API) + scriptName := d.Get("script_name").(string) + + client.UpdateWorkerCronTriggers(context.Background(), scriptName, []cloudflare.WorkerCronTrigger{}) + + d.SetId("") + + return nil +} + +func resourceCloudflareWorkerCronTriggerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + d.SetId(stringChecksum(d.Id())) + + resourceCloudflareWorkerCronTriggerRead(d, meta) + + return []*schema.ResourceData{d}, nil +} + +func transformWorkerCronTriggerStructToSet(triggers []cloudflare.WorkerCronTrigger) *schema.Set { + returnSet := schema.NewSet(schema.HashString, []interface{}{}) + + for _, trigger := range triggers { + returnSet.Add(trigger.Cron) + } + + return returnSet +} + +func transformSchemaToWorkerCronTriggerStruct(d *schema.ResourceData) []cloudflare.WorkerCronTrigger { + triggers := []cloudflare.WorkerCronTrigger{} + schedules := d.Get("schedules").(*schema.Set).List() + + for _, schedule := range schedules { + triggers = append(triggers, cloudflare.WorkerCronTrigger{Cron: schedule.(string)}) + } + + return triggers +} diff --git a/cloudflare/resource_cloudflare_worker_cron_trigger_test.go b/cloudflare/resource_cloudflare_worker_cron_trigger_test.go new file mode 100644 index 0000000000..8f58ee263f --- /dev/null +++ b/cloudflare/resource_cloudflare_worker_cron_trigger_test.go @@ -0,0 +1,46 @@ +package cloudflare + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccCloudflareWorkerCronTriggerBasic(t *testing.T) { + rnd := generateRandomResourceName() + name := fmt.Sprintf("cloudflare_worker_cron_trigger.%s", rnd) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccessAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCloudflareWorkerCronTriggerConfigBasic(rnd), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "script_name", rnd), + resource.TestCheckResourceAttr(name, "schedules.#", "2"), + ), + }, + }, + }) +} + +func testAccCloudflareWorkerCronTriggerConfigBasic(rnd string) string { + return fmt.Sprintf(` +resource "cloudflare_worker_script" "%[1]s" { + name = "%[1]s" + content = "addEventListener('fetch', event => {event.respondWith(new Response('test'))});" +} + +resource "cloudflare_worker_cron_trigger" "%[1]s" { + script_name = cloudflare_worker_script.%[1]s.name + schedules = [ + "*/5 * * * *", # every 5 minutes + "10 7 * * mon-fri", # 7:10am every weekday + ] +} +`, rnd) +} diff --git a/website/cloudflare.erb b/website/cloudflare.erb index 8632a4a262..367942c3b5 100644 --- a/website/cloudflare.erb +++ b/website/cloudflare.erb @@ -151,6 +151,9 @@ > cloudflare_waf_rule + > + cloudflare_worker_cron_trigger + > cloudflare_worker_route diff --git a/website/docs/r/worker_cron_trigger.html.markdown b/website/docs/r/worker_cron_trigger.html.markdown new file mode 100644 index 0000000000..b34093c34c --- /dev/null +++ b/website/docs/r/worker_cron_trigger.html.markdown @@ -0,0 +1,56 @@ +--- +layout: "cloudflare" +page_title: "Cloudflare: cloudflare_worker_cron_trigger" +sidebar_current: "docs-cloudflare-resource-worker-cron-trigger" +description: |- + Provides a Cloudflare Worker Cron Trigger resource. +--- + +# cloudflare_worker_cron_trigger + +Worker Cron Triggers allow users to map a cron expression to a Worker script +using a `ScheduledEvent` listener that enables Workers to be executed on a +schedule. Worker Cron Triggers are ideal for running periodic jobs for +maintenance or calling third-party APIs to collect up-to-date data. + +## Example Usage + +```hcl +resource "cloudflare_worker_script" "example_script" { + name = "example-script" + content = file("path/to/my.js") +} + +resource "cloudflare_worker_cron_trigger" "example_trigger" { + script_name = cloudflare_worker_script.example_script.name + schedules = [ + "*/5 * * * *", # every 5 minutes + "10 7 * * mon-fri", # 7:10am every weekday + ] +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `script_name` - (Required) Worker script to target for the schedules +* `schedules` - (Required) List of cron expressions to execute the Worker Script + +## Attributes Reference + +The following additional attributes are exported: + +* `id` - md5 checksum of the script name +* `script_name` - Name of the Worker Script being targeted +* `schedules` - List of cron expressions in use + +## Import + +Worker Cron Triggers can be imported using the script name of the Worker they +are targeting. + +``` +$ terraform import cloudflare_worker_cron_trigger.example my-script +```