Administration guide Red Hat OpenShift Dev Spaces 3.14 Administering Red Hat OpenShift Dev Spaces 3.14 Jana Vrbkova jvrbkova@redhat.com Red Hat Developer Group Documentation Team devtools-docs@redhat.com

Commands:
dsc
memoryLimit: 6G memoryRequest: 512M cpuRequest: 1000m cpuLimit: 4000m
memoryLimit: 128M memoryRequest: 64M cpuRequest: 10m cpuLimit: 1000m
memoryLimit: 256M memoryRequest: 64M cpuRequest: 50m cpuLimit: 500m
dsc server:delete
dsc server:deploy --platform openshift
dsc server:status
dsc dashboard:open
create namespace openshift-devspaces
bash prepare-restricted-environment.sh --devworkspace_operator_index registry.redhat.io/redhat/redhat-operator-index:v4.16 --devworkspace_operator_version "v0.28.0" --prod_operator_index "registry.redhat.io/redhat/redhat-operator-index:v4.16" --prod_operator_package_name "devspaces" --prod_operator_bundle_name "devspacesoperator" --prod_operator_version "v3.14.0" --my_registry " <my_registry> " 1
dsc server:deploy --platform=openshift --olm-channel stable --catalog-source-name=devspaces-disconnected-install --catalog-source-namespace=openshift-marketplace --skip-devworkspace-operator --che-operator-cr-patch-yaml=che-operator-cr-patch.yaml
ghcr.io/ansible/ansible-workspace-env-reference@sha256:03d7f0fe6caaae62ff2266906b63d67ebd9cf6e4a056c7c0a0c1320e6cfbebce registry.access.redhat.com/ubi8/python-39@sha256:301fec66443f80c3cc507ccaf72319052db5a1dc56deb55c8f169011d4bbaacb
.ansible.com .ansible-galaxy-ng.s3.dualstack.us-east-1.amazonaws.com
get checluster devspaces -n openshift-devspaces -o jsonpath='{.status.cheURL}'
spec: <component> : <property_to_configure> : <value>
dsc server:deploy --che-operator-cr-patch-yaml=che-operator-cr-patch.yaml --platform <chosen_platform>
oc get configmap che -o jsonpath='{.data. <configured_property> }' -n openshift-devspaces
oc edit checluster/devspaces -n openshift-devspaces
oc get configmap che -o jsonpath='{.data. <configured_property> }' -n openshift-devspaces
apiVersion: org.eclipse.che/v2 kind: CheCluster metadata: name: devspaces namespace: openshift-devspaces spec: components: {} devEnvironments: {} networking: {}
spec: components: devEnvironments: defaultNamespace: template: <workspace_namespace_template_>
kind: Namespace apiVersion: v1 metadata: name: <project_name> 1 labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-namespace annotations: che.eclipse.org/username: <username>
apiVersion: v1 kind: Secret metadata: name: custom-settings labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret
apiVersion: v1 kind: ConfigMap metadata: name: custom-settings labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap
apiVersion: v1 kind: Secret metadata: name: custom-data annotations: che.eclipse.org/mount-as: file che.eclipse.org/mount-path: /data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret
apiVersion: v1 kind: ConfigMap metadata: name: custom-data annotations: che.eclipse.org/mount-as: file che.eclipse.org/mount-path: /data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap
apiVersion: v1 kind: Secret metadata: name: custom-data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret annotations: che.eclipse.org/mount-as: file che.eclipse.org/mount-path: /data data: ca.crt: <base64 encoded data content here>
apiVersion: v1 kind: ConfigMap metadata: name: custom-data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap annotations: che.eclipse.org/mount-as: file che.eclipse.org/mount-path: /data data: ca.crt: <data content here>
apiVersion: v1 kind: Secret metadata: name: custom-settings labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret
apiVersion: v1 kind: ConfigMap metadata: name: custom-settings labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap
apiVersion: v1 kind: Secret metadata: name: custom-data annotations: che.eclipse.org/mount-as: subpath che.eclipse.org/mount-path: /data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret
apiVersion: v1 kind: ConfigMap metadata: name: custom-data annotations: che.eclipse.org/mount-as: subpath che.eclipse.org/mount-path: /data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap
apiVersion: v1 kind: Secret metadata: name: custom-data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret annotations: che.eclipse.org/mount-as: subpath che.eclipse.org/mount-path: /data data: ca.crt: <base64 encoded data content here>
apiVersion: v1 kind: ConfigMap metadata: name: custom-data labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap annotations: che.eclipse.org/mount-as: subpath che.eclipse.org/mount-path: /data data: ca.crt: <data content here>
apiVersion: v1 kind: Secret metadata: name: custom-settings labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret
apiVersion: v1 kind: ConfigMap metadata: name: custom-settings labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap
apiVersion: v1 kind: Secret metadata: name: custom-settings annotations: che.eclipse.org/env-name: FOO_ENV che.eclipse.org/mount-as: env labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret data: mykey: myvalue
apiVersion: v1 kind: ConfigMap metadata: name: custom-settings annotations: che.eclipse.org/env-name: FOO_ENV che.eclipse.org/mount-as: env labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap data: mykey: myvalue
apiVersion: v1 kind: Secret metadata: name: custom-settings annotations: che.eclipse.org/mount-as: env che.eclipse.org/mykey_env-name: FOO_ENV che.eclipse.org/otherkey_env-name: OTHER_ENV labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-secret stringData: mykey: <data_content_here> otherkey: <data_content_here>
apiVersion: v1 kind: ConfigMap metadata: name: custom-settings annotations: che.eclipse.org/mount-as: env che.eclipse.org/mykey_env-name: FOO_ENV che.eclipse.org/otherkey_env-name: OTHER_ENV labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: devspaces-configmap data: mykey: <data content here> otherkey: <data content here>
apiVersion: org.eclipse.che/v2 kind: CheCluster spec: components: cheServer: extraProperties: CHE_LOGS_APPENDERS_IMPL: json
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: scaler namespace: openshift-devspaces spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: <deployment_name> 1
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: devspaces-scaler namespace: openshift-devspaces spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: devspaces minReplicas: 2 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 75
spec: devEnvironments: maxNumberOfWorkspacesPerUser: <kept_workspaces_limit> 1
oc get checluster --all-namespaces -o=jsonpath="{.items[*].metadata.namespace}"
oc patch checluster/devspaces -n openshift-devspaces \ 1 --type='merge' -p '{"spec":{"devEnvironments":{"maxNumberOfWorkspacesPerUser": <kept_workspaces_limit> }}}' 2
spec: devEnvironments: maxNumberOfRunningWorkspacesPerUser: <running_workspaces_limit> 1
oc get checluster --all-namespaces -o=jsonpath="{.items[*].metadata.namespace}"
oc patch checluster/devspaces -n openshift-devspaces \ 1 --type='merge' -p '{"spec":{"devEnvironments":{"maxNumberOfRunningWorkspacesPerUser": <running_workspaces_limit> }}}' 2
oc create configmap che-git-self-signed-cert --from-file=ca.crt= <path_to_certificate> \ 1 --from-literal=githost= <git_server_url> -n openshift-devspaces 2
oc label configmap che-git-self-signed-cert app.kubernetes.io/part-of=che.eclipse.org -n openshift-devspaces
spec: devEnvironments: trustedCerts: gitTrustedCertsConfigMapName: che-git-self-signed-cert
[http "https://10.33.177.118:3000"] sslCAInfo = /etc/config/che-git-tls-creds/certificate
spec: devEnvironments: nodeSelector: key: value
spec: devEnvironments: tolerations: - effect: NoSchedule key: key value: value operator: Equal
spec: components: [...] pluginRegistry: openVSXURL: <your_open_vsx_registy> [...]
kind: ConfigMap apiVersion: v1 metadata: name: user-configmap namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config data:
kind: ConfigMap apiVersion: v1 metadata: name: user-settings-xml namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config annotations: controller.devfile.io/mount-as: subpath controller.devfile.io/mount-path: /home/user/.m2 data: settings.xml: | <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>/home/user/.m2/repository</localRepository> <interactiveMode>true</interactiveMode> <offline>false</offline> </settings>
kind: Secret apiVersion: v1 metadata: name: user-secret namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config data:
kind: Secret apiVersion: v1 metadata: name: user-certificates namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config annotations: controller.devfile.io/mount-as: subpath controller.devfile.io/mount-path: /etc/pki/ca-trust/source/anchors stringData: trusted-certificates.crt: |
kind: Secret apiVersion: v1 metadata: name: user-env namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config annotations: controller.devfile.io/mount-as: env stringData: ENV_VAR_1: value_1 ENV_VAR_2: value_2
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: user-pvc namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config spec:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: user-pvc namespace: openshift-devspaces labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: workspaces-config controller.devfile.io/mount-to-devworkspace: 'true' annotations: controller.devfile.io/mount-path: /home/user/data controller.devfile.io/read-only: 'true' spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi volumeMode: Filesystem
(memory limit) * (number of images) * (number of nodes in the cluster)
git clone https://github.com/che-incubator/kubernetes-image-puller cd kubernetes-image-puller/deploy/openshift
oc new-project <k8s-image-puller>
oc process -f serviceaccount.yaml | oc apply -f - oc process -f configmap.yaml | oc apply -f - oc process -f app.yaml | oc apply -f -
oc get deployment,daemonset,pod --namespace <k8s-image-puller>
oc get configmap <kubernetes-image-puller> --output yaml
patch checluster/devspaces --namespace openshift-devspaces --type='merge' --patch '{ "spec": { "components": { "imagePuller": { "enable": true } } } }'
patch checluster/devspaces --namespace openshift-devspaces --type='merge' --patch '{ "spec": { "components": { "imagePuller": { "enable": true, "spec": { "images": " NAME-1 = IMAGE-1 ; NAME-2 = IMAGE-2 " 1 } } } } }'
create namespace k8s-image-puller
apply -f - <<EOF apiVersion: che.eclipse.org/v1alpha1 kind: KubernetesImagePuller metadata: name: k8s-image-puller-images namespace: k8s-image-puller spec: images: "__NAME-1__=__IMAGE-1__;__NAME-2__=__IMAGE-2__" 1 EOF
spec: devEnvironments: defaultPlugins: - editor: eclipse/che-theia/next 1 plugins: 2 - 'https://your-web-server/plugin.yaml'
package main import ( "io/ioutil" "net/http" "go.uber.org/zap" ) var logger *zap.SugaredLogger func event(w http.ResponseWriter, req *http.Request) { switch req.Method { case "GET": logger.Info("GET /event") case "POST": logger.Info("POST /event") } body, err := req.GetBody() if err != nil { logger.With("err", err).Info("error getting body") return } responseBody, err := ioutil.ReadAll(body) if err != nil { logger.With("error", err).Info("error reading response body") return } logger.With("body", string(responseBody)).Info("got event") } func activity(w http.ResponseWriter, req *http.Request) { switch req.Method { case "GET": logger.Info("GET /activity, doing nothing") case "POST": logger.Info("POST /activity") body, err := req.GetBody() if err != nil { logger.With("error", err).Info("error getting body") return } responseBody, err := ioutil.ReadAll(body) if err != nil { logger.With("error", err).Info("error reading response body") return } logger.With("body", string(responseBody)).Info("got activity") } } func main() { log, _ := zap.NewProduction() logger = log.Sugar() http.HandleFunc("/event", event) http.HandleFunc("/activity", activity) logger.Info("Added Handlers") logger.Info("Starting to serve") http.ListenAndServe(":8080", nil) }
git clone https://github.com/che-incubator/telemetry-server-example cd telemetry-server-example podman build -t registry/organization/telemetry-server-example:latest . podman push registry/organization/telemetry-server-example:latest
kubectl apply -f manifest_with_[ingress|route].yaml -n openshift-devspaces
mvn io.quarkus:quarkus-maven-plugin:2.7.1.Final:create -DprojectGroupId=mygroup -DprojectArtifactId=devworkspace-telemetry-example-plugin -DprojectVersion=1.0.0-SNAPSHOT
<!-- Required --> <dependency> <groupId>org.eclipse.che.incubator.workspace-telemetry</groupId> <artifactId>backend-base</artifactId> <version>LATEST VERSION FROM PREVIOUS STEP</version> </dependency> <!-- Used to make http requests to the telemetry server --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client-jackson</artifactId> </dependency>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <servers> <server> <id>che-incubator</id> <username>YOUR GITHUB USERNAME</username> <password>YOUR GITHUB TOKEN</password> </server> </servers> <profiles> <profile> <id>github</id> <activation> <activeByDefault>true</activeByDefault> </activation> <repositories> <repository> <id>central</id> <url>https://repo1.maven.org/maven2</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>false</enabled></snapshots> </repository> <repository> <id>che-incubator</id> <url>https://maven.pkg.github.com/che-incubator/che-workspace-telemetry-client</url> </repository> </repositories> </profile> </profiles> </settings>
package org.my.group; import java.util.Optional; import javax.enterprise.context.Dependent; import javax.enterprise.inject.Alternative; import org.eclipse.che.incubator.workspace.telemetry.base.BaseConfiguration; import org.eclipse.microprofile.config.inject.ConfigProperty; @Dependent @Alternative public class MainConfiguration extends BaseConfiguration { @ConfigProperty(name = "welcome.message") 1 Optional<String> welcomeMessage; 2 }
package org.my.group; import java.util.HashMap; import java.util.Map; import javax.enterprise.context.Dependent; import javax.enterprise.inject.Alternative; import javax.inject.Inject; import org.eclipse.che.incubator.workspace.telemetry.base.AbstractAnalyticsManager; import org.eclipse.che.incubator.workspace.telemetry.base.AnalyticsEvent; import org.eclipse.che.incubator.workspace.telemetry.finder.DevWorkspaceFinder; import org.eclipse.che.incubator.workspace.telemetry.finder.UsernameFinder; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.slf4j.Logger; import static org.slf4j.LoggerFactory.getLogger; @Dependent @Alternative public class AnalyticsManager extends AbstractAnalyticsManager { private static final Logger LOG = getLogger(AbstractAnalyticsManager.class); public AnalyticsManager(MainConfiguration mainConfiguration, DevWorkspaceFinder devworkspaceFinder, UsernameFinder usernameFinder) { super(mainConfiguration, devworkspaceFinder, usernameFinder); mainConfiguration.welcomeMessage.ifPresentOrElse( 1 (str) -> LOG.info("The welcome message is: {}", str), () -> LOG.info("No welcome message provided") ); } @Override public boolean isEnabled() { return true; } @Override public void destroy() {} @Override public void onEvent(AnalyticsEvent event, String ownerId, String ip, String userAgent, String resolution, Map<String, Object> properties) { LOG.info("The received event is: {}", event); 2 } @Override public void increaseDuration(AnalyticsEvent event, Map<String, Object> properties) { } @Override public void onActivity() {} }
quarkus.arc.selected-alternatives=MainConfiguration,AnalyticsManager
spec: template: attributes: workspaceEnv: - name: DEVWORKSPACE_TELEMETRY_BACKEND_PORT value: '4167'
mvn --settings=settings.xml quarkus:dev -Dquarkus.http.port=USD{DEVWORKSPACE_TELEMETRY_BACKEND_PORT}
INFO [org.ecl.che.inc.AnalyticsManager] (Quarkus Main Thread) No welcome message provided INFO [io.quarkus] (Quarkus Main Thread) devworkspace-telemetry-example-plugin 1.0.0-SNAPSHOT on JVM (powered by Quarkus 2.7.2.Final) started in 0.323s. Listening on: http://localhost:4167 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated. INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes-client, rest-client, rest-client-jackson, resteasy, resteasy-jsonb, smallrye-context-propagation, smallrye-openapi, swagger-ui, vertx]
INFO [io.qua.dep.dev.RuntimeUpdatesProcessor] (Aesh InputStream Reader) Live reload disabled INFO [org.ecl.che.inc.AnalyticsManager] (executor-thread-2) The received event is: Edit Workspace File in Che
@Override public boolean isEnabled() { return true; }
package org.my.group; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @RegisterRestClient public interface TelemetryService { @POST @Path("/event") 1 @Consumes(MediaType.APPLICATION_JSON) Response sendEvent(Map<String, Object> payload); }
org.my.group.TelemetryService/mp-rest/url=http://little-telemetry-server-che.apps-crc.testing
@Dependent @Alternative public class AnalyticsManager extends AbstractAnalyticsManager { @Inject @RestClient TelemetryService telemetryService; @Override public void onEvent(AnalyticsEvent event, String ownerId, String ip, String userAgent, String resolution, Map<String, Object> properties) { Map<String, Object> payload = new HashMap<String, Object>(properties); payload.put("event", event); telemetryService.sendEvent(payload); }
@Override public void increaseDuration(AnalyticsEvent event, Map<String, Object> properties) {}
public class AnalyticsManager extends AbstractAnalyticsManager { private long inactiveTimeLimit = 60000 * 3; @Override public void onActivity() { if (System.currentTimeMillis() - lastEventTime >= inactiveTimeLimit) { onEvent(WORKSPACE_INACTIVE, lastOwnerId, lastIp, lastUserAgent, lastResolution, commonProperties); } }
@Override public void destroy() { onEvent(WORKSPACE_STOPPED, lastOwnerId, lastIp, lastUserAgent, lastResolution, commonProperties); }
FROM registry.access.redhat.com/ubi8/openjdk-11:1.11 ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ COPY --chown=185 target/quarkus-app/*.jar /deployments/ COPY --chown=185 target/quarkus-app/app/ /deployments/app/ COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ EXPOSE 8080 USER 185 ENTRYPOINT ["java", "-Dquarkus.http.host=0.0.0.0", "-Djava.util.logging.manager=org.jboss.logmanager.LogManager", "-Dquarkus.http.port=USD{DEVWORKSPACE_TELEMETRY_BACKEND_PORT}", "-jar", "/deployments/quarkus-run.jar"]
mvn package && build -f src/main/docker/Dockerfile.jvm -t image:tag .
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5 WORKDIR /work/ RUN chown 1001 /work && chmod "g+rwX" /work && chown 1001:root /work COPY --chown=1001:root target/*-runner /work/application EXPOSE 8080 USER 1001 CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Dquarkus.http.port=USDDEVWORKSPACE_TELEMETRY_BACKEND_PORT}"]
mvn package -Pnative -Dquarkus.native.container-build=true && build -f src/main/docker/Dockerfile.native -t image:tag .
schemaVersion: 2.1.0 metadata: name: devworkspace-telemetry-backend-plugin version: 0.0.1 description: A Demo telemetry backend displayName: Devworkspace Telemetry Backend components: - name: devworkspace-telemetry-backend-plugin attributes: workspaceEnv: - name: DEVWORKSPACE_TELEMETRY_BACKEND_PORT value: '4167' container: image: YOUR IMAGE 1 env: - name: WELCOME_MESSAGE 2 value: 'hello world!'
oc create configmap --from-file=plugin.yaml -n openshift-devspaces telemetry-plugin-yaml
kind: Deployment apiVersion: apps/v1 metadata: name: apache spec: replicas: 1 selector: matchLabels: app: apache template: metadata: labels: app: apache spec: volumes: - name: plugin-yaml configMap: name: telemetry-plugin-yaml defaultMode: 420 containers: - name: apache image: 'registry.redhat.io/rhscl/httpd-24-rhel7:latest' ports: - containerPort: 8080 protocol: TCP resources: {} volumeMounts: - name: plugin-yaml mountPath: /var/www/html strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% revisionHistoryLimit: 10 progressDeadlineSeconds: 600 --- kind: Service apiVersion: v1 metadata: name: apache spec: ports: - protocol: TCP port: 8080 targetPort: 8080 selector: app: apache type: ClusterIP --- kind: Route apiVersion: route.openshift.io/v1 metadata: name: apache spec: host: apache-che.apps-crc.testing to: kind: Service name: apache weight: 100 port: targetPort: 8080 wildcardPolicy: None
oc apply -f manifest.yaml
curl apache-che.apps-crc.testing/plugin.yaml
components: - name: telemetry-plugin plugin: uri: http://apache-che.apps-crc.testing/plugin.yaml
spec: devEnvironments: defaultPlugins: - editor: eclipse/che-theia/next 1 plugins: 2 - 'http://apache-che.apps-crc.testing/plugin.yaml'
spec: components: cheServer: extraProperties: CHE_LOGGER_CONFIG: " <key1=value1,key2=value2> " 1
spec: components: cheServer: extraProperties: CHE_LOGGER_CONFIG: "org.eclipse.che.api.workspace.server.WorkspaceManager=DEBUG"
spec: components: cheServer: extraProperties: CHE_LOGGER_CONFIG: "che.infra.request-logging=TRACE"
dsc server:logs -d /home/user/che-logs/
Red Hat OpenShift Dev Spaces logs will be available in '/tmp/chectl-logs/1648575098344'
dsc server:logs -n my-namespace
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: devworkspace-controller namespace: openshift-devspaces 1 spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 10s 2 port: metrics scheme: https tlsConfig: insecureSkipVerify: true namespaceSelector: matchNames: - openshift-operators selector: matchLabels: app.kubernetes.io/name: devworkspace-controller
oc label namespace openshift-devspaces openshift.io/cluster-monitoring=true
oc get pods -l app.kubernetes.io/name=prometheus -n openshift-monitoring -o=jsonpath='{.items[*].metadata.name}'
oc logs --tail=20 <prometheus_pod_name> -c prometheus -n openshift-monitoring
oc create configmap grafana-dashboard-dwo --from-literal=dwo-dashboard.json="USD(curl https://raw.githubusercontent.com/devfile/devworkspace-operator/main/docs/grafana/openshift-console-dashboard.json)" -n openshift-config-managed
oc label configmap grafana-dashboard-dwo console.openshift.io/dashboard=true -n openshift-config-managed
spec: components: metrics: enable: <boolean> 1
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: che-host namespace: openshift-devspaces 1 spec: endpoints: - interval: 10s 2 port: metrics scheme: http namespaceSelector: matchNames: - openshift-devspaces 3 selector: matchLabels: app.kubernetes.io/name: devspaces
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: prometheus-k8s namespace: openshift-devspaces 1 rules: - verbs: - get - list - watch apiGroups: - '' resources: - services - endpoints - pods
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: view-devspaces-openshift-monitoring-prometheus-k8s namespace: openshift-devspaces 1 subjects: - kind: ServiceAccount name: prometheus-k8s namespace: openshift-monitoring roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s
oc label namespace openshift-devspaces openshift.io/cluster-monitoring=true
oc get pods -l app.kubernetes.io/name=prometheus -n openshift-monitoring -o=jsonpath='{.items[*].metadata.name}'
oc logs --tail=20 <prometheus_pod_name> -c prometheus -n openshift-monitoring
oc create configmap grafana-dashboard-devspaces-server --from-literal=devspaces-server-dashboard.json="USD(curl https://raw.githubusercontent.com/eclipse-che/che-server/main/docs/grafana/openshift-console-dashboard.json)" -n openshift-config-managed
oc label configmap grafana-dashboard-devspaces-server console.openshift.io/dashboard=true -n openshift-config-managed
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-from-openshift-devspaces spec: ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: openshift-devspaces 1 podSelector: {} 2 policyTypes: - Ingress
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-from-openshift-apiserver namespace: openshift-devspaces 1 spec: podSelector: matchLabels: app.kubernetes.io/name: devworkspace-webhook-server 2 ingress: - from: - podSelector: {} namespaceSelector: matchLabels: kubernetes.io/metadata.name: openshift-apiserver policyTypes: - Ingress
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-from-workspaces-namespaces namespace: openshift-devspaces 1 spec: podSelector: matchLabels: app.kubernetes.io/component: che-gateway 2 ingress: - from: - podSelector: {} namespaceSelector: matchLabels: app.kubernetes.io/component: workspaces-namespace policyTypes: - Ingress
oc create project openshift-devspaces
oc create secret TLS <tls_secret_name> \ 1 --key <key_file> \ 2 --cert <cert_file> \ 3 -n openshift-devspaces
oc label secret <tls_secret_name> \ 1 app.kubernetes.io/part-of=che.eclipse.org -n openshift-devspaces
spec: networking: hostname: <hostname> 1 tlsSecretName: <secret> 2
cat ca-cert-for-devspaces-*.pem | tr -d '\r' > custom-ca-certificates.pem
oc create configmap custom-ca-certificates --from-file=custom-ca-certificates.pem --namespace=openshift-devspaces
oc label configmap custom-ca-certificates app.kubernetes.io/component=ca-bundle app.kubernetes.io/part-of=che.eclipse.org --namespace=openshift-devspaces
oc get configmap --namespace=openshift-devspaces --output='jsonpath={.items[0:].data.custom-ca-certificates\.pem}' --selector=app.kubernetes.io/component=ca-bundle,app.kubernetes.io/part-of=che.eclipse.org
oc get pod --selector=app.kubernetes.io/component=devspaces --output='jsonpath={.items[0].spec.volumes[0:].configMap.name}' --namespace=openshift-devspaces | grep ca-certs-merged
oc exec -t deploy/devspaces --namespace=openshift-devspaces -- cat /public-certs/custom-ca-certificates.pem
oc logs deploy/devspaces --namespace=openshift-devspaces | grep custom-ca-certificates.pem
for certificate in ca-cert*.pem ; do openssl x509 -in USDcertificate -digest -sha256 -fingerprint -noout | cut -d= -f2; done
oc exec -t deploy/devspaces --namespace=openshift-devspaces -- keytool -list -keystore /home/user/cacerts | grep --after-context=1 custom-ca-certificates.pem
oc get configmap che-trusted-ca-certs --namespace= <workspace_namespace> --output='jsonpath={.data.custom-ca-certificates\.custom-ca-certificates\.pem}'
oc get pod --namespace= <workspace_namespace> --selector='controller.devfile.io/devworkspace_name= <workspace_name> ' --output='jsonpath={.items[0:].spec.volumes[0:].configMap.name}' | grep che-trusted-ca-certs
oc get pod --namespace= <workspace_namespace> --selector='controller.devfile.io/devworkspace_name= <workspace_name> ' --output='jsonpath={.items[0:].spec.containers[0:]}' | jq 'select (.volumeMounts[].name == "che-trusted-ca-certs") | .name'
oc get pod --namespace= <workspace_namespace> --selector='controller.devfile.io/devworkspace_name= <workspace_name> ' --output='jsonpath={.items[0:].metadata.name}' \
oc exec <workspace_pod_name> --namespace= <workspace_namespace> -- cat /public-certs/custom-ca-certificates.custom-ca-certificates.pem
spec: networking: labels: <labels> 1 domain: <domain> 2 annotations: <annotations> 3
spec: devEnvironments: storage: perUserStrategyPvcConfig: claimSize: <claim_size> 1 storageClass: <storage_class_name> 2 perWorkspaceStrategyPvcConfig: claimSize: <claim_size> 3 storageClass: <storage_class_name> 4 pvcStrategy: <pvc_strategy> 5
spec: devEnvironments: storage: pvc: pvcStrategy: 'per-user' 1
per-user: 10Gi
per-workspace: 5Gi
spec: devEnvironments: storage: pvc: pvcStrategy: ' <strategy_name> ' 1 perUserStrategyPvcConfig: 2 claimSize: <resource_quantity> 3 perWorkspaceStrategyPvcConfig: 4 claimSize: <resource_quantity> 5
cat > my-samples.json <<EOF [ { "displayName": " <display_name> ", 1 "description": " <description> ", 2 "tags": <tags> , 3 "url": " <url> ", 4 "icon": { "base64data": " <base64data> ", 5 "mediatype": " <mediatype> " 6 } } ] EOF
create configmap getting-started-samples --from-file=my-samples.json -n openshift-devspaces
label configmap getting-started-samples app.kubernetes.io/part-of=che.eclipse.org app.kubernetes.io/component=getting-started-samples -n openshift-devspaces
apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: devspaces-dashboard-customization namespace: openshift-devspaces annotations: che.eclipse.org/mount-as: subpath che.eclipse.org/mount-path: /public/dashboard/assets/branding labels: app.kubernetes.io/component: devspaces-dashboard-secret app.kubernetes.io/part-of: che.eclipse.org data: loader.svg: <Base64_encoded_content_of_the_image> 1 type: Opaque EOF
kind: Secret apiVersion: v1 metadata: name: github-oauth-config namespace: openshift-devspaces 1 labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: oauth-scm-configuration annotations: che.eclipse.org/oauth-scm-server: github che.eclipse.org/scm-server-endpoint: <github_server_url> 2 che.eclipse.org/scm-github-disable-subdomain-isolation: 'false' 3 type: Opaque stringData: id: <GitHub_OAuth_Client_ID> 4 secret: <GitHub_OAuth_Client_Secret> 5
oc apply -f - <<EOF <Secret_prepared_in_the_previous_step> EOF
kind: Secret apiVersion: v1 metadata: name: gitlab-oauth-config namespace: openshift-devspaces 1 labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: oauth-scm-configuration annotations: che.eclipse.org/oauth-scm-server: gitlab che.eclipse.org/scm-server-endpoint: <gitlab_server_url> 2 type: Opaque stringData: id: <GitLab_Application_ID> 3 secret: <GitLab_Client_Secret> 4
oc apply -f - <<EOF <Secret_prepared_in_the_previous_step> EOF
kind: Secret apiVersion: v1 metadata: name: bitbucket-oauth-config namespace: openshift-devspaces 1 labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: oauth-scm-configuration annotations: che.eclipse.org/oauth-scm-server: bitbucket che.eclipse.org/scm-server-endpoint: <bitbucket_server_url> 2 type: Opaque stringData: id: <Bitbucket_Client_ID> 3 secret: <Bitbucket_Client_Secret> 4
oc apply -f - <<EOF <Secret_prepared_in_the_previous_step> EOF
kind: Secret apiVersion: v1 metadata: name: bitbucket-oauth-config namespace: openshift-devspaces 1 labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: oauth-scm-configuration annotations: che.eclipse.org/oauth-scm-server: bitbucket type: Opaque stringData: id: <Bitbucket_Oauth_Consumer_Key> 2 secret: <Bitbucket_Oauth_Consumer_Secret> 3
oc apply -f - <<EOF <Secret_prepared_in_the_previous_step> EOF
openssl genrsa -out private.pem 2048 && openssl pkcs8 -topk8 -inform pem -outform pem -nocrypt -in private.pem -out privatepkcs8.pem && cat privatepkcs8.pem | sed 's/-----BEGIN PRIVATE KEY-----//g' | sed 's/-----END PRIVATE KEY-----//g' | tr -d '\n' > privatepkcs8-stripped.pem && openssl rsa -in private.pem -pubout > public.pub && cat public.pub | sed 's/-----BEGIN PUBLIC KEY-----//g' | sed 's/-----END PUBLIC KEY-----//g' | tr -d '\n' > public-stripped.pub && openssl rand -base64 24 > bitbucket-consumer-key && openssl rand -base64 24 > bitbucket-shared-secret
kind: Secret apiVersion: v1 metadata: name: bitbucket-oauth-config namespace: openshift-devspaces 1 labels: app.kubernetes.io/component: oauth-scm-configuration app.kubernetes.io/part-of: che.eclipse.org annotations: che.eclipse.org/oauth-scm-server: bitbucket che.eclipse.org/scm-server-endpoint: <bitbucket_server_url> 2 type: Opaque stringData: private.key: <Content_of_privatepkcs8-stripped.pem> 3 consumer.key: <Content_of_bitbucket-consumer-key> 4 shared_secret: <Content_of_bitbucket-shared-secret> 5
oc apply -f - <<EOF <Secret_prepared_in_the_previous_step> EOF
kind: Secret apiVersion: v1 metadata: name: azure-devops-oauth-config namespace: openshift-devspaces 1 labels: app.kubernetes.io/part-of: che.eclipse.org app.kubernetes.io/component: oauth-scm-configuration annotations: che.eclipse.org/oauth-scm-server: azure-devops type: Opaque stringData: id: <Microsoft_Azure_DevOps_Services_OAuth_App_ID> 2 secret: <Microsoft_Azure_DevOps_Services_OAuth_Client_Secret> 3
oc apply -f - <<EOF <Secret_prepared_in_the_previous_step> EOF
USER_ROLES= <name> 1
OPERATOR_NAMESPACE=USD(oc get pods -l app.kubernetes.io/component=devspaces-operator -o jsonpath={".items[0].metadata.namespace"} --all-namespaces)
kubectl apply -f - <<EOF kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: USD{USER_ROLES} labels: app.kubernetes.io/part-of: che.eclipse.org rules: - verbs: - <verbs> 1 apiGroups: - <apiGroups> 2 resources: - <resources> 3 EOF
kubectl apply -f - <<EOF kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: USD{USER_ROLES} labels: app.kubernetes.io/part-of: che.eclipse.org subjects: - kind: ServiceAccount name: devspaces-operator namespace: USD{OPERATOR_NAMESPACE} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: USD{USER_ROLES} EOF
kubectl patch checluster devspaces --patch '{"spec": {"components": {"cheServer": {"clusterRoles": ["'USD{USER_ROLES}'"]}}}}' --type=merge -n openshift-devspaces
kubectl patch checluster devspaces --patch '{"spec": {"devEnvironments": {"user": {"clusterRoles": ["'USD{USER_ROLES}'"]}}}}' --type=merge -n openshift-devspaces
spec: networking: auth: advancedAuthorization: allowUsers: - <allow_users> 1 allowGroups: - <allow_groups> 2 denyUsers: - <deny_users> 3 denyGroups: - <deny_groups> 4
oc get users
oc delete user <username>
NODE_ROLE=master
NODE_ROLE=worker
VERSION=4.12.0
cat << EOF | butane | oc apply -f - variant: openshift version: USD{VERSION} metadata: labels: machineconfiguration.openshift.io/role: USD{NODE_ROLE} name: 99-podman-dev-fuse-USD{NODE_ROLE} storage: files: - path: /etc/crio/crio.conf.d/99-podman-fuse 1 mode: 0644 overwrite: true contents: 2 inline: | [crio.runtime.workloads.podman-fuse] 3 activation_annotation = "io.openshift.podman-fuse" 4 allowed_annotations = [ "io.kubernetes.cri-o.Devices" 5 ] [crio.runtime] allowed_devices = ["/dev/fuse"] 6 EOF
oc get nodes
NAME STATUS ROLES AGE VERSION ip-10-0-136-161.ec2.internal Ready worker 28m v1.27.9 ip-10-0-136-243.ec2.internal Ready master 34m v1.27.9 ip-10-0-141-105.ec2.internal Ready,SchedulingDisabled worker 28m v1.27.9 ip-10-0-142-249.ec2.internal Ready master 34m v1.27.9 ip-10-0-153-11.ec2.internal Ready worker 28m v1.27.9 ip-10-0-153-150.ec2.internal Ready master 34m v1.27.9
io.openshift.podman-fuse: '' io.kubernetes.cri-o.Devices: /dev/fuse
oc get nodes
oc debug node/ <nodename>
sh-4.4# stat /host/etc/crio/crio.conf.d/99-podman-fuse
spec: components: pluginRegistry: openVSXURL: " <url_of_an_open_vsx_registry_instance> " 1
https://www.open-vsx.org/extension/ <publisher> / <extension>
git checkout devspaces-USDPRODUCT_VERSION-rhel-8
id:  <publisher> . <extension> 
id:  <publisher> . <extension> 
download:  <url_to_download_vsix_file> 
version:  <extension_version> 
./build.sh -o <username> -r quay.io -t custom
podman push quay.io/ <username/plugin_registry:custom>
spec: components: pluginRegistry: deployment: containers: - image: quay.io/ <username/plugin_registry:custom> openVSXURL: ''
"trustedExtensionAuthAccess": [ "<publisher1>.<extension1>", "<publisher2>.<extension2>" ]
env: - name: VSCODE_TRUSTED_EXTENSIONS value: "<publisher1>.<extension1>,<publisher2>.<extension2>"
kind: ConfigMap apiVersion: v1 metadata: name: trusted-extensions labels: controller.devfile.io/mount-to-devworkspace: 'true' controller.devfile.io/watch-configmap: 'true' annotations: controller.devfile.io/mount-as: env data: VSCODE_TRUSTED_EXTENSIONS: '<publisher1>.<extension1>,<publisher2>.<extension2>'
{ "folders": [ { "name": "project-1", "path": "/projects/project-1" }, { "name": "project-2", "path": "/projects/project-2" } ] }
{ "folders": [ { "name": "project-name", "path": "." } ] }
env: - name: VSCODE_DEFAULT_WORKSPACE value: "/projects/project-name/workspace-file"
env: - name: VSCODE_DEFAULT_WORKSPACE value: "/"
dsc server:update -n openshift-devspaces
bash prepare-restricted-environment.sh --devworkspace_operator_index registry.redhat.io/redhat/redhat-operator-index:v4.16 --devworkspace_operator_version "v0.28.0" --prod_operator_index "registry.redhat.io/redhat/redhat-operator-index:v4.16" --prod_operator_package_name "devspaces" --prod_operator_bundle_name "devspacesoperator" --prod_operator_version "v3.14.0" --my_registry " <my_registry> " 1
dsc server:update --che-operator-image="USDTAG" -n openshift-devspaces --k8spodwaittimeout=1800000
spec: conversion: strategy: None status:
oc delete sub devworkspace-operator -n openshift-operators 1
oc get csv | grep devworkspace
oc delete csv <devworkspace_operator.vX.Y.Z> -n openshift-operators 1
cat <<EOF | oc apply -f - apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: devworkspace-operator namespace: openshift-operators spec: channel: fast name: devworkspace-operator source: redhat-operators sourceNamespace: openshift-marketplace installPlanApproval: Automatic 1 startingCSV: devworkspace-operator.v0.28.0 EOF
dsc server:delete