Skip to content

Commit

Permalink
feat(background): support custom background processes in ide
Browse files Browse the repository at this point in the history
  • Loading branch information
tunahanertekin authored Dec 5, 2023
2 parents 219f24e + 4f892df commit 0a2ad97
Show file tree
Hide file tree
Showing 12 changed files with 299 additions and 71 deletions.
49 changes: 49 additions & 0 deletions config/crd/bases/robot.roboscale.io_robotides.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,55 @@ spec:
status:
description: Most recently observed status of the RobotIDE.
properties:
configMapStatus:
description: Config map status. It's used to add background apps.
properties:
created:
description: Shows if the owned resource is created.
type: boolean
phase:
description: Phase of the owned resource.
type: string
reference:
description: Reference to the owned resource.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a valid
JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen
only to have some well-defined way of referencing a part
of an object. TODO: this design is not final and this field
is subject to change in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
x-kubernetes-map-type: atomic
required:
- created
type: object
customPortIngressStatus:
description: Status of Cloud IDE ingress for custom ports service.
Created only if the robot has an additional config with key `IDE_CUSTOM_PORT_RANGE`
Expand Down
49 changes: 49 additions & 0 deletions internal/configure/background.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package configure

import (
corev1 "k8s.io/api/core/v1"
)

func (cfg *PodConfigInjector) InjectBackgroundConfigFiles(pod *corev1.Pod, configMap corev1.ConfigMap) *corev1.Pod {

cfg.placeBackgroundConfigFiles(pod, configMap)

return pod
}

func (cfg *PodConfigInjector) placeBackgroundConfigFiles(pod *corev1.Pod, configMap corev1.ConfigMap) {

var mode int32 = 511

volume := corev1.Volume{
Name: "background-config",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: configMap.Name,
},
},
},
}

for key := range configMap.Data {
volume.VolumeSource.ConfigMap.Items = append(volume.VolumeSource.ConfigMap.Items, corev1.KeyToPath{
Key: key,
Path: key,
Mode: &mode,
})
}

pod.Spec.Volumes = append(pod.Spec.Volumes, volume)

volumeMount := corev1.VolumeMount{
Name: "background-config",
MountPath: "/etc/robolaunch/services/custom/",
}

for k, container := range pod.Spec.Containers {
container.VolumeMounts = append(container.VolumeMounts, volumeMount)
pod.Spec.Containers[k] = container
}

}
19 changes: 18 additions & 1 deletion internal/resources/robot_ide.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func getRobotIDESelector(robotIDE robotv1alpha1.RobotIDE) map[string]string {
}
}

