Skip to content

Commit cfa6d0e

Browse files
committed
Convert resourceGithubActionsSecret to use StateUpgraders for schema migrations
Signed-off-by: Timo Sand <[email protected]>
1 parent 4e94c7d commit cfa6d0e

3 files changed

Lines changed: 93 additions & 71 deletions

File tree

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,66 @@
11
package github
22

33
import (
4-
"fmt"
4+
"context"
55
"log"
66

7-
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
88
)
99

10-
func resourceGithubActionsSecretMigrateState(v int, is *terraform.InstanceState, meta any) (*terraform.InstanceState, error) {
11-
switch v {
12-
case 0:
13-
log.Printf("[INFO] Found GitHub Actions Secret State v0; migrating to v1")
14-
return migrateGithubActionsSecretStateV0toV1(is)
15-
default:
16-
return is, fmt.Errorf("unexpected schema version: %d", v)
10+
func resourceGithubActionsSecretResourceV0() *schema.Resource {
11+
return &schema.Resource{
12+
Schema: map[string]*schema.Schema{
13+
"repository": {
14+
Type: schema.TypeString,
15+
Required: true,
16+
ForceNew: true,
17+
Description: "Name of the repository.",
18+
},
19+
"secret_name": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
ForceNew: true,
23+
Description: "Name of the secret.",
24+
ValidateDiagFunc: validateSecretNameFunc,
25+
},
26+
"encrypted_value": {
27+
Type: schema.TypeString,
28+
ForceNew: true,
29+
Optional: true,
30+
Sensitive: true,
31+
ConflictsWith: []string{"plaintext_value"},
32+
Description: "Encrypted value of the secret using the GitHub public key in Base64 format.",
33+
},
34+
"plaintext_value": {
35+
Type: schema.TypeString,
36+
ForceNew: true,
37+
Optional: true,
38+
Sensitive: true,
39+
ConflictsWith: []string{"encrypted_value"},
40+
Description: "Plaintext value of the secret to be encrypted.",
41+
},
42+
"created_at": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
Description: "Date of 'actions_secret' creation.",
46+
},
47+
"updated_at": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
Description: "Date of 'actions_secret' update.",
51+
},
52+
},
1753
}
1854
}
1955

