-
Notifications
You must be signed in to change notification settings - Fork 632
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2850 from Cyb3r-Jak3/d1
Adds support for D1
- Loading branch information
Showing
10 changed files
with
362 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-resource | ||
cloudflare_d1_database | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
page_title: "cloudflare_d1_database Resource - Cloudflare" | ||
subcategory: "" | ||
description: |- | ||
The D1 Database https://developers.cloudflare.com/d1/ resource allows you to manage Cloudflare D1 databases. | ||
--- | ||
|
||
# cloudflare_d1_database (Resource) | ||
|
||
The [D1 Database](https://developers.cloudflare.com/d1/) resource allows you to manage Cloudflare D1 databases. | ||
|
||
!> When a D1 Database is replaced all the data is lost. Please ensure you have a backup of your data before replacing a D1 Database. | ||
|
||
|
||
## Example Usage | ||
|
||
```terraform | ||
resource "cloudflare_d1_database" "example" { | ||
account_id = "f037e56e89293a057740de681ac9abbe" | ||
name = "terraform-database" | ||
} | ||
``` | ||
|
||
<!-- schema generated by tfplugindocs --> | ||
## Schema | ||
|
||
### Required | ||
|
||
- `account_id` (String) The account identifier to target for the resource. | ||
- `name` (String) The name of the D1 Database. | ||
|
||
### Read-Only | ||
|
||
- `id` (String) The identifier of this resource. | ||
- `version` (String) The backend version of the database. | ||
|
||
## Import | ||
|
||
|
||
Import is supported using the following syntax: | ||
|
||
```shell | ||
$ terraform import cloudflare_d1_database.example <account id>/<database id> | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
$ terraform import cloudflare_d1_database.example <account id>/<database id> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
resource "cloudflare_d1_database" "example" { | ||
account_id = "f037e56e89293a057740de681ac9abbe" | ||
name = "terraform-database" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package d1 | ||
|
||
import "github.com/hashicorp/terraform-plugin-framework/types" | ||
|
||
type DatabaseModel struct { | ||
AccountID types.String `tfsdk:"account_id"` | ||
Name types.String `tfsdk:"name"` | ||
ID types.String `tfsdk:"id"` | ||
Version types.String `tfsdk:"version"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package d1 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/cloudflare/cloudflare-go" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
// Ensure provider defined types fully satisfy framework interfaces. | ||
var _ resource.Resource = &DatabaseResource{} | ||
var _ resource.ResourceWithImportState = &DatabaseResource{} | ||
|
||
func NewResource() resource.Resource { | ||
return &DatabaseResource{} | ||
} | ||
|
||
// DatabaseResource defines the resource implementation. | ||
type DatabaseResource struct { | ||
client *cloudflare.API | ||
} | ||
|
||
func (r *DatabaseResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = req.ProviderTypeName + "_d1_database" | ||
} | ||
|
||
func (r *DatabaseResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
if req.ProviderData == nil { | ||
return | ||
} | ||
|
||
client, ok := req.ProviderData.(*cloudflare.API) | ||
|
||
if !ok { | ||
resp.Diagnostics.AddError( | ||
"unexpected resource configure type", | ||
fmt.Sprintf("Expected *cloudflare.API, got: %T. Please report this issue to the provider developers.", req.ProviderData), | ||
) | ||
|
||
return | ||
} | ||
|
||
r.client = client | ||
} | ||
|
||
func (r *DatabaseResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
var data *DatabaseModel | ||
|
||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
database, err := r.client.CreateD1Database(ctx, cloudflare.AccountIdentifier(data.AccountID.ValueString()), | ||
cloudflare.CreateD1DatabaseParams{ | ||
Name: data.Name.ValueString(), | ||
}, | ||
) | ||
if err != nil { | ||
resp.Diagnostics.AddError("failed to create D1 database", err.Error()) | ||
return | ||
} | ||
data.ID = types.StringValue(database.UUID) | ||
data.Name = types.StringValue(database.Name) | ||
data.Version = types.StringValue(database.Version) | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||
} | ||
|
||
func (r *DatabaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
var data *DatabaseModel | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
database, err := r.client.GetD1Database(ctx, cloudflare.AccountIdentifier(data.AccountID.ValueString()), data.ID.ValueString()) | ||
if err != nil { | ||
resp.Diagnostics.AddError("failed reading D1 database", err.Error()) | ||
return | ||
} | ||
data.ID = types.StringValue(database.UUID) | ||
data.Name = types.StringValue(database.Name) | ||
data.Version = types.StringValue(database.Version) | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) | ||
} | ||
|
||
func (r *DatabaseResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
var data *DatabaseModel | ||
|
||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
resp.Diagnostics.AddError("failed to update D1 database", "Not implemented") | ||
} | ||
|
||
func (r *DatabaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var data *DatabaseModel | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
err := r.client.DeleteD1Database(ctx, cloudflare.AccountIdentifier(data.AccountID.ValueString()), data.ID.ValueString()) | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("failed to delete D1 database", err.Error()) | ||
return | ||
} | ||
} | ||
|
||
func (r *DatabaseResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
idparts := strings.Split(req.ID, "/") | ||
if len(idparts) != 2 { | ||
resp.Diagnostics.AddError("error importing D1 database", "invalid ID specified. Please specify the ID as \"account_id/name\"") | ||
return | ||
} | ||
resp.Diagnostics.Append(resp.State.SetAttribute( | ||
ctx, path.Root("account_id"), idparts[0], | ||
)...) | ||
resp.Diagnostics.Append(resp.State.SetAttribute( | ||
ctx, path.Root("id"), idparts[1], | ||
)...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package d1_test | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"testing" | ||
|
||
"github.com/cloudflare/cloudflare-go" | ||
"github.com/cloudflare/terraform-provider-cloudflare/internal/acctest" | ||
"github.com/cloudflare/terraform-provider-cloudflare/internal/utils" | ||
"github.com/hashicorp/terraform-plugin-testing/helper/resource" | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
resource.TestMain(m) | ||
} | ||
|
||
func init() { | ||
resource.AddTestSweepers("cloudflare_d1_database", &resource.Sweeper{ | ||
Name: "cloudflare_d1_database", | ||
F: func(region string) error { | ||
client, err := acctest.SharedClient() | ||
accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID") | ||
|
||
if err != nil { | ||
return fmt.Errorf("error establishing client: %w", err) | ||
} | ||
|
||
ctx := context.Background() | ||
databases, _, err := client.ListD1Databases(ctx, cloudflare.AccountIdentifier(accountID), cloudflare.ListD1DatabasesParams{}) | ||
if err != nil { | ||
return fmt.Errorf("failed to fetch R2 buckets: %w", err) | ||
} | ||
|
||
for _, database := range databases { | ||
err := client.DeleteD1Database(ctx, cloudflare.AccountIdentifier(accountID), database.UUID) | ||
if err != nil { | ||
return fmt.Errorf("failed to delete D1 database %q: %w", database.Name, err) | ||
} | ||
} | ||
|
||
return nil | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccCloudflareD1Database_Basic(t *testing.T) { | ||
rnd := utils.GenerateRandomResourceName() | ||
accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID") | ||
resourceName := "cloudflare_d1_database." + rnd | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acctest.TestAccPreCheck(t) }, | ||
ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCheckCloudflareD1DatabaseBasic(rnd, accountID), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(resourceName, "name", rnd), | ||
resource.TestCheckResourceAttrSet(resourceName, "id"), | ||
resource.TestCheckResourceAttr(resourceName, "version", "beta"), | ||
), | ||
}, | ||
{ | ||
ResourceName: resourceName, | ||
ImportStateIdPrefix: fmt.Sprintf("%s/", accountID), | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckCloudflareD1DatabaseBasic(rnd, accountID string) string { | ||
return fmt.Sprintf(` | ||
resource "cloudflare_d1_database" "%[1]s" { | ||
account_id = "%[2]s" | ||
name = "%[1]s" | ||
}`, rnd, accountID) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package d1 | ||
|
||
import ( | ||
"context" | ||
"github.com/hashicorp/terraform-plugin-framework/schema/validator" | ||
"regexp" | ||
|
||
"github.com/MakeNowJust/heredoc/v2" | ||
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts" | ||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" | ||
) | ||
|
||
func (r *DatabaseResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
MarkdownDescription: heredoc.Doc(` | ||
The [D1 Database](https://developers.cloudflare.com/d1/) resource allows you to manage Cloudflare D1 databases. | ||
`), | ||
|
||
Attributes: map[string]schema.Attribute{ | ||
consts.AccountIDSchemaKey: schema.StringAttribute{ | ||
MarkdownDescription: consts.AccountIDSchemaDescription, | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
consts.IDSchemaKey: schema.StringAttribute{ | ||
MarkdownDescription: consts.IDSchemaDescription, | ||
Computed: true, | ||
}, | ||
"name": schema.StringAttribute{ | ||
Required: true, | ||
MarkdownDescription: "The name of the D1 Database.", | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
Validators: []validator.String{ | ||
stringvalidator.RegexMatches( | ||
regexp.MustCompile(`^[a-z0-9][a-z0-9-_]*$`), | ||
"must contain only lowercase alphanumeric characters", | ||
), | ||
}, | ||
}, | ||
"version": schema.StringAttribute{ | ||
Computed: true, | ||
MarkdownDescription: "The backend version of the database.", | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
page_title: "{{.Name}} {{.Type}} - {{.RenderedProviderName}}" | ||
subcategory: "" | ||
description: |- | ||
{{ .Description | plainmarkdown | trimspace | prefixlines " " }} | ||
--- | ||
|
||
# {{.Name}} ({{.Type}}) | ||
|
||
{{ .Description | trimspace }} | ||
|
||
!> When a D1 Database is replaced all the data is lost. Please ensure you have a backup of your data before replacing a D1 Database. | ||
|
||
|
||
## Example Usage | ||
|
||
{{ tffile (printf "%s%s%s" "examples/resources/" .Name "/resource.tf") }} | ||
|
||
{{ .SchemaMarkdown | trimspace }} | ||
|
||
## Import | ||
|
||
|
||
Import is supported using the following syntax: | ||
|
||
{{ codefile "shell" (printf "%s%s%s" "examples/resources/" .Name "/import.sh") }} | ||
|