Skip to content

Commit 184bd65

Browse files
committed
Various fixes in SAML group link resource
1 parent cd3014a commit 184bd65

File tree

3 files changed

+98
-143
lines changed

3 files changed

+98
-143
lines changed

docs/resources/group_saml_link.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "gitlab_group_saml_link Resource - terraform-provider-gitlab"
4+
subcategory: ""
5+
description: |-
6+
The gitlab_group_saml_link resource allows to manage the lifecycle of an SAML integration with a group.
7+
Upstream API: GitLab REST API docs https://docs.gitlab.com/ee/api/groups.html#saml-group-links
8+
---
9+
10+
# gitlab_group_saml_link (Resource)
11+
12+
The `gitlab_group_saml_link` resource allows to manage the lifecycle of an SAML integration with a group.
13+
14+
**Upstream API**: [GitLab REST API docs](https://docs.gitlab.com/ee/api/groups.html#saml-group-links)
15+
16+
## Example Usage
17+
18+
```terraform
19+
resource "gitlab_group_saml_link" "test" {
20+
group_id = "12345"
21+
access_level = "Developer"
22+
saml_group_name = "samlgroupname1"
23+
}
24+
```
25+
26+
<!-- schema generated by tfplugindocs -->
27+
## Schema
28+
29+
### Required
30+
31+
- `access_level` (String) Access level for members of the SAML group. Valid values are: `Guest`, `Reporter`, `Developer`, `Maintainer`, `Owner`.
32+
- `group` (String) The ID or path of the group to add the SAML Group Link to.
33+
- `saml_group_name` (String) The name of the SAML group.
34+
35+
### Read-Only
36+
37+
- `id` (String) The ID of this resource.
38+
39+
## Import
40+
41+
Import is supported using the following syntax:
42+
43+
```shell
44+
# GitLab group saml links can be imported using an id made up of `group_id:saml_group_name`, e.g.
45+
terraform import gitlab_group_saml_link.test "12345:samlgroupname1"
46+
```

internal/provider/resource_gitlab_group_saml_link.go

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import (
1111
gitlab "github.com/xanzy/go-gitlab"
1212
)
1313

14-
var validGroupSamlLinkAccessLevelNames = []string{
15-
"Guest",
16-
"Reporter",
17-
"Developer",
18-
"Maintainer",
19-
"Owner",
20-
}
21-
2214
var _ = registerResource("gitlab_group_saml_link", func() *schema.Resource {
15+
validGroupSamlLinkAccessLevelNames := []string{
16+
"Guest",
17+
"Reporter",
18+
"Developer",
19+
"Maintainer",
20+
"Owner",
21+
}
22+
2323
return &schema.Resource{
2424
Description: `The ` + "`gitlab_group_saml_link`" + ` resource allows to manage the lifecycle of an SAML integration with a group.
2525
@@ -39,19 +39,19 @@ var _ = registerResource("gitlab_group_saml_link", func() *schema.Resource {
3939
Required: true,
4040
ForceNew: true,
4141
},
42-
"access_level": {
43-
Description: fmt.Sprintf("Minimum access level for members of the SAML group. Valid values are: %s", renderValueListForDocs(validGroupSamlLinkAccessLevelNames)),
44-
Type: schema.TypeString,
45-
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(validGroupSamlLinkAccessLevelNames, false)),
46-
Required: true,
47-
ForceNew: true,
48-
},
4942
"saml_group_name": {
5043
Description: "The name of the SAML group.",
5144
Type: schema.TypeString,
5245
Required: true,
5346
ForceNew: true,
5447
},
48+
"access_level": {
49+
Description: fmt.Sprintf("Access level for members of the SAML group. Valid values are: %s.", renderValueListForDocs(validGroupSamlLinkAccessLevelNames)),
50+
Type: schema.TypeString,
51+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(validGroupSamlLinkAccessLevelNames, false)),
52+
Required: true,
53+
ForceNew: true,
54+
},
5555
},
5656
}
5757
})
@@ -60,22 +60,21 @@ func resourceGitlabGroupSamlLinkCreate(ctx context.Context, d *schema.ResourceDa
6060
client := meta.(*gitlab.Client)
6161

6262
group := d.Get("group").(string)
63-
accessLevel := d.Get("access_level").(string)
6463
samlGroupName := d.Get("saml_group_name").(string)
64+
accessLevel := accessLevelNameToValue[d.Get("access_level").(string)]
6565

6666
options := &gitlab.AddGroupSAMLLinkOptions{
67-
AccessLevel: gitlab.String(accessLevel),
68-
SamlGroupName: gitlab.String(samlGroupName),
67+
SAMLGroupName: gitlab.String(samlGroupName),
68+
AccessLevel: gitlab.AccessLevel(accessLevel),
6969
}
7070

71-
log.Printf("[DEBUG] Create GitLab group SamlLink %s", d.Id())
71+
log.Printf("[DEBUG] Create GitLab Group SAML Link for group %q with name %q", group, samlGroupName)
7272
SamlLink, _, err := client.Groups.AddGroupSAMLLink(group, options, gitlab.WithContext(ctx))
7373
if err != nil {
7474
return diag.FromErr(err)
7575
}
7676

7777
d.SetId(buildTwoPartID(&group, &SamlLink.Name))
78-
7978
return resourceGitlabGroupSamlLinkRead(ctx, d, meta)
8079
}
8180

@@ -87,21 +86,21 @@ func resourceGitlabGroupSamlLinkRead(ctx context.Context, d *schema.ResourceData
8786
}
8887

8988
// Try to fetch all group links from GitLab
90-
log.Printf("[DEBUG] Read GitLab group SamlLinks %s", group)
89+
log.Printf("[DEBUG] Read GitLab Group SAML Link for group %q", group)
9190
samlLink, _, err := client.Groups.GetGroupSAMLLink(group, samlGroupName, nil, gitlab.WithContext(ctx))
9291
if err != nil {
9392
if is404(err) {
94-
log.Printf("[DEBUG] GitLab SAML Group Link %d, group ID %s not found, removing from state", samlGroupName, group)
93+
log.Printf("[DEBUG] GitLab SAML Group Link %s for group ID %s not found, removing from state", samlGroupName, group)
9594
d.SetId("")
9695
return nil
9796
}
9897
return diag.FromErr(err)
9998
}
10099

101100
d.Set("group", group)
102-
d.Set("access_level", samlLink.AccessLevel)
101+
d.Set("access_level", accessLevelValueToName[samlLink.AccessLevel])
103102
d.Set("saml_group_name", samlLink.Name)
104-
103+
105104
return nil
106105
}
107106

@@ -112,7 +111,7 @@ func resourceGitlabGroupSamlLinkDelete(ctx context.Context, d *schema.ResourceDa
112111
return diag.FromErr(parse_err)
113112
}
114113

115-
log.Printf("[DEBUG] Delete GitLab group SamlLink %s", d.Id())
114+
log.Printf("[DEBUG] Delete GitLab Group SAML Link for group %q with name %q", group, samlGroupName)
116115
_, err := client.Groups.DeleteGroupSAMLLink(group, samlGroupName, gitlab.WithContext(ctx))
117116
if err != nil {
118117
if is404(err) {

internal/provider/resource_gitlab_group_saml_link_test.go

Lines changed: 28 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -4,122 +4,70 @@
44
package provider
55

66
import (
7-
"errors"
87
"fmt"
98
"testing"
109

11-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
1210
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1311
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
14-
"github.com/xanzy/go-gitlab"
1512
)
1613

1714
func TestAccGitlabGroupSamlLink_basic(t *testing.T) {
18-
rInt := acctest.RandInt()
19-
resourceName := "gitlab_group_saml_link.foo"
15+
testAccCheckEE(t)
2016

21-
// PreCheck runs after Config so load test data here
22-
var samlLink gitlab.SAMLGroupLink
23-
testSamlLink := gitlab.SAMLGroupLink{
24-
Name: "test_saml_group",
25-
}
17+
testGroup := testAccCreateGroups(t, 1)[0]
2618

2719
resource.ParallelTest(t, resource.TestCase{
2820
ProviderFactories: providerFactories,
2921
CheckDestroy: testAccCheckGitlabGroupSamlLinkDestroy,
3022
Steps: []resource.TestStep{
3123

32-
// Create a group SAML link as a developer (uses testAccGitlabGroupLdapSamlCreateConfig for Config)
24+
// Create a group SAML link as a developer
3325
{
34-
SkipFunc: isRunningInCE,
3526
Config: fmt.Sprintf(`
36-
resource "gitlab_group_saml_link" "foo" {
37-
group_id = "%d"
38-
access_level = "Developer"
39-
saml_group_name = "%s"
40-
41-
}`, rInt, rInt, testSamlLink.Name),
42-
Check: resource.ComposeTestCheckFunc(
43-
testAccCheckGitlabGroupSamlLinkExists(resourceName, &samlLink)),
44-
},
27+
resource "gitlab_group_saml_link" "this" {
28+
group = "%d"
29+
access_level = "Developer"
30+
saml_group_name = "test_saml_group"
4531
46-
// Import the group SAML link (re-uses testAccGitlabGroupSamlLinkCreateConfig for Config)
32+
}
33+
`, testGroup.ID),
34+
},
35+
// Verify Import
4736
{
48-
SkipFunc: isRunningInCE,
49-
ResourceName: resourceName,
50-
ImportStateIdFunc: getGitlabGroupSamlLinkImportID(resourceName),
37+
ResourceName: "gitlab_group_saml_link.this",
5138
ImportState: true,
5239
ImportStateVerify: true,
5340
},
54-
55-
// Update the group SAML link to change the access level (uses testAccGitlabGroupSamlLinkUpdateConfig for Config)
41+
// Update the group SAML link to change the access level
5642
{
57-
SkipFunc: isRunningInCE,
5843
Config: fmt.Sprintf(`
59-
resource "gitlab_group_saml_link" "foo" {
60-
group_id = "%d"
61-
access_level = "Maintainer"
62-
saml_group_name = "%s"
63-
}`, rInt, rInt, testSamlLink.Name),
64-
Check: resource.ComposeTestCheckFunc(
65-
testAccCheckGitlabGroupSamlLinkExists(resourceName, &samlLink)),
44+
resource "gitlab_group_saml_link" "this" {
45+
group = "%d"
46+
access_level = "Maintainer"
47+
saml_group_name = "test_saml_group"
48+
49+
}
50+
`, testGroup.ID),
6651
},
6752
},
6853
})
6954
}
7055

71-
func getGitlabGroupSamlLinkImportID(resourceName string) resource.ImportStateIdFunc {
72-
return func(s *terraform.State) (string, error) {
73-
rs, ok := s.RootModule().Resources[resourceName]
74-
if !ok {
75-
return "", fmt.Errorf("Not Found: %s", resourceName)
76-
}
77-
78-
groupID := rs.Primary.Attributes["group_id"]
79-
if groupID == "" {
80-
return "", fmt.Errorf("No group ID is set")
81-
}
82-
samlGroupName := rs.Primary.Attributes["saml_group_name"]
83-
if samlGroupName == "" {
84-
return "", fmt.Errorf("No SAML group name is set")
85-
}
86-
87-
return fmt.Sprintf("%s:%s", groupID, samlGroupName), nil
88-
}
89-
}
90-
91-
func testAccCheckGitlabGroupSamlLinkExists(resourceName string, samlLink *gitlab.SAMLGroupLink) resource.TestCheckFunc {
92-
return func(s *terraform.State) error {
93-
// Clear the "found" SAML link before checking for existence
94-
*samlLink = gitlab.SAMLGroupLink{}
95-
96-
resourceState, ok := s.RootModule().Resources[resourceName]
97-
if !ok {
98-
return fmt.Errorf("Not found: %s", resourceName)
56+
func testAccCheckGitlabGroupSamlLinkDestroy(s *terraform.State) error {
57+
for _, resourceState := range s.RootModule().Resources {
58+
if resourceState.Type != "gitlab_group_saml_link" {
59+
continue
9960
}
10061

101-
err := testAccGetGitlabGroupSamlLink(samlLink, resourceState)
62+
group, samlGroupName, err := parseTwoPartID(resourceState.Primary.ID)
10263
if err != nil {
10364
return err
10465
}
10566

106-
return nil
107-
}
108-
}
109-
110-
func testAccCheckGitlabGroupSamlLinkDestroy(s *terraform.State) error {
111-
// Can't check for links if the group is destroyed so make sure all groups are destroyed instead
112-
for _, resourceState := range s.RootModule().Resources {
113-
if resourceState.Type != "gitlab_group" {
114-
continue
115-
}
116-
117-
group, _, err := testGitlabClient.Groups.GetGroup(resourceState.Primary.ID, nil)
67+
samlGroupLink, _, err := testGitlabClient.Groups.GetGroupSAMLLink(group, samlGroupName)
11868
if err == nil {
119-
if group != nil && fmt.Sprintf("%d", group.ID) == resourceState.Primary.ID {
120-
if group.MarkedForDeletionOn == nil {
121-
return fmt.Errorf("Group still exists")
122-
}
69+
if samlGroupLink != nil {
70+
return fmt.Errorf("SAML Group Link still exists")
12371
}
12472
}
12573
if !is404(err) {
@@ -129,41 +77,3 @@ func testAccCheckGitlabGroupSamlLinkDestroy(s *terraform.State) error {
12977
}
13078
return nil
13179
}
132-
133-
func testAccGetGitlabGroupSamlLink(samlLink *gitlab.SAMLGroupLink, resourceState *terraform.ResourceState) error {
134-
groupId := resourceState.Primary.Attributes["group_id"]
135-
if groupId == "" {
136-
return fmt.Errorf("No group ID is set")
137-
}
138-
139-
// Construct our desired SAML Link from the config values
140-
desiredSamlLink := gitlab.SAMLGroupLink{
141-
AccessLevel: resourceState.Primary.Attributes["access_level"],
142-
Name: resourceState.Primary.Attributes["saml_group_name"],
143-
}
144-
145-
desiredSamlLinkId := buildTwoPartID(&groupId, &desiredSamlLink.Name)
146-
147-
// Try to fetch all group links from GitLab
148-
currentSamlLinks, _, err := testGitlabClient.Groups.ListGroupSamlLinks(groupId, nil)
149-
if err != nil {
150-
return err
151-
}
152-
153-
found := false
154-
155-
// Check if the SAML link exists in the returned list of links
156-
for _, currentSamlLink := range currentSamlLinks {
157-
if buildTwoPartID(&groupId, &currentSamlLink.Name) == desiredSamlLinkId {
158-
found = true
159-
*samlLink = *currentSamlLink
160-
break
161-
}
162-
}
163-
164-
if !found {
165-
return errors.New(fmt.Sprintf("SamlLink %s does not exist.", desiredSamlLinkId)) // nolint // TODO: Resolve this golangci-lint issue: S1028: should use fmt.Errorf(...) instead of errors.New(fmt.Sprintf(...)) (gosimple)
166-
}
167-
168-
return nil
169-
}

0 commit comments

Comments
 (0)