Skip to content

Commit 915f6f7

Browse files
committedMar 13, 2025
feat(waiting_rooms): add account level list API (#5310)
1 parent 0285def commit 915f6f7

File tree

9 files changed

+509
-7
lines changed

9 files changed

+509
-7
lines changed
 

‎.stats.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
configured_endpoints: 1575
1+
configured_endpoints: 1576
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare%2Fcloudflare-631fbdf54fd976bda40c2ca2faf1070662d412482a32092bf54671975300491c.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
data "cloudflare_waiting_rooms" "example_waiting_rooms" {
2+
account_id = "account_id"
3+
zone_id = "zone_id"
4+
}

‎internal/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,7 @@ func (p *CloudflareProvider) DataSources(ctx context.Context) []func() datasourc
667667
rate_limit.NewRateLimitDataSource,
668668
rate_limit.NewRateLimitsDataSource,
669669
waiting_room.NewWaitingRoomDataSource,
670+
waiting_room.NewWaitingRoomsDataSource,
670671
waiting_room_event.NewWaitingRoomEventDataSource,
671672
waiting_room_event.NewWaitingRoomEventsDataSource,
672673
waiting_room_rules.NewWaitingRoomRulesDataSource,

‎internal/services/waiting_room/data_source_model.go

+16-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ type WaitingRoomResultDataSourceEnvelope struct {
1818
}
1919

2020
type WaitingRoomDataSourceModel struct {
21-
WaitingRoomID types.String `tfsdk:"waiting_room_id" path:"waiting_room_id,required"`
21+
ID types.String `tfsdk:"id" json:"-,computed"`
22+
WaitingRoomID types.String `tfsdk:"waiting_room_id" path:"waiting_room_id,optional"`
2223
ZoneID types.String `tfsdk:"zone_id" path:"zone_id,required"`
2324
CookieSuffix types.String `tfsdk:"cookie_suffix" json:"cookie_suffix,computed"`
2425
CreatedOn timetypes.RFC3339 `tfsdk:"created_on" json:"created_on,computed" format:"date-time"`
@@ -27,7 +28,6 @@ type WaitingRoomDataSourceModel struct {
2728
Description types.String `tfsdk:"description" json:"description,computed"`
2829
DisableSessionRenewal types.Bool `tfsdk:"disable_session_renewal" json:"disable_session_renewal,computed"`
2930
Host types.String `tfsdk:"host" json:"host,computed"`
30-
ID types.String `tfsdk:"id" json:"id,computed"`
3131
JsonResponseEnabled types.Bool `tfsdk:"json_response_enabled" json:"json_response_enabled,computed"`
3232
ModifiedOn timetypes.RFC3339 `tfsdk:"modified_on" json:"modified_on,computed" format:"date-time"`
3333
Name types.String `tfsdk:"name" json:"name,computed"`
@@ -56,6 +56,20 @@ func (m *WaitingRoomDataSourceModel) toReadParams(_ context.Context) (params wai
5656
return
5757
}
5858

59+
func (m *WaitingRoomDataSourceModel) toListParams(_ context.Context) (params waiting_rooms.WaitingRoomListParams, diags diag.Diagnostics) {
60+
params = waiting_rooms.WaitingRoomListParams{
61+
ZoneID: cloudflare.F(m.ZoneID.ValueString()),
62+
}
63+
64+
if !m.AccountID.IsNull() {
65+
params.AccountID = cloudflare.F(m.AccountID.ValueString())
66+
} else {
67+
params.ZoneID = cloudflare.F(m.ZoneID.ValueString())
68+
}
69+
70+
return
71+
}
72+
5973
type WaitingRoomAdditionalRoutesDataSourceModel struct {
6074
Host types.String `tfsdk:"host" json:"host,computed"`
6175
Path types.String `tfsdk:"path" json:"path,computed"`

‎internal/services/waiting_room/data_source_schema.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ var _ datasource.DataSourceWithConfigValidators = (*WaitingRoomDataSource)(nil)
2121
func DataSourceSchema(ctx context.Context) schema.Schema {
2222
return schema.Schema{
2323
Attributes: map[string]schema.Attribute{
24+
"id": schema.StringAttribute{
25+
Computed: true,
26+
},
2427
"waiting_room_id": schema.StringAttribute{
25-
Required: true,
28+
Optional: true,
2629
},
2730
"zone_id": schema.StringAttribute{
2831
Description: "Identifier",
@@ -98,9 +101,6 @@ func DataSourceSchema(ctx context.Context) schema.Schema {
98101
Description: "The host name to which the waiting room will be applied (no wildcards). Please do not include the scheme (http:// or https://). The host and path combination must be unique.",
99102
Computed: true,
100103
},
101-
"id": schema.StringAttribute{
102-
Computed: true,
103-
},
104104
"json_response_enabled": schema.BoolAttribute{
105105
Description: "Only available for the Waiting Room Advanced subscription. If `true`, requests to the waiting room with the header `Accept: application/json` will receive a JSON response object with information on the user's status in the waiting room as opposed to the configured static HTML page. This JSON response object has one property `cfWaitingRoom` which is an object containing the following fields:\n1. `inWaitingRoom`: Boolean indicating if the user is in the waiting room (always **true**).\n2. `waitTimeKnown`: Boolean indicating if the current estimated wait times are accurate. If **false**, they are not available.\n3. `waitTime`: Valid only when `waitTimeKnown` is **true**. Integer indicating the current estimated time in minutes the user will wait in the waiting room. When `queueingMethod` is **random**, this is set to `waitTime50Percentile`.\n4. `waitTime25Percentile`: Valid only when `queueingMethod` is **random** and `waitTimeKnown` is **true**. Integer indicating the current estimated maximum wait time for the 25% of users that gain entry the fastest (25th percentile).\n5. `waitTime50Percentile`: Valid only when `queueingMethod` is **random** and `waitTimeKnown` is **true**. Integer indicating the current estimated maximum wait time for the 50% of users that gain entry the fastest (50th percentile). In other words, half of the queued users are expected to let into the origin website before `waitTime50Percentile` and half are expected to be let in after it.\n6. `waitTime75Percentile`: Valid only when `queueingMethod` is **random** and `waitTimeKnown` is **true**. Integer indicating the current estimated maximum wait time for the 75% of users that gain entry the fastest (75th percentile).\n7. `waitTimeFormatted`: String displaying the `waitTime` formatted in English for users. If `waitTimeKnown` is **false**, `waitTimeFormatted` will display **unavailable**.\n8. `queueIsFull`: Boolean indicating if the waiting room's queue is currently full and not accepting new users at the moment.\n9. `queueAll`: Boolean indicating if all users will be queued in the waiting room and no one will be let into the origin website.\n10. `lastUpdated`: String displaying the timestamp as an ISO 8601 string of the user's last attempt to leave the waiting room and be let into the origin website. The user is able to make another attempt after `refreshIntervalSeconds` past this time. If the user makes a request too soon, it will be ignored and `lastUpdated` will not change.\n11. `refreshIntervalSeconds`: Integer indicating the number of seconds after `lastUpdated` until the user is able to make another attempt to leave the waiting room and be let into the origin website. When the `queueingMethod` is `reject`, there is no specified refresh time — it will always be **zero**.\n12. `queueingMethod`: The queueing method currently used by the waiting room. It is either **fifo**, **random**, **passthrough**, or **reject**.\n13. `isFIFOQueue`: Boolean indicating if the waiting room uses a FIFO (First-In-First-Out) queue.\n14. `isRandomQueue`: Boolean indicating if the waiting room uses a Random queue where users gain access randomly.\n15. `isPassthroughQueue`: Boolean indicating if the waiting room uses a passthrough queue. Keep in mind that when passthrough is enabled, this JSON response will only exist when `queueAll` is **true** or `isEventPrequeueing` is **true** because in all other cases requests will go directly to the origin.\n16. `isRejectQueue`: Boolean indicating if the waiting room uses a reject queue.\n17. `isEventActive`: Boolean indicating if an event is currently occurring. Events are able to change a waiting room's behavior during a specified period of time. For additional information, look at the event properties `prequeue_start_time`, `event_start_time`, and `event_end_time` in the documentation for creating waiting room events. Events are considered active between these start and end times, as well as during the prequeueing period if it exists.\n18. `isEventPrequeueing`: Valid only when `isEventActive` is **true**. Boolean indicating if an event is currently prequeueing users before it starts.\n19. `timeUntilEventStart`: Valid only when `isEventPrequeueing` is **true**. Integer indicating the number of minutes until the event starts.\n20. `timeUntilEventStartFormatted`: String displaying the `timeUntilEventStart` formatted in English for users. If `isEventPrequeueing` is **false**, `timeUntilEventStartFormatted` will display **unavailable**.\n21. `timeUntilEventEnd`: Valid only when `isEventActive` is **true**. Integer indicating the number of minutes until the event ends.\n22. `timeUntilEventEndFormatted`: String displaying the `timeUntilEventEnd` formatted in English for users. If `isEventActive` is **false**, `timeUntilEventEndFormatted` will display **unavailable**.\n23. `shuffleAtEventStart`: Valid only when `isEventActive` is **true**. Boolean indicating if the users in the prequeue are shuffled randomly when the event starts.\n\nAn example cURL to a waiting room could be:\n\n\tcurl -X GET \"https://example.com/waitingroom\" \\\n\t\t-H \"Accept: application/json\"\n\nIf `json_response_enabled` is **true** and the request hits the waiting room, an example JSON response when `queueingMethod` is **fifo** and no event is active could be:\n\n\t{\n\t\t\"cfWaitingRoom\": {\n\t\t\t\"inWaitingRoom\": true,\n\t\t\t\"waitTimeKnown\": true,\n\t\t\t\"waitTime\": 10,\n\t\t\t\"waitTime25Percentile\": 0,\n\t\t\t\"waitTime50Percentile\": 0,\n\t\t\t\"waitTime75Percentile\": 0,\n\t\t\t\"waitTimeFormatted\": \"10 minutes\",\n\t\t\t\"queueIsFull\": false,\n\t\t\t\"queueAll\": false,\n\t\t\t\"lastUpdated\": \"2020-08-03T23:46:00.000Z\",\n\t\t\t\"refreshIntervalSeconds\": 20,\n\t\t\t\"queueingMethod\": \"fifo\",\n\t\t\t\"isFIFOQueue\": true,\n\t\t\t\"isRandomQueue\": false,\n\t\t\t\"isPassthroughQueue\": false,\n\t\t\t\"isRejectQueue\": false,\n\t\t\t\"isEventActive\": false,\n\t\t\t\"isEventPrequeueing\": false,\n\t\t\t\"timeUntilEventStart\": 0,\n\t\t\t\"timeUntilEventStartFormatted\": \"unavailable\",\n\t\t\t\"timeUntilEventEnd\": 0,\n\t\t\t\"timeUntilEventEndFormatted\": \"unavailable\",\n\t\t\t\"shuffleAtEventStart\": false\n\t\t}\n\t}\n\nIf `json_response_enabled` is **true** and the request hits the waiting room, an example JSON response when `queueingMethod` is **random** and an event is active could be:\n\n\t{\n\t\t\"cfWaitingRoom\": {\n\t\t\t\"inWaitingRoom\": true,\n\t\t\t\"waitTimeKnown\": true,\n\t\t\t\"waitTime\": 10,\n\t\t\t\"waitTime25Percentile\": 5,\n\t\t\t\"waitTime50Percentile\": 10,\n\t\t\t\"waitTime75Percentile\": 15,\n\t\t\t\"waitTimeFormatted\": \"5 minutes to 15 minutes\",\n\t\t\t\"queueIsFull\": false,\n\t\t\t\"queueAll\": false,\n\t\t\t\"lastUpdated\": \"2020-08-03T23:46:00.000Z\",\n\t\t\t\"refreshIntervalSeconds\": 20,\n\t\t\t\"queueingMethod\": \"random\",\n\t\t\t\"isFIFOQueue\": false,\n\t\t\t\"isRandomQueue\": true,\n\t\t\t\"isPassthroughQueue\": false,\n\t\t\t\"isRejectQueue\": false,\n\t\t\t\"isEventActive\": true,\n\t\t\t\"isEventPrequeueing\": false,\n\t\t\t\"timeUntilEventStart\": 0,\n\t\t\t\"timeUntilEventStartFormatted\": \"unavailable\",\n\t\t\t\"timeUntilEventEnd\": 15,\n\t\t\t\"timeUntilEventEndFormatted\": \"15 minutes\",\n\t\t\t\"shuffleAtEventStart\": true\n\t\t}\n\t}.",
106106
Computed: true,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
package waiting_room
4+
5+
import (
6+
"context"
7+
"fmt"
8+
9+
"github.com/cloudflare/cloudflare-go/v4"
10+
"github.com/cloudflare/terraform-provider-cloudflare/internal/apijson"
11+
"github.com/cloudflare/terraform-provider-cloudflare/internal/customfield"
12+
"github.com/hashicorp/terraform-plugin-framework/attr"
13+
"github.com/hashicorp/terraform-plugin-framework/datasource"
14+
)
15+
16+
type WaitingRoomsDataSource struct {
17+
client *cloudflare.Client
18+
}
19+
20+
var _ datasource.DataSourceWithConfigure = (*WaitingRoomsDataSource)(nil)
21+
22+
func NewWaitingRoomsDataSource() datasource.DataSource {
23+
return &WaitingRoomsDataSource{}
24+
}
25+
26+
func (d *WaitingRoomsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
27+
resp.TypeName = req.ProviderTypeName + "_waiting_rooms"
28+
}
29+
30+
func (d *WaitingRoomsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
31+
if req.ProviderData == nil {
32+
return
33+
}
34+
35+
client, ok := req.ProviderData.(*cloudflare.Client)
36+
37+
if !ok {
38+
resp.Diagnostics.AddError(
39+
"unexpected resource configure type",
40+
fmt.Sprintf("Expected *cloudflare.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
41+
)
42+
43+
return
44+
}
45+
46+
d.client = client
47+
}
48+
49+
func (d *WaitingRoomsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
50+
var data *WaitingRoomsDataSourceModel
51+
52+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
53+
54+
if resp.Diagnostics.HasError() {
55+
return
56+
}
57+
58+
params, diags := data.toListParams(ctx)
59+
resp.Diagnostics.Append(diags...)
60+
if resp.Diagnostics.HasError() {
61+
return
62+
}
63+
64+
env := WaitingRoomsResultListDataSourceEnvelope{}
65+
maxItems := int(data.MaxItems.ValueInt64())
66+
acc := []attr.Value{}
67+
if maxItems <= 0 {
68+
maxItems = 1000
69+
}
70+
page, err := d.client.WaitingRooms.List(ctx, params)
71+
if err != nil {
72+
resp.Diagnostics.AddError("failed to make http request", err.Error())
73+
return
74+
}
75+
76+
for page != nil && len(page.Result) > 0 {
77+
bytes := []byte(page.JSON.RawJSON())
78+
err = apijson.UnmarshalComputed(bytes, &env)
79+
if err != nil {
80+
resp.Diagnostics.AddError("failed to unmarshal http request", err.Error())
81+
return
82+
}
83+
acc = append(acc, env.Result.Elements()...)
84+
if len(acc) >= maxItems {
85+
break
86+
}
87+
page, err = page.GetNextPage()
88+
if err != nil {
89+
resp.Diagnostics.AddError("failed to fetch next page", err.Error())
90+
return
91+
}
92+
}
93+
94+
acc = acc[:min(len(acc), maxItems)]
95+
result, diags := customfield.NewObjectListFromAttributes[WaitingRoomsResultDataSourceModel](ctx, acc)
96+
resp.Diagnostics.Append(diags...)
97+
data.Result = result
98+
99+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
100+
}

0 commit comments

Comments
 (0)
Please sign in to comment.