From 5d72ab130ee7a2c9bbc348349b816cb06e605e9a Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Tue, 18 Jun 2019 01:28:41 +0000 Subject: [PATCH 01/10] Install `sudo` for the vanilla K8s. Signed-off-by: Masaki Muranaka --- dockerfiles/theia/e2e/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockerfiles/theia/e2e/Dockerfile b/dockerfiles/theia/e2e/Dockerfile index b529f767bf..7fed5f36f8 100644 --- a/dockerfiles/theia/e2e/Dockerfile +++ b/dockerfiles/theia/e2e/Dockerfile @@ -15,7 +15,7 @@ ENV NOCDN=true RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list RUN apt-get update && \ - apt-get install -y libx11-dev libxkbfile-dev + apt-get install -y libx11-dev libxkbfile-dev sudo CMD /root/docker-run.sh RUN yarn global add typescript@2.9.2 node-gyp From c209cd6d04090a30a073503682d4ef8a14275536 Mon Sep 17 00:00:00 2001 From: Sun Seng David TAN Date: Tue, 18 Jun 2019 02:41:59 +0200 Subject: [PATCH 02/10] README badges: use right labels for question/bug kind/bug and kind/question --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3feb408cd6..b458a6c050 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ [![Build Status](https://ci.codenvycorp.com/buildStatus/icon?job=che-theia-master-ci)](https://ci.codenvycorp.com/job/che-theia-master-ci) [![mattermost](https://img.shields.io/badge/chat-on%20mattermost-blue.svg)](https://mattermost.eclipse.org/eclipse/channels/eclipse-che-ide2-team) - [![Open questions](https://img.shields.io/badge/Open-questions-blue.svg?style=flat-curved)](https://github.com/eclipse/che-theia/labels/question) - [![Open bugs](https://img.shields.io/badge/Open-bugs-red.svg?style=flat-curved)](https://github.com/eclipse/che-theia/labels/bug) + [![Open questions](https://img.shields.io/badge/Open-questions-blue.svg?style=flat-curved)](https://github.com/eclipse/che-theia/labels/kind%2Fquestion) + [![Open bugs](https://img.shields.io/badge/Open-bugs-red.svg?style=flat-curved)](https://github.com/eclipse/che-theia/labels/kind%2Fbug) From 57821880a33a67fd8743f64978fec145ad910e48 Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Tue, 18 Jun 2019 01:42:03 +0000 Subject: [PATCH 03/10] Watch if Theia starts listening the port. Signed-off-by: Masaki Muranaka --- dockerfiles/theia/e2e/Dockerfile | 2 +- dockerfiles/theia/e2e/src/docker-run.sh | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dockerfiles/theia/e2e/Dockerfile b/dockerfiles/theia/e2e/Dockerfile index 7fed5f36f8..f64c3d880d 100644 --- a/dockerfiles/theia/e2e/Dockerfile +++ b/dockerfiles/theia/e2e/Dockerfile @@ -15,7 +15,7 @@ ENV NOCDN=true RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list RUN apt-get update && \ - apt-get install -y libx11-dev libxkbfile-dev sudo + apt-get install -y libx11-dev libxkbfile-dev sudo iproute2 CMD /root/docker-run.sh RUN yarn global add typescript@2.9.2 node-gyp diff --git a/dockerfiles/theia/e2e/src/docker-run.sh b/dockerfiles/theia/e2e/src/docker-run.sh index e20f50b800..fbaee1dbe8 100755 --- a/dockerfiles/theia/e2e/src/docker-run.sh +++ b/dockerfiles/theia/e2e/src/docker-run.sh @@ -6,13 +6,32 @@ # # SPDX-License-Identifier: EPL-2.0 +# (5 + 2 * 30 = 65 seconds) is the default timeout. +: "${WAIT_COUNT:=30}" + echo "Starting Theia..." rm -rf /root/logs/* HOME=/home/theia /entrypoint.sh > /root/logs/theia.log 2>/root/logs/theia-error.log& -sleep 10s + echo "Cleaning videos folder..." # Cleanup previous videos -rm -rf /root/cypress/videos +rm -rf /root/cypress/videos/* + +# Find TCP 0.0.0.0:3100 that will be opened by Theia. +sleep 5s +while [ $WAIT_COUNT -gt 0 ]; do + # Check the listening port + ss -nlt | grep -Fq ':3100' && break + # not found + WAIT_COUNT=$((WAIT_COUNT-1)); + echo "Waiting for booting up Theia..." + sleep 2s +done + +if [ $WAIT_COUNT -eq 0 ]; then + echo "Timeout. Theia is dead?" + exit 1 +fi # Run tests echo "Run the tests" From 5eee28efdc9f2c1921f43369ac70c0b4eaf92167 Mon Sep 17 00:00:00 2001 From: Oleksii Kurinnyi Date: Fri, 14 Jun 2019 10:50:50 +0000 Subject: [PATCH 04/10] expose some methods from CheApiService to Che Plugin API --- .../src/browser/che-api-provider.ts | 2 + .../src/browser/che-user-main.ts | 38 ++++++++++++++++ .../src/common/che-protocol.ts | 12 ++++++ .../src/plugin/che-api.ts | 20 ++++++++- .../src/plugin/che-user.ts | 43 +++++++++++++++++++ .../src/che-proposed.d.ts | 13 ++++++ 6 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 extensions/eclipse-che-theia-plugin-ext/src/browser/che-user-main.ts create mode 100644 extensions/eclipse-che-theia-plugin-ext/src/plugin/che-user.ts diff --git a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-api-provider.ts b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-api-provider.ts index c464081de2..d0839da395 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-api-provider.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-api-provider.ts @@ -18,6 +18,7 @@ import { CheVariablesMainImpl } from './che-variables-main'; import { CheTaskMainImpl } from './che-task-main'; import { CheSshMainImpl } from './che-ssh-main'; import { CheDevfileMainImpl } from './che-devfile-main'; +import { CheUserMainImpl } from './che-user-main'; @injectable() export class CheApiProvider implements MainPluginApiProvider { @@ -29,6 +30,7 @@ export class CheApiProvider implements MainPluginApiProvider { rpc.set(PLUGIN_RPC_CONTEXT.CHE_VARIABLES_MAIN, new CheVariablesMainImpl(container, rpc)); rpc.set(PLUGIN_RPC_CONTEXT.CHE_TASK_MAIN, new CheTaskMainImpl(container, rpc)); rpc.set(PLUGIN_RPC_CONTEXT.CHE_SSH_MAIN, new CheSshMainImpl(container)); + rpc.set(PLUGIN_RPC_CONTEXT.CHE_USER_MAIN, new CheUserMainImpl(container)); } } diff --git a/extensions/eclipse-che-theia-plugin-ext/src/browser/che-user-main.ts b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-user-main.ts new file mode 100644 index 0000000000..b527c1de49 --- /dev/null +++ b/extensions/eclipse-che-theia-plugin-ext/src/browser/che-user-main.ts @@ -0,0 +1,38 @@ +/********************************************************************* + * Copyright (c) 2019 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ + +import { interfaces } from 'inversify'; +import { CheApiService, CheUserMain } from '../common/che-protocol'; +import { Preferences } from '@eclipse-che/plugin'; + +export class CheUserMainImpl implements CheUserMain { + + private readonly cheApiService: CheApiService; + + constructor(container: interfaces.Container) { + this.cheApiService = container.get(CheApiService); + } + + $getUserPreferences(filter?: string): Promise { + return this.cheApiService.getUserPreferences(filter); + } + + $updateUserPreferences(preferences: Preferences): Promise { + return this.cheApiService.updateUserPreferences(preferences); + } + + $replaceUserPreferences(preferences: Preferences): Promise { + return this.cheApiService.replaceUserPreferences(preferences); + } + + $deleteUserPreferences(list?: string[]): Promise { + return this.cheApiService.deleteUserPreferences(list); + } +} diff --git a/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts b/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts index 32c4fd264a..2ba61310ea 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts @@ -366,6 +366,9 @@ export const PLUGIN_RPC_CONTEXT = { CHE_SSH: >createProxyIdentifier('CheSsh'), CHE_SSH_MAIN: >createProxyIdentifier('CheSshMain'), + + CHE_USER: >createProxyIdentifier('CheUser'), + CHE_USER_MAIN: >createProxyIdentifier('CheUserMain'), }; // Theia RPC protocol @@ -487,3 +490,12 @@ export interface ChePluginService { removePlugin(pluginKey: string): Promise; } + +export interface CheUser { } + +export interface CheUserMain { + $getUserPreferences(filter?: string): Promise; + $updateUserPreferences(preferences: Preferences): Promise; + $replaceUserPreferences(preferences: Preferences): Promise; + $deleteUserPreferences(list?: string[]): Promise; +} diff --git a/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-api.ts b/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-api.ts index 11d1b027c1..eb5c739cb2 100644 --- a/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-api.ts +++ b/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-api.ts @@ -19,6 +19,7 @@ import { CheFactoryImpl } from './che-factory'; import { CheDevfileImpl } from './che-devfile'; import { CheTaskImpl } from './che-task-impl'; import { CheSshImpl } from './che-ssh'; +import { CheUserImpl } from './che-user'; export interface CheApiFactory { (plugin: Plugin): typeof che; @@ -31,6 +32,7 @@ export function createAPIFactory(rpc: RPCProtocol): CheApiFactory { const cheVariablesImpl = rpc.set(PLUGIN_RPC_CONTEXT.CHE_VARIABLES, new CheVariablesImpl(rpc)); const cheTaskImpl = rpc.set(PLUGIN_RPC_CONTEXT.CHE_TASK, new CheTaskImpl(rpc)); const cheSshImpl = rpc.set(PLUGIN_RPC_CONTEXT.CHE_SSH, new CheSshImpl(rpc)); + const cheUserImpl = rpc.set(PLUGIN_RPC_CONTEXT.CHE_USER, new CheUserImpl(rpc)); return function (plugin: Plugin): typeof che { const workspace: typeof che.workspace = { @@ -124,13 +126,29 @@ export function createAPIFactory(rpc: RPCProtocol): CheApiFactory { } }; + const user: typeof che.user = { + getUserPreferences(filter?: string): Promise { + return cheUserImpl.getUserPreferences(filter); + }, + updateUserPreferences(update: che.Preferences): Promise { + return cheUserImpl.updateUserPreferences(update); + }, + replaceUserPreferences(preferences: che.Preferences): Promise { + return cheUserImpl.replaceUserPreferences(preferences); + }, + deleteUserPreferences(list?: string[]): Promise { + return cheUserImpl.deleteUserPreferences(list); + } + }; + return { workspace, factory, devfile, variables, task, - ssh + ssh, + user }; }; diff --git a/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-user.ts b/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-user.ts new file mode 100644 index 0000000000..03b5594b08 --- /dev/null +++ b/extensions/eclipse-che-theia-plugin-ext/src/plugin/che-user.ts @@ -0,0 +1,43 @@ +/********************************************************************* + * Copyright (c) 2019 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ + +import { RPCProtocol } from '@theia/plugin-ext/lib/api/rpc-protocol'; +import { Preferences } from '@eclipse-che/plugin'; +import { + CheUser, + CheUserMain, + PLUGIN_RPC_CONTEXT, +} from '../common/che-protocol'; + +export class CheUserImpl implements CheUser { + + private readonly userMain: CheUserMain; + + constructor(rpc: RPCProtocol) { + this.userMain = rpc.getProxy(PLUGIN_RPC_CONTEXT.CHE_USER_MAIN); + } + + getUserPreferences(filter?: string): Promise { + return this.userMain.$getUserPreferences(filter); + } + + updateUserPreferences(update: Preferences): Promise { + return this.userMain.$updateUserPreferences(update); + } + + replaceUserPreferences(preferences: Preferences): Promise { + return this.userMain.$replaceUserPreferences(preferences); + } + + deleteUserPreferences(list?: string[]): Promise { + return this.userMain.$deleteUserPreferences(list); + } + +} diff --git a/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts b/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts index 33417c16ab..71b347df99 100644 --- a/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts +++ b/extensions/eclipse-che-theia-plugin/src/che-proposed.d.ts @@ -156,4 +156,17 @@ declare module '@eclipse-che/plugin' { /** Additional task type specific properties. */ readonly [key: string]: any; } + + export namespace user { + export function getUserPreferences(): Promise; + export function getUserPreferences(filter: string | undefined): Promise; + export function updateUserPreferences(update: Preferences): Promise; + export function replaceUserPreferences(preferences: Preferences): Promise; + export function deleteUserPreferences(): Promise; + export function deleteUserPreferences(list: string[] | undefined): Promise; + } + + export interface Preferences { + [key: string]: string; + } } From 494158af65edf281af3a39c91a64f69ae84d5f5f Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Tue, 18 Jun 2019 12:39:01 +0900 Subject: [PATCH 05/10] Run `node-gyp install` before rebuilds. The parallel install by Yarn will break rebuild processes. Signed-off-by: Masaki Muranaka --- dockerfiles/remote-plugin-dotnet-2.2.105/Dockerfile | 3 ++- dockerfiles/theia-dev/Dockerfile | 2 ++ dockerfiles/theia/Dockerfile | 2 +- dockerfiles/theia/e2e/Dockerfile | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dockerfiles/remote-plugin-dotnet-2.2.105/Dockerfile b/dockerfiles/remote-plugin-dotnet-2.2.105/Dockerfile index 5d7bfe4f94..979ce7c8b8 100644 --- a/dockerfiles/remote-plugin-dotnet-2.2.105/Dockerfile +++ b/dockerfiles/remote-plugin-dotnet-2.2.105/Dockerfile @@ -54,7 +54,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Install typescript@2.9.2 and node-gyp - && yarn global add typescript@2.9.2 node-gyp + && yarn global add typescript@2.9.2 node-gyp \ + && node-gyp install ENV HOME=/home/theia COPY --from=endpoint /home/theia /home/theia diff --git a/dockerfiles/theia-dev/Dockerfile b/dockerfiles/theia-dev/Dockerfile index 870da64561..42d1d1f5f9 100644 --- a/dockerfiles/theia-dev/Dockerfile +++ b/dockerfiles/theia-dev/Dockerfile @@ -49,6 +49,8 @@ EXPOSE 3000 3030 # Configure npm and yarn to use home folder for global dependencies RUN npm config set prefix "${HOME}/.npm-global" && \ echo "--global-folder \"${HOME}/.yarn-global\"" > ${HOME}/.yarnrc && \ + # Setup node-gyp. Yarn will be failed unless installing required files here. + yarn global add node-gyp && node-gyp install && \ # add eclipse che theia generator yarn global add yo @theia/generator-plugin@0.0.1-1540209403 ${THEIA_GENERATOR_PACKAGE} && \ # Generate .passwd.template \ diff --git a/dockerfiles/theia/Dockerfile b/dockerfiles/theia/Dockerfile index e4de6ffe99..833b5c47ea 100644 --- a/dockerfiles/theia/Dockerfile +++ b/dockerfiles/theia/Dockerfile @@ -72,7 +72,7 @@ RUN che:theia init -c ${HOME}/che-theia-init-sources.yml RUN che:theia cdn --theia="${CDN_PREFIX}" --monaco="${MONACO_CDN_PREFIX}" # Compile Theia -RUN yarn +RUN yarn global add node-gyp && node-gyp install && yarn # Run into production mode RUN che:theia production diff --git a/dockerfiles/theia/e2e/Dockerfile b/dockerfiles/theia/e2e/Dockerfile index f64c3d880d..11ab4da213 100644 --- a/dockerfiles/theia/e2e/Dockerfile +++ b/dockerfiles/theia/e2e/Dockerfile @@ -17,7 +17,7 @@ RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://ar RUN apt-get update && \ apt-get install -y libx11-dev libxkbfile-dev sudo iproute2 CMD /root/docker-run.sh -RUN yarn global add typescript@2.9.2 node-gyp +RUN yarn global add typescript@2.9.2 node-gyp && node-gyp install # Add cypress scripts and grab dependencies COPY src /root/ From 4e76f53080005ae92503c334279cd654f2c556e2 Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Thu, 20 Jun 2019 02:39:01 +0000 Subject: [PATCH 06/10] Refactor passwd/group related processes. Signed-off-by: Masaki Muranaka --- dockerfiles/theia-dev/Dockerfile | 43 ++++++++++++++----------- dockerfiles/theia-dev/src/entrypoint.sh | 23 +++++++++---- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/dockerfiles/theia-dev/Dockerfile b/dockerfiles/theia-dev/Dockerfile index 42d1d1f5f9..08649aca0d 100644 --- a/dockerfiles/theia-dev/Dockerfile +++ b/dockerfiles/theia-dev/Dockerfile @@ -13,6 +13,15 @@ # FROM node:10.15-alpine +# Add npm global bin directory to the path +ENV HOME=/home/theia-dev \ + PATH=/home/theia-dev/.npm-global/bin:${PATH} \ + # Specify the directory of git (avoid to search at init of Theia) + USE_LOCAL_GIT=true \ + LOCAL_GIT_DIRECTORY=/usr \ + GIT_EXEC_PATH=/usr/libexec/git-core \ + THEIA_ELECTRON_SKIP_REPLACE_FFMPEG=true + RUN apk add --update --no-cache \ # Download some files curl \ @@ -26,17 +35,15 @@ RUN apk add --update --no-cache \ less \ # bash shell bash \ + # give root privilege + sudo \ + # for useradd command + shadow \ # some lib to compile 'native-keymap' npm mpdule - libx11-dev libxkbfile-dev - -# Add npm global bin directory to the path -ENV HOME=/home/theia-dev \ - PATH=/home/theia-dev/.npm-global/bin:${PATH} \ - # Specify the directory of git (avoid to search at init of Theia) - USE_LOCAL_GIT=true \ - LOCAL_GIT_DIRECTORY=/usr \ - GIT_EXEC_PATH=/usr/libexec/git-core \ - THEIA_ELECTRON_SKIP_REPLACE_FFMPEG=true + libx11-dev libxkbfile-dev && \ + useradd -u 1001 -U -G root -d ${HOME} -s /bin/bash theia-dev && \ + apk del --no-cache shadow && \ + echo "%root ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers # Define package of the theia generator to use ARG THEIA_GENERATOR_PACKAGE=@eclipse-che/theia-generator@0.0.1-1559634039 @@ -54,13 +61,10 @@ RUN npm config set prefix "${HOME}/.npm-global" && \ # add eclipse che theia generator yarn global add yo @theia/generator-plugin@0.0.1-1540209403 ${THEIA_GENERATOR_PACKAGE} && \ # Generate .passwd.template \ - cat /etc/passwd | \ - sed s#root:x.*#theia-dev:x:\${USER_ID}:\${GROUP_ID}::${HOME}:/bin/bash#g \ - > ${HOME}/.passwd.template && \ - # Generate .group.template \ - cat /etc/group | \ - sed s#root:x:0:#root:x:0:0,\${USER_ID}:#g \ - > ${HOME}/.group.template && \ + sed -e "s#^theia-dev:x.*#theia-dev:x:\${USER_ID}:\${GROUP_ID}::${HOME}:/bin/bash#g" \ + /etc/passwd > ${HOME}/.passwd.template && \ + sed -e 's#^theia-dev:.*#theia-dev:x:${GROUP_ID}:#g' \ + /etc/group > ${HOME}/.group.template && \ mkdir /projects && \ # Define default prompt echo "export PS1='\[\033[01;33m\](\u@container)\[\033[01;36m\] (\w) \$ \[\033[00m\]'" > ${HOME}/.bashrc && \ @@ -68,8 +72,9 @@ RUN npm config set prefix "${HOME}/.npm-global" && \ mkdir -p ${HOME}/.config/insight-nodejs/ && \ echo '{"optOut": true}' > ${HOME}/.config/insight-nodejs/insight-yo.json && \ # Change permissions to let any arbitrary user - for f in "${HOME}" "/etc/passwd" "/etc/group" "/projects"; do \ - echo "Changing permissions on ${f}" && chgrp -R 0 ${f} && \ + for f in "${HOME}" /projects /etc/passwd /etc/group; do \ + echo "Changing permissions on ${f}" && \ + chgrp -R 0 ${f} && \ chmod -R g+rwX ${f}; \ done diff --git a/dockerfiles/theia-dev/src/entrypoint.sh b/dockerfiles/theia-dev/src/entrypoint.sh index 7ac4e2ea33..8034d33945 100755 --- a/dockerfiles/theia-dev/src/entrypoint.sh +++ b/dockerfiles/theia-dev/src/entrypoint.sh @@ -17,13 +17,24 @@ if ! grep -Fq "${USER_ID}" /etc/passwd; then # current user is an arbitrary # user (its uid is not in the # container /etc/passwd). Let's fix that - cat ${HOME}/.passwd.template | \ - sed "s/\${USER_ID}/${USER_ID}/g" | \ - sed "s/\${GROUP_ID}/${GROUP_ID}/g" > /etc/passwd + sed \ + -e "s/\${USER_ID}/${USER_ID}/g" \ + -e "s/\${GROUP_ID}/${GROUP_ID}/g" \ + -e "s/\${HOME}/\/home\/theia/g" \ + ${HOME}/.passwd.template > /etc/passwd + sed \ + -e "s/\${GROUP_ID}/${GROUP_ID}/g" \ + ${HOME}/.group.template > /etc/group - cat ${HOME}/.group.template | \ - sed "s/\${USER_ID}/${USER_ID}/g" | \ - sed "s/\${GROUP_ID}/${GROUP_ID}/g" > /etc/group + # now the user `theia-dev` (that have uid:gid == $USER_ID,$GROUPID) can use `sudo`. +fi + +# Grant access to projects volume in case of non root user with sudo rights +if [ "$USER_ID" -ne 0 ] && command -v sudo >/dev/null 2>&1 && sudo -n true > /dev/null 2>&1; then + sudo chmod 644 /etc/passwd /etc/group + sudo chown root:root /etc/passwd /etc/group + + sudo chown ${USER_ID}:${GROUP_ID} /projects ${HOME} fi exec "$@" From 1a4ee6b0fb39d81517a857fbaf2db2b73458c8c6 Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Thu, 20 Jun 2019 02:39:10 +0000 Subject: [PATCH 07/10] Add tests for non-root environments. Signed-off-by: Masaki Muranaka --- dockerfiles/theia-dev/e2e/Dockerfile | 6 ++-- dockerfiles/theia-dev/e2e/build.sh | 3 ++ .../theia-dev/e2e/src/test-entrypoint.sh | 9 ++++++ dockerfiles/theia-dev/e2e/test.sh | 28 +++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100755 dockerfiles/theia-dev/e2e/src/test-entrypoint.sh create mode 100755 dockerfiles/theia-dev/e2e/test.sh diff --git a/dockerfiles/theia-dev/e2e/Dockerfile b/dockerfiles/theia-dev/e2e/Dockerfile index 31b0454fe3..216992c172 100644 --- a/dockerfiles/theia-dev/e2e/Dockerfile +++ b/dockerfiles/theia-dev/e2e/Dockerfile @@ -11,7 +11,7 @@ FROM ${BUILD_ORGANIZATION}/${BUILD_PREFIX}-theia-dev:${BUILD_TAG} # define in env variable GITHUB_TOKEN ARG GITHUB_TOKEN -# Just try to build the latest theia with current image -RUN git clone -b 'master' --single-branch --depth 1 https://github.com/theia-ide/theia theia -RUN cd theia && yarn +ADD src/test-entrypoint.sh /test-entrypoint.sh + +CMD ["/test-entrypoint.sh"] diff --git a/dockerfiles/theia-dev/e2e/build.sh b/dockerfiles/theia-dev/e2e/build.sh index bcc6a701a9..4eb735012f 100755 --- a/dockerfiles/theia-dev/e2e/build.sh +++ b/dockerfiles/theia-dev/e2e/build.sh @@ -11,3 +11,6 @@ base_dir=$(cd "$(dirname "$0")"; pwd) init --name:theia-builder-e2e "$@" build +if ! skip_tests; then + bash "${base_dir}"/test.sh "$@" +fi diff --git a/dockerfiles/theia-dev/e2e/src/test-entrypoint.sh b/dockerfiles/theia-dev/e2e/src/test-entrypoint.sh new file mode 100755 index 0000000000..a8ecfc0d41 --- /dev/null +++ b/dockerfiles/theia-dev/e2e/src/test-entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +. /entrypoint.sh + +cd /projects + +# Just try to build the latest theia with current image +git clone -b 'master' --single-branch --depth 1 https://github.com/theia-ide/theia theia +cd theia && yarn diff --git a/dockerfiles/theia-dev/e2e/test.sh b/dockerfiles/theia-dev/e2e/test.sh new file mode 100755 index 0000000000..a01545689f --- /dev/null +++ b/dockerfiles/theia-dev/e2e/test.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Copyright (c) 2018 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 + +base_dir=$(cd "$(dirname "$0")"; pwd) +. "${base_dir}/../../build.include" + +init --name:theia-builder-e2e "$@" + +DOCKER_RUN_OPTIONS="" +# run bats with terminal mode (pretty print) if supported by current shell +if [ -t 1 ]; then + DOCKER_RUN_OPTIONS="-t" +fi + +# Runs E2E tests in a docker container. +run_test_in_docker_container() { + docker_exec run --rm ${DOCKER_RUN_OPTIONS} \ + --user $1 --group-add 0 \ + $IMAGE_NAME +} + +run_test_in_docker_container 0:0 +run_test_in_docker_container 1234:5678 From 13a0bf8893bc1038f9f50d5ba64e136198065625 Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Thu, 20 Jun 2019 02:39:41 +0000 Subject: [PATCH 08/10] Refactor passwd/group related processes. Signed-off-by: Masaki Muranaka --- dockerfiles/theia/Dockerfile | 31 +++++++++++++++-------------- dockerfiles/theia/src/entrypoint.sh | 26 ++++++++++++++---------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/dockerfiles/theia/Dockerfile b/dockerfiles/theia/Dockerfile index 833b5c47ea..da7e70d836 100644 --- a/dockerfiles/theia/Dockerfile +++ b/dockerfiles/theia/Dockerfile @@ -112,25 +112,22 @@ COPY --from=builder /home/theia-dev/theia-source-code/production/plugins /defaul # Install curl and bash # Install ssh for cloning ssh-repositories # Install less for handling git diff properly -RUN apk add --update --no-cache sudo git bzip2 which bash curl openssh openssh-keygen less -RUN adduser -D -S -u 1001 -G root -h ${HOME} -s /bin/sh theia \ - && echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers \ - # Create /projects for Che - && mkdir /projects \ - # Create root node_modules in order to not use node_modules in each project folder - && mkdir /node_modules \ +RUN apk add --update --no-cache sudo git bzip2 which bash curl openssh openssh-keygen less shadow \ + && useradd -u 1001 -U -G root -d ${HOME} -s /bin/bash theia-dev \ + && apk del --no-cache shadow \ + && echo "%root ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +RUN mkdir /projects /node_modules \ # Download yeoman generator plug-in && curl -L -o /default-theia-plugins/theia_yeoman_plugin.theia https://github.com/eclipse/theia-yeoman-plugin/releases/download/untagged-04f28ee329e479cc465b/theia_yeoman_plugin.theia \ - && for f in "${HOME}" "/etc/passwd" "/etc/group /node_modules /default-theia-plugins /projects"; do\ - sudo chgrp -R 0 ${f} && \ - sudo chmod -R g+rwX ${f}; \ - done \ - && cat /etc/passwd | sed s#root:x.*#root:x:\${USER_ID}:\${GROUP_ID}::\${HOME}:/bin/bash#g > ${HOME}/passwd.template \ - && cat /etc/group | sed s#root:x:0:#root:x:0:0,\${USER_ID}:#g > ${HOME}/group.template \ + # For non-root instances. File permissions will be fixed in `entrypoint.sh`. + && sed -e 's#theia:x.*#theia:x:\${USER_ID}:\${GROUP_ID}::\${HOME}:/bin/bash#g' \ + /etc/passwd > ${HOME}/.passwd.template \ + && sed -e 's#^theia:.*#theia:x:${GROUP_ID}:#g' \ + /etc/group > ${HOME}/.group.template \ # Add yeoman, theia plugin generator and typescript (to have tsc/typescript working) && yarn global add yo @theia/generator-plugin@0.0.1-1540209403 typescript@2.9.2 \ && mkdir -p ${HOME}/.config/insight-nodejs/ \ - && chmod -R 777 ${HOME}/.config/ \ # Disable the statistics for yeoman && echo '{"optOut": true}' > $HOME/.config/insight-nodejs/insight-yo.json \ # Link yarn global modules for yeoman @@ -140,9 +137,13 @@ RUN adduser -D -S -u 1001 -G root -h ${HOME} -s /bin/sh theia \ # Cleanup yarn cache && yarn cache clean \ # Change permissions to allow editing of files for openshift user - && find ${HOME} -exec sh -c "chgrp 0 {}; chmod g+rwX {}" \; + && for f in "${HOME}" /etc/passwd /etc/group /node_modules /default-theia-plugins /projects; do\ + sudo chgrp -R 0 ${f} && \ + sudo chmod -R g+rwX ${f}; \ + done COPY --chown=theia:root --from=builder /home/theia-dev/theia-source-code/production /home/theia + USER theia WORKDIR /projects ADD src/entrypoint.sh /entrypoint.sh diff --git a/dockerfiles/theia/src/entrypoint.sh b/dockerfiles/theia/src/entrypoint.sh index 99c92a1b28..7a68fcdaca 100755 --- a/dockerfiles/theia/src/entrypoint.sh +++ b/dockerfiles/theia/src/entrypoint.sh @@ -18,20 +18,24 @@ if ! grep -Fq "${USER_ID}" /etc/passwd; then # current user is an arbitrary # user (its uid is not in the # container /etc/passwd). Let's fix that - cat ${HOME}/passwd.template | \ - sed "s/\${USER_ID}/${USER_ID}/g" | \ - sed "s/\${GROUP_ID}/${GROUP_ID}/g" | \ - sed "s/\${HOME}/\/home\/theia/g" > /etc/passwd + sed \ + -e "s/\${USER_ID}/${USER_ID}/g" \ + -e "s/\${GROUP_ID}/${GROUP_ID}/g" \ + -e "s/\${HOME}/\/home\/theia/g" \ + ${HOME}/.passwd.template > /etc/passwd + sed \ + -e "s/\${GROUP_ID}/${GROUP_ID}/g" \ + ${HOME}/.group.template > /etc/group - cat ${HOME}/group.template | \ - sed "s/\${USER_ID}/${USER_ID}/g" | \ - sed "s/\${GROUP_ID}/${GROUP_ID}/g" | \ - sed "s/\${HOME}/\/home\/theia/g" > /etc/group + # now the user `theia` (that have uid:gid == $USER_ID,$GROUPID) can use `sudo`. fi # Grant access to projects volume in case of non root user with sudo rights -if [ "$(id -u)" -ne 0 ] && command -v sudo >/dev/null 2>&1 && sudo -n true > /dev/null 2>&1; then - sudo chown ${USER_ID}:${GROUP_ID} /projects +if [ "$USER_ID" -ne 0 ] && command -v sudo >/dev/null 2>&1 && sudo -n true > /dev/null 2>&1; then + sudo chmod 644 /etc/passwd /etc/group + sudo chown root:root /etc/passwd /etc/group + + sudo chown ${USER_ID}:${GROUP_ID} /projects "${HOME}" fi if [ -z "$THEIA_PORT" ]; then @@ -77,7 +81,7 @@ fi shopt -u nocasematch # run che -node src-gen/backend/main.js /projects --hostname=0.0.0.0 --port=${THEIA_PORT} & +sudo node src-gen/backend/main.js /projects --hostname=0.0.0.0 --port=${THEIA_PORT} & PID=$! From 6e2d592e42d99b2b1f8e995b812b61dc9578c83c Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Thu, 20 Jun 2019 02:40:10 +0000 Subject: [PATCH 09/10] Add tests for non-root environments. Signed-off-by: Masaki Muranaka --- dockerfiles/theia/e2e/Dockerfile | 11 ++++++----- dockerfiles/theia/e2e/src/docker-run.sh | 8 ++++---- dockerfiles/theia/e2e/test.sh | 9 ++++++--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/dockerfiles/theia/e2e/Dockerfile b/dockerfiles/theia/e2e/Dockerfile index 11ab4da213..992028b62c 100644 --- a/dockerfiles/theia/e2e/Dockerfile +++ b/dockerfiles/theia/e2e/Dockerfile @@ -10,22 +10,23 @@ FROM ${BUILD_ORGANIZATION}/${BUILD_PARENT_IMAGE}:${BUILD_TAG} as theia FROM cypress/browsers:chrome67 USER root -ENV HOME=/root ENV NOCDN=true RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list RUN apt-get update && \ apt-get install -y libx11-dev libxkbfile-dev sudo iproute2 -CMD /root/docker-run.sh RUN yarn global add typescript@2.9.2 node-gyp && node-gyp install # Add cypress scripts and grab dependencies -COPY src /root/ -RUN cd /root && yarn +COPY src /projects/ +RUN cd /projects && yarn # Add tests -ADD cypress /root/cypress/ +ADD cypress /projects/cypress/ COPY --from=theia /home/theia /home/theia COPY --from=theia /entrypoint.sh /entrypoint.sh RUN find /home/theia/ -name "binding.gyp" | xargs -i sh -c 'cd $(dirname {}) && node-gyp rebuild' + +USER theia +CMD /projects/docker-run.sh diff --git a/dockerfiles/theia/e2e/src/docker-run.sh b/dockerfiles/theia/e2e/src/docker-run.sh index fbaee1dbe8..8a30bb48ae 100755 --- a/dockerfiles/theia/e2e/src/docker-run.sh +++ b/dockerfiles/theia/e2e/src/docker-run.sh @@ -10,12 +10,12 @@ : "${WAIT_COUNT:=30}" echo "Starting Theia..." -rm -rf /root/logs/* -HOME=/home/theia /entrypoint.sh > /root/logs/theia.log 2>/root/logs/theia-error.log& +rm -rf /projects/logs/* +HOME=/home/theia /entrypoint.sh > /projects/logs/theia.log 2>/projects/logs/theia-error.log& echo "Cleaning videos folder..." # Cleanup previous videos -rm -rf /root/cypress/videos/* +rm -rf /projects/cypress/videos/* # Find TCP 0.0.0.0:3100 that will be opened by Theia. sleep 5s @@ -35,4 +35,4 @@ fi # Run tests echo "Run the tests" -cd /root && unset LD_LIBRARY_PATH && /root/node_modules/.bin/cypress run -c trashAssetsBeforeRuns=false --browser chrome +cd /projects && unset LD_LIBRARY_PATH && /projects/node_modules/.bin/cypress run -c trashAssetsBeforeRuns=false --browser chrome diff --git a/dockerfiles/theia/e2e/test.sh b/dockerfiles/theia/e2e/test.sh index f4b4fd08f3..414318f553 100755 --- a/dockerfiles/theia/e2e/test.sh +++ b/dockerfiles/theia/e2e/test.sh @@ -19,11 +19,14 @@ fi # Runs E2E tests in a docker container. run_test_in_docker_container() { + mkdir -p ${base_dir}/$1 docker_exec run --rm ${DOCKER_RUN_OPTIONS} \ - -v "${base_dir}/videos":/root/cypress/videos \ - -v "${base_dir}/logs":/root/logs \ + --user $1 \ + -v "${base_dir}/$1/videos":/projects/cypress/videos \ + -v "${base_dir}/$1/logs":/projects/logs \ -v /var/run/docker.sock:/var/run/docker.sock \ $IMAGE_NAME } -run_test_in_docker_container +run_test_in_docker_container '0:0' +run_test_in_docker_container '1234:5678' From 95fbc188cb4d2db3f102a0845b81a248c120b673 Mon Sep 17 00:00:00 2001 From: Masaki Muranaka Date: Thu, 20 Jun 2019 17:00:29 +0900 Subject: [PATCH 10/10] Refactor passwd/group related processes in `theia-endpoint-runtime`. Signed-off-by: Masaki Muranaka --- dockerfiles/theia-endpoint-runtime/Dockerfile | 12 +++++++---- .../theia-endpoint-runtime/etc/entrypoint.sh | 21 +++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/dockerfiles/theia-endpoint-runtime/Dockerfile b/dockerfiles/theia-endpoint-runtime/Dockerfile index 27baf53073..afad5baf09 100644 --- a/dockerfiles/theia-endpoint-runtime/Dockerfile +++ b/dockerfiles/theia-endpoint-runtime/Dockerfile @@ -56,13 +56,17 @@ COPY --from=builder /home/workspace/node_modules /home/theia/node_modules RUN rm -rf /home/theia/node_modules/@eclipse-che/theia-plugin-ext /home/theia/node_modules/@eclipse-che/theia-remote COPY --from=builder /home/workspace/packages/theia-plugin-ext /home/theia/node_modules/@eclipse-che/theia-plugin-ext COPY --from=builder /home/workspace/packages/theia-remote/lib /home/theia/lib +COPY --from=builder /.passwd.template /.passwd.template +COPY --from=builder /.group.template /.group.template +COPY --from=builder /etc/sudoers /etc/sudoers + RUN mkdir /projects \ # Store passwd/group as template files - && cat /etc/passwd | sed s#root:x.*#root:x:\${USER_ID}:\${GROUP_ID}::\${HOME}:/bin/sh#g > ${HOME}/passwd.template \ - && cat /etc/group | sed s#root:x:0:#root:x:0:0,\${USER_ID}:#g > ${HOME}/group.template \ # Change permissions to let any arbitrary user - && for f in "${HOME}" "/etc/passwd" "/etc/group" "/projects"; do \ - echo "Changing permissions on ${f}" && chgrp -R 0 ${f} && \ + && sed -i -e 's/theia-dev/theia/g' /.passwd.template /.group.template \ + && for f in "${HOME}" /etc/passwd /etc/group /projects; do \ + echo "Changing permissions on ${f}" && \ + chgrp -R 0 ${f} && \ chmod -R g+rwX ${f}; \ done ADD etc/entrypoint.sh /entrypoint.sh diff --git a/dockerfiles/theia-endpoint-runtime/etc/entrypoint.sh b/dockerfiles/theia-endpoint-runtime/etc/entrypoint.sh index 1f85f5768c..0c6740ecdd 100755 --- a/dockerfiles/theia-endpoint-runtime/etc/entrypoint.sh +++ b/dockerfiles/theia-endpoint-runtime/etc/entrypoint.sh @@ -18,20 +18,23 @@ if ! grep -Fq "${USER_ID}" /etc/passwd; then # current user is an arbitrary # user (its uid is not in the # container /etc/passwd). Let's fix that - cat ${HOME}/passwd.template | \ - sed "s/\${USER_ID}/${USER_ID}/g" | \ - sed "s/\${GROUP_ID}/${GROUP_ID}/g" | \ - sed "s/\${HOME}/\/home\/theia/g" > /etc/passwd + sed -e "s/\${USER_ID}/${USER_ID}/g" \ + -e "s/\${GROUP_ID}/${GROUP_ID}/g" \ + -e "s/\${HOME}/\/home\/theia/g" \ + /.passwd.template > /etc/passwd - cat ${HOME}/group.template | \ - sed "s/\${USER_ID}/${USER_ID}/g" | \ - sed "s/\${GROUP_ID}/${GROUP_ID}/g" | \ - sed "s/\${HOME}/\/home\/theia/g" > /etc/group + sed -e "s/\${USER_ID}/${USER_ID}/g" \ + -e "s/\${GROUP_ID}/${GROUP_ID}/g" \ + -e "s/\${HOME}/\/home\/theia/g" + /.group.template > /etc/group fi # Grant access to projects volume in case of non root user with sudo rights if [ "$(id -u)" -ne 0 ] && command -v sudo >/dev/null 2>&1 && sudo -n true > /dev/null 2>&1; then - sudo chown ${USER_ID}:${GROUP_ID} /projects + sudo chmod 644 /etc/passwd /etc/group + sudo chown root:root /etc/passwd /etc/group + + sudo chown ${USER_ID}:${GROUP_ID} /projects "${HOME}" fi # SITTERM / SIGINT