Skip to content

Commit aec4d64

Browse files
committed
Add schema migrations
Signed-off-by: Timo Sand <timo.sand@f-secure.com>
1 parent c4bde87 commit aec4d64

3 files changed

Lines changed: 173 additions & 6 deletions

github/resource_github_repository_autolink_reference.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {
3030
CustomizeDiff: diffRepository,
3131

3232
SchemaVersion: 1,
33+
StateUpgraders: []schema.StateUpgrader{
34+
{
35+
Type: resourceGithubRepositoryAutolinkReferenceV0().CoreConfigSchema().ImpliedType(),
36+
Upgrade: resourceGithubRepositoryAutolinkReferenceStateUpgradeV0,
37+
Version: 0,
38+
},
39+
},
3340
Schema: map[string]*schema.Schema{
3441
"repository": {
3542
Type: schema.TypeString,
@@ -73,7 +80,7 @@ func resourceGithubRepositoryAutolinkReference() *schema.Resource {
7380
}
7481
}
7582

76-
func resourceGithubRepositoryAutolinkReferenceImport(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) {
83+
func resourceGithubRepositoryAutolinkReferenceImport(ctx context.Context, d *schema.ResourceData, m any) ([]*schema.ResourceData, error) {
7784
parts := strings.Split(d.Id(), "/")
7885
if len(parts) != 2 {
7986
return nil, fmt.Errorf("invalid ID specified: supplied ID must be written as <repository>/<autolink_reference_id>")
@@ -82,8 +89,9 @@ func resourceGithubRepositoryAutolinkReferenceImport(ctx context.Context, d *sch
8289
repository := parts[0]
8390
id := parts[1]
8491

85-
client := meta.(*Owner).v3client
86-
owner := meta.(*Owner).name
92+
meta, _ := m.(*Owner)
93+
client := meta.v3client
94+
owner := meta.name
8795

8896
// If the second part of the provided ID isn't an integer, assume that the
8997
// caller provided the key prefix for the autolink reference, and look up
@@ -117,7 +125,7 @@ func resourceGithubRepositoryAutolinkReferenceImport(ctx context.Context, d *sch
117125
}
118126

119127
func resourceGithubRepositoryAutolinkReferenceCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
120-
meta := m.(*Owner)
128+
meta, _ := m.(*Owner)
121129
client := meta.v3client
122130
owner := meta.name
123131

@@ -153,7 +161,7 @@ func resourceGithubRepositoryAutolinkReferenceCreate(ctx context.Context, d *sch
153161
func resourceGithubRepositoryAutolinkReferenceRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
154162
ctx = tflog.SetField(ctx, "id", d.Id())
155163

156-
meta := m.(*Owner)
164+
meta, _ := m.(*Owner)
157165
client := meta.v3client
158166
owner := meta.name
159167

@@ -187,6 +195,15 @@ func resourceGithubRepositoryAutolinkReferenceRead(ctx context.Context, d *schem
187195
if err = d.Set("repository", repoName); err != nil {
188196
return diag.FromErr(err)
189197
}
198+
199+
repo, _, err := client.Repositories.Get(ctx, owner, repoName)
200+
if err != nil {
201+
return diag.FromErr(err)
202+
}
203+
if err = d.Set("repository_id", int(repo.GetID())); err != nil {
204+
return diag.FromErr(err)
205+
}
206+
190207
if err = d.Set("key_prefix", autolinkRef.KeyPrefix); err != nil {
191208
return diag.FromErr(err)
192209
}
@@ -212,7 +229,7 @@ func resourceGithubRepositoryAutolinkReferenceUpdate(ctx context.Context, d *sch
212229
func resourceGithubRepositoryAutolinkReferenceDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
213230
ctx = tflog.SetField(ctx, "id", d.Id())
214231

215-
meta := m.(*Owner)
232+
meta, _ := m.(*Owner)
216233
client := meta.v3client
217234
owner := meta.name
218235

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-log/tflog"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
)
10+
11+
func resourceGithubRepositoryAutolinkReferenceV0() *schema.Resource {
12+
return &schema.Resource{
13+
Schema: map[string]*schema.Schema{
14+
"repository": {
15+
Type: schema.TypeString,
16+
Required: true,
17+
ForceNew: true,
18+
},
19+
"key_prefix": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
ForceNew: true,
23+
},
24+
"target_url_template": {
25+
Type: schema.TypeString,
26+
Required: true,
27+
ForceNew: true,
28+
},
29+
"is_alphanumeric": {
30+
Type: schema.TypeBool,
31+
Optional: true,
32+
ForceNew: true,
33+
Default: true,
34+
},
35+
"etag": {
36+
Type: schema.TypeString,
37+
Computed: true,
38+
},
39+
},
40+
}
41+
}
42+
43+
func resourceGithubRepositoryAutolinkReferenceStateUpgradeV0(ctx context.Context, rawState map[string]any, m any) (map[string]any, error) {
44+
tflog.Debug(ctx, "GitHub Repository Autolink Reference state before v0 migration", rawState)
45+
46+
meta, _ := m.(*Owner)
47+
client := meta.v3client
48+
owner := meta.name
49+
50+
repoName := ""
51+
if v, ok := rawState["repository"]; ok {
52+
if s, ok := v.(string); ok && s != "" {
53+
repoName = s
54+
}
55+
}
56+
if repoName == "" {
57+
return nil, fmt.Errorf("state upgrade v0: repository is not a string or not set")
58+
}
59+
60+
repo, _, err := client.Repositories.Get(ctx, owner, repoName)
61+
if err != nil {
62+
return nil, fmt.Errorf("state upgrade v0: failed to retrieve repository '%s': %w", repoName, err)
63+
}
64+
65+
rawState["repository_id"] = int(repo.GetID())
66+
67+
tflog.Debug(ctx, "GitHub Repository Autolink Reference state after v0 migration", rawState)
68+
69+
return rawState, nil
70+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package github
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"testing"
8+
9+
"github.com/google/go-cmp/cmp"
10+
"github.com/google/go-github/v88/github"
11+
)
12+
13+
func buildMockResponsesForRepositoryAutolinkReferenceMigrationV0toV1(mockOwner, mockRepo string, wantRepoID int) []*mockResponse {
14+
responseBodyJSON, err := json.Marshal(github.Repository{
15+
ID: new(int64(wantRepoID)),
16+
Name: new(mockRepo),
17+
})
18+
if err != nil {
19+
panic(fmt.Sprintf("error marshalling repository response: %s", err))
20+
}
21+
22+
return []*mockResponse{{
23+
ExpectedUri: fmt.Sprintf("/repos/%s/%s", mockOwner, mockRepo),
24+
ExpectedHeaders: map[string]string{
25+
"Accept": "application/vnd.github.scarlet-witch-preview+json, application/vnd.github.mercy-preview+json, application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json",
26+
},
27+
ResponseBody: string(responseBodyJSON),
28+
StatusCode: http.StatusOK,
29+
}}
30+
}
31+
32+
func Test_resourceGithubRepositoryAutolinkReferenceStateUpgradeV0toV1(t *testing.T) {
33+
t.Parallel()
34+
35+
for _, d := range []struct {
36+
testName string
37+
rawState map[string]any
38+
want map[string]any
39+
shouldError bool
40+
}{
41+
{
42+
testName: "adds_repository_id",
43+
rawState: map[string]any{
44+
"id": "12345",
45+
"repository": "test-repo",
46+
"key_prefix": "TEST-",
47+
"target_url_template": "https://example.com/TEST-<num>",
48+
"is_alphanumeric": true,
49+
},
50+
want: map[string]any{
51+
"id": "12345",
52+
"repository": "test-repo",
53+
"repository_id": 1234567890,
54+
"key_prefix": "TEST-",
55+
"target_url_template": "https://example.com/TEST-<num>",
56+
"is_alphanumeric": true,
57+
},
58+
shouldError: false,
59+
},
60+
} {
61+
t.Run(d.testName, func(t *testing.T) {
62+
t.Parallel()
63+
64+
meta := &Owner{name: "test-org"}
65+
ts := githubApiMock(buildMockResponsesForRepositoryAutolinkReferenceMigrationV0toV1(meta.name, "test-repo", 1234567890))
66+
defer ts.Close()
67+
68+
meta.v3client = mustGitHubClient(t, ts.URL)
69+
70+
got, err := resourceGithubRepositoryAutolinkReferenceStateUpgradeV0(t.Context(), d.rawState, meta)
71+
if (err != nil) != d.shouldError {
72+
t.Fatalf("unexpected error state: got error %v, shouldError %v", err, d.shouldError)
73+
}
74+
75+
if diff := cmp.Diff(got, d.want); diff != "" && !d.shouldError {
76+
t.Fatalf("got %+v, want %+v, diff %s", got, d.want, diff)
77+
}
78+
})
79+
}
80+
}

0 commit comments

Comments
 (0)