Repository: mrparkers/terraform-provider-keycloak
Pull request #306 (2020-05-28 09:50:02)

Introduction of testUtil function keycloakVersionIsHigherOrEqualThan + plus fix tests
test_utils function keycloakVersionIsHigherOrEqualThan is used to fix the number of events and micorprofilejwt scope test failures on older keycloaks
see #294 

tomrutsaert: @mrparkers @hawknewton
What do you guys think?
KEYCLOAK_VERSION ENV VAR is always available in our ci test sets, So I used it to make a little function that can be used in tests.
I think this PR will make everything green in #294

Patch:
diff --git a/go.mod b/go.mod
index 09b704c..e59845e 100644
--- a/go.mod
+++ b/go.mod
@@ -2,6 +2,7 @@ module github.com/mrparkers/terraform-provider-keycloak
 
 require (
 	github.com/hashicorp/errwrap v1.0.0
+	github.com/hashicorp/go-version v1.2.0
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/hashicorp/terraform-plugin-sdk v1.6.0
 	golang.org/x/net v0.0.0-20191009170851-d66e71096ffb
diff --git a/keycloak/server_info.go b/keycloak/server_info.go
index 8d238a7..0a0898d 100644
--- a/keycloak/server_info.go
+++ b/keycloak/server_info.go
@@ -1,10 +1,11 @@
 package keycloak
 
-type ComponentType struct {
-	Id string `json:"id"`
+type SystemInfo struct {
+	ServerVersion string `json:"version"`
 }
 
-type Provider struct {
+type ComponentType struct {
+	Id string `json:"id"`
 }
 
 type ProviderType struct {
@@ -12,10 +13,7 @@ type ProviderType struct {
 	Providers map[string]Provider `json:"providers"`
 }
 
-type ServerInfo struct {
-	ComponentTypes map[string][]ComponentType `json:"componentTypes"`
-	ProviderTypes  map[string]ProviderType    `json:"providers"`
-	Themes         map[string][]Theme         `json:"themes"`
+type Provider struct {
 }
 
 type Theme struct {
@@ -23,6 +21,13 @@ type Theme struct {
 	Locales []string `json:"locales,omitempty"`
 }
 
+type ServerInfo struct {
+	SystemInfo     SystemInfo                 `json:"systemInfo"`
+	ComponentTypes map[string][]ComponentType `json:"componentTypes"`
+	ProviderTypes  map[string]ProviderType    `json:"providers"`
+	Themes         map[string][]Theme         `json:"themes"`
+}
+
 func (serverInfo *ServerInfo) ThemeIsInstalled(t, themeName string) bool {
 	if themes, ok := serverInfo.Themes[t]; ok {
 		for _, theme := range themes {


Test patch:
diff --git a/provider/provider_test.go b/provider/provider_test.go
index f1100cd..49bf3a0 100644
--- a/provider/provider_test.go
+++ b/provider/provider_test.go
@@ -3,12 +3,14 @@ package provider
 import (
 	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
 	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
 	"os"
 	"testing"
 )
 
 var testAccProviders map[string]terraform.ResourceProvider
 var testAccProvider *schema.Provider
+var keycloakClient *keycloak.KeycloakClient
 
 var requiredEnvironmentVariables = []string{
 	"KEYCLOAK_CLIENT_ID",
@@ -22,6 +24,8 @@ func init() {
 	testAccProviders = map[string]terraform.ResourceProvider{
 		"keycloak": testAccProvider,
 	}
+
+	keycloakClient, _ = keycloak.NewKeycloakClient(os.Getenv("KEYCLOAK_URL"), os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), "", "", true, 5, "", false)
 }
 
 func TestProvider(t *testing.T) {
diff --git a/provider/resource_keycloak_openid_client_default_scopes_test.go b/provider/resource_keycloak_openid_client_default_scopes_test.go
index d1e1b35..ae54af3 100644
--- a/provider/resource_keycloak_openid_client_default_scopes_test.go
+++ b/provider/resource_keycloak_openid_client_default_scopes_test.go
@@ -293,7 +293,7 @@ func TestAccKeycloakOpenidClientDefaultScopes_validateDuplicateScopeAssignment(t
 	client := "terraform-client-" + acctest.RandString(10)
 	clientScope := "terraform-client-scope-" + acctest.RandString(10)
 
-	optionalClientScopes := append(preAssignedOptionalClientScopes, clientScope)
+	optionalClientScopes := append(getPreAssignedOptionalClientScopes(t), clientScope)
 
 	resource.Test(t, resource.TestCase{
 		Providers: testAccProviders,
diff --git a/provider/resource_keycloak_openid_client_optional_scopes_test.go b/provider/resource_keycloak_openid_client_optional_scopes_test.go
index 35f591c..0a3e159 100644
--- a/provider/resource_keycloak_openid_client_optional_scopes_test.go
+++ b/provider/resource_keycloak_openid_client_optional_scopes_test.go
@@ -12,14 +12,24 @@ import (
 )
 
 // All openid clients in Keycloak will automatically have these scopes listed as "optional client scopes".
-var preAssignedOptionalClientScopes = []string{"address", "phone", "offline_access", "microprofile-jwt"}
+func getPreAssignedOptionalClientScopes(t *testing.T) []string {
+	keycloakVersionIsGreaterThanOrEqualTo6, err := keycloakVersionIsGreaterThanOrEqualTo(keycloakClient, getKeycloakVersion600())
+	if err != nil {
+		t.Fatal(err)
+	}
+	if keycloakVersionIsGreaterThanOrEqualTo6 {
+		return []string{"address", "phone", "offline_access", "microprofile-jwt"}
+	} else {
+		return []string{"address", "phone", "offline_access"}
+	}
+}
 
 func TestAccKeycloakOpenidClientOptionalScopes_basic(t *testing.T) {
 	realm := "terraform-realm-" + acctest.RandString(10)
 	client := "terraform-client-" + acctest.RandString(10)
 	clientScope := "terraform-client-scope-" + acctest.RandString(10)
 
-	clientScopes := append(preAssignedOptionalClientScopes, clientScope)
+	clientScopes := append(getPreAssignedOptionalClientScopes(t), clientScope)
 
 	resource.Test(t, resource.TestCase{
 		Providers: testAccProviders,
@@ -45,7 +55,7 @@ func TestAccKeycloakOpenidClientOptionalScopes_updateClientForceNew(t *testing.T
 	clientTwo := "terraform-client-" + acctest.RandString(10)
 	clientScope := "terraform-client-scope-" + acctest.RandString(10)
 
-	clientScopes := append(preAssignedOptionalClientScopes, clientScope)
+	clientScopes := append(getPreAssignedOptionalClientScopes(t), clientScope)
 
 	resource.Test(t, resource.TestCase{
 		Providers: testAccProviders,
@@ -68,7 +78,7 @@ func TestAccKeycloakOpenidClientOptionalScopes_updateInPlace(t *testing.T) {
 	client := "terraform-client-" + acctest.RandString(10)
 	clientScope := "terraform-client-scope-" + acctest.RandString(10)
 
-	allClientScopes := append(preAssignedOptionalClientScopes, clientScope)
+	allClientScopes := append(getPreAssignedOptionalClientScopes(t), clientScope)
 
 	clientScopeToRemove := allClientScopes[acctest.RandIntRange(0, 2)]
 	var subsetOfClientScopes []string
@@ -139,7 +149,7 @@ func TestAccKeycloakOpenidClientOptionalScopes_validateClientAccessType(t *testi
 func TestAccKeycloakOpenidClientOptionalScopes_authoritativeAdd(t *testing.T) {
 	realm := "terraform-realm-" + acctest.RandString(10)
 	client := "terraform-client-" + acctest.RandString(10)
-	clientScopes := append(preAssignedOptionalClientScopes,
+	clientScopes := append(getPreAssignedOptionalClientScopes(t),
 		"terraform-client-scope-"+acctest.RandString(10),
 		"terraform-client-scope-"+acctest.RandString(10),
 		"terraform-client-scope-"+acctest.RandString(10),
@@ -185,7 +195,7 @@ func TestAccKeycloakOpenidClientOptionalScopes_authoritativeRemove(t *testing.T)
 		"terraform-client-scope-" + acctest.RandString(10),
 		"terraform-client-scope-" + acctest.RandString(10),
 	}
-	allClientScopes := append(preAssignedOptionalClientScopes, randomClientScopes...)
+	allClientScopes := append(getPreAssignedOptionalClientScopes(t), randomClientScopes...)
 
 	clientToManuallyAttach := randomClientScopes[acctest.RandIntRange(0, len(randomClientScopes)-1)]
 	var attachedClientScopes []string
@@ -233,7 +243,7 @@ func TestAccKeycloakOpenidClientOptionalScopes_noImportNeeded(t *testing.T) {
 	client := "terraform-client-" + acctest.RandString(10)
 	clientScope := "terraform-client-scope-" + acctest.RandString(10)
 
-	clientScopes := append(preAssignedOptionalClientScopes, clientScope)
+	clientScopes := append(getPreAssignedOptionalClientScopes(t), clientScope)
 
 	resource.Test(t, resource.TestCase{
 		Providers: testAccProviders,
@@ -281,7 +291,7 @@ func TestAccKeycloakOpenidClientOptionalScopes_profileAndEmailOptionalScopes(t *
 		Steps: []resource.TestStep{
 			{
 				Config:             testKeycloakOpenidClientOptionalScopes_listOfScopes(realm, client, clientScope, []string{clientScope}),
-				Check:              testAccCheckKeycloakOpenidClientHasOptionalScopes("keycloak_openid_client.client", append(preAssignedOptionalClientScopes, clientScope)),
+				Check:              testAccCheckKeycloakOpenidClientHasOptionalScopes("keycloak_openid_client.client", append(getPreAssignedOptionalClientScopes(t), clientScope)),
 				ExpectNonEmptyPlan: true,
 			},
 		},
@@ -399,7 +409,9 @@ func testAccCheckKeycloakOpenidClientOptionalScopeIsNotAttached(resourceName, cl
 }
 
 func testKeycloakOpenidClientOptionalScopes_basic(realm, client, clientScope string) string {
-	return fmt.Sprintf(`
+	keycloakVersionIsHigherOrEqualTo6, _ := keycloakVersionIsGreaterThanOrEqualTo(keycloakClient, getKeycloakVersion600())
+	if keycloakVersionIsHigherOrEqualTo6 {
+		return fmt.Sprintf(`
 resource "keycloak_realm" "realm" {
 	realm = "%s"
 }
@@ -429,6 +441,37 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
 	]
 }
 	`, realm, client, clientScope)
+	} else {
+		return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_openid_client" "client" {
+	client_id   = "%s"
+	realm_id    = "${keycloak_realm.realm.id}"
+	access_type = "PUBLIC"
+}
+
+resource "keycloak_openid_client_scope" "client_scope" {
+	name        = "%s"
+	realm_id    = "${keycloak_realm.realm.id}"
+
+	description = "test description"
+}
+
+resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
+	realm_id       = "${keycloak_realm.realm.id}"
+	client_id      = "${keycloak_openid_client.client.id}"
+	optional_scopes = [
+		"address",
+		"phone",
+		"offline_access",
+		"${keycloak_openid_client_scope.client_scope.name}"
+	]
+}
+	`, realm, client, clientScope)
+	}
 }
 
 func testKeycloakOpenidClientOptionalScopes_noOptionalScopes(realm, client, clientScope string) string {
@@ -482,7 +525,9 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
 }
 
 func testKeycloakOpenidClientOptionalScopes_validationNoClient(realm, client, clientScope string) string {
-	return fmt.Sprintf(`
+	keycloakVersionIsHigherOrEqualTo6, _ := keycloakVersionIsGreaterThanOrEqualTo(keycloakClient, getKeycloakVersion600())
+	if keycloakVersionIsHigherOrEqualTo6 {
+		return fmt.Sprintf(`
 resource "keycloak_realm" "realm" {
 	realm = "%s"
 }
@@ -506,10 +551,38 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
 	]
 }
 	`, realm, clientScope, client)
+	} else {
+		return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_openid_client_scope" "client_scope" {
+	name        = "%s"
+	realm_id    = "${keycloak_realm.realm.id}"
+
+	description = "test description"
+}
+
+resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
+	realm_id       = "${keycloak_realm.realm.id}"
+	client_id      = "%s"
+	optional_scopes = [
+		"address",
+		"phone",
+		"offline_access",
+		"${keycloak_openid_client_scope.client_scope.name}"
+	]
+}
+	`, realm, clientScope, client)
+	}
 }
 
 func testKeycloakOpenidClientOptionalScopes_validationBearerOnlyClient(realm, client, clientScope string) string {
-	return fmt.Sprintf(`
+
+	keycloakVersionIsHigherOrEqualTo6, _ := keycloakVersionIsGreaterThanOrEqualTo(keycloakClient, getKeycloakVersion600())
+	if keycloakVersionIsHigherOrEqualTo6 {
+		return fmt.Sprintf(`
 resource "keycloak_realm" "realm" {
 	realm = "%s"
 }
@@ -539,6 +612,37 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
 	]
 }
 	`, realm, client, clientScope)
+	} else {
+		return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_openid_client" "client" {
+	client_id   = "%s"
+	realm_id    = "${keycloak_realm.realm.id}"
+	access_type = "BEARER-ONLY"
+}
+
+resource "keycloak_openid_client_scope" "client_scope" {
+	name        = "%s"
+	realm_id    = "${keycloak_realm.realm.id}"
+
+	description = "test description"
+}
+
+resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
+	realm_id       = "${keycloak_realm.realm.id}"
+	client_id      = "${keycloak_openid_client.client.id}"
+	optional_scopes = [
+		"address",
+		"phone",
+		"offline_access",
+		"${keycloak_openid_client_scope.client_scope.name}"
+	]
+}
+	`, realm, client, clientScope)
+	}
 }
 
 func testKeycloakOpenidClientOptionalScopes_multipleClientScopes(realm, client string, allClientScopes, attachedClientScopes []string) string {
@@ -585,7 +689,9 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
 }
 
 func testKeycloakOpenidClientOptionalScopes_duplicateScopeAssignment(realm, client, clientScope string) string {
-	return fmt.Sprintf(`
+	keycloakVersionIsHigherOrEqualTo6, _ := keycloakVersionIsGreaterThanOrEqualTo(keycloakClient, getKeycloakVersion600())
+	if keycloakVersionIsHigherOrEqualTo6 {
+		return fmt.Sprintf(`
 %s
 
 resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
@@ -600,4 +706,20 @@ resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
 	]
 }
 	`, testKeycloakOpenidClientDefaultScopes_basic(realm, client, clientScope))
+	} else {
+		return fmt.Sprintf(`
+%s
+
+resource "keycloak_openid_client_optional_scopes" "optional_scopes" {
+	realm_id       = "${keycloak_realm.realm.id}"
+	client_id      = "${keycloak_openid_client.client.id}"
+	optional_scopes = [
+		"address",
+		"phone",
+		"offline_access",
+		"${keycloak_openid_client_scope.client_scope.name}"
+	]
+}
+	`, testKeycloakOpenidClientDefaultScopes_basic(realm, client, clientScope))
+	}
 }
diff --git a/provider/resource_keycloak_realm_events_test.go b/provider/resource_keycloak_realm_events_test.go
index 0fc943f..6b4d495 100644
--- a/provider/resource_keycloak_realm_events_test.go
+++ b/provider/resource_keycloak_realm_events_test.go
@@ -164,9 +164,20 @@ func TestAccKeycloakRealmEvents_unsetEnabledEventTypes(t *testing.T) {
 						if err != nil {
 							return err
 						}
+						keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+						keycloakVersionIsGreaterThanOrEqualTo7, err := keycloakVersionIsGreaterThanOrEqualTo(keycloakClient, getKeycloakVersion700())
+						if err != nil {
+							return err
+						}
 
-						if len(realmEventsConfig.EnabledEventTypes) != 67 {
-							return fmt.Errorf("exptected to enabled_event_types to contain all (67) event types, but it contains %d", len(realmEventsConfig.EnabledEventTypes))
+						if keycloakVersionIsGreaterThanOrEqualTo7 { //keycloak versions < 7.0.0 have 63 events, versions >=7.0.0 have 67 events
+							if len(realmEventsConfig.EnabledEventTypes) != 67 {
+								return fmt.Errorf("exptected to enabled_event_types to contain all(67) event types, but it contains %d", len(realmEventsConfig.EnabledEventTypes))
+							}
+						} else {
+							if len(realmEventsConfig.EnabledEventTypes) != 63 {
+								return fmt.Errorf("exptected to enabled_event_types to contain all(63) event types, but it contains %d", len(realmEventsConfig.EnabledEventTypes))
+							}
 						}
 
 						return nil
diff --git a/provider/test_utils.go b/provider/test_utils.go
index 99cef15..dc5ff53 100644
--- a/provider/test_utils.go
+++ b/provider/test_utils.go
@@ -2,6 +2,8 @@ package provider
 
 import (
 	"fmt"
+	"github.com/hashicorp/go-version"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
 	"math/rand"
 	"os"
 	"strings"
@@ -75,3 +77,44 @@ func TestCheckResourceAttrNot(name, key, value string) resource.TestCheckFunc {
 		return nil
 	}
 }
+
+var keycloakServerInfoVersion *version.Version
+
+func keycloakVersionIsGreaterThanOrEqualTo(keycloakClient *keycloak.KeycloakClient, keycloakMajorVersion *version.Version) (bool, error) {
+	if keycloakServerInfoVersion == nil {
+		serverInfo, err := keycloakClient.GetServerInfo()
+		if err != nil {
+			return false, fmt.Errorf("/serverInfo endpoint retuned an error, server Keycloak version could not be determined: %s", err)
+		}
+		keycloakServerInfoVersion, err = version.NewVersion(serverInfo.SystemInfo.ServerVersion)
+		if err != nil {
+			return false, fmt.Errorf("/serverInfo endpoint retuned an unreadable version, server Keycloak version could not be determined: %s", err)
+		}
+	}
+	return keycloakServerInfoVersion.GreaterThanOrEqual(keycloakMajorVersion), nil
+}
+
+func getKeycloakVersion600() *version.Version {
+	v, _ := version.NewVersion("6.0.0")
+	return v
+}
+
+func getKeycloakVersion700() *version.Version {
+	v, _ := version.NewVersion("7.0.0")
+	return v
+}
+
+func getKeycloakVersion800() *version.Version {
+	v, _ := version.NewVersion("8.0.0")
+	return v
+}
+
+func getKeycloakVersion900() *version.Version {
+	v, _ := version.NewVersion("9.0.0")
+	return v
+}
+
+func getKeycloakVersion1000() *version.Version {
+	v, _ := version.NewVersion("10.0.0")
+	return v
+}