20-
func migrateGithubActionsSecretStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
21-
if is.Empty() {
22-
log.Printf("[DEBUG] Empty InstanceState; nothing to migrate.")
23-
return is, nil
24-
}
25-
26-
log.Printf("[DEBUG] GitHub Actions Secret Attributes before migration: %#v", is.Attributes)
27-
56+
func resourceGithubActionsSecretInstanceStateUpgradeV0(ctx context.Context, rawState map[string]any, meta any) (map[string]any, error) {
57+
log.Printf("[DEBUG] GitHub Actions Secret State before migration: %#v", rawState)
2858
// Add the destroy_on_drift field with default value true if it doesn't exist
29-
if _, ok := is.Attributes["destroy_on_drift"]; !ok {
30-
is.Attributes["destroy_on_drift"] = "true"
59+
if _, ok := rawState["destroy_on_drift"]; !ok {
60+
rawState["destroy_on_drift"] = true
3161
}
3262

33-
log.Printf("[DEBUG] GitHub Actions Secret Attributes after State Migration: %#v", is.Attributes)
63+
log.Printf("[DEBUG] GitHub Actions Secret State after migration: %#v", rawState)
3464

35-
return is, nil
65+
return rawState, nil
3666
}

github/migrate_github_actions_secret_test.go

Lines changed: 35 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,53 @@ package github
33
import (
44
"reflect"
55
"testing"
6-
7-
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
86
)
97

10-
func TestMigrateGithubActionsSecretStateV0toV1(t *testing.T) {
11-
// Secret without destroy_on_drift should get default value
12-
oldAttributes := map[string]string{
8+
func testResourceGithubActionsSecretInstanceStateDataV0() map[string]any {
9+
return map[string]any{
1310
"id": "test-secret",
1411
"repository": "test-repo",
1512
"secret_name": "test-secret",
1613
"created_at": "2023-01-01T00:00:00Z",
1714
"updated_at": "2023-01-01T00:00:00Z",
1815
"plaintext_value": "secret-value",
1916
}
17+
}
2018

21-
newState, err := migrateGithubActionsSecretStateV0toV1(&terraform.InstanceState{
22-
ID: "test-secret",
23-
Attributes: oldAttributes,
24-
})
25-
if err != nil {
26-
t.Fatal(err)
27-
}
28-
29-
expectedAttributes := map[string]string{
30-
"id": "test-secret",
31-
"repository": "test-repo",
32-
"secret_name": "test-secret",
33-
"created_at": "2023-01-01T00:00:00Z",
34-
"updated_at": "2023-01-01T00:00:00Z",
35-
"plaintext_value": "secret-value",
36-
"destroy_on_drift": "true",
37-
}
38-
if !reflect.DeepEqual(newState.Attributes, expectedAttributes) {
39-
t.Fatalf("Expected attributes:\n%#v\n\nGiven:\n%#v\n",
40-
expectedAttributes, newState.Attributes)
41-
}
19+
func testResourceGithubActionsSecretInstanceStateDataV0_WithDrift() map[string]any {
20+
v0 := testResourceGithubActionsSecretInstanceStateDataV0()
21+
v0["destroy_on_drift"] = false
22+
return v0
23+
}
4224

43-
// Secret with existing destroy_on_drift should be preserved
44-
oldAttributesWithDrift := map[string]string{
45-
"id": "test-secret",
46-
"repository": "test-repo",
47-
"secret_name": "test-secret",
48-
"destroy_on_drift": "false",
49-
}
25+
func testResourceGithubActionsSecretInstanceStateDataV1() map[string]any {
26+
v0 := testResourceGithubActionsSecretInstanceStateDataV0()
27+
v0["destroy_on_drift"] = true
28+
return v0
29+
}
5030

51-
newState2, err := migrateGithubActionsSecretStateV0toV1(&terraform.InstanceState{
52-
ID: "test-secret",
53-
Attributes: oldAttributesWithDrift,
31+
func TestGithub_MigrateActionsSecretStateV0toV1(t *testing.T) {
32+
t.Run("without destroy_on_drift", func(t *testing.T) {
33+
expected := testResourceGithubActionsSecretInstanceStateDataV1()
34+
actual, err := resourceGithubActionsSecretInstanceStateUpgradeV0(t.Context(), testResourceGithubActionsSecretInstanceStateDataV0(), nil)
35+
if err != nil {
36+
t.Fatalf("error migrating state: %s", err)
37+
}
38+
39+
if !reflect.DeepEqual(expected, actual) {
40+
t.Fatalf("\n\nexpected:\n\n%#v\n\ngot:\n\n%#v\n\n", expected, actual)
41+
}
5442
})
55-
if err != nil {
56-
t.Fatal(err)
57-
}
5843

59-
expectedAttributesWithDrift := map[string]string{
60-
"id": "test-secret",
61-
"repository": "test-repo",
62-
"secret_name": "test-secret",
63-
"destroy_on_drift": "false",
64-
}
65-
if !reflect.DeepEqual(newState2.Attributes, expectedAttributesWithDrift) {
66-
t.Fatalf("Expected attributes:\n%#v\n\nGiven:\n%#v\n",
67-
expectedAttributesWithDrift, newState2.Attributes)
68-
}
44+
t.Run("with destroy_on_drift", func(t *testing.T) {
45+
expected := testResourceGithubActionsSecretInstanceStateDataV0_WithDrift()
46+
actual, err := resourceGithubActionsSecretInstanceStateUpgradeV0(t.Context(), testResourceGithubActionsSecretInstanceStateDataV0_WithDrift(), nil)
47+
if err != nil {
48+
t.Fatalf("error migrating state: %s", err)
49+
}
50+
51+
if !reflect.DeepEqual(expected, actual) {
52+
t.Fatalf("\n\nexpected:\n\n%#v\n\ngot:\n\n%#v\n\n", expected, actual)
53+
}
54+
})
6955
}

github/resource_github_actions_secret.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ func resourceGithubActionsSecret() *schema.Resource {
2626
// Schema migration added to handle the addition of destroy_on_drift field
2727
// Resources created before this field was added need it populated with default value
2828
SchemaVersion: 1,
29-
MigrateState: resourceGithubActionsSecretMigrateState,
29+
StateUpgraders: []schema.StateUpgrader{
30+
{
31+
Type: resourceGithubActionsSecretResourceV0().CoreConfigSchema().ImpliedType(),
32+
Upgrade: resourceGithubActionsSecretInstanceStateUpgradeV0,
33+
Version: 0,
34+
},
35+
},
3036

3137
Schema: map[string]*schema.Schema{
3238
"repository": {

0 commit comments

Comments
 (0)