func GetRobotIDEPod(robotIDE *robotv1alpha1.RobotIDE, podNamespacedName *types.NamespacedName, robot robotv1alpha1.Robot, robotVDI robotv1alpha1.RobotVDI, node corev1.Node) *corev1.Pod {
func GetRobotIDEPod(robotIDE *robotv1alpha1.RobotIDE, podNamespacedName *types.NamespacedName, robot robotv1alpha1.Robot, robotVDI robotv1alpha1.RobotVDI, node corev1.Node, cm corev1.ConfigMap) *corev1.Pod {

podCfg := configure.PodConfigInjector{}
containerCfg := configure.ContainerConfigInjector{}
Expand Down Expand Up @@ -97,6 +97,7 @@ func GetRobotIDEPod(robotIDE *robotv1alpha1.RobotIDE, podNamespacedName *types.N
podCfg.InjectImagePullPolicy(&idePod)
podCfg.SchedulePod(&idePod, robotIDE)
podCfg.InjectVolumeConfiguration(&idePod, robot)
podCfg.InjectBackgroundConfigFiles(&idePod, cm)
podCfg.InjectGenericEnvironmentVariables(&idePod, robot)
podCfg.InjectRuntimeClass(&idePod, robot, node)
if robotIDE.Spec.Display && label.GetTargetRobotVDI(robotIDE) != "" {
Expand Down Expand Up @@ -374,3 +375,19 @@ func GetRobotIDECustomIngress(robotIDE *robotv1alpha1.RobotIDE, ingressNamespace

return ingress
}

func GetRobotIDEConfigMap(robotIDE *robotv1alpha1.RobotIDE, cmNamespacedName *types.NamespacedName) *corev1.ConfigMap {

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: cmNamespacedName.Name,
Namespace: cmNamespacedName.Namespace,
},
Data: map[string]string{
"custom.conf": internal.CUSTOM_SUPERVISORD_CONFIG,
"custom.sh": internal.CUSTOM_BACKGROUND_SCRIPT,
},
}

return cm
}
159 changes: 92 additions & 67 deletions internal/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const (
INGRESS_IDE_POSTFIX = ""
CUSTOM_PORT_SVC_IDE_POSTFIX = "-custom"
CUSTOM_PORT_INGRESS_IDE_POSTFIX = "-custom"
CONFIGMAP_IDE_POSTFIX = ""
)

// RobotDevSuite owned resources' postfixes
Expand All @@ -105,45 +106,40 @@ const (
X11_UNIX_PATH = "/tmp/.X11-unix"
)

// Super client configuration
const (
SUPER_CLIENT_CONFIG = "" +
"<?xml version='1.0' encoding='UTF-8' ?>" +
"<dds>" +
" <profiles xmlns='http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles'>" +
" <transport_descriptors>" +
" <transport_descriptor>" +
" <transport_id>udp_transport</transport_id>" +
" <type>UDPv4</type>" +
" </transport_descriptor>" +
" </transport_descriptors>" +
" <participant profile_name='super_client_profile' is_default_profile='true'>" +
" <rtps>" +
" <userTransports>" +
" <transport_id>udp_transport</transport_id>" +
" </userTransports>" +
" <useBuiltinTransports>false</useBuiltinTransports>" +
" <builtin>" +
" <discovery_config>" +
" <discoveryProtocol>SUPER_CLIENT</discoveryProtocol>" +
" <discoveryServersList>" +
" <RemoteServer prefix='44.53.00.5f.45.50.52.4f.53.49.4d.41'>" +
" <metatrafficUnicastLocatorList>" +
" <locator>" +
" <udpv4>" +
" <address>" + "%s" + "</address>" +
" <port>11811</port>" +
" </udpv4>" +
" </locator>" +
" </metatrafficUnicastLocatorList>" +
" </RemoteServer>" +
" </discoveryServersList>" +
" </discovery_config>" +
" </builtin>" +
" </rtps>" +
" </participant>" +
" </profiles>" +
"</dds>"
IMAGE_MAP_CONFIG_MAP_NAME = "platform"
IMAGE_MAP_CONFIG_MAP_NAMESPACE = "kube-system"
IMAGE_MAP_CONFIG_MAP_DATA_KEY = "platform.yaml"
IMAGE_MAP_URL = "https://raw.githubusercontent.com/robolaunch/robolaunch/main/platform.yaml"
)

// Commands for collecting metrics
const (
CMD_GET_CPU = "cat /sys/fs/cgroup/cpu/cpuacct.usage"
CMD_GET_MEMORY = "cat /sys/fs/cgroup/memory/memory.usage_in_bytes"
CMD_GET_NETWORK_LOAD = "cat /proc/net/dev | awk -F ' ' '{print $1 $2 \":\" $10}' | tail -n+3"
)

const (
GRANT_PERMISSION_KEY = "GRANT_PERMISSION"
PERSISTENT_DIRS_KEY = "PERSISTENT_DIRS"
HOST_DIRS_KEY = "HOST_DIRS"
IDE_CUSTOM_PORT_RANGE_KEY = "IDE_CUSTOM_PORT_RANGE"
VDI_CUSTOM_PORT_RANGE_KEY = "VDI_CUSTOM_PORT_RANGE"
)

// regex
const (
GRANT_PERMISSION_REGEX = "^(/([A-Za-z0-9./_-])+:)*(/[A-Za-z0-9./_-]+)$"
PERSISTENT_DIRS_REGEX = "^(/([A-Za-z0-9./_-])+:)*(/[A-Za-z0-9./_-]+)$"
HOST_DIRS_REGEX = "^(((/[A-Za-z0-9./_-]+):(/[A-Za-z0-9./_-]+))+,)*(((/[A-Za-z0-9./_-]+):(/[A-Za-z0-9./_-]+))+)$"
CUSTOM_PORT_RANGE_REGEX = "^([a-z0-9]{4}-[0-9]{5}:[0-9]{2,5}/)*([a-z0-9]{4}-[0-9]{5}:[0-9]{2,5})$"
)

// file browser ports
const (
FILE_BROWSER_PORT_NAME = "filebrowser"
FILE_BROWSER_PORT = 2000
)

// Ingress annotations
Expand Down Expand Up @@ -184,40 +180,69 @@ const (
"}"
)

const (
IMAGE_MAP_CONFIG_MAP_NAME = "platform"
IMAGE_MAP_CONFIG_MAP_NAMESPACE = "kube-system"
IMAGE_MAP_CONFIG_MAP_DATA_KEY = "platform.yaml"
IMAGE_MAP_URL = "https://raw.githubusercontent.com/robolaunch/robolaunch/main/platform.yaml"
)

// Commands for collecting metrics
const (
CMD_GET_CPU = "cat /sys/fs/cgroup/cpu/cpuacct.usage"
CMD_GET_MEMORY = "cat /sys/fs/cgroup/memory/memory.usage_in_bytes"
CMD_GET_NETWORK_LOAD = "cat /proc/net/dev | awk -F ' ' '{print $1 $2 \":\" $10}' | tail -n+3"
)
// File contents

// Super client configuration
const (
GRANT_PERMISSION_KEY = "GRANT_PERMISSION"
PERSISTENT_DIRS_KEY = "PERSISTENT_DIRS"
HOST_DIRS_KEY = "HOST_DIRS"
IDE_CUSTOM_PORT_RANGE_KEY = "IDE_CUSTOM_PORT_RANGE"
VDI_CUSTOM_PORT_RANGE_KEY = "VDI_CUSTOM_PORT_RANGE"
)

// regex
const (
GRANT_PERMISSION_REGEX = "^(/([A-Za-z0-9./_-])+:)*(/[A-Za-z0-9./_-]+)$"
PERSISTENT_DIRS_REGEX = "^(/([A-Za-z0-9./_-])+:)*(/[A-Za-z0-9./_-]+)$"
HOST_DIRS_REGEX = "^(((/[A-Za-z0-9./_-]+):(/[A-Za-z0-9./_-]+))+,)*(((/[A-Za-z0-9./_-]+):(/[A-Za-z0-9./_-]+))+)$"
CUSTOM_PORT_RANGE_REGEX = "^([a-z0-9]{4}-[0-9]{5}:[0-9]{2,5}/)*([a-z0-9]{4}-[0-9]{5}:[0-9]{2,5})$"
SUPER_CLIENT_CONFIG = "" +
"<?xml version='1.0' encoding='UTF-8' ?>" +
"<dds>" +
" <profiles xmlns='http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles'>" +
" <transport_descriptors>" +
" <transport_descriptor>" +
" <transport_id>udp_transport</transport_id>" +
" <type>UDPv4</type>" +
" </transport_descriptor>" +
" </transport_descriptors>" +
" <participant profile_name='super_client_profile' is_default_profile='true'>" +
" <rtps>" +
" <userTransports>" +
" <transport_id>udp_transport</transport_id>" +
" </userTransports>" +
" <useBuiltinTransports>false</useBuiltinTransports>" +
" <builtin>" +
" <discovery_config>" +
" <discoveryProtocol>SUPER_CLIENT</discoveryProtocol>" +
" <discoveryServersList>" +
" <RemoteServer prefix='44.53.00.5f.45.50.52.4f.53.49.4d.41'>" +
" <metatrafficUnicastLocatorList>" +
" <locator>" +
" <udpv4>" +
" <address>" + "%s" + "</address>" +
" <port>11811</port>" +
" </udpv4>" +
" </locator>" +
" </metatrafficUnicastLocatorList>" +
" </RemoteServer>" +
" </discoveryServersList>" +
" </discovery_config>" +
" </builtin>" +
" </rtps>" +
" </participant>" +
" </profiles>" +
"</dds>"
)

// file browser ports
const (
FILE_BROWSER_PORT_NAME = "filebrowser"
FILE_BROWSER_PORT = 2000
CUSTOM_SUPERVISORD_CONFIG = "" +
"# replace your daemon's configuration" + "\n" +
"# for reference, see http://supervisord.org/configuration.html" + "\n" +
"[program:custom]" + "\n" +
"environment=HOME='/home/robolaunch',USER='robolaunch',FILE_BROWSER_PORT='%(ENV_FILE_BROWSER_PORT)s'" + "\n" +
"command=/bin/bash /etc/robolaunch/services/custom/custom.sh" + "\n" +
"stopsignal=INT" + "\n" +
"stopwaitsecs=5" + "\n" +
"autorestart=true" + "\n" +
"priority=800" + "\n" +
"user=robolaunch" + "\n" +
"stdout_logfile=/var/log/services/custom.log" + "\n" +
"stdout_logfile_maxbytes=100MB" + "\n" +
"stdout_logfile_backups=10" + "\n" +
"redirect_stderr=true" + "\n"
CUSTOM_BACKGROUND_SCRIPT = "" +
"#!/bin/bash" + "\n" +
"# replace your autostart script" + "\n" +
"sleep infinity" + "\n"
)

func Bash(command string) []string {
Expand Down
7 changes: 7 additions & 0 deletions pkg/api/roboscale.io/v1alpha1/dev_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ func (robotide *RobotIDE) GetRobotIDECustomIngressMetadata() *types.NamespacedNa
}
}

func (robotide *RobotIDE) GetRobotIDEConfigMapMetadata() *types.NamespacedName {
return &types.NamespacedName{
Namespace: robotide.Namespace,
Name: robotide.Name + internal.CONFIGMAP_IDE_POSTFIX,
}
}

// ********************************
// RobotVDI helpers
// ********************************
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/roboscale.io/v1alpha1/dev_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ type RobotIDEStatus struct {
CustomPortServiceStatus OwnedServiceStatus `json:"customPortServiceStatus,omitempty"`
// Status of Cloud IDE ingress for custom ports service. Created only if the robot has an additional config with key `IDE_CUSTOM_PORT_RANGE` and `.spec.ingress` is `true`.
CustomPortIngressStatus OwnedResourceStatus `json:"customPortIngressStatus,omitempty"`
// Config map status. It's used to add background apps.
ConfigMapStatus OwnedResourceStatus `json:"configMapStatus,omitempty"`
}

// ********************************
Expand Down
1 change: 1 addition & 0 deletions pkg/api/roboscale.io/v1alpha1/phases.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const (
RobotIDEPhaseCreatingIngress RobotIDEPhase = "CreatingIngress"
RobotIDEPhaseCreatingCustomPortService RobotIDEPhase = "CreatingCustomPortService"
RobotIDEPhaseCreatingCustomPortIngress RobotIDEPhase = "CreatingCustomPortIngress"
RobotIDEPhaseCreatingConfigMap RobotIDEPhase = "CreatingConfigMap"
RobotIDEPhaseRunning RobotIDEPhase = "Running"
)

Expand Down
1 change: 1 addition & 0 deletions pkg/api/roboscale.io/v1alpha1/zz_generated.deepcopy.go

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

18 changes: 18 additions & 0 deletions pkg/controllers/robot_dev_suite/robot_ide/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,21 @@ func (r *RobotIDEReconciler) reconcileCheckCustomIngress(ctx context.Context, in

return nil
}

func (r *RobotIDEReconciler) reconcileCheckConfigMap(ctx context.Context, instance *robotv1alpha1.RobotIDE) error {

cmQuery := &corev1.ConfigMap{}
err := r.Get(ctx, *instance.GetRobotIDEConfigMapMetadata(), cmQuery)
if err != nil {
if errors.IsNotFound(err) {
instance.Status.ConfigMapStatus = robotv1alpha1.OwnedResourceStatus{}
} else {
return err
}
} else {
instance.Status.ConfigMapStatus.Created = true
reference.SetReference(&instance.Status.IngressStatus.Reference, cmQuery.TypeMeta, cmQuery.ObjectMeta)
}

return nil
}
Loading

0 comments on commit 0a2ad97

Please sign in to comment.