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

Upgrade Keycloak #899

Merged
merged 4 commits into from
Dec 19, 2023
Merged
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
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,
Victoremepunto marked this conversation as resolved.
Show resolved Hide resolved
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",
Victoremepunto marked this conversation as resolved.
Show resolved Hide resolved
},
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
Loading