Skip to content

Commit f30b68f

Browse files
authored
Add support for managing Function CPU (#180)
* Add support for managing Function CPU - New resource can adjust the function cpu settings for a project. I've not added resource tests, as the data source tests cover all that is needed and more. * Allow null for read state
1 parent 93c110e commit f30b68f

File tree

10 files changed

+659
-1
lines changed

10 files changed

+659
-1
lines changed

client/project_function_cpu.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-log/tflog"
8+
)
9+
10+
type ProjectFunctionCPURequest struct {
11+
ProjectID string
12+
TeamID string
13+
CPU string
14+
}
15+
16+
type functionCPU struct {
17+
DefaultMemoryType *string `json:"defaultMemoryType"`
18+
}
19+
20+
type ProjectFunctionCPU struct {
21+
ProjectID string
22+
TeamID string
23+
CPU *string
24+
}
25+
26+
var toCPUNetwork = map[string]string{
27+
"basic": "standard_legacy",
28+
"standard": "standard",
29+
"performance": "performance",
30+
}
31+
32+
var fromCPUNetwork = map[string]string{
33+
"standard_legacy": "basic",
34+
"standard": "standard",
35+
"performance": "performance",
36+
}
37+
38+
func (c *Client) GetProjectFunctionCPU(ctx context.Context, projectID, teamID string) (p ProjectFunctionCPU, err error) {
39+
url := fmt.Sprintf("%s/v1/projects/%s/resource-config", c.baseURL, projectID)
40+
if c.teamID(teamID) != "" {
41+
url = fmt.Sprintf("%s?teamId=%s", url, c.teamID(teamID))
42+
}
43+
tflog.Info(ctx, "get project function cpu", map[string]interface{}{
44+
"url": url,
45+
})
46+
var f functionCPU
47+
err = c.doRequest(clientRequest{
48+
ctx: ctx,
49+
method: "GET",
50+
url: url,
51+
}, &f)
52+
if err != nil {
53+
return p, err
54+
}
55+
var cpu *string
56+
if f.DefaultMemoryType != nil {
57+
v := fromCPUNetwork[*f.DefaultMemoryType]
58+
cpu = &v
59+
}
60+
return ProjectFunctionCPU{
61+
ProjectID: projectID,
62+
TeamID: teamID,
63+
CPU: cpu,
64+
}, err
65+
}
66+
67+
func (c *Client) UpdateProjectFunctionCPU(ctx context.Context, request ProjectFunctionCPURequest) (p ProjectFunctionCPU, err error) {
68+
url := fmt.Sprintf("%s/v1/projects/%s/resource-config", c.baseURL, request.ProjectID)
69+
if c.teamID(request.TeamID) != "" {
70+
url = fmt.Sprintf("%s?teamId=%s", url, c.teamID(request.TeamID))
71+
}
72+
73+
v := toCPUNetwork[request.CPU]
74+
payload := string(mustMarshal(functionCPU{
75+
DefaultMemoryType: &v,
76+
}))
77+
var f functionCPU
78+
err = c.doRequest(clientRequest{
79+
ctx: ctx,
80+
method: "PATCH",
81+
url: url,
82+
body: payload,
83+
}, &f)
84+
if err != nil {
85+
return p, err
86+
}
87+
var cpu *string
88+
if f.DefaultMemoryType != nil {
89+
v := fromCPUNetwork[*f.DefaultMemoryType]
90+
cpu = &v
91+
}
92+
return ProjectFunctionCPU{
93+
ProjectID: request.ProjectID,
94+
TeamID: request.TeamID,
95+
CPU: cpu,
96+
}, err
97+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "vercel_project_function_cpu Data Source - terraform-provider-vercel"
4+
subcategory: ""
5+
description: |-
6+
Provides information about a Project's Function CPU setting.
7+
This controls the maximum amount of CPU utilization your Serverless Functions can use while executing. Standard is optimal for most frontend workloads. You can override this per function using the vercel.json file.
8+
---
9+
10+
# vercel_project_function_cpu (Data Source)
11+
12+
Provides information about a Project's Function CPU setting.
13+
14+
This controls the maximum amount of CPU utilization your Serverless Functions can use while executing. Standard is optimal for most frontend workloads. You can override this per function using the vercel.json file.
15+
16+
## Example Usage
17+
18+
```terraform
19+
data "vercel_project" "example" {
20+
name = "example"
21+
}
22+
23+
data "vercel_project_function_cpu" "example" {
24+
project_id = data.vercel_project.example.id
25+
}
26+
```
27+
28+
<!-- schema generated by tfplugindocs -->
29+
## Schema
30+
31+
### Required
32+
33+
- `project_id` (String) The ID of the Project to read the Function CPU setting for.
34+
35+
### Optional
36+
37+
- `team_id` (String) The ID of the team the Project exists under. Required when configuring a team resource if a default team has not been set in the provider.
38+
39+
### Read-Only
40+
41+
- `cpu` (String) The amount of CPU available to your Serverless Functions. Should be one of 'basic' (0.6vCPU), 'standard' (1vCPU) or 'performance' (1.7vCPUs).
42+
- `id` (String) The ID of the resource.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "vercel_project_function_cpu Resource - terraform-provider-vercel"
4+
subcategory: ""
5+
description: |-
6+
Provides a Function CPU resource for a Project.
7+
This controls the maximum amount of CPU utilization your Serverless Functions can use while executing. Standard is optimal for most frontend workloads. You can override this per function using the vercel.json file.
8+
A new Deployment is required for your changes to take effect.
9+
---
10+
11+
# vercel_project_function_cpu (Resource)
12+
13+
Provides a Function CPU resource for a Project.
14+
15+
This controls the maximum amount of CPU utilization your Serverless Functions can use while executing. Standard is optimal for most frontend workloads. You can override this per function using the vercel.json file.
16+
17+
A new Deployment is required for your changes to take effect.
18+
19+
## Example Usage
20+
21+
```terraform
22+
resource "vercel_project" "example" {
23+
name = "example"
24+
}
25+
26+
resource "vercel_project_function_cpu" "example" {
27+
project_id = vercel_project.example.id
28+
cpu = "performance"
29+
}
30+
```
31+
32+
<!-- schema generated by tfplugindocs -->
33+
## Schema
34+
35+
### Required
36+
37+
- `cpu` (String) The amount of CPU available to your Serverless Functions. Should be one of 'basic' (0.6vCPU), 'standard' (1vCPU) or 'performance' (1.7vCPUs).
38+
- `project_id` (String) The ID of the Project to adjust the CPU for.
39+
40+
### Optional
41+
42+
- `team_id` (String) The ID of the team the Project exists under. Required when configuring a team resource if a default team has not been set in the provider.
43+
44+
### Read-Only
45+
46+
- `id` (String) The ID of the resource.
47+
48+
## Import
49+
50+
Import is supported using the following syntax:
51+
52+
```shell
53+
# You can import via the team_id and project_id.
54+
# - team_id can be found in the team `settings` tab in the Vercel UI.
55+
# - project_id can be found in the project `settings` tab in the Vercel UI.
56+
terraform import vercel_project_function_cpu.example team_xxxxxxxxxxxxxxxxxxxxxxxx/prj_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
57+
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
data "vercel_project" "example" {
2+
name = "example"
3+
}
4+
5+
data "vercel_project_function_cpu" "example" {
6+
project_id = data.vercel_project.example.id
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# You can import via the team_id and project_id.
2+
# - team_id can be found in the team `settings` tab in the Vercel UI.
3+
# - project_id can be found in the project `settings` tab in the Vercel UI.
4+
terraform import vercel_project_function_cpu.example team_xxxxxxxxxxxxxxxxxxxxxxxx/prj_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
resource "vercel_project" "example" {
2+
name = "example"
3+
}
4+
5+
resource "vercel_project_function_cpu" "example" {
6+
project_id = vercel_project.example.id
7+
cpu = "performance"
8+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package vercel
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
9+
"github.com/hashicorp/terraform-plugin-log/tflog"
10+
"github.com/vercel/terraform-provider-vercel/client"
11+
)
12+
13+
// Ensure the implementation satisfies the expected interfaces.
14+
var (
15+
_ datasource.DataSource = &projectFunctionCPUDataSource{}
16+
_ datasource.DataSourceWithConfigure = &projectFunctionCPUDataSource{}
17+
)
18+
19+
func newProjectFunctionCPUDataSource() datasource.DataSource {
20+
return &projectFunctionCPUDataSource{}
21+
}
22+
23+
type projectFunctionCPUDataSource struct {
24+
client *client.Client
25+
}
26+
27+
func (d *projectFunctionCPUDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
28+
resp.TypeName = req.ProviderTypeName + "_project_function_cpu"
29+
}
30+
31+
func (d *projectFunctionCPUDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
32+
// Prevent panic if the provider has not been configured.
33+
if req.ProviderData == nil {
34+
return
35+
}
36+
37+
client, ok := req.ProviderData.(*client.Client)
38+
if !ok {
39+
resp.Diagnostics.AddError(
40+
"Unexpected Data Source Configure Type",
41+
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
42+
)
43+
return
44+
}
45+
46+
d.client = client
47+
}
48+
49+
func (r *projectFunctionCPUDataSource) Schema(_ context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
50+
resp.Schema = schema.Schema{
51+
Description: `Provides information about a Project's Function CPU setting.
52+
53+
This controls the maximum amount of CPU utilization your Serverless Functions can use while executing. Standard is optimal for most frontend workloads. You can override this per function using the vercel.json file.
54+
`,
55+
Attributes: map[string]schema.Attribute{
56+
"id": schema.StringAttribute{
57+
Description: "The ID of the resource.",
58+
Computed: true,
59+
},
60+
"project_id": schema.StringAttribute{
61+
Description: "The ID of the Project to read the Function CPU setting for.",
62+
Required: true,
63+
},
64+
"team_id": schema.StringAttribute{
65+
Optional: true,
66+
Computed: true,
67+
Description: "The ID of the team the Project exists under. Required when configuring a team resource if a default team has not been set in the provider.",
68+
},
69+
"cpu": schema.StringAttribute{
70+
Description: "The amount of CPU available to your Serverless Functions. Should be one of 'basic' (0.6vCPU), 'standard' (1vCPU) or 'performance' (1.7vCPUs).",
71+
Computed: true,
72+
},
73+
},
74+
}
75+
}
76+
77+
func (d *projectFunctionCPUDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
78+
var config ProjectFunctionCPU
79+
diags := req.Config.Get(ctx, &config)
80+
resp.Diagnostics.Append(diags...)
81+
if resp.Diagnostics.HasError() {
82+
return
83+
}
84+
85+
out, err := d.client.GetProjectFunctionCPU(ctx, config.ProjectID.ValueString(), config.TeamID.ValueString())
86+
if client.NotFound(err) {
87+
resp.State.RemoveResource(ctx)
88+
return
89+
}
90+
if err != nil {
91+
resp.Diagnostics.AddError(
92+
"Error reading project Function CPU",
93+
fmt.Sprintf("Could not get Project Function CPU %s %s, unexpected error: %s",
94+
config.TeamID.ValueString(),
95+
config.ProjectID.ValueString(),
96+
err,
97+
),
98+
)
99+
return
100+
}
101+
102+
result := convertResponseToProjectFunctionCPU(out)
103+
tflog.Info(ctx, "read project function cpu", map[string]interface{}{
104+
"team_id": result.TeamID.ValueString(),
105+
"project_id": result.ProjectID.ValueString(),
106+
})
107+
108+
diags = resp.State.Set(ctx, result)
109+
resp.Diagnostics.Append(diags...)
110+
if resp.Diagnostics.HasError() {
111+
return
112+
}
113+
}

0 commit comments

Comments
 (0)