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

[#135] Allow specifying the mount path for ConfigMaps #136

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
19 changes: 17 additions & 2 deletions deploy/crds/wildfly.org_wildflyservers_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,23 @@ spec:
configMaps:
description: ConfigMaps is a list of ConfigMaps in the same namespace
as the WildFlyServer object, which shall be mounted into the WildFlyServer
Pods. The ConfigMaps are mounted into /etc/configmaps/<configmap-name>.
Pods. It can optionally specify the path, as an absolute or relative
path, within the container at which the volume should be mounted.
If the specified mount path is a relative path, then it will be treated
relative to JBOSS_HOME. If a MountPath is not specified, then the
ConfigMap is mount by default into /etc/configmaps/<configmap-name>.
items:
type: string
description: ConfigMapSpec represents a ConfigMap definition with
a name and a mount path. MountPath cannot contains ':'
properties:
mountPath:
pattern: ^[^:]+$
type: string
name:
type: string
required:
- name
type: object
minItems: 1
type: array
disableHTTPRoute:
Expand Down Expand Up @@ -502,6 +516,7 @@ spec:
- replicas
- scalingdownPods
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
Expand Down
12 changes: 11 additions & 1 deletion doc/apis.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ It uses a `StatefulSet` with a pod spec that mounts the volume specified by `sto
| `envFrom` | List of environment variable present in the containers from source (either `ConfigMap` or `Secret`) | []https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#envfromsource-v1-core[corev1.EnvFromSource] |false
| `env` | List of environment variable present in the containers | []https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#envvar-v1-core[corev1.EnvVar] | false
| `secrets` | List of secret names to mount as volumes in the containers. Each secret is mounted as a read-only volume under `/etc/secrets/<secret name>` | string[] | false
| `configMaps` | List of ConfigMap names to mount as volumes in the containers. Each config map is mounted as a read-only volume under `/etc/configmaps/<config map name>` | string[] | false
| `configMaps` | List of ConfigMap definitions to mount as volumes in the containers. | []<<configmapspec>> | false
| `disableHTTPRoute`| Disable the creation a route to the HTTP port of the application service (false if omitted) | bool | false
| `sessionAffinity`| If connections from the same client IP are passed to the same WildFlyServer instance/pod each time (false if omitted) | bool | false
|=======================
Expand Down Expand Up @@ -82,6 +82,16 @@ transaction, make sure to specify a `volumeClaimTemplate` that so that the same
| `key` | Key of the ConfigMap whose value is the standalone configuration XML file. If omitted, the spec will look for the `standalone.xml` key. | string |false
|=======================

[[configmapspec]]
## `ConfigMapSpec`

`ConfigMapSpec` defines a `ConfigMap` name to mount as volume in the container. By specifying `mountPath` it is possible to configure the path where this config map should be mounted.
[options="header,footer"]
|=======================
| Field | Description |Scheme| Required
| `name` | Name of the `ConfigMap` to mount as a volume. | string | true
| `mountPath` | Path within the volume from which the container's volume should be mounted. Must not contain ':'. In case of a relative path, the path is treated as relative to `JBOSS_HOME`. It defaults to `/etc/configmaps/<config map name>` | string |false
yersan marked this conversation as resolved.
Show resolved Hide resolved
|=======================

[[wildflyserverstatus]]
## `WildFlyServerStatus`
Expand Down
39 changes: 29 additions & 10 deletions doc/user-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -140,34 +140,53 @@ my-very-secure-pasword

ConfigMaps can be mounted as volumes to be accessed from the application.

The config maps must be created *before* the WildFly Operator deploys the application. For example we can create a config map named `my-config` with a command such as:
The config maps must be created *before* the WildFly Operator deploys the application. We can configure the Operator to mount multiple config maps.

For example, we can create one config map named `my-literals` to supply two literal values with a command such as:

[source,shell]
----
$ kubectl create configmap my-literals --from-literal=key1=value1 --from-literal=key2=value2
configmap/my-literals created
----

We can create another config map named `my-extensions` to supply two files with a command such as:

[source,shell]
----
$ kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2
configmap/my-config created
$ kubectl create configmap my-extensions --from-file=preconfigure.sh --from-file=postconfigure.sh
configmap/extesions created
----

Once the config map has been created, we can specify its name in the WildFlyServer Spec to have it mounted as a volume in the pods running the application:
Once our config maps have been created, we can configure them in the WildFlyServer Spec to have them mounted as a volumes in the pods running the application.

For each config map, we have to specify its name and, optionally, an absolute or relative path where we want them mounted.
If we do not specify a mount path, then the config map will be mounted by default under `/etc/configmaps/<config map name>`. If the mount path is relative, then the mount path is treated as relative to `JBOSS_HOME`. This path cannot contains ':', if so, the resource creation will be rejected. Notice when the config maps are mounted, if they are mounted to an existing filesystem directory, the files on that directly will not be accessible to the image until the config map is unmounted. It is left to the user to take the precautions to do not override a directory that is used by the container to work properly.

For example, given two config maps `my-literals` and `my-extensions`, we could configure them in the WildFlyServer Spec as:

[source,yaml]
.Example of mounting config maps
----
spec:
configMaps:
- my-config
- name: my-literals
- name: my-extensions
mountPath: extensions
----

The config maps will then be mounted under `/etc/configmaps/<config map name>` and each key/value will be stored in a file (whose name is the key and the content is the value).
This configuration will result in the following content available in our running pod:

[source,shell]
.Config Map is mounted as a volume inside the Pod
.Config Maps mounted as a volume inside the Pod
----
[jboss@quickstart-0 ~]$ ls /etc/configmaps/my-config/
[jboss@quickstart-0 ~]$ ls $JBOSS_HOME/extensions
preconfigure.sh postconfigure.sh
[jboss@quickstart-0 ~]$ ls /etc/configmaps/my-literals
key1 key2
[jboss@quickstart-0 ~]$ cat /etc/configmaps/my-config/key1
[jboss@quickstart-0 ~]$ cat /etc/configmaps/my-literals/key1
value1
[jboss@quickstart-0 ~]$ cat /etc/configmaps/my-config/key2
[jboss@quickstart-0 ~]$ cat /etc/configmaps/my-literals/key2
value2
----

Expand Down
151 changes: 151 additions & 0 deletions examples/extensions/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
= The Extension mechanism

This example shows how to use the extension mechanism available on the WildFly images by using the WildFly Operator.

The extension mechanism allows the execution of arbitrary bash scripts before and after server configuration by using environment variables.

When the server is launched, the `$JBOSS_HOME/extensions` directory on the image filesystem is examined to look for any of these two files:

* `$JBOSS_HOME/extensions/preconfigure.sh`
* `$JBOSS_HOME/extensions/postconfigure.sh`

If `preconfigure.sh` exists, then it is executed as an initial step before configuring the server by using the environment variables. Similarly, once the server is configured, if `postconfigure.sh` exists, it is executed. Those specific scripts give you the opportunity to prepare the image for the server configuration and to execute any task once the server is configured.

In this example, we will use the WildFly Operator to place our scripts under `$JBOSS_HOME/extensions/`. We can do it by using a config map to supply the scripts to the image. The WildFly Operator allows specifying the mount path where a config map should be mounted. That makes the use of the extension mechanism pretty simply; the files on the config map must be mounted under `$JBOSS_HOME/extensions/`, that is all.

== Prerequisites

* Install OpenShift (or Code Ready Containers, minishift or minikube)
* Install the WildFly Operator as explained in the https://github.com/wildfly/wildfly-operator#install-the-operator-and-associate-resources[README].

== Create a ConfigMap to supply our scripts

The `preconfigure.sh` and `postconfigure.sh` scripts are under the https://github.com/wildfly/wildfly-operator/tree/master/examples/extensions/config[config] directory of this example. The command to add both to a config map is the following:

[source,shell]
----
$ oc create configmap extensions-configmap --from-file=./config/
configmap/extensions-configmap created
----

Let us examine its content:

https://github.com/wildfly/wildfly-operator/blob/master/examples/extensions/config/preconfigure.sh[preconfigure.sh]
[source,shell]
....
#!/bin/bash

echo "========== Executing preconfigure.sh =========="

for ((i=0;i<5;i++)); do echo ${i}; sleep 1; done

echo "========== End preconfigure.sh =========="
....

https://github.com/wildfly/wildfly-operator/blob/master/examples/extensions/config/postconfigure.sh[postconfigure.sh]
[source,shell]
....
#!/bin/bash

echo "========== Executing postconfigure.sh =========="

for ((i=0;i<5;i++)); do echo ${i}; sleep 1; done

echo "========== End postconfigure.sh =========="
....

The files are regular bash scripts for testing purposes that print messages simulating a task being executed before and after the server is configured.

Once we have configured the config map, we can post our custom resource to the Openshift cluster. This resource will be instantiated by the WildFly Operator.

== Deploy the image

The custom resource for this example is defined in the https://github.com/wildfly/wildfly-operator/blob/master/examples/extensions/crds/extensions-app.yaml[extensions-app.yaml file]:

[source,yaml]
----
apiVersion: wildfly.org/v1alpha1
kind: WildFlyServer
metadata:
name: extensions-app
spec:
applicationImage: "quay.io/wildfly/wildfly-centos7:latest"
replicas: 2
configMaps:
- name: extensions-configmap
mountPath: extensions
----

This custom resource will run the https://quay.io/repository/wildfly/wildfly-centos7?tab=tags[wildfly-centos7 image], which is the server image without any application deployed. We do not need an application deployed for this example, so we have used just the server image.

The custom resource defines a config map with a mount path being relative; the mount path does not start with the slash character. Since it is a relative path, this config map will be mounted under `$JBOSS_HOME/extensions`. This directory will include our scripts that will be executed by the extension mechanism.

The image can be deployed on the OpenShift cluster using the WildFly Operator:

[source,shell]
----
$ oc apply -f crds/extensions-app.yaml
wildflyserver.wildfly.org/extensions-app created
----

You can then check the status of the image:

[source,shell]
----
$ oc describe wildflyserver extensions-app
Name: extensions-app
Namespace: op-default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"wildfly.org/v1alpha1","kind":"WildFlyServer","metadata":{"annotations":{},"name":"extensions-app","namespace":"op-default"}...
API Version: wildfly.org/v1alpha1
Kind: WildFlyServer
Metadata:
Creation Timestamp: 2020-03-10T15:15:31Z
Generation: 1
Resource Version: 385073
Self Link: /apis/wildfly.org/v1alpha1/namespaces/op-default/wildflyservers/extensions-app
UID: fb98cc9b-62e1-11ea-86d4-0ef0e3c74fbe
Spec:
Application Image: quay.io/wildfly/wildfly-centos7:latest
Config Maps:
Mount Path: extensions
Name: extensions-configmap
Replicas: 2
Status:
Hosts:
extensions-app-route-op-default.apps-crc.testing
Pods:
Name: extensions-app-0
Pod IP: 10.128.1.188
State: ACTIVE
Name: extensions-app-1
Pod IP: 10.128.1.187
State: ACTIVE
Replicas: 2
Scalingdown Pods: 0
Events: <none>
----


== Validate the configuration

Once we have created our custom resource, we will see the pods created, each of them running the WildFly server:

[source,shell]
----
$ oc get pods
NAME READY STATUS RESTARTS AGE
extensions-app-0 1/1 Running 0 17s
extensions-app-1 1/1 Running 0 17s
wildfly-operator-667b5dfb57-b2wp9 1/1 Running 0 98s
----

We can check the logs of each application pod to verify the echo messages of our scripts were printed:

[source,shell]
----
$ oc logs extensions-app-0
----

You will see how our scripts were executed before and after the server is configured.
7 changes: 7 additions & 0 deletions examples/extensions/config/postconfigure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

echo "========== Executing postconfigure.sh =========="

for ((i=0;i<5;i++)); do echo ${i}; sleep 1; done

echo "========== End postconfigure.sh =========="
7 changes: 7 additions & 0 deletions examples/extensions/config/preconfigure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

echo "========== Executing preconfigure.sh =========="

for ((i=0;i<5;i++)); do echo ${i}; sleep 1; done

echo "========== End preconfigure.sh =========="
10 changes: 10 additions & 0 deletions examples/extensions/crds/extensions-app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: wildfly.org/v1alpha1
kind: WildFlyServer
metadata:
name: extensions-app
spec:
applicationImage: "quay.io/wildfly/wildfly-centos7:latest"
replicas: 2
configMaps:
- name: extensions-configmap
mountPath: extensions
14 changes: 12 additions & 2 deletions pkg/apis/wildfly/v1alpha1/wildflyserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ type WildFlyServerSpec struct {
Secrets []string `json:"secrets,omitempty"`
// ConfigMaps is a list of ConfigMaps in the same namespace as the WildFlyServer
// object, which shall be mounted into the WildFlyServer Pods.
// The ConfigMaps are mounted into /etc/configmaps/<configmap-name>.
// It can optionally specify the path, as an absolute or relative path, within the container at which the volume should be mounted.
// If the specified mount path is a relative path, then it will be treated relative to JBOSS_HOME.
// If a MountPath is not specified, then the ConfigMap is mount by default into /etc/configmaps/<configmap-name>.
// +kubebuilder:validation:MinItems=1
// +listType=set
ConfigMaps []string `json:"configMaps,omitempty"`
ConfigMaps []ConfigMapSpec `json:"configMaps,omitempty"`
}

// StandaloneConfigMapSpec defines the desired configMap configuration to obtain the standalone configuration for WildFlyServer
Expand Down Expand Up @@ -135,6 +137,14 @@ type WildFlyServerList struct {
Items []WildFlyServer `json:"items"`
}

// ConfigMapSpec represents a ConfigMap definition with a name and a mount path. MountPath cannot contains ':'
// +k8s:openapi-gen=true
type ConfigMapSpec struct {
Name string `json:"name"`
// +kubebuilder:validation:Pattern=`^[^:]+$`
MountPath string `json:"mountPath,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

could you please move the comment about the mount path from ConfigMapSpec to here so that is is correctly picked when the openapi and k8s resources are generated?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

}

func init() {
SchemeBuilder.Register(&WildFlyServer{}, &WildFlyServerList{})
}
18 changes: 17 additions & 1 deletion pkg/apis/wildfly/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading