Skip to content

Commit

Permalink
Merge pull request #926 from cloudflare/worker-cron-triggers-support
Browse files Browse the repository at this point in the history
resource/cloudflare_worker_cron_trigger: Add initial support
  • Loading branch information
jacobbednarz authored Feb 1, 2021
2 parents 126a0be + 2fcca2f commit 28fad82
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 0 deletions.
1 change: 1 addition & 0 deletions cloudflare/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
109 changes: 109 additions & 0 deletions cloudflare/resource_cloudflare_worker_cron_trigger.go
Original file line number Diff line number Diff line change
@@ -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
}
46 changes: 46 additions & 0 deletions cloudflare/resource_cloudflare_worker_cron_trigger_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
3 changes: 3 additions & 0 deletions website/cloudflare.erb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@
<li<%= sidebar_current("docs-cloudflare-resource-waf-rule") %>>
<a href="/docs/providers/cloudflare/r/waf_rule.html">cloudflare_waf_rule</a>
</li>
<li<%= sidebar_current("docs-cloudflare-resource-worker-cron-trigger") %>>
<a href="/docs/providers/cloudflare/r/worker_cron_trigger.html">cloudflare_worker_cron_trigger</a>
</li>
<li<%= sidebar_current("docs-cloudflare-resource-worker-route") %>>
<a href="/docs/providers/cloudflare/r/worker_route.html">cloudflare_worker_route</a>
</li>
Expand Down
56 changes: 56 additions & 0 deletions website/docs/r/worker_cron_trigger.html.markdown
Original file line number Diff line number Diff line change
@@ -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
```

0 comments on commit 28fad82

Please sign in to comment.