Skip to content

Commit d1f9bdd

Browse files
authored
Merge pull request #988 from timofurrer/feature/delete-project-mirror
resource/gitlab_project_mirror: Support deletion on destroy
2 parents 39bf02f + 7a23ffc commit d1f9bdd

File tree

4 files changed

+103
-53
lines changed

4 files changed

+103
-53
lines changed

docs/resources/project_mirror.md

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ description: |-
66
The gitlab_project_mirror resource allows to manage the lifecycle of a project mirror.
77
This is for pushing changes to a remote repository. Pull Mirroring can be configured using a combination of the
88
importurl, mirror, and mirrortriggerbuilds properties on the gitlabproject resource.
9+
-> Destroy Behavior GitLab 14.10 introduced an API endpoint to delete a project mirror.
10+
Therefore, for GitLab 14.10 and newer the project mirror will be destroyed when the resource is destroyed.
11+
For older versions, the mirror will be disabled and the resource will be destroyed.
912
Upstream API: GitLab REST API docs https://docs.gitlab.com/ee/api/remote_mirrors.html
1013
---
1114

@@ -16,6 +19,10 @@ The `gitlab_project_mirror` resource allows to manage the lifecycle of a project
1619
This is for *pushing* changes to a remote repository. *Pull Mirroring* can be configured using a combination of the
1720
import_url, mirror, and mirror_trigger_builds properties on the gitlab_project resource.
1821

