forked from integrations/terraform-provider-github
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutil_diff.go
More file actions
162 lines (137 loc) · 4.2 KB
/
util_diff.go
File metadata and controls
162 lines (137 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package github
import (
"context"
"errors"
"fmt"
"log"
"net/http"
"github.com/google/go-github/v82/github"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// diffRepository checks if the repository has changed and forces a new resource if the repository ID does not match.
// The resource must have both "repository" and "repository_id" attributes.
func diffRepository(ctx context.Context, diff *schema.ResourceDiff, m any) error {
if len(diff.Id()) == 0 {
return nil
}
if diff.HasChange("repository") {
meta := m.(*Owner)
client := meta.v3client
owner := meta.name
var repoID int
if o, ok := diff.GetOk("repository_id"); ok {
if v, ok := o.(int); ok {
repoID = v
} else {
return fmt.Errorf("repository_id is not an int")
}
} else {
return fmt.Errorf("repository_id is not set")
}
var repoName string
if o, ok := diff.GetOk("repository"); ok {
if v, ok := o.(string); ok {
repoName = v
} else {
return fmt.Errorf("repository is not a string")
}
} else {
return fmt.Errorf("repository is not set")
}
repo, _, err := client.Repositories.Get(ctx, owner, repoName)
if err != nil {
var ghErr *github.ErrorResponse
if errors.As(err, &ghErr) {
if ghErr.Response.StatusCode != http.StatusNotFound {
return ghErr
}
log.Printf("[INFO] Repository %s not found when checking repository change diff %s", repoName, diff.Id())
} else {
return err
}
} else {
log.Printf("[INFO] Repository %s found when checking repository change diff %s", repoName, diff.Id())
if repoID != int(repo.GetID()) {
return diff.ForceNew("repository")
}
}
}
return nil
}
// diffSecret compares the remote_updated_at and updated_at fields to determine if the secret has changed remotely.
func diffSecret(ctx context.Context, diff *schema.ResourceDiff, _ any) error {
if len(diff.Id()) == 0 {
return nil
}
if diff.HasChange("remote_updated_at") {
remoteUpdatedAt := diff.Get("remote_updated_at").(string)
if len(remoteUpdatedAt) == 0 {
return nil
}
updatedAt := diff.Get("updated_at").(string)
if updatedAt != remoteUpdatedAt {
if len(updatedAt) == 0 {
return diff.SetNew("updated_at", remoteUpdatedAt)
}
return diff.SetNewComputed("updated_at")
}
}
return nil
}
// diffSecretVariableVisibility ensures that selected_repository_ids is only set when visibility is set to selected.
func diffSecretVariableVisibility(ctx context.Context, d *schema.ResourceDiff, _ any) error {
if len(d.Id()) == 0 {
return nil
}
visibility := d.Get("visibility").(string)
if visibility != "selected" {
if _, ok := d.GetOk("selected_repository_ids"); ok {
return fmt.Errorf("cannot use selected_repository_ids without visibility being set to selected")
}
}
return nil
}
// diffTeam compares the team_id and team_slug fields to determine if the team has changed.
func diffTeam(ctx context.Context, diff *schema.ResourceDiff, m any) error {
// Skip for new resources - no existing team_id to compare against
if len(diff.Id()) == 0 {
return nil
}
if diff.HasChange("team_slug") {
if isNewTeamID(ctx, diff, m) {
return diff.ForceNew("team_slug")
}
}
return nil
}
// helper function to determine if the team has changed or was renamed.
func isNewTeamID(ctx context.Context, diff *schema.ResourceDiff, m any) bool {
// Get old team_id from state
oldTeamID := toInt64(diff.Get("team_id"))
if oldTeamID == 0 {
return false
}
meta := m.(*Owner)
// Resolve new team_slug to team ID via API
oldTeamSlug, newTeamSlug := diff.GetChange("team_slug")
newTeamID, err := lookupTeamID(ctx, meta, newTeamSlug.(string))
if err != nil {
// If team doesn't exist or API fails, skip ForceNew check and let Read handle it
tflog.Debug(ctx, "Unable to resolve new team_slug to team ID, skipping ForceNew check", map[string]any{
"new_team_slug": newTeamSlug,
"error": err.Error(),
})
return false
}
if newTeamID != oldTeamID {
tflog.Debug(ctx, "Team ID changed, forcing new resource", map[string]any{
"old_team_id": oldTeamID,
"new_team_id": newTeamID,
"new_team_slug": newTeamSlug,
"old_team_slug": oldTeamSlug,
})
return true
}
return false
}