diff --git a/.che/che-theia-plugins.yaml b/.che/che-theia-plugins.yaml deleted file mode 100644 index 3fade276..00000000 --- a/.che/che-theia-plugins.yaml +++ /dev/null @@ -1,4 +0,0 @@ -- id: errata-ai/vale-server/latest - override: - preferences: - "vale.core.useCLI": true diff --git a/.devfile.yaml b/.devfile.yaml index 5e8b8a0e..8de80668 100644 --- a/.devfile.yaml +++ b/.devfile.yaml @@ -23,7 +23,7 @@ commands: exec: label: 0. Install Gemfile dependencies component: jekyll - commandLine: bundle install + commandLine: bundle install --gemfile=/projects/che-blog/Gemfile group: kind: build isDefault: true @@ -31,8 +31,7 @@ commands: exec: label: 1. Start the jekyll based blog server component: jekyll - # commandLine: bundle jekyll serve --incremental --watch --host 0.0.0.0 --livereload --livereload-port 35729 - commandLine: bundle exec jekyll serve --incremental --watch --host 0.0.0.0 + commandLine: bundle exec jekyll serve --watch --host 0.0.0.0 --future group: kind: run isDefault: true @@ -43,3 +42,17 @@ commands: group: kind: build isDefault: false + - id: publish-blog-to-surge + exec: + component: jekyll + commandLine: | + read -p "ENTER your GitHub login to customize the URL: " GH_LOGIN && + read -p "ENTER a surge.sh token: " SURGE_TOKEN && + export SURGE_TOKEN && + export GH_LOGIN && + npm install -g surge && + surge ./_site --domain https://pr-${GH_LOGIN}-che-blog.surge.sh + +events: + postStart: + - bundle-install diff --git a/.docker/.vale.ini b/.docker/.vale.ini index 7c18bb12..b15c3e7d 100644 --- a/.docker/.vale.ini +++ b/.docker/.vale.ini @@ -1,4 +1,4 @@ -StylesPath = /home/jekyll/.vale/styles +StylesPath = /home/user/.vale/styles # Minimum alert level # ------------------- diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..b82fe432 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "sunday" + time: "16:00" + groups: + all-actions: + patterns: [ "*" ] + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "weekly" + day: "sunday" + time: "16:00" \ No newline at end of file diff --git a/.github/workflows/publish-surge-pr-check.yml b/.github/workflows/publish-surge-pr-check.yml index b017b038..27151ade 100644 --- a/.github/workflows/publish-surge-pr-check.yml +++ b/.github/workflows/publish-surge-pr-check.yml @@ -50,18 +50,26 @@ jobs: echo "PR_SHA=$pr_sha" >> $GITHUB_ENV - uses: actions/setup-node@v3 with: - node-version: '16' + node-version: '20' - name: publish env: SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} run: | npm install -g surge - export DEPLOY_DOMAIN=https://pr-check-${PR_NUMBER}-${{matrix.dist}}-che-blog.surge.sh + export DEPLOY_DOMAIN=https://pr-check-${PR_NUMBER}-che-blog.surge.sh echo "DEPLOY_DOMAIN=$DEPLOY_DOMAIN" >> $GITHUB_ENV surge ./_site --domain $DEPLOY_DOMAIN - name: 'Comment PR' - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { repo: { owner, repo } } = context; - await github.repos.createCommitStatus({ owner, repo, sha: process.env.PR_SHA, state: "success", target_url: process.env.DEPLOY_DOMAIN, description: "Browse PR check blog content live", context: "surge"}) + await github.rest.repos.createCommitStatus({ + owner, + repo, + sha: process.env.PR_SHA, + state: "success", + target_url: process.env.DEPLOY_DOMAIN, + description: "Browse PR check blog content live", + context: "surge" + }) diff --git a/.github/workflows/vale.yml b/.github/workflows/vale.yml index 8d3f4cd0..6b95bbca 100644 --- a/.github/workflows/vale.yml +++ b/.github/workflows/vale.yml @@ -49,7 +49,7 @@ jobs: run: echo using '${{ env.CHANGED_FILES }}' files - name: Vale Linter - uses: benoitf/vale-action@comment-pr + uses: benoitf/vale-action@reviewdog with: files: '${{ env.CHANGED_FILES }}' styles: | diff --git a/_posts/2024-02-05-cde-customization.adoc b/_posts/2024-02-05-cde-customization.adoc new file mode 100644 index 00000000..7d66f0b2 --- /dev/null +++ b/_posts/2024-02-05-cde-customization.adoc @@ -0,0 +1,441 @@ +--- +title: Customizing Eclipse Che Cloud Development Environments +layout: post +author: Mario Loriedo +description: >- + In this article we review the different ways to customize an Eclipse Che Cloud Development Environment +categories: [] +keywords: ['CDE'] +slug: /@mario.loriedo/cde-customization +--- + +Eclipse Che provides Cloud Development Environments (CDEs) with a click. The default container of those CDEs, what we call the https://github.com/devfile/developer-images/[universal developer image], has a lot of pre-installed development tools but may not have the right version or the right tool for you. If that's the case, no worries: one of Eclipse Che CDEs' main assets is configurability! + +In this blog post we will review Eclipse Che CDEs' customization in 4 parts: + +<> + +<> + +<> + +<> + + +NOTE: To help illustrate this blog post we will use a https://github.com/l0rd/rails-sample[Ruby on Rails project]. Ruby is a good example because the default development container doesn't include Ruby development tools at all. For other languages such as Java, Go, NodeJS, Python and .NET, the Eclipse Che default development image includes a few tools, and all the customizations in this blog post may not be necessary. + +## PART 1: Eclipse Che default CDE [[part1]] + +When no Devfile is found in a git repository and the developer doesn't provide a URL, Eclipse Che uses a default development environment. + +image::/assets/img/cde-customization/ruby-sample-main-branch.gif[] +{nbsp} + +The https://github.com/l0rd/rails-sample[rails-sample] git repository has no `devfile.yaml`, and Che informs us about that: + +> Devfile could not be found in https://github.com/l0rd/rails-sample. Applying the default configuration + +NOTE: Click https://workspaces.openshift.com/#https://github.com/l0rd/rails-sample[here] to open https://github.com/l0rd/rails-sample[] in the Red Hat Developer Sandbox to try it out. + +### Default CDE Pod details + +Let's have a look at the Kubernetes objects that get created when the default Eclipse Che CDE is started. From the Visual Studio Code Terminal we can list Kubernetes Pods: + +[attributes] +.... +$ kubectl get pod +NAME READY STATUS RESTARTS AGE +workspacef14b414e91574d61-675c894dbb-ch727 2/2 Running 0 2m +.... + +This is the CDE Pod. Then we can look at the images of the containers of the Pod: + +[attributes] +.... +$ kubectl get pods -o jsonpath='{range ..containers[*]}{.image}{"\n"}{end}' +quay.io/devfile/universal-developer-image:ubi8-latest +quay.io/eclipse/che--traefik:v2.9.10-8d81a9df1435f9f3d... +.... + +The first container image is `registry.redhat.io/devspaces/udi-rhel8` or `UDI` (Universal Developer Image) and has a default set of development tools. The second is `traefik`, a https://github.com/traefik/traefik/[reverse proxy] that Eclipse Che uses to authenticate CDE users. + +NOTE: You may see a different output. That's because Eclipse Che can be configured to use a different default image. For example, on Red Hat Developer Sandbox, the default image is `registry.redhat.io/devspaces/udi-rhel8`. + +### Universal Developer Image + +The default container image, `quay.io/devfile/universal-developer-image`, includes quite a few development tools: essential CLI tools, popular programming languages and cloud development tools. It's called _Universal Developer Image_ and the following diagram summarizes its content. + +image::/assets/img/cde-customization/udi.png[] +{nbsp} + +The Universal Developer Image https://github.com/devfile/developer-images/blob/main/universal/ubi8/Dockerfile[Dockerfile] has the details of all the tools, runtimes, environment variables etc...that are included (https://github.com/redhat-developer/devspaces-images/blob/devspaces-3-rhel-8/devspaces-udi/Dockerfile[here is the OpenShift Dev Spaces version]). + +### When the default is not enough + +The configuration of the `rails-sample` Cloud Development Environment is good enough for reading the source code and doing some basic editing, but some essential features of the IDE are missing: + +*Starting the rails application fails:* Rails requires Ruby which is not installed in the default container. + +image::/assets/img/cde-customization/ruby-sample-main-branch-rails-server.png[] +{nbsp} + + +*The https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp[Ruby LSP extension] activation fails:* the extension from Shopify fails because Ruby is not installed. + +image::/assets/img/cde-customization/ruby-sample-main-branch-ruby-lsp.png[] +{nbsp} + + +In PART2 we are going to address those problems by using a container image with the required development tools. + +## PART2: Customize the CDE container image [[part2]] + +In PART 1 we have seen that Eclipse Che CDEs run in a container of a Kubernetes Pod. In this section we are going to see how to replace the default Eclipe Che CDE image with a custom one. + +### The Dockerfile + +We want to build an image with the pre-requisite to run the https://github.com/l0rd/rails-sample[ruby on rails example] seen in PART 1. The following Dockerfile provides the specification of such image. + +```docker +FROM quay.io/devfile/universal-developer-image:latest + +# Switching to root user (setting UID to 0) because next +# commands require root privileges. Universal Developer +# Image default user has UID set to 10001. +USER 0 + +# Install a recent version of ruby +ENV RUBY_VERSION 3.1.2 +RUN dnf -y update && \ + dnf -y install rbenv ruby-build sqlite && \ + dnf -y clean all --enablerepo='*' && \ + rbenv install $RUBY_VERSION && \ + rbenv global $RUBY_VERSION && \ + echo 'eval "$(rbenv init - bash)"' >> $HOME/.bashrc && \ + echo 'eval "$(rbenv init - sh)"' > /etc/profile.d/rbenv.sh + +ENV PATH="${HOME}/.rbenv/shims:${PATH}" ENV="/etc/profile" + +# Install rails +RUN gem install rails + +# Switch back to default user +USER 10001 + +# Set bundle config +RUN bundle config --global path $HOME/.bundle +``` + +The base image in the Dockerfile above is Eclipse Che Universal Developer Image (`quay.io/devfile/universal-developer-image:latest`). The remaining instructions in the Dockerfile install `ruby` and `rails`. + +NOTE: It's not necessary to use the Eclipse Che default image as the base image. I am maintaining https://github.com/devfile/developer-images/[a repository with a list of Dockerfiles for Che CDEs] using popular base images. + +### Build and publish the custom image + +The Dockerfile can be built locally (on your laptop) and pushed to a remote registry such as Docker Hub or Quay.io. That requires `docker` or `podman` and a good Internet connection (the base image, UDI, has a size of a few Gigabytes). + +Another option is to build and push the `Dockerfile` without leaving the `ruby-sample` CDE started in STEP1. `podman` is included in the universal developer image and can be used to build and push the Dockerfile above. + +My preferred alternative though, and the one used in https://github.com/l0rd/rails-sample/blob/dockerfile/.devfile.Dockerfile[branch `dockerfile` of the ruby-sample repository], is to leverage GitHub actions to automatically build and push the image: + +1. Add the Dockerfile to the git repository as `.devfile.Dockerfile` +2. Add a GitHub workflow to build and push the image automatically (https://github.com/l0rd/rails-sample/blob/dockerfile/.github/workflows/image-build.yaml[see an example here]) +3. Push both files to a remote branch of the git repository + +Last step will trigger the GitHub action job that builds the image: + +image::/assets/img/cde-customization/github-action.png[] +{nbsp} + +As a result the image will be built and published on `quay.io` automatically after every push to the repository. The job in the https://github.com/l0rd/rails-sample/blob/dockerfile/.github/workflows/image-build.yaml#L29[branch `dockerfile` of the ruby-sample repository] builds and publishes the image `quay.io/mloriedo/rails-blog-cde:latest`. + +NOTE: I have named the file as `.devfile.Dockerfile`: even though any name is ok, I like to use the `.devfile` prefix as these images are usually used in devfiles (as we will do STEP 3). + +### Start a new CDE using the custom image + +The simplest way to start a workspace using a new custom image is to use Eclispe Che URL parameter https://eclipse.dev/che/docs/stable/end-user-guide/url-parameter-for-container-image/[`?image=`]. + +For example, to start a CDE using the custom image `quay.io/mloriedo/rails-blog-cde` and cloning rails-sample, the following string can be used in the "Create Workspace" page: + +[attributes] +.... +https://github.com/l0rd/rails-sample&image=quay.io/mloriedo/rails-blog-cde +.... + +image::/assets/img/cde-customization/image-url-parameter.png[] +{nbsp} + + +Clicking https://workspaces.openshift.com/#https://github.com/l0rd/rails-sample&image=quay.io/mloriedo/rails-blog-cde[on this URL] automatically starts the customized CDE on the Red Hat Developer Sandbox. + +### Verify the new CDE Pod image + +The CDE Pod now uses a `rails-blog-cde` container rather than the Eclipse Che default universal developer image. To verify it open a Terminal from Visual Studio Code and run `kubectl`: + +[attributes] +.... +$ kubectl get pods -o jsonpath='{range ..containers[*]}{.image}{"\n"}{end}' +quay.io/mloriedo/rails-blog-cde:latest +quay.io/eclipse/che--traefik:v2.9.10-8d81a9df1435f9f3d... +.... + +### Run Ruby on Rails from the Terminal + +We can verify that the `rails-sample` application starts successfully from the Visual Studio Code Terminal: + +[attributes] +.... +$ bundle install && ./bin/rails server +(...) +=> Booting Puma +=> Rails 7.0.8 application starting in development +=> Run `bin/rails server --help` for more startup options +Puma starting in single mode... +* Puma version: 5.6.8 (ruby 3.1.2-p20) ("Birdie's Version") +* Min threads: 5 +* Max threads: 5 +* Environment: development +* PID: 4119 +* Listening on http://127.0.0.1:3000 +* Listening on http://[::1]:3000 +Use Ctrl-C to stop +.... + +### Install `ruby-lsp` Visual Studio Code extension + +Finally, the Ruby LSP extension, which failed to activate in STEP1, is now fully working: + +image::/assets/img/cde-customization/ruby-lsp-extension-fully-functional.png[] +{nbsp} + +Replacing the Eclipse Che default image with a custom one allowed us to include the right pre-requisites (ruby and rails) to the CDE. With that, we are able to run the application and the Visual Studio Code ruby extension. + +But there are still some issues with the CDE that we would like to fix (e.g. CPU and memory are not enough, running the application is not automated, the application dependencies are not pre-fetch at startup etc...). We will cover those in the next session where we will use the Devfile to perform more advanced configurations for the CDE. + +[TIP] +==== +We have seen how to replace the image of the CDE using a URL parameter. We will see in the next section that it can be done with a Devfile too. A third alternative is changing the image "on the fly" using `kubectl patch` against the DevWorkspace object: +```bash +DW_NAME="rails-sample" && \ +IMAGE="quay.io/mloriedo/rails-blog-cde:latest" && \ +kubectl patch dw "${DW_NAME}" --type='merge' \ + -p '{"spec": + {"template": + {"components": + [ + { "name":"universal-developer-image", + "container":{"image":"'$IMAGE'"} } + ] + } + } + }' +``` +==== + +## PART3: Change CDE properties with a Devfile [[part3]] + +In Part 2 we have seen how to customize a CDE with a new container image. That helps to include some development tools that are not in Eclipse Che default environment. + +But what about properties such as the required memory or CPU, the containers to run in the CDE Pod (a CDE can have multiple containers!), the exposed endpoints, the commands triggered at startup, at shutdown? These properties can be customized using a Devfile and in this Part 3 we are reviewing how to do that. + +### Define a Devfile for an Eclipse Che CDE + +A Devfile is an https://www.cncf.io/projects/devfile/[open standard] to define Cloud Development Environments. It's a YAML file used to configure Eclipse Che CDEs. + +Here is a simple Devfile that specifies the container image built in STEP 2: + +```yaml +schemaVersion: 2.2.0 +metadata: + name: rails-sample +components: + - name: devtools + container: + image: quay.io/mloriedo/rails-blog-cde:latest +``` + +It's recommended to add the Devfile in the same git repository of the application being developed using the name `.devfile.yaml` (as in the https://github.com/l0rd/rails-sample/tree/devfile[`devfile` branch of the `rails-sample`]). A Devfile in the git repository will evolve along with the application and will be applied automatically whenever a developer provides the git repository URL to start a CDE. + +When it's not possible to add a `.devfile.yaml` in the git repository, there is still the option to publish it (in a gist, pastebin or another git repository) and https://eclipse.dev/che/docs/stable/end-user-guide/starting-a-workspace-from-a-raw-devfile-url/[start the CDE by providing the raw URL to it]. + +TIP: To change the configuration of a running CDE, add a new `.devfile.yaml` (or edit the existing one), and restart the CDE using the command `Eclipse Che: Restart Workspace from Local Devfile` from the Visual Studio Code command palette. This command is also quickly accessible by clicking on the bottom-left corner of Visual Studio Code. + +TIP: https://open-vsx.org/extension/Devfile/vscode-devfile[The Devfile Visual Studio Code walkthrough extension] helps generating a Devfile using a GUI wizard. + +### Step by step guide to an optimal Devfile + +The https://devfile.io/docs/2.2.2/what-is-a-devfile[documentation website] includes a detailed Devfiles syntax reference. In this section I will share a practical step by step guide to write an optimal Devfile for the https://github.com/l0rd/rails-sample/[`rails-sample`]. + +++++ +include::/assets/html/cde-customization/devfile-table.html[] +++++ +{nbsp} + + +These steps can be tested iteratively from a running CDE using the "Eclipse Che: Restart Workspace from Local Devfile" command in Visual Studio Code. You get the best experience installing https://open-vsx.org/extension/redhat/vscode-yaml[Visual Studio Code YAML extension] that provides code completion when editing a Devfile. + +After the last step, the CDE will be fully functional. After the Devfile has been pushed to the git repository any new contributor will be able to run the application, do some changes, and debug them in a flash. + +For example you can use https://workspaces.openshift.com/#https://github.com/l0rd/rails-sample/tree/devfile[this link] to test the rails-sample using the Devfile in step 7. After the workspace has started, use task `server-start` in VS Code (Terminal => Run Tasks => Devfile) to start the Ruby on Rails application. And install the VS Code extension `ruby-lsp` to get full language support. + +## PART4: Secrets and other CDE configurations that cannot be specified in Devfile [[part4]] + +There are some properties of your CDE that you don't want to specify in a Devfile. Either because they contain sensitive information (like a password or an SSH private key), or because you want to customize your CDE without affecting the rest of the team. In any case the Devfile, which is a shared in the git repository, cannot be used. In this section we will go through a few techniques to add user specific configurations. + +### Add environment variables using Kubernetes `ConfigMaps` and `Secrets` + +The Devfile allows to specify environment variables but in some situations you don't want to add them there. Eclipse Che provides a mechanism to automatically add variables to CDEs containers without Devfiles but using Kubernetes ConfigMaps or Secrets. + +#### Using `ConfigMaps` + +For example, adding an environment variable that holds the URL of the specific Kubernetes cluster (`RAILS_DEVELOPMENT_HOSTS=.apps.che-dev.x6e0.p1.openshiftapps.com`), would make the Devfile less portable. + +Instead we can create, in the namespace when our CDEs are created, a `ConfigMap` with labels `controller.devfile.io/mount-to-devworkspace: "true"` and `controller.devfile.io/watch-configmap: "true"` and with the annotation `controller.devfile.io/mount-as: env`: + +```bash +kubectl apply -f - << EOF +apiVersion: v1 +kind: ConfigMap +metadata: + name: workspaces-env-vars + labels: + controller.devfile.io/mount-to-devworkspace: "true" + controller.devfile.io/watch-configmap: "true" + annotations: + controller.devfile.io/mount-as: env +data: + RAILS_DEVELOPMENT_HOSTS: ".apps.che-dev.x6e0.p1.openshiftapps.com" +EOF +``` + +The environment variables specified in the `data` field of the `ConfigMap` (in this case `RAILS_DEVELOPMENT_HOSTS=.apps.che-dev.x6e0.p1.openshiftapps.com`) will be added automatically to every CDE created in the same namespace. + +#### Using `Secrets` + +An example of environment variables holding sensitive information are those that specify developers' tokens (for example `GITHUB_TOKEN` used by the GitHub CLI). + +In this case, we can create a `Secret` with labels `controller.devfile.io/mount-to-devworkspace: "true"` and `controller.devfile.io/watch-secret: "true"` and with the annotation `controller.devfile.io/mount-as: env`: + +```bash +kubectl apply -f - << EOF +apiVersion: v1 +kind: Secret +metadata: + name: workspaces-env-vars + labels: + controller.devfile.io/mount-to-devworkspace: "true" + controller.devfile.io/watch-secret: "true" + annotations: + controller.devfile.io/mount-as: env +stringData: + GITHUB_TOKEN: "" +EOF +``` + +The environment variable specified in the `stringData` field of the `Secret` (in this case `GITHUB_TOKEN=`) will be added automatically to every CDE created in the same namespace. + +TIP: These ConfigMap and Secret should be created in the developer namespace. The variables specified in `data` will be added to the CDEs of the owner of the namespace only. Eclipse Che uses namespaces to isolate developers CDEs: it's critical to allow read access to the objects in the namespaces only to the developer owning it. + +### Add files to a CDE using Kubernetes `ConfigMaps` and `Secrets` + +Regular files can be projected into CDEs using `ConfigMaps` and `Secrets` too. In this case the required annotation is `controller.devfile.io/mount-as: file`. + +When projecting files, there are two extra annotations read by Eclipse Che: `controller.devfile.io/mount-path: ` specifies the projected file folder, and `controller.devfile.io/mount-access-mode` specifies the projected file's access mode. + +#### Using `ConfigMaps` + +The following `ConfigMap` projects a Visual Studio Code `settings.json` file (remote VS Code data folder is `/checode/remote/data/machine`) that specifies a couple of Visual Studio Code Terminal settings: + +```bash +kubectl apply -f - << EOF +apiVersion: v1 +kind: ConfigMap +metadata: + name: vscode-settings + labels: + controller.devfile.io/mount-to-devworkspace: "true" + controller.devfile.io/watch-configmap: "true" + annotations: + controller.devfile.io/mount-as: file + controller.devfile.io/mount-path: /checode/remote/data/Machine/ + controller.devfile.io/mount-access-mode: "511" +data: + settings.json: | + { + "terminal.integrated.copyOnSelection": true, + "terminal.integrated.cursorBlinking": true + } +EOF +``` + +#### Using `Secrets` + +The following `Secret` projects file `credentials` in fodler `/home/user/.aws`: + +```bash +kubectl apply -f - << EOF +apiVersion: v1 +kind: Secret +metadata: + name: aws-credentials + labels: + controller.devfile.io/mount-to-devworkspace: "true" + controller.devfile.io/watch-secret: "true" + annotations: + controller.devfile.io/mount-as: file + controller.devfile.io/mount-path: /home/user/.aws/ + controller.devfile.io/mount-access-mode: "511" +stringData: + credentials: | + [default] + aws_access_key_id = ABCDEFGHILMNOPQRSTUVZ + aws_secret_access_key = ABCDEFGHILMNOPQRSTUVZ123456789+abcdefg +EOF +``` + +### Override defaults configurations using a DevWorkspace Operator Configuration + +In this last section we want to show a mechanism to override CDEs' default properties. In this case, by using a https://doc.crds.dev/github.com/devfile/devworkspace-operator[DevWorkspaceOperatorConfig Custom Resource]. + +`DevWorkspaceOperatorConfig` objects specify advanced CDE properties such as the `Pod` `schedulerName`, whether the `/home/user` folder will persist after a restart or not, and many more. + +Applying a particular `DevWorkspaceOperatorConfig` to a CDEs takes 2 steps: + +1. Create the `DevWorkspaceOperatorConfig` custom resource in the Kubernetes cluster +2. Edit the Devfile to apply that specific configuration + +The following `DevWorkspaceOperatorConfig` override CDEs Pod `schedulerName` configuration: + +```bash +kubectl apply -f - << EOF +apiVersion: controller.devfile.io/v1alpha1 +kind: DevWorkspaceOperatorConfig +metadata: + name: custom-dwoc + namespace: +config: + workspace: + schedulerName: my-scheduler +EOF +``` + +To apply this configuration to a CDE it's required that the CDE Devfile references it: + +[#temper-change,diff] +.... +schemaVersion: 2.2.0 +metadata: + name: rails-blog ++ attributes: ++ controller.devfile.io/devworkspace-config: ++ name: custom-dwoc ++ namespace: +components: +... +.... + +With that attribute, the CDE started using this devfile will use the scheduler `my-scheduler` (if it exists) rather than the default Kubernetes scheduler. + +NOTE: If the DevWorkspaceOpenratorConfig referenced in a Devfile doesn't exist in the Kubernetes cluster, then Che will silently ignore it. + +## Conclusion + +Most of the time, the Eclipse Che default Cloud Development Environment (CDE) that we have covered in <>, is good enough to start navigating and doing some simple editing of the source code. + +To build and run an application in a CDE, it may be necessary to create a custom container image to replace the default one. This is described in <>. + +But it's in <> that we shared how to make to most out of Eclipse Che development environments. The Devfile allows us to specify development environments as code and share it with the rest of the team. + +Finally, in <>, some more advanced techniques to configure development environments, beyond the devfile, are reviewed. diff --git a/assets/html/cde-customization/devfile-table.css b/assets/html/cde-customization/devfile-table.css new file mode 100644 index 00000000..400af761 --- /dev/null +++ b/assets/html/cde-customization/devfile-table.css @@ -0,0 +1,70 @@ +@import url(https://iosevka-webfonts.github.io/iosevka/iosevka.css); +/* @import url(https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css); */ + +legend { + background-color: #000; + color: #fff; + padding: 3px 6px; + font-family: "Iosevka Web", sans-serif; +} + +input { + margin: 0.4rem; +} + +label { + font-family: "Iosevka Web", sans-serif; +} + +.devfiles { + border: 1px solid black; +} + +pre { + /* margin: 0.4rem; */ + /* padding: 10px 20px 20px 20px; */ + font-family: "Iosevka Web", sans-serif; +} + +code { + font-family: "Iosevka Web", sans-serif; +} + +del, +ins { + display: block; + text-decoration: none; + position: relative; +} + +del { + background-color: #fbb; +} + +ins { + background-color: #d4fcbc; +} + +.area { + display: none; + clear: both; +} + +.steps { + margin: 0.4rem 0.4rem 0.4rem 0.4rem; + /* border: 1px solid black; */ + /* padding: 200px 200px 200px 200px; */ + font-family: "Iosevka Web", sans-serif; +} + +/* (A) FLEX CONTAINER */ +/* .flex-wrap { + display: flex; +} */ + +/* (B) OPTIONAL COSMETICS */ +.flex-wrap > * { + box-sizing: border-box; + /* width: 800px; */ + padding: 10px; +} diff --git a/assets/html/cde-customization/devfile-table.html b/assets/html/cde-customization/devfile-table.html new file mode 100644 index 00000000..649f65b3 --- /dev/null +++ b/assets/html/cde-customization/devfile-table.html @@ -0,0 +1,307 @@ + + + + + Iterative devfile Creation + + + + + +
+ Iterative Devfile Creation +
+
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+
+
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+
+    
+  
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+
+    
+  
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+commands:
+  - id: bundle-install
+    exec:
+      component: devtools
+      commandLine: bundle install
+      workingDir: ${PROJECT_SOURCE}
+  - id: server-start
+    exec:
+      component: devtools
+      commandLine: |
+        ./bin/rails server --binding 0.0.0.0
+  - id: server-kill
+    exec:
+      component: devtools
+      commandLine: kill $(pidof "ruby")
+
+    
+    
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+      memoryRequest: 2G
+      memoryLimit: 4G
+      cpuRequest: '1'
+      cpuLimit: '2'
+commands:
+  - id: bundle-install
+    exec:
+      component: devtools
+      commandLine: bundle install
+      workingDir: ${PROJECT_SOURCE}
+  - id: server-start
+    exec:
+      component: devtools
+      commandLine: |
+        ./bin/rails server --binding 0.0.0.0
+  - id: server-kill
+    exec:
+      component: devtools
+      commandLine: kill $(pidof "ruby")
+    
+    
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+      memoryRequest: 2G
+      memoryLimit: 4G
+      cpuRequest: '1'
+      cpuLimit: '2'
+commands:
+  - id: bundle-install
+    exec:
+      component: devtools
+      commandLine: bundle install
+      workingDir: ${PROJECT_SOURCE}
+  - id: server-start
+    exec:
+      component: devtools
+      commandLine: |
+        ./bin/rails server --binding 0.0.0.0
+  - id: server-kill
+    exec:
+      component: devtools
+      commandLine: kill $(pidof "ruby")
+events:
+  postStart:
+    - bundle-install
+
+
+    
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: bundle-volume
+    volume:
+      size: 1G
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+      memoryRequest: 2G
+      memoryLimit: 4G
+      cpuRequest: '1'
+      cpuLimit: '2'
+      volumeMounts:
+        - name: bundle-volume
+          path: /home/user/.bundle/vendor
+commands:
+  - id: bundle-install
+    exec:
+      component: devtools
+      commandLine: bundle install
+      workingDir: ${PROJECT_SOURCE}
+  - id: server-start
+    exec:
+      component: devtools
+      commandLine: |
+        ./bin/rails server --binding 0.0.0.0
+  - id: server-kill
+    exec:
+      component: devtools
+      commandLine: kill $(pidof "ruby")
+events:
+  postStart:
+    - bundle-install
+    
+    
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: bundle-volume
+    volume:
+      size: 1G
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+      memoryRequest: 2G
+      memoryLimit: 4G
+      cpuRequest: '1'
+      cpuLimit: '2'
+      volumeMounts:
+        - name: bundle-volume
+          path: /home/user/.bundle/vendor
+commands:
+  - id: bundle-install
+    exec:
+      component: devtools
+      commandLine: bundle install
+      workingDir: ${PROJECT_SOURCE}
+  - id: server-start
+    exec:
+      component: devtools
+      commandLine: |
+        export RAILS_DEVELOPMENT_HOSTS="${CHE_DASHBOARD_URL/https:\/\/devspaces/}" &&
+        ./bin/rails server --binding 0.0.0.0
+  - id: server-kill
+    exec:
+      component: devtools
+      commandLine: kill $(pidof "ruby")
+events:
+  postStart:
+    - bundle-install
+    
+    
+
+ +
+
+    
+schemaVersion: 2.2.0
+metadata:
+  name: rails-blog
+components:
+  - name: bundle-volume
+    volume:
+      size: 1G
+  - name: devtools
+    container:
+      image: quay.io/mloriedo/rails-blog-cde:latest
+      memoryRequest: 2G
+      memoryLimit: 4G
+      cpuRequest: '1'
+      cpuLimit: '2'
+      volumeMounts:
+        - name: bundle-volume
+          path: /home/user/.bundle/vendor
+      endpoints:
+        - name: blog
+          exposure: public
+          protocol: https
+          targetPort: 3000
+          path: /articlescommands:
+  - id: bundle-install
+    exec:
+      component: devtools
+      commandLine: bundle install
+      workingDir: ${PROJECT_SOURCE}
+  - id: server-start
+    exec:
+      component: devtools
+      commandLine: |
+        export RAILS_DEVELOPMENT_HOSTS="${CHE_DASHBOARD_URL/https:\/\/devspaces/}" &&
+        ./bin/rails server --binding 0.0.0.0
+  - id: server-kill
+    exec:
+      component: devtools
+      commandLine: kill $(pidof "ruby")
+events:
+  postStart:
+    - bundle-install
+    
+    
+
+
+
+ +
+ + + + + diff --git a/assets/html/cde-customization/devfile-table.js b/assets/html/cde-customization/devfile-table.js new file mode 100644 index 00000000..88d80ead --- /dev/null +++ b/assets/html/cde-customization/devfile-table.js @@ -0,0 +1,13 @@ +const inputelmements = document.querySelectorAll("input"); +const devfiles = document.getElementsByClassName("area"); + +inputelmements.forEach(function (elem) { + elem.addEventListener("click", updateValue); +}); + +function updateValue(e) { + Array.from(devfiles).forEach((devfile) => (devfile.style.display = "none")); + document.getElementById(e.target.value).style.display = "block"; +} + +// hljs.highlightAll(); diff --git a/assets/img/cde-customization/github-action.png b/assets/img/cde-customization/github-action.png new file mode 100644 index 00000000..334e42f7 Binary files /dev/null and b/assets/img/cde-customization/github-action.png differ diff --git a/assets/img/cde-customization/image-url-parameter.png b/assets/img/cde-customization/image-url-parameter.png new file mode 100644 index 00000000..9ed4471e Binary files /dev/null and b/assets/img/cde-customization/image-url-parameter.png differ diff --git a/assets/img/cde-customization/ruby-lsp-extension-fully-functional.png b/assets/img/cde-customization/ruby-lsp-extension-fully-functional.png new file mode 100644 index 00000000..70dcc51c Binary files /dev/null and b/assets/img/cde-customization/ruby-lsp-extension-fully-functional.png differ diff --git a/assets/img/cde-customization/ruby-sample-main-branch-rails-server.png b/assets/img/cde-customization/ruby-sample-main-branch-rails-server.png new file mode 100644 index 00000000..81c34b43 Binary files /dev/null and b/assets/img/cde-customization/ruby-sample-main-branch-rails-server.png differ diff --git a/assets/img/cde-customization/ruby-sample-main-branch-ruby-lsp.png b/assets/img/cde-customization/ruby-sample-main-branch-ruby-lsp.png new file mode 100644 index 00000000..8a285ed8 Binary files /dev/null and b/assets/img/cde-customization/ruby-sample-main-branch-ruby-lsp.png differ diff --git a/assets/img/cde-customization/ruby-sample-main-branch.gif b/assets/img/cde-customization/ruby-sample-main-branch.gif new file mode 100644 index 00000000..c2777459 Binary files /dev/null and b/assets/img/cde-customization/ruby-sample-main-branch.gif differ diff --git a/assets/img/cde-customization/udi.png b/assets/img/cde-customization/udi.png new file mode 100644 index 00000000..192fb1d9 Binary files /dev/null and b/assets/img/cde-customization/udi.png differ