Skip to content

Commit 560e2dd

Browse files
authored
feat(container): add trigger resource (#2036)
* feat(container): add trigger resource * add doc * fix return
1 parent caaf6d8 commit 560e2dd

6 files changed

+2797
-0
lines changed

docs/resources/container_trigger.md

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
subcategory: "Containers"
3+
page_title: "Scaleway: scaleway_container_trigger"
4+
---
5+
6+
# scaleway_container_trigger
7+
8+
Creates and manages Scaleway Container Triggers.
9+
For more information see [the documentation](https://www.scaleway.com/en/developers/api/serverless-containers/#path-triggers).
10+
11+
## Examples
12+
13+
### Basic
14+
15+
```hcl
16+
resource scaleway_container_trigger main {
17+
container_id = scaleway_container.main.id
18+
name = "my-trigger"
19+
sqs {
20+
namespace_id = scaleway_mnq_namespace.main.id
21+
queue = "MyQueue"
22+
# If project or region is different
23+
project_id = scaleway_mnq_namespace.main.project_id
24+
region = scaleway_mnq_namespace.main.region
25+
}
26+
}
27+
```
28+
29+
## Arguments Reference
30+
31+
The following arguments are supported:
32+
33+
- `container_id` (Required) The ID of the container to create a trigger for
34+
35+
- `name` - (Optional) The unique name of the trigger. Default to a generated name.
36+
37+
- `description` (Optional) The description of the trigger.
38+
39+
- `sqs` The configuration of the Scaleway's SQS used by the trigger
40+
- `namespace_id` (Required) ID of the mnq namespace
41+
- `queue` (Required) Name of the queue
42+
- `project_id` (Optional) ID of the project that contain the mnq namespace, defaults to provider's project
43+
- `region` (Optional) Region where the mnq namespace is, defaults to provider's region
44+
45+
- `region` - (Defaults to [provider](../index.md#region) `region`). The [region](../guides/regions_and_zones.md#regions) in which the namespace should be created.
46+
47+
48+
## Attributes Reference
49+
50+
In addition to all arguments above, the following attributes are exported:
51+
52+
- `id` - The ID of the container trigger
53+
54+
- ~> **Important:** Container Triggers' IDs are [regional](../guides/regions_and_zones.md#resource-ids), which means they are of the form `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111`
55+
56+
## Import
57+
58+
Container Triggers can be imported using the `{region}/{id}`, e.g.
59+
60+
```bash
61+
$ terraform import scaleway_container_trigger.main fr-par/11111111-1111-1111-1111-111111111111
62+
```
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package scaleway
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
container "github.com/scaleway/scaleway-sdk-go/api/container/v1beta1"
10+
"github.com/scaleway/scaleway-sdk-go/scw"
11+
)
12+
13+
func waitForContainerTrigger(ctx context.Context, containerAPI *container.API, region scw.Region, id string, timeout time.Duration) (*container.Trigger, error) {
14+
retryInterval := defaultFunctionRetryInterval
15+
if DefaultWaitRetryInterval != nil {
16+
retryInterval = *DefaultWaitRetryInterval
17+
}
18+
19+
trigger, err := containerAPI.WaitForTrigger(&container.WaitForTriggerRequest{
20+
Region: region,
21+
TriggerID: id,
22+
RetryInterval: &retryInterval,
23+
Timeout: scw.TimeDurationPtr(timeout),
24+
}, scw.WithContext(ctx))
25+
26+
return trigger, err
27+
}
28+
29+
func expandContainerTriggerMnqSqsCreationConfig(i interface{}) *container.CreateTriggerRequestMnqSqsClientConfig {
30+
m := i.(map[string]interface{})
31+
32+
return &container.CreateTriggerRequestMnqSqsClientConfig{
33+
MnqNamespaceID: expandID(m["namespace_id"].(string)),
34+
Queue: m["queue"].(string),
35+
MnqProjectID: m["project_id"].(string),
36+
MnqRegion: m["region"].(string),
37+
}
38+
}
39+
40+
func completeContainerTriggerMnqSqsCreationConfig(i interface{}, d *schema.ResourceData, meta interface{}, region scw.Region) error {
41+
m := i.(map[string]interface{})
42+
43+
if sqsRegion, exists := m["region"]; !exists || sqsRegion == "" {
44+
m["region"] = region.String()
45+
}
46+
47+
if projectID, exists := m["project_id"]; !exists || projectID == "" {
48+
projectID, _, err := extractProjectID(d, meta.(*Meta))
49+
if err != nil {
50+
return fmt.Errorf("failed to find a valid project_id")
51+
}
52+
m["project_id"] = projectID
53+
}
54+
55+
return nil
56+
}

scaleway/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
9494
"scaleway_container_namespace": resourceScalewayContainerNamespace(),
9595
"scaleway_container_cron": resourceScalewayContainerCron(),
9696
"scaleway_container_domain": resourceScalewayContainerDomain(),
97+
"scaleway_container_trigger": resourceScalewayContainerTrigger(),
9798
"scaleway_domain_record": resourceScalewayDomainRecord(),
9899
"scaleway_domain_zone": resourceScalewayDomainZone(),
99100
"scaleway_flexible_ip": resourceScalewayFlexibleIP(),
+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package scaleway
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
container "github.com/scaleway/scaleway-sdk-go/api/container/v1beta1"
10+
"github.com/scaleway/scaleway-sdk-go/scw"
11+
)
12+
13+
func resourceScalewayContainerTrigger() *schema.Resource {
14+
return &schema.Resource{
15+
CreateContext: resourceScalewayContainerTriggerCreate,
16+
ReadContext: resourceScalewayContainerTriggerRead,
17+
UpdateContext: resourceScalewayContainerTriggerUpdate,
18+
DeleteContext: resourceScalewayContainerTriggerDelete,
19+
Importer: &schema.ResourceImporter{
20+
StateContext: schema.ImportStatePassthroughContext,
21+
},
22+
Timeouts: &schema.ResourceTimeout{
23+
Default: schema.DefaultTimeout(defaultFunctionTimeout),
24+
Read: schema.DefaultTimeout(defaultFunctionTimeout),
25+
Update: schema.DefaultTimeout(defaultFunctionTimeout),
26+
Delete: schema.DefaultTimeout(defaultFunctionTimeout),
27+
Create: schema.DefaultTimeout(defaultFunctionTimeout),
28+
},
29+
SchemaVersion: 0,
30+
Schema: map[string]*schema.Schema{
31+
"container_id": {
32+
Type: schema.TypeString,
33+
Required: true,
34+
Description: "The ID of the container to create a trigger for",
35+
ValidateFunc: validationUUIDorUUIDWithLocality(),
36+
},
37+
"name": {
38+
Type: schema.TypeString,
39+
Computed: true,
40+
Optional: true,
41+
Description: "The trigger name",
42+
},
43+
"description": {
44+
Type: schema.TypeString,
45+
Optional: true,
46+
Description: "The trigger description",
47+
},
48+
"sqs": {
49+
Type: schema.TypeList,
50+
MaxItems: 1,
51+
Description: "Config for sqs based trigger using scaleway mnq",
52+
Optional: true,
53+
ForceNew: true,
54+
Elem: &schema.Resource{
55+
Schema: map[string]*schema.Schema{
56+
"namespace_id": {
57+
Required: true,
58+
Type: schema.TypeString,
59+
Description: "ID of the mnq namespace",
60+
DiffSuppressFunc: diffSuppressFuncLocality,
61+
},
62+
"queue": {
63+
Required: true,
64+
Type: schema.TypeString,
65+
Description: "Name of the queue",
66+
},
67+
"project_id": {
68+
Computed: true,
69+
Optional: true,
70+
Type: schema.TypeString,
71+
Description: "Project ID of the project where the mnq sqs exists, defaults to provider project_id",
72+
},
73+
"region": {
74+
Computed: true,
75+
Optional: true,
76+
Type: schema.TypeString,
77+
Description: "Region where the mnq sqs exists, defaults to function's region",
78+
},
79+
},
80+
},
81+
},
82+
"region": regionSchema(),
83+
},
84+
CustomizeDiff: customizeDiffLocalityCheck("container_id"),
85+
}
86+
}
87+
88+
func resourceScalewayContainerTriggerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
89+
api, region, err := containerAPIWithRegion(d, meta)
90+
if err != nil {
91+
return diag.FromErr(err)
92+
}
93+
94+
req := &container.CreateTriggerRequest{
95+
Region: region,
96+
Name: expandOrGenerateString(d.Get("name").(string), "trigger"),
97+
ContainerID: expandID(d.Get("container_id")),
98+
Description: expandStringPtr(d.Get("description")),
99+
}
100+
101+
if scwSqs, isScwSqs := d.GetOk("sqs.0"); isScwSqs {
102+
err := completeContainerTriggerMnqSqsCreationConfig(scwSqs, d, meta, region)
103+
if err != nil {
104+
return diag.FromErr(fmt.Errorf("failed to complete sqs config: %w", err))
105+
}
106+
107+
_ = d.Set("sqs", []any{scwSqs})
108+
req.ScwSqsConfig = expandContainerTriggerMnqSqsCreationConfig(scwSqs)
109+
}
110+
111+
trigger, err := api.CreateTrigger(req, scw.WithContext(ctx))
112+
if err != nil {
113+
return diag.FromErr(err)
114+
}
115+
116+
d.SetId(newRegionalIDString(region, trigger.ID))
117+
118+
_, err = waitForContainerTrigger(ctx, api, region, trigger.ID, d.Timeout(schema.TimeoutCreate))
119+
if err != nil {
120+
return diag.FromErr(err)
121+
}
122+
123+
return resourceScalewayContainerTriggerRead(ctx, d, meta)
124+
}
125+
126+
func resourceScalewayContainerTriggerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
127+
api, region, id, err := containerAPIWithRegionAndID(meta, d.Id())
128+
if err != nil {
129+
return diag.FromErr(err)
130+
}
131+
132+
trigger, err := waitForContainerTrigger(ctx, api, region, id, d.Timeout(schema.TimeoutRead))
133+
if err != nil {
134+
if is404Error(err) {
135+
d.SetId("")
136+
return nil
137+
}
138+
return diag.FromErr(err)
139+
}
140+
141+
_ = d.Set("name", trigger.Name)
142+
_ = d.Set("description", trigger.Description)
143+
144+
diags := diag.Diagnostics(nil)
145+
146+
if trigger.Status == container.TriggerStatusError {
147+
errMsg := ""
148+
if trigger.ErrorMessage != nil {
149+
errMsg = *trigger.ErrorMessage
150+
}
151+
diags = append(diags, diag.Diagnostic{
152+
Severity: diag.Warning,
153+
Summary: "Trigger in error state",
154+
Detail: errMsg,
155+
})
156+
}
157+
158+
return diags
159+
}
160+
161+
func resourceScalewayContainerTriggerUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
162+
api, region, id, err := containerAPIWithRegionAndID(meta, d.Id())
163+
if err != nil {
164+
return diag.FromErr(err)
165+
}
166+
167+
trigger, err := waitForContainerTrigger(ctx, api, region, id, d.Timeout(schema.TimeoutUpdate))
168+
if err != nil {
169+
if is404Error(err) {
170+
d.SetId("")
171+
return nil
172+
}
173+
return diag.FromErr(err)
174+
}
175+
176+
req := &container.UpdateTriggerRequest{
177+
Region: region,
178+
TriggerID: trigger.ID,
179+
}
180+
181+
if d.HasChange("name") {
182+
req.Name = expandUpdatedStringPtr(d.Get("name"))
183+
}
184+
185+
if d.HasChange("description") {
186+
req.Description = expandUpdatedStringPtr(d.Get("description"))
187+
}
188+
189+
if _, err := api.UpdateTrigger(req, scw.WithContext(ctx)); err != nil {
190+
return diag.FromErr(err)
191+
}
192+
193+
return resourceScalewayContainerTriggerRead(ctx, d, meta)
194+
}
195+
196+
func resourceScalewayContainerTriggerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
197+
api, region, id, err := containerAPIWithRegionAndID(meta, d.Id())
198+
if err != nil {
199+
return diag.FromErr(err)
200+
}
201+
202+
_, err = waitForContainerTrigger(ctx, api, region, id, d.Timeout(schema.TimeoutDelete))
203+
if err != nil {
204+
return diag.FromErr(err)
205+
}
206+
207+
_, err = api.DeleteTrigger(&container.DeleteTriggerRequest{
208+
Region: region,
209+
TriggerID: id,
210+
}, scw.WithContext(ctx))
211+
if err != nil {
212+
return diag.FromErr(err)
213+
}
214+
215+
_, err = waitForContainerTrigger(ctx, api, region, id, d.Timeout(schema.TimeoutDelete))
216+
if err != nil && !is404Error(err) {
217+
return diag.FromErr(err)
218+
}
219+
220+
return nil
221+
}

0 commit comments

Comments
 (0)