Skip to content

Commit

Permalink
Allow resource importing
Browse files Browse the repository at this point in the history
  • Loading branch information
grongor committed Jul 8, 2024
1 parent 3ab6d76 commit 78a9a29
Show file tree
Hide file tree
Showing 13 changed files with 449 additions and 16 deletions.
12 changes: 12 additions & 0 deletions docs/resources/cdn.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,15 @@ Optional:
- `port` (Number)
- `protocol` (String)
- `query_key` (String)

## Import

Import is supported using the following syntax:

```shell
$ terraform import cdn77_cdn.example <id>

# <id> must be the ID (unsigned integer) of the CDN
# Example:
$ terraform import cdn77_cdn.example 1837865409
```
33 changes: 33 additions & 0 deletions docs/resources/origin.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,36 @@ resource "cdn77_origin" "example" {
- `access_key_id` (String) Access key to your Object Storage bucket
- `access_key_secret` (String, Sensitive) Access secret to your Object Storage bucket
- `id` (String) Origin ID (UUID)

## Import

Import is supported using the following syntax:

```shell
$ terraform import cdn77_origin.example <id>,<type>[,type-specific parameters,...]

# <id> must be the ID (UUID) of the Origin
# <type> must be a type of the Origin (one of: "aws", "object-storage", "url")
# Depending on the type of the origin there may be other required parameters:

# URL type doesn't need other parameters
$ terraform import cdn77_origin.example <id>,url

# AWS type requires access key secret
# <aws_access_key_secret> must be the secret of the AWS access key that you provided when creating the Origin
$ terraform import cdn77_origin.example <id>,aws,<aws_access_key_secret>

# Object Storage type requires ACL, cluster ID, access key ID and access key secret
# <acl> must be ACL type (one of: "authenticated-read", "private", "public-read", "public-read-write")
# <cluster_id> must be an ID (UUID) of the Object Storage cluster
# <access_key_id> must be the ID of the access key that was returned when creating the Origin
# <access_key_secret> must be the secret of the access key that was returned when creating the Origin
$ terraform import cdn77_origin.example <id>,object-storage,<acl>,<cluster_id>,<access_key_id>,<access_key_secret>

# Examples:
$ terraform import cdn77_origin.example_url 4cd2378b-dec8-49e2-aa17-bf7561452998,url
$ terraform import cdn77_origin.example_aws 4cd2378b-dec8-49e2-aa17-bf7561452998,aws,\
VWK92izmd7zpY8Khs/Dllv4yLYc4sFWNyg2XtuNF
$ terraform import cdn77_origin.example_object_storage 4cd2378b-dec8-49e2-aa17-bf7561452998,object-storage,\
private,842b5641-b641-4723-ac81-f8cc286e288f,I17DXFE00GNJZVQUTQPW,7UG7WbcIz4VhZnVxV4XQcDR2X0APApuvthyATf2v
```
21 changes: 21 additions & 0 deletions docs/resources/ssl.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,24 @@ resource "cdn77_ssl" "example" {
- `expires_at` (String) Date and time of the SNI certificate expiration
- `id` (String) ID (UUID) of the SSL certificate
- `subjects` (Set of String) Subjects (domain names) of the certificate

## Import

Import is supported using the following syntax:

```shell
$ terraform import cdn77_ssl.example <id>,<private_key>

# <id> must be the ID (UUID) of the SSL certificate
# <privateKey> must be an entire private key (including PEM headers) encoded via base64.
# Example:
$ key=$(base64 --wrap=0 key.pem <<EOL
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHqBB2YZkISl1T5TmmZciLN4cJfJPZ6CDpkLgwTiDVyEoAoGCCqGSM49
AwEHoUQDQgAE+lmT51fh5oPIAvtPOEvDw4Ct2sKCt1kYhASlD5b62pT2UyXPrRWp
ekd7UQCYC8K86F1OFeupn2DCOnyGCyK8mw==
-----END EC PRIVATE KEY-----
EOL
)
$ terraform import cdn77_ssl.example "4cd2378b-dec8-49e2-aa17-bf7561452998,$key"
```
5 changes: 5 additions & 0 deletions examples/resources/cdn77_cdn/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$ terraform import cdn77_cdn.example <id>

# <id> must be the ID (unsigned integer) of the CDN
# Example:
$ terraform import cdn77_cdn.example 1837865409
26 changes: 26 additions & 0 deletions examples/resources/cdn77_origin/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
$ terraform import cdn77_origin.example <id>,<type>[,type-specific parameters,...]

# <id> must be the ID (UUID) of the Origin
# <type> must be a type of the Origin (one of: "aws", "object-storage", "url")
# Depending on the type of the origin there may be other required parameters:

# URL type doesn't need other parameters
$ terraform import cdn77_origin.example <id>,url

# AWS type requires access key secret
# <aws_access_key_secret> must be the secret of the AWS access key that you provided when creating the Origin
$ terraform import cdn77_origin.example <id>,aws,<aws_access_key_secret>

# Object Storage type requires ACL, cluster ID, access key ID and access key secret
# <acl> must be ACL type (one of: "authenticated-read", "private", "public-read", "public-read-write")
# <cluster_id> must be an ID (UUID) of the Object Storage cluster
# <access_key_id> must be the ID of the access key that was returned when creating the Origin
# <access_key_secret> must be the secret of the access key that was returned when creating the Origin
$ terraform import cdn77_origin.example <id>,object-storage,<acl>,<cluster_id>,<access_key_id>,<access_key_secret>

# Examples:
$ terraform import cdn77_origin.example_url 4cd2378b-dec8-49e2-aa17-bf7561452998,url
$ terraform import cdn77_origin.example_aws 4cd2378b-dec8-49e2-aa17-bf7561452998,aws,\
VWK92izmd7zpY8Khs/Dllv4yLYc4sFWNyg2XtuNF
$ terraform import cdn77_origin.example_object_storage 4cd2378b-dec8-49e2-aa17-bf7561452998,object-storage,\
private,842b5641-b641-4723-ac81-f8cc286e288f,I17DXFE00GNJZVQUTQPW,7UG7WbcIz4VhZnVxV4XQcDR2X0APApuvthyATf2v
14 changes: 14 additions & 0 deletions examples/resources/cdn77_ssl/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
$ terraform import cdn77_ssl.example <id>,<private_key>

# <id> must be the ID (UUID) of the SSL certificate
# <privateKey> must be an entire private key (including PEM headers) encoded via base64.
# Example:
$ key=$(base64 --wrap=0 key.pem <<EOL
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHqBB2YZkISl1T5TmmZciLN4cJfJPZ6CDpkLgwTiDVyEoAoGCCqGSM49
AwEHoUQDQgAE+lmT51fh5oPIAvtPOEvDw4Ct2sKCt1kYhASlD5b62pT2UyXPrRWp
ekd7UQCYC8K86F1OFeupn2DCOnyGCyK8mw==
-----END EC PRIVATE KEY-----
EOL
)
$ terraform import cdn77_ssl.example "4cd2378b-dec8-49e2-aa17-bf7561452998,$key"
21 changes: 21 additions & 0 deletions internal/provider/cdn_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package provider

import (
"context"
"fmt"
"strconv"
"time"

"github.com/cdn77/cdn77-client-go"
Expand All @@ -16,6 +18,7 @@ import (
var (
_ resource.ResourceWithConfigure = &CdnResource{}
_ resource.ResourceWithConfigValidators = &CdnResource{}
_ resource.ResourceWithImportState = &CdnResource{}
)

func NewCdnResource() resource.Resource {
Expand Down Expand Up @@ -185,6 +188,24 @@ func (r *CdnResource) Delete(ctx context.Context, req resource.DeleteRequest, re
util.CheckResponse(&resp.Diagnostics, errMessage, response, response.JSON404, response.JSONDefault)
}

func (*CdnResource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
id, err := strconv.ParseUint(req.ID, 10, 64)
if err != nil {
resp.Diagnostics.AddError(
"Invalid Import Identifier",
fmt.Sprintf("Expected unsigned integer, got: %q", req.ID),
)

return
}

resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), id)...)
}

func (*CdnResource) createDefaultEditRequest() cdn77.CdnEditJSONRequestBody {
return cdn77.CdnEditJSONRequestBody{
Cache: &cdn77.Cache{
Expand Down
37 changes: 36 additions & 1 deletion internal/provider/cdn_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,12 +514,47 @@ func TestAccCdnResource(t *testing.T) {
})
}

func TestAccCdnResourceImport(t *testing.T) {
client := acctest.GetClient(t)
rsc := "cdn77_cdn.lorem"
var cdnId string

resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: acctest.GetProviderFactories(),
CheckDestroy: func(state *terraform.State) error {
return errors.Join(checkCdnsDestroyed(client)(state), checkOriginsDestroyed(client)(state))
},
Steps: []resource.TestStep{
{
Config: OriginResourceConfig + `resource "cdn77_cdn" "lorem" {
origin_id = cdn77_origin.url.id
label = "my cdn"
note = "custom note"
}`,
Check: resource.TestCheckResourceAttrWith(rsc, "id", func(value string) (err error) {
cdnId = value

return nil
}),
},
{
ResourceName: rsc,
ImportState: true,
ImportStateIdFunc: func(*terraform.State) (string, error) {
return cdnId, nil
},
ImportStateVerify: true,
},
},
})
}

func checkCdn(
client cdn77.ClientWithResponsesInterface,
cdnId *int,
fn func(o *cdn77.Cdn) error,
) func(*terraform.State) error {
return func(_ *terraform.State) error {
return func(*terraform.State) error {
response, err := client.CdnDetailWithResponse(context.Background(), *cdnId)
message := fmt.Sprintf("failed to get CDN[id=%d]: %%s", *cdnId)

Expand Down
5 changes: 5 additions & 0 deletions internal/provider/object_storages_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@ func TestAccObjectStoragesDataSource_All(t *testing.T) {
const objectStoragesDataSourceConfig = `
data "cdn77_object_storages" "all" {
}
locals {
eu_cluster_id = one([for os in data.cdn77_object_storages.all.clusters : os.id if os.label == "EU"])
us_cluster_id = one([for os in data.cdn77_object_storages.all.clusters : os.id if os.label == "US"])
}
`
69 changes: 69 additions & 0 deletions internal/provider/origin_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"context"
"fmt"
"net/http"
"strings"

"github.com/cdn77/cdn77-client-go"
"github.com/cdn77/terraform-provider-cdn77/internal/util"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand All @@ -17,6 +19,7 @@ import (
var (
_ resource.ResourceWithConfigure = &OriginResource{}
_ resource.ResourceWithConfigValidators = &OriginResource{}
_ resource.ResourceWithImportState = &OriginResource{}
)

func NewOriginResource() resource.Resource {
Expand Down Expand Up @@ -145,6 +148,72 @@ func (r *OriginResource) Delete(ctx context.Context, req resource.DeleteRequest,
}
}

func (*OriginResource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
idParts := strings.Split(req.ID, ",")
if len(idParts) < 2 {
resp.Diagnostics.AddError(
"Invalid Import Identifier",
fmt.Sprintf(
`Expected one of: \n\t"<id>,url"\n\t"<id>,aws,<aws_access_key_secret>" \n\t`+
`"<id>,object-storage,<acl>,<cluster_id>,<access_key_id>,<access_key_secret>")\nGot: %q`,
req.ID,
),
)
}

id := idParts[0]
originType := idParts[1]

resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("id"), id)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("type"), originType)...)

switch originType {
case OriginTypeAws:
if len(idParts) != 3 {
resp.Diagnostics.AddError(
"Invalid AWS Origin Import Identifier",
fmt.Sprintf(`Expected "<id>,aws,<aws_access_key_secret>"; got: %q`, req.ID),
)

return
}

resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("aws_access_key_secret"), idParts[2])...)
case OriginTypeObjectStorage:
if len(idParts) != 6 {
resp.Diagnostics.AddError(
"Invalid Object Storage Origin Import Identifier",
fmt.Sprintf(
`Expected "<id>,object-storage,<acl>,<cluster_id>,<access_key_id>,<access_key_secret>"; got: %q`,
req.ID,
),
)

return
}

resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("acl"), idParts[2])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("cluster_id"), idParts[3])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("access_key_id"), idParts[4])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("access_key_secret"), idParts[5])...)
case OriginTypeUrl:
if len(idParts) != 2 {
resp.Diagnostics.AddError(
"Invalid URL Origin Import Identifier",
fmt.Sprintf(`Expected "<id>,url"; got: %q`, req.ID),
)

return
}
default:
addUnknownOriginTypeError(&resp.Diagnostics, OriginModel{Type: types.StringValue(originType)})
}
}

func (r *OriginResource) createAws(
ctx context.Context,
diags *diag.Diagnostics,
Expand Down
Loading

0 comments on commit 78a9a29

Please sign in to comment.