Skip to content

Commit

Permalink
Merge pull request #899 from RedHatInsights/psav/upgrade_keycloak
Browse files Browse the repository at this point in the history
Upgrade Keycloak
  • Loading branch information
psav authored Dec 19, 2023
2 parents 02384b8 + 10f7a93 commit 08a8d8c
Show file tree
Hide file tree
Showing 13 changed files with 514 additions and 294 deletions.
3 changes: 3 additions & 0 deletions apis/cloud.redhat.com/v1alpha1/clowdenvironment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ type WebConfig struct {
// Optional keycloak version override -- used only in (*_local_*) mode -- if not set, a hard-coded default is used.
KeycloakVersion string `json:"keycloakVersion,omitempty"`

// Optionally use PVC storage for keycloak db
KeycloakPVC bool `json:"keycloakPVC,omitempty"`

// Optional images to use for web provider components -- only applies when running in (*_local_*) mode.
Images WebImages `json:"images,omitempty"`

Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/cloud.redhat.com_clowdenvironments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,9 @@ spec:
ingressClass:
description: Ingress Class Name used only in (*_local_*) mode.
type: string
keycloakPVC:
description: Optionally use PVC storage for keycloak db
type: boolean
keycloakVersion:
description: Optional keycloak version override -- used only
in (*_local_*) mode -- if not set, a hard-coded default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ var LocalFFDeployment = rc.NewSingleResourceIdent(ProvName, "ff_deployment", &ap
// LocalFFService is the ident referring to the local Feature Flags service object.
var LocalFFService = rc.NewSingleResourceIdent(ProvName, "ff_service", &core.Service{})

// LocalFFSecret is the ident referring to the local Feature Flags secret object.
var LocalFFSecret = rc.NewSingleResourceIdent(ProvName, "ff_secret", &core.Secret{})

// LocalFFDBDeployment is the ident referring to the local Feature Flags DB deployment object.
var LocalFFDBDeployment = rc.NewSingleResourceIdent(ProvName, "ff_db_deployment", &apps.Deployment{})

Expand All @@ -41,18 +44,16 @@ var LocalFFDBPVC = rc.NewSingleResourceIdent(ProvName, "ff_db_pvc", &core.Persis
// LocalFFDBSecret is the ident referring to the local Feature Flags DB secret object.
var LocalFFDBSecret = rc.NewSingleResourceIdent(ProvName, "ff_db_secret", &core.Secret{})

// LocalFFSecret is the ident referring to the local Feature Flags secret object.
var LocalFFSecret = rc.NewSingleResourceIdent(ProvName, "ff_secret", &core.Secret{})

type localFeatureFlagsProvider struct {
providers.Provider
}

// NewLocalFeatureFlagsProvider returns a new local featureflags provider object.
func NewLocalFeatureFlagsProvider(p *providers.Provider) (providers.ClowderProvider, error) {
p.Cache.AddPossibleGVKFromIdent(
LocalFFDBDeployment,
LocalFFDeployment,
LocalFFService,
LocalFFSecret,
LocalFFDBDeployment,
LocalFFDBService,
LocalFFDBPVC,
Expand Down
4 changes: 2 additions & 2 deletions controllers/cloud.redhat.com/providers/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
var DefaultImageCaddySideCar = "quay.io/cloudservices/crc-caddy-plugin:a988cd2"
var DefaultImageCaddyGateway = DefaultImageCaddySideCar
var DefaultImageMBOP = "quay.io/cloudservices/mbop:959d00d"
var DefaultImageMocktitlements = "quay.io/cloudservices/mocktitlements:e24820c"
var DefaultKeyCloakVersion = "15.0.2"
var DefaultImageMocktitlements = "quay.io/cloudservices/mocktitlements:81fd80e"
var DefaultKeyCloakVersion = "23.0.1"
var DefaultImageKeyCloak = fmt.Sprintf("quay.io/keycloak/keycloak:%s", DefaultKeyCloakVersion)

// MakeLocalDB populates the given deployment object with the local DB struct.
Expand Down
8 changes: 8 additions & 0 deletions controllers/cloud.redhat.com/providers/web/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func NewLocalWebProvider(p *providers.Provider) (providers.ClowderProvider, erro
WebKeycloakService,
WebKeycloakIngress,
WebKeycloakImportSecret,
WebKeycloakDBDeployment,
WebKeycloakDBPVC,
WebKeycloakDBService,
WebKeycloakDBSecret,
WebBOPDeployment,
WebBOPService,
WebMocktitlementsDeployment,
Expand Down Expand Up @@ -68,6 +72,10 @@ func (web *localWebProvider) EnvProvide() error {
}
}

if err := configureKeycloakDB(web); err != nil {
return err
}

if err := configureKeycloak(web); err != nil {
return err
}
Expand Down
187 changes: 177 additions & 10 deletions controllers/cloud.redhat.com/providers/web/resources_keycloak.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import (
"strings"

crd "github.com/RedHatInsights/clowder/apis/cloud.redhat.com/v1alpha1"
"github.com/RedHatInsights/clowder/controllers/cloud.redhat.com/config"
"github.com/RedHatInsights/clowder/controllers/cloud.redhat.com/errors"
obj "github.com/RedHatInsights/clowder/controllers/cloud.redhat.com/object"
"github.com/RedHatInsights/clowder/controllers/cloud.redhat.com/providers"
"github.com/RedHatInsights/clowder/controllers/cloud.redhat.com/providers/sizing"
provutils "github.com/RedHatInsights/clowder/controllers/cloud.redhat.com/providers/utils"

rc "github.com/RedHatInsights/rhc-osdk-utils/resourceCache"
Expand Down Expand Up @@ -38,6 +40,113 @@ var WebKeycloakImportSecret = rc.NewSingleResourceIdent(ProvName, "web_keycloak_
// WebKeycloakSecret is the mocked secret config
var WebKeycloakSecret = rc.NewSingleResourceIdent(ProvName, "web_keycloak_secret", &core.Secret{}, rc.ResourceOptions{WriteNow: true})

// WebKeycloakDBDeployment is the ident referring to the local Feature Flags DB deployment object.
var WebKeycloakDBDeployment = rc.NewSingleResourceIdent(ProvName, "web_keycloak_db_deployment", &apps.Deployment{})

// WebKeycloakDBService is the ident referring to the local Feature Flags DB service object.
var WebKeycloakDBService = rc.NewSingleResourceIdent(ProvName, "web_keycloak_db_service", &core.Service{})

// WebKeycloakDBPVC is the ident referring to the local Feature Flags DB PVC object.
var WebKeycloakDBPVC = rc.NewSingleResourceIdent(ProvName, "web_keycloak_db_pvc", &core.PersistentVolumeClaim{})

// WebKeycloakDBSecret is the ident referring to the local Feature Flags DB secret object.
var WebKeycloakDBSecret = rc.NewSingleResourceIdent(ProvName, "web_keycloak_db_secret", &core.Secret{})

func configureKeycloakDB(web *localWebProvider) error {
namespacedNameDb := types.NamespacedName{
Name: "keycloak-db",
Namespace: web.Env.Status.TargetNamespace,
}

dd := &apps.Deployment{}
if err := web.Cache.Create(WebKeycloakDBDeployment, namespacedNameDb, dd); err != nil {
return err
}

dbCfg := config.DatabaseConfig{}

password, err := utils.RandPassword(16, provutils.RCharSet)
if err != nil {
return errors.Wrap("password generate failed", err)
}

pgPassword, err := utils.RandPassword(16, provutils.RCharSet)
if err != nil {
return errors.Wrap("pgPassword generate failed", err)
}

username := utils.RandString(16)
hostname := fmt.Sprintf("%v.%v.svc", namespacedNameDb.Name, namespacedNameDb.Namespace)

dataInitDb := func() map[string]string {

return map[string]string{
"hostname": hostname,
"port": "5432",
"username": username,
"password": password,
"pgPass": pgPassword,
"name": "keycloak",
}
}

secMapDb, err := providers.MakeOrGetSecret(web.Env, web.Cache, WebKeycloakDBSecret, namespacedNameDb, dataInitDb)
if err != nil {
return errors.Wrap("Couldn't set/get secret", err)
}

err = dbCfg.Populate(secMapDb)
if err != nil {
return errors.Wrap("couldn't convert to int", err)
}
dbCfg.AdminUsername = "postgres"

labels := &map[string]string{"sub": "keycloak"}

res := core.ResourceRequirements{
Limits: core.ResourceList{
"memory": resource.MustParse("200Mi"),
"cpu": resource.MustParse("100m"),
},
Requests: core.ResourceList{
"memory": resource.MustParse("100Mi"),
"cpu": resource.MustParse("50m"),
},
}

provutils.MakeLocalDB(dd, namespacedNameDb, web.Env, labels, &dbCfg, "quay.io/cloudservices/postgresql-rds:15-53ac80c", web.Env.Spec.Providers.Web.KeycloakPVC, "keycloak", &res)

if err = web.Cache.Update(WebKeycloakDBDeployment, dd); err != nil {
return err
}

s := &core.Service{}
if err := web.Cache.Create(WebKeycloakDBService, namespacedNameDb, s); err != nil {
return err
}

provutils.MakeLocalDBService(s, namespacedNameDb, web.Env, labels)

if err = web.Cache.Update(WebKeycloakDBService, s); err != nil {
return err
}

if web.Env.Spec.Providers.Web.KeycloakPVC {
pvc := &core.PersistentVolumeClaim{}
if err = web.Cache.Create(WebKeycloakDBPVC, namespacedNameDb, pvc); err != nil {
return err
}

provutils.MakeLocalDBPVC(pvc, namespacedNameDb, web.Env, sizing.GetDefaultVolCapacity())

if err = web.Cache.Update(WebKeycloakDBPVC, pvc); err != nil {
return err
}
}

return nil
}

func configureKeycloak(web *localWebProvider) error {
nn := providers.GetNamespacedName(web.Env, "keycloak")

Expand Down Expand Up @@ -140,15 +249,63 @@ func makeKeycloak(o obj.ClowdObject, objMap providers.ObjectMap, _ bool, nodePor

envVars := []core.EnvVar{
{
Name: "DB_VENDOR",
Value: "h2",
Name: "KC_DB",
Value: "postgres",
},
{
Name: "KC_DB_USERNAME",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "keycloak-db",
},
Key: "username",
},
},
},
{
Name: "KC_DB_PASSWORD",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "keycloak-db",
},
Key: "password",
},
},
},
{
Name: "KC_DB_URL_DATABASE",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "keycloak-db",
},
Key: "name",
},
},
},
{
Name: "KC_DB_URL_HOST",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "keycloak-db",
},
Key: "hostname",
},
},
},
{
Name: "KC_DB_URL_PORT",
Value: "5432",
},
{
Name: "PROXY_ADDRESS_FORWARDING",
Value: "true",
},
{
Name: "KEYCLOAK_USER",
Name: "KEYCLOAK_ADMIN",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Expand All @@ -159,7 +316,7 @@ func makeKeycloak(o obj.ClowdObject, objMap providers.ObjectMap, _ bool, nodePor
},
},
{
Name: "KEYCLOAK_PASSWORD",
Name: "KEYCLOAK_ADMIN_PASSWORD",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Expand Down Expand Up @@ -194,15 +351,15 @@ func makeKeycloak(o obj.ClowdObject, objMap providers.ObjectMap, _ bool, nodePor

livenessProbe := core.Probe{
ProbeHandler: probeHandler,
InitialDelaySeconds: 10,
InitialDelaySeconds: 60,
TimeoutSeconds: 2,
PeriodSeconds: 10,
SuccessThreshold: 1,
FailureThreshold: 3,
}
readinessProbe := core.Probe{
ProbeHandler: probeHandler,
InitialDelaySeconds: 20,
InitialDelaySeconds: 60,
TimeoutSeconds: 2,
PeriodSeconds: 10,
SuccessThreshold: 1,
Expand All @@ -213,9 +370,19 @@ func makeKeycloak(o obj.ClowdObject, objMap providers.ObjectMap, _ bool, nodePor
image := provutils.GetKeycloakImage(env)

c := core.Container{
Name: nn.Name,
Image: image,
Env: envVars,
Name: nn.Name,
Image: image,
Env: envVars,
Args: []string{
"start",
"--import-realm",
"--hostname-strict",
"false",
"--http-enabled",
"true",
"--http-relative-path",
"/auth",
},
Ports: ports,
LivenessProbe: &livenessProbe,
ReadinessProbe: &readinessProbe,
Expand All @@ -235,7 +402,7 @@ func makeKeycloak(o obj.ClowdObject, objMap providers.ObjectMap, _ bool, nodePor
VolumeMounts: []core.VolumeMount{
{
Name: "realm-import",
MountPath: "/json",
MountPath: "/opt/keycloak/data/import/",
},
},
}
Expand Down
3 changes: 3 additions & 0 deletions deploy-mutate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6966,6 +6966,9 @@ objects:
description: Ingress Class Name used only in (*_local_*)
mode.
type: string
keycloakPVC:
description: Optionally use PVC storage for keycloak db
type: boolean
keycloakVersion:
description: Optional keycloak version override -- used
only in (*_local_*) mode -- if not set, a hard-coded default
Expand Down
3 changes: 3 additions & 0 deletions deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6966,6 +6966,9 @@ objects:
description: Ingress Class Name used only in (*_local_*)
mode.
type: string
keycloakPVC:
description: Optionally use PVC storage for keycloak db
type: boolean
keycloakVersion:
description: Optional keycloak version override -- used
only in (*_local_*) mode -- if not set, a hard-coded default
Expand Down
1 change: 1 addition & 0 deletions docs/antora/modules/ROOT/pages/api_reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1617,6 +1617,7 @@ WebConfig configures the Clowder provider controlling the creation of web servic
| *`bopURL`* __string__ | The URL of BOP - only used in (*_none_*/*_operator_*) mode.
| *`ingressClass`* __string__ | Ingress Class Name used only in (*_local_*) mode.
| *`keycloakVersion`* __string__ | Optional keycloak version override -- used only in (*_local_*) mode -- if not set, a hard-coded default is used.
| *`keycloakPVC`* __boolean__ | Optionally use PVC storage for keycloak db
| *`images`* __xref:{anchor_prefix}-github-com-redhatinsights-clowder-apis-cloud-redhat-com-v1alpha1-webimages[$$WebImages$$]__ | Optional images to use for web provider components -- only applies when running in (*_local_*) mode.
| *`tls`* __xref:{anchor_prefix}-github-com-redhatinsights-clowder-apis-cloud-redhat-com-v1alpha1-tls[$$TLS$$]__ | TLS sidecar enablement
| *`gatewayCert`* __xref:{anchor_prefix}-github-com-redhatinsights-clowder-apis-cloud-redhat-com-v1alpha1-gatewaycert[$$GatewayCert$$]__ | Gateway cert
Expand Down
Loading

0 comments on commit 08a8d8c

Please sign in to comment.