Skip to content

Commit

Permalink
feat: add an ability to add localhost to allows list for keycloak (#937)
Browse files Browse the repository at this point in the history
* feat: add an ability to mount configmap to deployment
* feat: add an ability to configure additional weborigins and redirecturls for keycloak
  • Loading branch information
sleshchenko authored Jul 21, 2021
1 parent 6bf5c65 commit 5ab4154
Show file tree
Hide file tree
Showing 5 changed files with 414 additions and 10 deletions.
16 changes: 10 additions & 6 deletions controllers/che/checluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
return []ctrl.Request{}
}

var toEclipseCheSecretRequestMapper handler.ToRequestsFunc = func(obj handler.MapObject) []ctrl.Request {
isEclipseCheSecret, reconcileRequest := isEclipseCheSecret(mgr, obj)
if isEclipseCheSecret {
var toEclipseCheRelatedObjRequestMapper handler.ToRequestsFunc = func(obj handler.MapObject) []ctrl.Request {
isEclipseCheRelatedObj, reconcileRequest := isEclipseCheRelatedObj(mgr, obj)
if isEclipseCheRelatedObj {
return []ctrl.Request{reconcileRequest}
}
return []ctrl.Request{}
Expand Down Expand Up @@ -194,7 +194,11 @@ func (r *CheClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
builder.WithPredicates(onAllExceptGenericEventsPredicate),
).
Watches(&source.Kind{Type: &corev1.Secret{}},
&handler.EnqueueRequestsFromMapFunc{ToRequests: toEclipseCheSecretRequestMapper},
&handler.EnqueueRequestsFromMapFunc{ToRequests: toEclipseCheRelatedObjRequestMapper},
builder.WithPredicates(onAllExceptGenericEventsPredicate),
).
Watches(&source.Kind{Type: &corev1.ConfigMap{}},
&handler.EnqueueRequestsFromMapFunc{ToRequests: toEclipseCheRelatedObjRequestMapper},
builder.WithPredicates(onAllExceptGenericEventsPredicate),
)

Expand Down Expand Up @@ -727,9 +731,9 @@ func (r *CheClusterReconciler) autoEnableOAuth(deployContext *deploy.DeployConte
return reconcile.Result{}, nil
}

// isEclipseCheSecret indicates if there is a secret with
// isEclipseCheRelatedObj indicates if there is a object with
// the label 'app.kubernetes.io/part-of=che.eclipse.org' in a che namespace
func isEclipseCheSecret(mgr ctrl.Manager, obj handler.MapObject) (bool, ctrl.Request) {
func isEclipseCheRelatedObj(mgr ctrl.Manager, obj handler.MapObject) (bool, ctrl.Request) {
checlusters := &orgv1.CheClusterList{}
if err := mgr.GetClient().List(context.TODO(), checlusters, &client.ListOptions{}); err != nil {
return false, ctrl.Request{}
Expand Down
104 changes: 104 additions & 0 deletions pkg/deploy/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ func SyncDeploymentSpecToCluster(
return false, err
}

if err := MountConfigMaps(deploymentSpec, deployContext); err != nil {
return false, err
}

done, err := Sync(deployContext, deploymentSpec, deploymentDiffOpts)
if err != nil || !done {
return false, err
Expand Down Expand Up @@ -176,3 +180,103 @@ func MountSecrets(specDeployment *appsv1.Deployment, deployContext *DeployContex

return nil
}

// MountConfigMaps mounts configmaps into a container as a file or as environment variable.
// Configmaps are selected by the following labels:
// - app.kubernetes.io/part-of=che.eclipse.org
// - app.kubernetes.io/component=<DEPLOYMENT-NAME>-configmap
func MountConfigMaps(specDeployment *appsv1.Deployment, deployContext *DeployContext) error {
configmaps := &corev1.ConfigMapList{}

kubernetesPartOfLabelSelectorRequirement, _ := labels.NewRequirement(KubernetesPartOfLabelKey, selection.Equals, []string{CheEclipseOrg})
kubernetesComponentLabelSelectorRequirement, _ := labels.NewRequirement(KubernetesComponentLabelKey, selection.Equals, []string{specDeployment.Name + "-configmap"})

listOptions := &client.ListOptions{
LabelSelector: labels.NewSelector().Add(*kubernetesPartOfLabelSelectorRequirement).Add(*kubernetesComponentLabelSelectorRequirement),
}
if err := deployContext.ClusterAPI.Client.List(context.TODO(), configmaps, listOptions); err != nil {
return err
}

// sort configmaps by name first to have the same order every time
sort.Slice(configmaps.Items, func(i, j int) bool {
return strings.Compare(configmaps.Items[i].Name, configmaps.Items[j].Name) < 0
})

container := &specDeployment.Spec.Template.Spec.Containers[0]
for _, configMapObj := range configmaps.Items {
switch configMapObj.Annotations[CheEclipseOrgMountAs] {
case "file":
voluseSource := corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: configMapObj.Name,
},
},
}

volume := corev1.Volume{
Name: configMapObj.Name,
VolumeSource: voluseSource,
}

volumeMount := corev1.VolumeMount{
Name: configMapObj.Name,
MountPath: configMapObj.Annotations[CheEclipseOrgMountPath],
}

specDeployment.Spec.Template.Spec.Volumes = append(specDeployment.Spec.Template.Spec.Volumes, volume)
container.VolumeMounts = append(container.VolumeMounts, volumeMount)

case "env":
configmap := &corev1.ConfigMap{}
exists, err := GetNamespacedObject(deployContext, configMapObj.Name, configmap)
if err != nil {
return err
} else if !exists {
return fmt.Errorf("ConfigMap '%s' not found", configMapObj.Name)
}

// grab all keys and sort first to have the same order every time
keys := make([]string, 0)
for k := range configmap.Data {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return strings.Compare(keys[i], keys[j]) < 0
})

for _, key := range keys {
var envName string

// check if evn name defined explicitly
envNameAnnotation := CheEclipseOrg + "/" + key + "_env-name"
envName, envNameExists := configMapObj.Annotations[envNameAnnotation]
if !envNameExists {
// check if there is only one env name to mount
envName, envNameExists = configMapObj.Annotations[CheEclipseOrgEnvName]
if len(configmap.Data) > 1 {
return fmt.Errorf("There are more than one environment variable to mount. Use annotation '%s' to specify a name", envNameAnnotation)
} else if !envNameExists {
return fmt.Errorf("Environment name to mount configmap key not found. Use annotation '%s' to specify a name", CheEclipseOrgEnvName)
}
}

env := corev1.EnvVar{
Name: envName,
ValueFrom: &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
Key: key,
LocalObjectReference: corev1.LocalObjectReference{
Name: configMapObj.Name,
},
},
},
}
container.Env = append(container.Env, env)
}
}
}

return nil
}
Loading

0 comments on commit 5ab4154

Please sign in to comment.