Skip to content

Commit a10bcf6

Browse files
committed
feat(#208): Added resource cloudtemple_object_storage_storage_account
1 parent b2dfe0a commit a10bcf6

6 files changed

Lines changed: 302 additions & 1 deletion

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "cloudtemple_object_storage_storage_account Resource - terraform-provider-cloudtemple"
4+
subcategory: ""
5+
description: |-
6+
Create and manage object storage storage accounts.
7+
To manage this resource you will need the object-storage_iam_management role.
8+
---
9+
10+
# cloudtemple_object_storage_storage_account (Resource)
11+
12+
Create and manage object storage storage accounts.
13+
14+
To manage this resource you will need the `object-storage_iam_management` role.
15+
16+
## Example Usage
17+
18+
```terraform
19+
# Create a storage account
20+
resource "cloudtemple_object_storage_storage_account" "example" {
21+
name = "my-storage-account"
22+
}
23+
24+
# Output the access credentials
25+
output "access_key_id" {
26+
value = cloudtemple_object_storage_storage_account.example.access_key_id
27+
}
28+
29+
output "access_secret_key" {
30+
value = cloudtemple_object_storage_storage_account.example.access_secret_key
31+
sensitive = true
32+
}
33+
34+
output "arn" {
35+
value = cloudtemple_object_storage_storage_account.example.arn
36+
}
37+
```
38+
39+
<!-- schema generated by tfplugindocs -->
40+
## Schema
41+
42+
### Required
43+
44+
- `name` (String) The name of the storage account.
45+
46+
### Read-Only
47+
48+
- `access_key_id` (String) The access key ID of the storage account.
49+
- `access_secret_key` (String, Sensitive) The secret access key of the storage account. This is only available during creation.
50+
- `arn` (String) The ARN of the storage account.
51+
- `create_date` (String) The creation date of the storage account.
52+
- `id` (String) The ID of the storage account.
53+
- `path` (String) The path of the storage account.
54+
- `tags` (List of Object) The tags associated with the storage account. (see [below for nested schema](#nestedatt--tags))
55+
56+
<a id="nestedatt--tags"></a>
57+
### Nested Schema for `tags`
58+
59+
Read-Only:
60+
61+
- `key` (String)
62+
- `value` (String)
63+
64+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Create a storage account
2+
resource "cloudtemple_object_storage_storage_account" "example" {
3+
name = "my-storage-account"
4+
}
5+
6+
# Output the access credentials
7+
output "access_key_id" {
8+
value = cloudtemple_object_storage_storage_account.example.access_key_id
9+
}
10+
11+
output "access_secret_key" {
12+
value = cloudtemple_object_storage_storage_account.example.access_secret_key
13+
sensitive = true
14+
}
15+
16+
output "arn" {
17+
value = cloudtemple_object_storage_storage_account.example.arn
18+
}

internal/client/object_storage_storage_account.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,37 @@ func (c *StorageAccountClient) Read(ctx context.Context, name string) (*StorageA
6161

6262
return &out, nil
6363
}
64+
65+
type CreateStorageAccountRequest struct {
66+
Name string `json:"name"`
67+
}
68+
69+
type CreateStorageAccountResponse struct {
70+
AccessKeyID string `json:"accessKeyId"`
71+
SecretAccessKey string `json:"secretAccessKey"`
72+
}
73+
74+
func (c *StorageAccountClient) Create(ctx context.Context, req *CreateStorageAccountRequest) (*CreateStorageAccountResponse, error) {
75+
r := c.c.newRequest("POST", "/object-storage/v1/storage_accounts")
76+
r.obj = req
77+
resp, err := c.c.doRequest(ctx, r)
78+
if err != nil {
79+
return nil, err
80+
}
81+
defer closeResponseBody(resp)
82+
if err := requireOK(resp); err != nil {
83+
return nil, err
84+
}
85+
86+
var out CreateStorageAccountResponse
87+
if err := decodeBody(resp, &out); err != nil {
88+
return nil, err
89+
}
90+
91+
return &out, nil
92+
}
93+
94+
func (c *StorageAccountClient) Delete(ctx context.Context, name string) (string, error) {
95+
r := c.c.newRequest("DELETE", "/object-storage/v1/storage_accounts/%s", name)
96+
return c.c.doRequestAndReturnActivity(ctx, r)
97+
}

internal/provider/provider.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ func New(version string) func() *schema.Provider {
184184
"cloudtemple_compute_iaas_opensource_replication_policy": documentResource(resourceOpenIaasReplicationPolicy(), "compute_iaas_opensource_management", "compute_iaas_opensource_read", "activity_read"),
185185

186186
// Object Storage
187-
"cloudtemple_object_storage_bucket": documentResource(resourceBucket(), "object-storage_write", "object-storage_read"),
187+
"cloudtemple_object_storage_bucket": documentResource(resourceBucket(), "object-storage_write", "object-storage_read"),
188+
"cloudtemple_object_storage_storage_account": documentResource(resourceStorageAccount(), "object-storage_iam_management"),
188189
},
189190
}
190191

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
6+
"github.com/cloud-temple/terraform-provider-cloudtemple/internal/client"
7+
"github.com/cloud-temple/terraform-provider-cloudtemple/internal/provider/helpers"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
)
11+
12+
func resourceStorageAccount() *schema.Resource {
13+
return &schema.Resource{
14+
Description: "Create and manage object storage storage accounts.",
15+
16+
CreateContext: objectStorageStorageAccountCreate,
17+
ReadContext: objectStorageStorageAccountRead,
18+
DeleteContext: objectStorageStorageAccountDelete,
19+
Importer: &schema.ResourceImporter{
20+
StateContext: schema.ImportStatePassthroughContext,
21+
},
22+
23+
Schema: map[string]*schema.Schema{
24+
// In
25+
"name": {
26+
Type: schema.TypeString,
27+
Required: true,
28+
ForceNew: true,
29+
Description: "The name of the storage account.",
30+
},
31+
32+
// Out
33+
"id": {
34+
Type: schema.TypeString,
35+
Computed: true,
36+
Description: "The ID of the storage account.",
37+
},
38+
"access_key_id": {
39+
Type: schema.TypeString,
40+
Computed: true,
41+
Description: "The access key ID of the storage account.",
42+
},
43+
"access_secret_key": {
44+
Type: schema.TypeString,
45+
Computed: true,
46+
Sensitive: true,
47+
Description: "The secret access key of the storage account. This is only available during creation.",
48+
},
49+
"arn": {
50+
Type: schema.TypeString,
51+
Computed: true,
52+
Description: "The ARN of the storage account.",
53+
},
54+
"create_date": {
55+
Type: schema.TypeString,
56+
Computed: true,
57+
Description: "The creation date of the storage account.",
58+
},
59+
"path": {
60+
Type: schema.TypeString,
61+
Computed: true,
62+
Description: "The path of the storage account.",
63+
},
64+
"tags": {
65+
Type: schema.TypeList,
66+
Computed: true,
67+
Description: "The tags associated with the storage account.",
68+
Elem: &schema.Resource{
69+
Schema: map[string]*schema.Schema{
70+
"key": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
},
74+
"value": {
75+
Type: schema.TypeString,
76+
Computed: true,
77+
},
78+
},
79+
},
80+
},
81+
},
82+
}
83+
}
84+
85+
func objectStorageStorageAccountCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
86+
c := getClient(meta)
87+
88+
createResp, err := c.ObjectStorage().StorageAccount().Create(ctx, &client.CreateStorageAccountRequest{
89+
Name: d.Get("name").(string),
90+
})
91+
if err != nil {
92+
return diag.Errorf("failed to create storage account: %s", err)
93+
}
94+
95+
// Set ID - the name is the ID
96+
d.SetId(d.Get("name").(string))
97+
98+
// Set the sensitive keys from creation response
99+
d.Set("access_key_id", createResp.AccessKeyID)
100+
d.Set("access_secret_key", createResp.SecretAccessKey)
101+
102+
return objectStorageStorageAccountRead(ctx, d, meta)
103+
}
104+
105+
func objectStorageStorageAccountRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
106+
c := getClient(meta)
107+
var diags diag.Diagnostics
108+
109+
storageAccount, err := c.ObjectStorage().StorageAccount().Read(ctx, d.Id())
110+
if err != nil {
111+
return diag.Errorf("failed to read storage account: %s", err)
112+
}
113+
if storageAccount == nil {
114+
d.SetId("")
115+
return nil
116+
}
117+
118+
// Use helper to flatten the storage account data
119+
storageAccountData := helpers.FlattenStorageAccount(storageAccount)
120+
121+
// Add tags
122+
tags := make([]map[string]interface{}, len(storageAccount.Tags))
123+
for i, tag := range storageAccount.Tags {
124+
tags[i] = map[string]interface{}{
125+
"key": tag.Key,
126+
"value": tag.Value,
127+
}
128+
}
129+
storageAccountData["tags"] = tags
130+
131+
// Set all data in state (except sensitive keys which are only available at creation)
132+
for k, v := range storageAccountData {
133+
if err := d.Set(k, v); err != nil {
134+
return diag.FromErr(err)
135+
}
136+
}
137+
138+
return diags
139+
}
140+
141+
func objectStorageStorageAccountDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
142+
c := getClient(meta)
143+
144+
activityId, err := c.ObjectStorage().StorageAccount().Delete(ctx, d.Id())
145+
if err != nil {
146+
return diag.Errorf("failed to delete storage account: %s", err)
147+
}
148+
if _, err := c.Activity().WaitForCompletion(ctx, activityId, getWaiterOptions(ctx)); err != nil {
149+
return diag.Errorf("failed to delete storage account: %s", err)
150+
}
151+
152+
return nil
153+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package provider
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
7+
)
8+
9+
func TestAccResourceObjectStorageStorageAccount_Basic(t *testing.T) {
10+
resource.Test(t, resource.TestCase{
11+
PreCheck: func() { testAccPreCheck(t) },
12+
ProviderFactories: providerFactories,
13+
Steps: []resource.TestStep{
14+
{
15+
Config: testAccResourceObjectStorageStorageAccountBasic,
16+
Check: resource.ComposeAggregateTestCheckFunc(
17+
resource.TestCheckResourceAttr("cloudtemple_object_storage_storage_account.test", "name", "terraform-test-storage-account"),
18+
resource.TestCheckResourceAttrSet("cloudtemple_object_storage_storage_account.test", "id"),
19+
resource.TestCheckResourceAttrSet("cloudtemple_object_storage_storage_account.test", "access_key_id"),
20+
resource.TestCheckResourceAttrSet("cloudtemple_object_storage_storage_account.test", "access_secret_key"),
21+
),
22+
},
23+
},
24+
})
25+
}
26+
27+
const testAccResourceObjectStorageStorageAccountBasic = `
28+
resource "cloudtemple_object_storage_storage_account" "test" {
29+
name = "terraform-test-storage-account"
30+
}
31+
`

0 commit comments

Comments
 (0)