Skip to content

Commit ec78658

Browse files
refactor rules into skills. improve skills
1 parent 928dc55 commit ec78658

6 files changed

Lines changed: 106 additions & 48 deletions

File tree

.cursor/rules/general.mdc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ The old `resource_gateway_producer_*` resources are the legacy format of dynamic
5353
- **`Sensitive: true`** — secrets, passwords, private keys, API keys, tokens, client secrets
5454
- **`Default` type must match `Type`** — e.g. `Default: 0` for `TypeInt`, `Default: false` for `TypeBool` (never use string `"0"` or `"false"`)
5555
- **`ForceNew: true`** — for the item's identifier field (e.g. `name`)
56+
- **`DiffSuppressFunc: common.DiffSuppressOnLeadingSlash`** — for any field that holds an **Akeyless item path** (e.g. `name`, issuer name, cert issuer, signer, target path, folder path). The API returns these paths with a leading `/`; without the suppressor the plan is never empty.
5657
- **`id`** is a reserved field in Terraform — do not use it as a custom schema field name; use a prefixed name like `migration_id` instead
5758
- All `d.Set()` calls in read functions **must** check for errors
5859
- When updating tags, use `common.GetTagsForUpdate` to handle both add and remove

.cursor/rules/item-description-field.mdc

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
---
2-
description: Rules for adding a new command (resource/data source) to the Terraform provider
3-
globs: akeyless/*.go
4-
alwaysApply: false
2+
name: add-new-command
3+
description: Guides adding a new Terraform resource or data source end-to-end — SDK update, schema, CRUD, provider registration, tests, and formatting. Use when creating a new resource_*.go or data_source_*.go file, or when the user asks to add a new Terraform resource.
54
---
65

76
# Adding a New Command (Resource or Data Source)
87

9-
When adding a new resource or data source to the Terraform provider, follow these steps:
10-
118
## 1. Update the Akeyless SDK
129

1310
1. Run `go get -u github.com/akeylesslabs/akeyless-go/v5`
@@ -57,41 +54,41 @@ func resourceMyNewFeatureCreate(ctx context.Context, d *schema.ResourceData, m i
5754

5855
### Schema Field Rules
5956

60-
When defining schema fields, follow these conventions:
6157
- **`Sensitive: true`** — for secrets, passwords, private keys, API keys, tokens, and client secrets
6258
- **`Computed: true`** — when the field has server-side defaults (e.g. protection keys)
6359
- **`Default`** — must match the field's `Type` (e.g. `Default: 0` for `TypeInt`, `Default: false` for `TypeBool`; never use string `"0"` or `"false"`)
6460
- **`Required` / `Optional`** — according to the SDK command requirements. If `Optional` is true, `Required` can be omitted.
6561
- **`ForceNew: true`** — for the field (or few fields, in special cases) that identify the item (e.g. `name`)
62+
- **`DiffSuppressFunc: common.DiffSuppressOnLeadingSlash`** — for any field that holds an Akeyless item path (e.g. `name`, issuer, signer, target path, folder). The API returns paths with a leading `/`; without the suppressor the plan is never empty.
6663
- **`id`** — reserved by Terraform; do not use as a custom schema field
6764
- All `d.Set()` calls in read functions **must** check for errors
6865
- Read functions must set **every writable field** that the API response exposes (skip Sensitive fields the API won't return)
6966
- When a resource replaces a legacy one, add `DeprecationMessage` to the old resource pointing to the new one
7067
- The Update handler must use an "override" approach -- always set all fields, not just the ones that are explicitly configured. Set all fields that the SDK support to update.
7168

72-
## 3. Register the New Command
69+
## 4. Register the New Command
7370

7471
1. Open `akeyless/provider.go`.
7572
2. Add the new resource to `ResourcesMap` or data source to `DataSourcesMap` in the `Provider()` function.
7673
* Key: `akeyless_<name>` (e.g., `akeyless_my_new_feature`)
7774
* Value: Function call (e.g., `resourceMyNewFeature()`)
7875

79-
## 4. Documentation
76+
## 5. Documentation
8077

8178
Documentation is auto-generated.
8279

8380
1. Ensure all schema fields have clear `Description`s.
8481
2. Run `go generate` in the root directory.
8582
3. This will create the documentation file in `docs/resources/` or `docs/data-sources/`.
8683

87-
## 5. Testing
84+
## 6. Testing
8885

8986
1. Add tests to an existing or new test file (not required to create a separate file per resource).
9087
2. Implement acceptance tests using `resource.TestCase`.
9188
3. Try to cover as much as input arguments, especially the arguments that are unique to the resource.
9289
4. For arguments with default value, ensure the updateConfig (step 2) set them to empty. This will add coverage for the defaulting mechanism.
9390
5. Run tests: `make testacc TEST=./akeyless/resource_<name>_test.go` (or similar).
9491

95-
## 6. Format
92+
## 7. Format
9693

9794
Run `gofmt -w .` to ensure code style compliance.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
name: item-description-field
3+
description: Correct field to use for item descriptions in Read functions — ItemMetadata for DescribeItem, Description for specific Get endpoints. Use when implementing or reviewing d.Set("description", ...) in resource read functions.
4+
---
5+
6+
# Item Description Field Pattern
7+
8+
When reading item descriptions in resource Read functions, use the correct field based on the API call.
9+
10+
## DescribeItem API
11+
12+
Use `ItemMetadata`:
13+
14+
```go
15+
if rOut.ItemMetadata != nil {
16+
err = d.Set("description", *rOut.ItemMetadata)
17+
if err != nil {
18+
return err
19+
}
20+
}
21+
```
22+
23+
**Do not use** `ItemGeneralInfo.DisplayMetadata`.
24+
25+
## Specific Get Endpoints
26+
27+
Use the direct `Description` field from the response structure.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
name: test-fixture-setup
3+
description: Create test fixture dependencies (keys, issuers, targets, secrets) via SDK API calls in test setup, not via Terraform depends_on. Use when writing or reviewing acceptance tests that need pre-existing items, or when a test fails because a Terraform resource references an item that doesn't exist.
4+
---
5+
6+
# Test Fixture Setup
7+
8+
## Rule
9+
10+
When an acceptance test resource depends on a pre-existing item (e.g. a gateway config resource that references an SSH cert issuer), create that item **via the SDK API** in the test function body, not as a Terraform resource with `depends_on`.
11+
12+
**Why:** Terraform resources inside test configs can fail with ordering issues, and mixing infrastructure setup with the resource under test makes failures harder to diagnose. API-created fixtures are deterministic and independent of the Terraform run.
13+
14+
## Pattern
15+
16+
```go
17+
func TestMyResource(t *testing.T) {
18+
testutils.SkipIfNoGateway(t)
19+
20+
// 1. Create fixtures via API
21+
keyPath := testPath("my_key")
22+
testutils.CreateDfcKey(t, keyPath)
23+
t.Cleanup(func() {
24+
testutils.DeleteItem(t, keyPath)
25+
})
26+
27+
issuerPath := testPath("my_issuer")
28+
testutils.CreateSshCertIssuer(t, keyPath, issuerPath, "test")
29+
t.Cleanup(func() {
30+
testutils.DeleteItem(t, issuerPath)
31+
})
32+
33+
// 2. Reference fixtures by path in Terraform config
34+
config := fmt.Sprintf(`
35+
resource "akeyless_my_resource" "%v" {
36+
some_item_ref = "%v"
37+
other_field = "value1"
38+
}
39+
`, name, issuerPath)
40+
41+
configUpdate := fmt.Sprintf(`
42+
resource "akeyless_my_resource" "%v" {
43+
some_item_ref = "%v"
44+
other_field = "value2"
45+
}
46+
`, name, issuerPath)
47+
48+
testutils.TestGatewayConfigResource(t, providerFactories, config, configUpdate)
49+
}
50+
```
51+
52+
## Available Helpers
53+
54+
All in `akeyless/tests/testutils/testutils.go`:
55+
56+
| Helper | Creates | Requires |
57+
|--------|---------|----------|
58+
| `CreateDfcKey(t, name)` | DFC key (RSA1024) ||
59+
| `CreateProtectionKey(t, name)` | AES128-GCM key ||
60+
| `CreateSshCertIssuer(t, keyName, issuerName, users)` | SSH cert issuer | DFC key |
61+
| `CreatePkiCertIssuer(t, keyName, issuerName, destPath, cn, uriSan)` | PKI cert issuer | DFC key |
62+
| `CreateCertificate(t, certName, certB64, keyB64)` | Certificate item | Generated cert/key pair |
63+
| `CreateSecret(t, *TestSecret)` | Static secret ||
64+
| `DeleteItem(t, path)` || Always `defer` after create |
65+
| `DeleteItemIfExists(t, path)` || Silent if missing |
66+
67+
## Cleanup
68+
69+
Always `defer testutils.DeleteItem(t, path)` immediately after each create call, before the next create. This ensures cleanup runs in reverse order even if a later create fails.

.cursor/rules/update-existing-command.mdc renamed to .cursor/skills/update-existing-command/SKILL.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
---
2-
description: Rules for updating an existing command/resource in the Terraform provider
3-
globs: akeyless/*.go
4-
alwaysApply: false
2+
name: update-existing-command
3+
description: Guides updating an existing Terraform resource or data source with new fields or functionality — schema changes, CRUD updates, backward compatibility, and docs regeneration. Use when adding fields to an existing resource_*.go or data_source_*.go file.
54
---
65

76
# Updating an Existing Command/Resource
87

9-
When updating an existing command (resource or data source) to support new fields or functionality, follow these steps:
10-
118
## 1. Update the Akeyless SDK
129

1310
1. Run `go get -u github.com/akeylesslabs/akeyless-go/v5`
1411
2. Run `go mod tidy`
1512

16-
1713
## 2. Update the Resource/Data Source Implementation
1814

1915
1. Identify the relevant file in the `akeyless/` directory (e.g., `resource_<name>.go`).

0 commit comments

Comments
 (0)