22+
-> **Destroy Behavior** GitLab 14.10 introduced an API endpoint to delete a project mirror.
23+
Therefore, for GitLab 14.10 and newer the project mirror will be destroyed when the resource is destroyed.
24+
For older versions, the mirror will be disabled and the resource will be destroyed.
25+
1926
**Upstream API**: [GitLab REST API docs](https://docs.gitlab.com/ee/api/remote_mirrors.html)
2027

2128
## Example Usage

go.sum

-4
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,6 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC
309309
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
310310
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
311311
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
312-
github.com/xanzy/go-gitlab v0.63.0 h1:a9fXpKWykUS6dowapFej/2Wjf4aOAEFC1q2ZIcz4IpI=
313-
github.com/xanzy/go-gitlab v0.63.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
314312
github.com/xanzy/go-gitlab v0.64.0 h1:rMgQdW9S1w3qvNAH2LYpFd2xh7KNLk+JWJd7sorNuTc=
315313
github.com/xanzy/go-gitlab v0.64.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM=
316314
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
@@ -413,8 +411,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
413411
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
414412
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
415413
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
416-
golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4=
417-
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
418414
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8=
419415
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
420416
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=

internal/provider/resource_gitlab_project_mirror.go

+74-43
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ var _ = registerResource("gitlab_project_mirror", func() *schema.Resource {
1919
This is for *pushing* changes to a remote repository. *Pull Mirroring* can be configured using a combination of the
2020
import_url, mirror, and mirror_trigger_builds properties on the gitlab_project resource.
2121
22+
-> **Destroy Behavior** GitLab 14.10 introduced an API endpoint to delete a project mirror.
23+
Therefore, for GitLab 14.10 and newer the project mirror will be destroyed when the resource is destroyed.
24+
For older versions, the mirror will be disabled and the resource will be destroyed.
25+
2226
**Upstream API**: [GitLab REST API docs](https://docs.gitlab.com/ee/api/remote_mirrors.html)`,
2327

2428
CreateContext: resourceGitlabProjectMirrorCreate,
@@ -139,29 +143,35 @@ func resourceGitlabProjectMirrorUpdate(ctx context.Context, d *schema.ResourceDa
139143
return resourceGitlabProjectMirrorRead(ctx, d, meta)
140144
}
141145

142-
// Documented remote mirrors API does not support a delete method, instead mirror is disabled.
143146
func resourceGitlabProjectMirrorDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
144147
client := meta.(*gitlab.Client)
145148

146-
enabled := false
147-
148149
mirrorID := d.Get("mirror_id").(int)
149150
projectID := d.Get("project").(string)
150-
onlyProtectedBranches := d.Get("only_protected_branches").(bool)
151-
keepDivergentRefs := d.Get("keep_divergent_refs").(bool)
152151

153-
options := gitlab.EditProjectMirrorOptions{
154-
Enabled: &enabled,
155-
OnlyProtectedBranches: &onlyProtectedBranches,
156-
KeepDivergentRefs: &keepDivergentRefs,
157-
}
158-
log.Printf("[DEBUG] Disable gitlab project mirror %v for %s", mirrorID, projectID)
159-
160-
_, _, err := client.ProjectMirrors.EditProjectMirror(projectID, mirrorID, &options, gitlab.WithContext(ctx))
152+
isDeleteSupported, err := isGitLabVersionAtLeast(ctx, client, "14.10")()
161153
if err != nil {
162154
return diag.FromErr(err)
163155
}
164156

157+
if isDeleteSupported {
158+
log.Printf("[DEBUG] delete gitlab project mirror %v for %s", mirrorID, projectID)
159+
160+
_, err := client.ProjectMirrors.DeleteProjectMirror(projectID, mirrorID, gitlab.WithContext(ctx))
161+
if err != nil {
162+
return diag.FromErr(err)
163+
}
164+
} else {
165+
// NOTE: this code only exists to support GitLab < 14.10.
166+
// It can be removed once ~ GitLab 15.2 is out and supported.
167+
options := gitlab.EditProjectMirrorOptions{Enabled: gitlab.Bool(false)}
168+
log.Printf("[DEBUG] Disable gitlab project mirror %v for %s", mirrorID, projectID)
169+
_, _, err := client.ProjectMirrors.EditProjectMirror(projectID, mirrorID, &options, gitlab.WithContext(ctx))
170+
if err != nil {
171+
return diag.FromErr(err)
172+
}
173+
}
174+
165175
return nil
166176
}
167177

@@ -170,42 +180,19 @@ func resourceGitlabProjectMirrorRead(ctx context.Context, d *schema.ResourceData
170180

171181
ids := strings.Split(d.Id(), ":")
172182
projectID := ids[0]
173-
mirrorID := ids[1]
174-
integerMirrorID, err := strconv.Atoi(mirrorID)
183+
rawMirrorID := ids[1]
184+
mirrorID, err := strconv.Atoi(rawMirrorID)
175185
if err != nil {
176186
return diag.FromErr(err)
177187
}
178188
log.Printf("[DEBUG] read gitlab project mirror %s id %v", projectID, mirrorID)
179-
180-
var mirror *gitlab.ProjectMirror
181-
found := false
182-
183-
opts := &gitlab.ListProjectMirrorOptions{
184-
Page: 1,
185-
PerPage: 20,
186-
}
187-
188-
for {
189-
mirrors, response, err := client.ProjectMirrors.ListProjectMirror(projectID, opts, gitlab.WithContext(ctx))
190-
if err != nil {
191-
return diag.FromErr(err)
192-
}
193-
194-
for _, m := range mirrors {
195-
log.Printf("[DEBUG] project mirror found %v", m.ID)
196-
if m.ID == integerMirrorID {
197-
mirror = m
198-
found = true
199-
break
200-
}
201-
}
202-
if response.CurrentPage >= response.TotalPages {
203-
break
204-
}
205-
opts.Page++
189+
mirror, err := resourceGitLabProjectMirrorGetMirror(ctx, client, projectID, mirrorID)
190+
if err != nil {
191+
return diag.FromErr(err)
206192
}
207193

208-
if !found {
194+
if mirror == nil {
195+
log.Printf("[DEBUG] mirror %d in project %s not found, removing from state", mirrorID, projectID)
209196
d.SetId("")
210197
return nil
211198
}
@@ -222,3 +209,47 @@ func resourceGitlabProjectMirrorSetToState(d *schema.ResourceData, projectMirror
222209
d.Set("project", projectID)
223210
d.Set("url", projectMirror.URL)
224211
}
212+
213+
func resourceGitLabProjectMirrorGetMirror(ctx context.Context, client *gitlab.Client, projectID string, mirrorID int) (*gitlab.ProjectMirror, error) {
214+
isGetProjectMirrorSupported, err := isGitLabVersionAtLeast(ctx, client, "14.10")()
215+
if err != nil {
216+
return nil, err
217+
}
218+
219+
var mirror *gitlab.ProjectMirror
220+
221+
if isGetProjectMirrorSupported {
222+
mirror, _, err = client.ProjectMirrors.GetProjectMirror(projectID, mirrorID, gitlab.WithContext(ctx))
223+
if err != nil {
224+
if is404(err) {
225+
return nil, nil
226+
}
227+
return nil, err
228+
}
229+
} else {
230+
// NOTE: remove this branch and move logic back to Read() function when GitLab older than 14.10 are not longer supported by this provider
231+
found := false
232+
options := &gitlab.ListProjectMirrorOptions{
233+
Page: 1,
234+
PerPage: 20,
235+
}
236+
237+
for options.Page != 0 && !found {
238+
mirrors, resp, err := client.ProjectMirrors.ListProjectMirror(projectID, options, gitlab.WithContext(ctx))
239+
if err != nil {
240+
return nil, err
241+
}
242+
243+
for _, m := range mirrors {
244+
if m.ID == mirrorID {
245+
mirror = m
246+
found = true
247+
break
248+
}
249+
}
250+
options.Page = resp.NextPage
251+
}
252+
}
253+
254+
return mirror, nil
255+
}

internal/provider/resource_gitlab_project_mirror_test.go

+22-6
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,28 @@ func testAccCheckGitlabProjectMirrorAttributes(mirror *gitlab.ProjectMirror, wan
146146
}
147147

148148
func testAccCheckGitlabProjectMirrorDestroy(s *terraform.State) error {
149-
var mirror gitlab.ProjectMirror
150-
if err := testAccCheckGitlabProjectMirrorExists("gitlab_project_mirror.foo", &mirror)(s); err != nil {
151-
return err
152-
}
153-
if mirror.Enabled {
154-
return errors.New("mirror is enabled")
149+
for _, rs := range s.RootModule().Resources {
150+
if rs.Type != "gitlab_project_mirror" {
151+
continue
152+
}
153+
154+
projectID, rawMirrorID, err := parseTwoPartID(rs.Primary.ID)
155+
if err != nil {
156+
return err
157+
}
158+
mirrorID, err := strconv.Atoi(rawMirrorID)
159+
if err != nil {
160+
return err
161+
}
162+
163+
mirror, _, err := testGitlabClient.ProjectMirrors.GetProjectMirror(projectID, mirrorID)
164+
if err == nil && mirror != nil && mirror.ID == mirrorID {
165+
return fmt.Errorf("Project Mirror still exists")
166+
}
167+
if err != nil && !is404(err) {
168+
return err
169+
}
170+
return nil
155171
}
156172
return nil
157173
}

0 commit comments

Comments
 (0)