Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add import attribute for keycloak_openid_client #536

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/resources/openid_client.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ is set to `true`.
- `decision_strategy` - (Optional) Dictates how the policies associated with a given permission are evaluated and how a final decision is obtained. Could be one of `AFFIRMATIVE`, `CONSENSUS`, or `UNANIMOUS`. Applies to permissions.
- `allow_remote_resource_management` - (Optional) When `true`, resources can be managed remotely by the resource server. Defaults to `false`.
- `keep_defaults` - (Optional) When `true`, defaults set by Keycloak will be respected. Defaults to `false`.
- `import` - (Optional) When `true`, the client with specified `client_id` must exists and it will be imported into terrafrom state instead of being created. This attribute is useful when dealing with clients created during realm creation (like `account`, `account-console`, etc). Note, that the client will not be removed during destruction if `import` is `true`.

## Attributes Reference

Expand Down
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test: fmtcheck vet
go test $(TEST)

testacc: fmtcheck vet
TF_ACC=1 CHECKPOINT_DISABLE=1 go test -v -timeout 30m -parallel 4 $(TEST) $(TESTARGS)
TF_ACC=1 CHECKPOINT_DISABLE=1 go test -v -timeout 60m -parallel 4 $(TEST) $(TESTARGS)

fmtcheck:
lineCount=$(shell gofmt -l -s $(GOFMT_FILES) | wc -l | tr -d ' ') && exit $$lineCount
Expand Down
29 changes: 26 additions & 3 deletions provider/resource_keycloak_openid_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ func resourceKeycloakOpenidClient() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"import": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
CustomizeDiff: customdiff.ComputedIf("service_account_user_id", func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool {
return d.HasChange("service_accounts_enabled")
Expand Down Expand Up @@ -401,9 +406,23 @@ func resourceKeycloakOpenidClientCreate(data *schema.ResourceData, meta interfac
return err
}

err = keycloakClient.NewOpenidClient(client)
if err != nil {
return err
if data.Get("import").(bool) {
existingClient, err := keycloakClient.GetOpenidClientByClientId(client.RealmId, client.ClientId)
if err != nil {
return err
}
rootUrlString := data.Get("root_url").(string)
client.Id = existingClient.Id
client.RootUrl = &rootUrlString
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we only setting RootUrl for the client as opposed to other fields. should we just call getOpenidClientFromData here?

err = keycloakClient.UpdateOpenidClient(client)
if err != nil {
return err
}
} else {
err = keycloakClient.NewOpenidClient(client)
if err != nil {
return err
}
}

err = setOpenidClientData(keycloakClient, data, client)
Expand Down Expand Up @@ -460,6 +479,10 @@ func resourceKeycloakOpenidClientUpdate(data *schema.ResourceData, meta interfac
}

func resourceKeycloakOpenidClientDelete(data *schema.ResourceData, meta interface{}) error {
if data.Get("import").(bool) {
return nil
}

keycloakClient := meta.(*keycloak.KeycloakClient)

realmId := data.Get("realm_id").(string)
Expand Down
72 changes: 72 additions & 0 deletions provider/resource_keycloak_openid_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,26 @@ func TestAccKeycloakOpenidClient_loginTheme(t *testing.T) {
})
}

func TestAccKeycloakOpenidClient_import(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakOpenidClientNotDestroyed(),
Steps: []resource.TestStep{
{
Config: testKeycloakOpenidClient_import("non-existing-client", true),
ExpectError: regexp.MustCompile("Error: openid client with name non-existing-client does not exist"),
},
{
Config: testKeycloakOpenidClient_import("account", false),
Check: testAccCheckKeycloakOpenidClientExistsWithEnabledStatus("keycloak_openid_client.client", false),
},
},
})
}

func testAccCheckKeycloakOpenidClientExistsWithCorrectProtocol(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client, err := getOpenidClientFromState(s, resourceName)
Expand Down Expand Up @@ -732,6 +752,26 @@ func testAccCheckKeycloakOpenidClientDestroy() resource.TestCheckFunc {
}
}

func testAccCheckKeycloakOpenidClientNotDestroyed() resource.TestCheckFunc {
return func(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "keycloak_openid_client" {
continue
}

id := rs.Primary.ID
realm := rs.Primary.Attributes["realm_id"]

client, _ := keycloakClient.GetOpenidClient(realm, id)
if client == nil {
return fmt.Errorf("openid client %s dost not exists", id)
}
}

return nil
}
}

func testAccCheckKeycloakOpenidClientHasPkceCodeChallengeMethod(resourceName, pkceCodeChallengeMethod string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client, err := getOpenidClientFromState(s, resourceName)
Expand Down Expand Up @@ -827,6 +867,21 @@ func testAccCheckKeycloakOpenidClientLoginTheme(resourceName string, loginTheme
}
}

func testAccCheckKeycloakOpenidClientExistsWithEnabledStatus(resourceName string, enabled bool) resource.TestCheckFunc {
return func(s *terraform.State) error {
client, err := getOpenidClientFromState(s, resourceName)
if err != nil {
return err
}

if client.Enabled != enabled {
return fmt.Errorf("expected openid client to have enabled status %t, but got %t", enabled, client.Enabled)
}

return nil
}
}

func getOpenidClientFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClient, error) {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
Expand Down Expand Up @@ -1210,3 +1265,20 @@ resource "keycloak_openid_client" "client" {
}
`, testAccRealm.Realm, clientId, loginTheme)
}

func testKeycloakOpenidClient_import(clientId string, enabled bool) string {
return fmt.Sprintf(`
data "keycloak_realm" "realm" {
realm = "%s"
}

resource "keycloak_openid_client" "client" {
client_id = "%s"
realm_id = data.keycloak_realm.realm.id
access_type = "PUBLIC"
root_url = ""
enabled = %t
import = true
}
`, testAccRealm.Realm, clientId, enabled)
}