diff --git a/ee/lib/remote_development/devfile_operations/restrictions_enforcer.rb b/ee/lib/remote_development/devfile_operations/restrictions_enforcer.rb index fc21a31e186ba2e5efd7cab4b665a942e528c9d1..377735942395430bb0af3234fcbb89d90ffde511 100644 --- a/ee/lib/remote_development/devfile_operations/restrictions_enforcer.rb +++ b/ee/lib/remote_development/devfile_operations/restrictions_enforcer.rb @@ -262,12 +262,26 @@ def self.validate_commands(context) next unless command_type component_name = command_type.fetch(:component) - next unless component_name.downcase.start_with?(RESTRICTED_PREFIX) + + if component_name.downcase.start_with?(RESTRICTED_PREFIX) + return err( + format( + _("Component name '%{component}' for command id '%{command}' must not start with '%{prefix}'"), + component: component_name, + command: command_id, + prefix: RESTRICTED_PREFIX + ), + context + ) + end + + command_label = command_type.fetch(:label, "") + next unless command_label.downcase.start_with?(RESTRICTED_PREFIX) return err( format( - _("Component name '%{component}' for command id '%{command}' must not start with '%{prefix}'"), - component: component_name, + _("Label '%{command_label}' for command id '%{command}' must not start with '%{prefix}'"), + command_label: command_label, command: command_id, prefix: RESTRICTED_PREFIX ), diff --git a/ee/lib/remote_development/files.rb b/ee/lib/remote_development/files.rb index 2c14889848f08884328e5148b4903ab894df5bb7..c4d98d251e00bbfb5ba9a0f256fa68e2175291b9 100644 --- a/ee/lib/remote_development/files.rb +++ b/ee/lib/remote_development/files.rb @@ -38,6 +38,8 @@ def self.read_file(path) read_file("workspace_operations/create/internal_poststart_command_sleep_until_workspace_is_running.sh") INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT = read_file("workspace_operations/create/internal_poststart_command_start_sshd.sh") + KUBERNETES_LEGACY_POSTSTART_HOOK_COMMAND = + read_file("workspace_operations/reconcile/output/kubernetes_legacy_poststart_hook_command.sh") KUBERNETES_POSTSTART_HOOK_COMMAND = read_file("workspace_operations/reconcile/output/kubernetes_poststart_hook_command.sh") MAIN_COMPONENT_UPDATER_CONTAINER_ARGS = diff --git a/ee/lib/remote_development/workspace_operations/create/internal_poststart_command_start_vscode.sh b/ee/lib/remote_development/workspace_operations/create/internal_poststart_command_start_vscode.sh index 1f11d7e5c90f7ee2e82e536112dfa0f8a1661b03..d585b4d5dc25aa8f4a5fd9523bb0402c36b8c44b 100644 --- a/ee/lib/remote_development/workspace_operations/create/internal_poststart_command_start_vscode.sh +++ b/ee/lib/remote_development/workspace_operations/create/internal_poststart_command_start_vscode.sh @@ -96,6 +96,4 @@ echo "$(date -Iseconds): - Workspace trust disabled: yes" --port "${GL_VSCODE_PORT}" \ --log "${GL_VSCODE_LOG_LEVEL}" \ --without-connection-token \ - --disable-workspace-trust - -echo "$(date -Iseconds): VS Code: Remote Extension Host process exited with code $?" + --disable-workspace-trust & diff --git a/ee/lib/remote_development/workspace_operations/create/internal_poststart_commands_inserter.rb b/ee/lib/remote_development/workspace_operations/create/internal_poststart_commands_inserter.rb index be6a89412ac726f453aaf9772ea13d5b034e7252..6f7d584c19d27c97f64775223ab83e7951ead7d3 100644 --- a/ee/lib/remote_development/workspace_operations/create/internal_poststart_commands_inserter.rb +++ b/ee/lib/remote_development/workspace_operations/create/internal_poststart_commands_inserter.rb @@ -5,6 +5,7 @@ module WorkspaceOperations module Create class InternalPoststartCommandsInserter include CreateConstants + include WorkspaceOperationsConstants include Files include RemoteDevelopmentConstants @@ -61,7 +62,8 @@ def self.insert(context) id: clone_project_command_id, exec: { commandLine: clone_project_script, - component: main_component_name + component: main_component_name, + label: INTERNAL_BLOCKING_COMMAND_LABEL } } poststart_events << clone_project_command_id @@ -72,7 +74,8 @@ def self.insert(context) id: start_sshd_command_id, exec: { commandLine: INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT, - component: main_component_name + component: main_component_name, + label: INTERNAL_BLOCKING_COMMAND_LABEL } } poststart_events << start_sshd_command_id @@ -83,7 +86,8 @@ def self.insert(context) id: start_vscode_command_id, exec: { commandLine: INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, - component: main_component_name + component: main_component_name, + label: INTERNAL_BLOCKING_COMMAND_LABEL } } poststart_events << start_vscode_command_id @@ -100,7 +104,8 @@ def self.insert(context) id: sleep_until_container_is_running_command_id, exec: { commandLine: sleep_until_container_is_running_script, - component: main_component_name + component: main_component_name, + label: INTERNAL_COMMAND_LABEL } } poststart_events << sleep_until_container_is_running_command_id diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_legacy_poststart_hook_command.sh b/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_legacy_poststart_hook_command.sh new file mode 100644 index 0000000000000000000000000000000000000000..c0963bf88df7eedd5df4aa3d047f440313f800c8 --- /dev/null +++ b/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_legacy_poststart_hook_command.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +mkdir -p "${GL_WORKSPACE_LOGS_DIR}" +ln -sf "${GL_WORKSPACE_LOGS_DIR}" /tmp +"%s" 1>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log" 2>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log" diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_command.sh b/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_command.sh index 0bc343174530222549f18501112fd3e54807de34..792e1cad5d3a5396d862b7ab42329b6da7abc45d 100644 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_command.sh +++ b/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_command.sh @@ -1,3 +1,21 @@ +#!/bin/sh + mkdir -p "${GL_WORKSPACE_LOGS_DIR}" ln -sf "${GL_WORKSPACE_LOGS_DIR}" /tmp -"%s" 1>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log" 2>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log" & + +{ + echo "$(date -Iseconds): ----------------------------------------" + echo "$(date -Iseconds): Running poststart commands for workspace..." + + echo "$(date -Iseconds): ----------------------------------------" + echo "$(date -Iseconds): Running internal blocking poststart commands script..." +} >> "${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log" + +"%s" 1>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log" 2>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log" + +{ + echo "$(date -Iseconds): ----------------------------------------" + echo "$(date -Iseconds): Running non-blocking poststart commands script..." +} >> "${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log" + +"%s" 1>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log" 2>>"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log" & diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter.rb index 408f5fd59484db543f4692761a301865bd1c9e5c..134a75aeb574ee23a79b08bfd4d7218cc4424426 100644 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter.rb +++ b/ee/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter.rb @@ -16,6 +16,10 @@ class KubernetesPoststartHookInserter # @param [Hash] devfile_events # @return [void] def self.insert(containers:, devfile_commands:, devfile_events:) + internal_blocking_command_label_present = devfile_commands.any? do |command| + command.dig(:exec, :label) == INTERNAL_BLOCKING_COMMAND_LABEL + end + devfile_events => { postStart: Array => poststart_command_ids } containers_with_devfile_poststart_commands = @@ -34,12 +38,23 @@ def self.insert(containers:, devfile_commands:, devfile_events:) next unless containers_with_devfile_poststart_commands.include?(container_name) - kubernetes_poststart_hook_script = - format( - KUBERNETES_POSTSTART_HOOK_COMMAND, - run_poststart_commands_script_file_path: - "#{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{RUN_POSTSTART_COMMANDS_SCRIPT_NAME}" - ) + if internal_blocking_command_label_present + kubernetes_poststart_hook_script = + format( + KUBERNETES_POSTSTART_HOOK_COMMAND, + run_internal_blocking_poststart_commands_script_file_path: + "#{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME}", + run_non_blocking_poststart_commands_script_file_path: + "#{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME}" + ) + else + kubernetes_poststart_hook_script = + format( + KUBERNETES_LEGACY_POSTSTART_HOOK_COMMAND, + run_internal_blocking_poststart_commands_script_file_path: + "#{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{LEGACY_RUN_POSTSTART_COMMANDS_SCRIPT_NAME}" + ) + end container[:lifecycle] = { postStart: { diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender.rb index 717b60d1b711295a52868a59b1b0bddb954d4945..95c0f49594e5d83941e940b53d11e39199a13733 100644 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender.rb +++ b/ee/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender.rb @@ -6,6 +6,7 @@ module Reconcile module Output class ScriptsConfigmapAppender include ReconcileConstants + include WorkspaceOperationsConstants # @param [Array] desired_config # @param [String] name @@ -39,6 +40,7 @@ def self.append(desired_config:, name:, namespace:, labels:, annotations:, devfi add_run_poststart_commands_script_to_configmap_data( configmap_data: configmap_data, + devfile_commands: devfile_commands, devfile_events: devfile_events ) @@ -75,33 +77,68 @@ def self.add_devfile_command_scripts_to_configmap_data(configmap_data:, devfile_ # @param [Array] devfile_commands # @param [Hash] devfile_events # @return [void] - def self.add_run_poststart_commands_script_to_configmap_data(configmap_data:, devfile_events:) + def self.add_run_poststart_commands_script_to_configmap_data( + configmap_data:, + devfile_commands:, + devfile_events: + ) devfile_events => { postStart: Array => poststart_command_ids } - script_command_lines = - poststart_command_ids.map do |poststart_command_id| - # NOTE: We force all the poststart scripts to exit successfully with `|| true`, to - # prevent the Kubernetes poststart hook from failing, and thus prevent the - # container from exitin. Then users can view logs to debug failures. - # See https://github.com/eclipse-che/che/issues/23404#issuecomment-2787779571 - # for more context. - <<~CMD - echo "$(date -Iseconds): Running #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id}..." - #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id} || true - CMD - end.join - - configmap_data[RUN_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym] = + internal_blocking_command_label_present = devfile_commands.find do |command| + command.dig(:exec, :label) == INTERNAL_BLOCKING_COMMAND_LABEL + end + + unless internal_blocking_command_label_present + configmap_data[LEGACY_RUN_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym] = + <<~SH.chomp + #!/bin/sh + #{get_poststart_command_script_content(poststart_command_ids: poststart_command_ids)} + SH + return + end + + # Segregate internal commands and user provided commands. + # Before any non-blocking post start command is executed, we wait for the workspace to be marked ready. + # TODO: User provided commands should be added to the non-blocking poststart script with https://gitlab.com/gitlab-org/gitlab/-/issues/505988 + internal_blocking_poststart_command_ids, non_blocking_poststart_command_ids = + poststart_command_ids.partition do |id| + command = devfile_commands.find { |cmd| cmd[:id] == id } + command && command.dig(:exec, :label) == INTERNAL_BLOCKING_COMMAND_LABEL + end + + configmap_data[RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym] = <<~SH.chomp #!/bin/sh - #{script_command_lines} + #{get_poststart_command_script_content(poststart_command_ids: internal_blocking_poststart_command_ids)} + SH + + configmap_data[RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym] = + <<~SH.chomp + #!/bin/sh + #{get_poststart_command_script_content(poststart_command_ids: non_blocking_poststart_command_ids)} SH nil end + # @param [Array] poststart_command_ids + # @return [String] + def self.get_poststart_command_script_content(poststart_command_ids:) + poststart_command_ids.map do |poststart_command_id| + # NOTE: We force all the poststart scripts to exit successfully with `|| true`, to + # prevent the Kubernetes poststart hook from failing, and thus prevent the + # container from exiting. Then users can view logs to debug failures. + # See https://github.com/eclipse-che/che/issues/23404#issuecomment-2787779571 + # for more context. + <<~SH + echo "$(date -Iseconds): Running #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id}..." + #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id} || true + SH + end.join + end + private_class_method :add_devfile_command_scripts_to_configmap_data, - :add_run_poststart_commands_script_to_configmap_data + :add_run_poststart_commands_script_to_configmap_data, :get_poststart_command_script_content end end end diff --git a/ee/lib/remote_development/workspace_operations/reconcile/reconcile_constants.rb b/ee/lib/remote_development/workspace_operations/reconcile/reconcile_constants.rb index 7e8c9925b137ee0af68e4fec90a0e3e95f689e0d..af9a4ece11b5c5f73e61c248f38cc4f006fbd028 100644 --- a/ee/lib/remote_development/workspace_operations/reconcile/reconcile_constants.rb +++ b/ee/lib/remote_development/workspace_operations/reconcile/reconcile_constants.rb @@ -13,8 +13,10 @@ module ReconcileConstants include WorkspaceOperationsConstants # Please keep alphabetized + LEGACY_RUN_POSTSTART_COMMANDS_SCRIPT_NAME = "gl-run-poststart-commands.sh" RUN_AS_USER = 5001 - RUN_POSTSTART_COMMANDS_SCRIPT_NAME = "gl-run-poststart-commands.sh" + RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME = "gl-run-internal-blocking-poststart-commands.sh" + RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME = "gl-run-non-blocking-poststart-commands.sh" WORKSPACE_SCRIPTS_VOLUME_DEFAULT_MODE = 0o555 WORKSPACE_SCRIPTS_VOLUME_NAME = "gl-workspace-scripts" WORKSPACE_SCRIPTS_VOLUME_PATH = "/workspace-scripts" diff --git a/ee/lib/remote_development/workspace_operations/workspace_operations_constants.rb b/ee/lib/remote_development/workspace_operations/workspace_operations_constants.rb index 0968ac4b118d119add66a974123afcbe9043b921..5232532367c4b273afc71bc6d36c1279b8dcf768 100644 --- a/ee/lib/remote_development/workspace_operations/workspace_operations_constants.rb +++ b/ee/lib/remote_development/workspace_operations/workspace_operations_constants.rb @@ -17,6 +17,8 @@ module WorkspaceOperations # See documentation at ../README.md#constant-declarations for more information. module WorkspaceOperationsConstants # Please keep alphabetized + INTERNAL_COMMAND_LABEL = "gl-internal" + INTERNAL_BLOCKING_COMMAND_LABEL = "#{INTERNAL_COMMAND_LABEL}-blocking".freeze VARIABLES_VOLUME_DEFAULT_MODE = 0o774 VARIABLES_VOLUME_NAME = "gl-workspace-variables" VARIABLES_VOLUME_PATH = "/.workspace-data/variables/file" diff --git a/ee/spec/fixtures/remote_development/example.desired_config.json b/ee/spec/fixtures/remote_development/example.desired_config.json index 8d9b5d32e0ae1a57acea3fe35084e7ef7407e42e..05273df55d3d8c0494d6e904d44f2264645824cf 100644 --- a/ee/spec/fixtures/remote_development/example.desired_config.json +++ b/ee/spec/fixtures/remote_development/example.desired_config.json @@ -149,7 +149,7 @@ "command": [ "/bin/sh", "-c", - "mkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\"/workspace-scripts/gl-run-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" + "#!/bin/sh\n\nmkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running poststart commands for workspace...\"\n\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running internal blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-internal-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\"\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running non-blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-non-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" ] } } diff --git a/ee/spec/fixtures/remote_development/example.internal-poststart-commands-inserted-devfile.yaml.erb b/ee/spec/fixtures/remote_development/example.internal-poststart-commands-inserted-devfile.yaml.erb index 4f6cd4db6b108e7b7fc62de5d37db764f247f0f6..b72337b3ac88172ea18a669a5a83a3425f6beb50 100644 --- a/ee/spec/fixtures/remote_development/example.internal-poststart-commands-inserted-devfile.yaml.erb +++ b/ee/spec/fixtures/remote_development/example.internal-poststart-commands-inserted-devfile.yaml.erb @@ -66,16 +66,19 @@ commands: indent_yaml_literal(script, 8) %> component: tooling-container + label: <%= INTERNAL_BLOCKING_COMMAND_LABEL %> - id: gl-start-sshd-command exec: commandLine: | <%= indent_yaml_literal(INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT, 8) %> component: tooling-container + label: <%= INTERNAL_BLOCKING_COMMAND_LABEL %> - id: gl-init-tools-command exec: commandLine: | <%= indent_yaml_literal(INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, 8) %> component: tooling-container + label: <%= INTERNAL_BLOCKING_COMMAND_LABEL %> - id: gl-sleep-until-container-is-running-command exec: commandLine: | @@ -87,6 +90,7 @@ commands: indent_yaml_literal(script, 8) %> component: tooling-container + label: <%= INTERNAL_COMMAND_LABEL %> events: preStart: - gl-tools-injector-command diff --git a/ee/spec/fixtures/remote_development/example.invalid-restricted-prefix-command-apply-label-devfile.yaml.erb b/ee/spec/fixtures/remote_development/example.invalid-restricted-prefix-command-apply-label-devfile.yaml.erb new file mode 100644 index 0000000000000000000000000000000000000000..ec80d211c10789f70e9b49d0442407548e2a14d9 --- /dev/null +++ b/ee/spec/fixtures/remote_development/example.invalid-restricted-prefix-command-apply-label-devfile.yaml.erb @@ -0,0 +1,15 @@ +--- +schemaVersion: 2.2.0 +components: + - name: example + attributes: + gl/inject-editor: true + container: + image: quay.io/mloriedo/universal-developer-image:ubi8-dw-demo +commands: + - id: example + apply: + component: example + label: gl-example +events: {} +variables: {} diff --git a/ee/spec/fixtures/remote_development/example.invalid-restricted-prefix-command-exec-label-devfile.yaml.erb b/ee/spec/fixtures/remote_development/example.invalid-restricted-prefix-command-exec-label-devfile.yaml.erb new file mode 100644 index 0000000000000000000000000000000000000000..599d5ed62eb43c27b2fb7ad663f73818fdd20e76 --- /dev/null +++ b/ee/spec/fixtures/remote_development/example.invalid-restricted-prefix-command-exec-label-devfile.yaml.erb @@ -0,0 +1,17 @@ +--- +schemaVersion: 2.2.0 +components: + - name: example + attributes: + gl/inject-editor: true + container: + image: quay.io/mloriedo/universal-developer-image:ubi8-dw-demo +commands: + - id: example + exec: + component: example + commandLine: mvn clean + workingDir: /projects/spring-petclinic + label: gl-example +events: {} +variables: {} diff --git a/ee/spec/fixtures/remote_development/example.legacy-scripts-in-container-command-processed-devfile.yaml.erb b/ee/spec/fixtures/remote_development/example.legacy-no-poststart-in-container-command-processed-devfile.yaml.erb similarity index 100% rename from ee/spec/fixtures/remote_development/example.legacy-scripts-in-container-command-processed-devfile.yaml.erb rename to ee/spec/fixtures/remote_development/example.legacy-no-poststart-in-container-command-processed-devfile.yaml.erb diff --git a/ee/spec/fixtures/remote_development/example.legacy-poststart-in-container-command-processed-devfile.yaml.erb b/ee/spec/fixtures/remote_development/example.legacy-poststart-in-container-command-processed-devfile.yaml.erb new file mode 100644 index 0000000000000000000000000000000000000000..ea73a5c21fcf5c7222b5b6f66107de9c8e5ec06e --- /dev/null +++ b/ee/spec/fixtures/remote_development/example.legacy-poststart-in-container-command-processed-devfile.yaml.erb @@ -0,0 +1,110 @@ +--- +schemaVersion: 2.2.0 +metadata: {} +components: + - name: tooling-container + attributes: + gl/inject-editor: true + container: + image: quay.io/mloriedo/universal-developer-image:ubi8-dw-demo + args: + - | + <%= indent_yaml_literal(MAIN_COMPONENT_UPDATER_CONTAINER_ARGS, 10) %> + command: + - "/bin/sh" + - "-c" + volumeMounts: + - name: gl-workspace-data + path: /projects + env: + - name: GL_TOOLS_DIR + value: "/projects/.gl-tools" + - name: GL_VSCODE_LOG_LEVEL + value: "info" + - name: GL_VSCODE_PORT + value: "<%= WORKSPACE_EDITOR_PORT %>" + - name: GL_SSH_PORT + value: "<%= WORKSPACE_SSH_PORT %>" + - name: GL_VSCODE_ENABLE_MARKETPLACE + value: "false" + endpoints: + - name: editor-server + targetPort: <%= WORKSPACE_EDITOR_PORT %> + exposure: public + secure: true + protocol: https + - name: ssh-server + targetPort: <%= WORKSPACE_SSH_PORT %> + exposure: internal + secure: true + dedicatedPod: false + mountSources: true + - name: database-container + container: + image: mysql + volumeMounts: + - name: gl-workspace-data + path: /projects + env: + - name: MYSQL_ROOT_PASSWORD + value: "my-secret-pw" + dedicatedPod: false + mountSources: true + - name: gl-tools-injector + container: + image: <%= WORKSPACE_TOOLS_IMAGE %> + volumeMounts: + - name: gl-workspace-data + path: /projects + env: + - name: GL_TOOLS_DIR + value: "/projects/.gl-tools" + memoryLimit: 512Mi + memoryRequest: 256Mi + cpuLimit: 500m + cpuRequest: 100m + - name: gl-workspace-data + volume: + size: 50Gi +commands: + - id: gl-tools-injector-command + apply: + component: gl-tools-injector + - id: gl-clone-project-command + exec: + commandLine: | + <%= + script = INTERNAL_POSTSTART_COMMAND_CLONE_PROJECT_SCRIPT + indent_yaml_literal(script, 8) + %> + component: tooling-container + - id: gl-start-sshd-command + exec: + commandLine: | + <%= indent_yaml_literal(INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT, 8) %> + component: tooling-container + - id: gl-init-tools-command + exec: + commandLine: | + <%= indent_yaml_literal(INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, 8) %> + component: tooling-container + - id: gl-sleep-until-container-is-running-command + exec: + commandLine: | + <%= + script = format( + INTERNAL_POSTSTART_COMMAND_SLEEP_UNTIL_CONTAINER_IS_RUNNING_SCRIPT, + workspace_reconciled_actual_state_file_path: WORKSPACE_RECONCILED_ACTUAL_STATE_FILE_PATH + ) + indent_yaml_literal(script, 8) + %> + component: tooling-container +events: + preStart: + - gl-tools-injector-command + postStart: + - gl-clone-project-command + - gl-start-sshd-command + - gl-init-tools-command + - gl-sleep-until-container-is-running-command +variables: {} diff --git a/ee/spec/fixtures/remote_development/example.processed-devfile.yaml.erb b/ee/spec/fixtures/remote_development/example.processed-devfile.yaml.erb index ea73a5c21fcf5c7222b5b6f66107de9c8e5ec06e..00be4f60fa32bd264367dec4ec1621e9f82e9e1a 100644 --- a/ee/spec/fixtures/remote_development/example.processed-devfile.yaml.erb +++ b/ee/spec/fixtures/remote_development/example.processed-devfile.yaml.erb @@ -78,16 +78,19 @@ commands: indent_yaml_literal(script, 8) %> component: tooling-container + label: <%= INTERNAL_BLOCKING_COMMAND_LABEL %> - id: gl-start-sshd-command exec: commandLine: | <%= indent_yaml_literal(INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT, 8) %> component: tooling-container + label: <%= INTERNAL_BLOCKING_COMMAND_LABEL %> - id: gl-init-tools-command exec: commandLine: | <%= indent_yaml_literal(INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, 8) %> component: tooling-container + label: <%= INTERNAL_BLOCKING_COMMAND_LABEL %> - id: gl-sleep-until-container-is-running-command exec: commandLine: | @@ -99,6 +102,7 @@ commands: indent_yaml_literal(script, 8) %> component: tooling-container + label: <%= INTERNAL_COMMAND_LABEL %> events: preStart: - gl-tools-injector-command diff --git a/ee/spec/lib/remote_development/devfile_operations/restrictions_enforcer_spec.rb b/ee/spec/lib/remote_development/devfile_operations/restrictions_enforcer_spec.rb index aa449daae6f331f6976914db7e43225c52ced691..20bc9be47c8849a76345c1272152a1433424471b 100644 --- a/ee/spec/lib/remote_development/devfile_operations/restrictions_enforcer_spec.rb +++ b/ee/spec/lib/remote_development/devfile_operations/restrictions_enforcer_spec.rb @@ -82,6 +82,8 @@ "example.invalid-restricted-prefix-component-name-devfile.yaml.erb" | "Component name 'gl-example' must not start with 'gl-'" "example.invalid-restricted-prefix-event-type-prestart-name-devfile.yaml.erb" | "Event 'gl-example' of type 'preStart' must not start with 'gl-'" "example.invalid-restricted-prefix-variable-name-devfile.yaml.erb" | "Variable name 'gl-example' must not start with 'gl-'" + "example.invalid-restricted-prefix-command-apply-label-devfile.yaml.erb" | "Label 'gl-example' for command id 'example' must not start with 'gl-'" + "example.invalid-restricted-prefix-command-exec-label-devfile.yaml.erb" | "Label 'gl-example' for command id 'example' must not start with 'gl-'" "example.invalid-restricted-prefix-variable-name-with-underscore-devfile.yaml.erb" | "Variable name 'gl_example' must not start with 'gl_'" "example.invalid-root-attributes-pod-overrides-devfile.yaml.erb" | "Attribute 'pod-overrides' is not yet supported" "example.invalid-unsupported-component-container-dedicated-pod-devfile.yaml.erb" | "Property 'dedicatedPod' of component 'example' is not yet supported" diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_golden_master_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_golden_master_spec.rb index cfbcabeeed261d1369c1f773b438d0154c3e433f..e163a714fbacb8cd7bf48b292a6090f9b28d0607 100644 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_golden_master_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_golden_master_spec.rb @@ -165,6 +165,15 @@ it_behaves_like "generated desired_config golden master checks" + context "with legacy devfile that includes postStart event" do + let(:input_processed_devfile_yaml) { input_processed_devfile_yaml_with_legacy_poststart_event } + let(:golden_master_desired_config) do + golden_master_desired_config_from_legacy_devfile_with_poststart_and_with_include_all_resources_true + end + + it_behaves_like "generated desired_config golden master checks" + end + context "with legacy devfile that does not include postStart event" do let(:input_processed_devfile_yaml) { input_processed_devfile_yaml_without_poststart_event } let(:golden_master_desired_config) do @@ -257,9 +266,88 @@ def input_processed_devfile_yaml_with_poststart_event volume: size: 50Gi commands: - - id: example-poststart-exec-command + - id: gl-internal-example-command-1 + exec: + commandLine: "echo 'gl-internal-example-command-1'" + component: tooling-container + label: gl-internal-blocking + - id: gl-internal-example-command-2 + exec: + commandLine: "echo 'gl-internal-example-command-2'" + component: tooling-container + - id: example-prestart-apply-command + apply: + component: sidecar-container + events: + preStart: + - example-prestart-apply-command + postStart: + - gl-internal-example-command-1 + - gl-internal-example-command-2 + variables: {} + YAML + end + + # @return [String] + def input_processed_devfile_yaml_with_legacy_poststart_event + <<~YAML + --- + schemaVersion: 2.2.0 + metadata: {} + components: + - name: tooling-container + attributes: + gl/inject-editor: true + container: + image: quay.io/mloriedo/universal-developer-image:ubi8-dw-demo + args: + - "echo 'tooling container args'" + command: + - "/bin/sh" + - "-c" + volumeMounts: + - name: gl-workspace-data + path: /projects + env: + - name: GL_ENV_NAME + value: "gl-env-value" + endpoints: + - name: server + targetPort: 60001 + exposure: public + secure: true + protocol: https + dedicatedPod: false + mountSources: true + - name: sidecar-container + container: + image: "sidecar-container:latest" + volumeMounts: + - name: gl-workspace-data + path: "/projects" + env: + - name: GL_ENV2_NAME + value: "gl-env2-value" + args: + - "echo 'sidecar container args'" + command: + - "/bin/sh" + - "-c" + memoryLimit: 1000Mi + memoryRequest: 500Mi + cpuLimit: 500m + cpuRequest: 100m + - name: gl-workspace-data + volume: + size: 50Gi + commands: + - id: gl-internal-example-command-1 + exec: + commandLine: "echo 'gl-internal-example-command-1'" + component: tooling-container + - id: gl-internal-example-command-2 exec: - commandLine: "echo 'example poststart exec command'" + commandLine: "echo 'gl-internal-example-command-2'" component: tooling-container - id: example-prestart-apply-command apply: @@ -268,7 +356,8 @@ def input_processed_devfile_yaml_with_poststart_event preStart: - example-prestart-apply-command postStart: - - example-poststart-exec-command + - gl-internal-example-command-1 + - gl-internal-example-command-2 variables: {} YAML end @@ -537,7 +626,7 @@ def golden_master_desired_config_with_include_all_resources_true command: [ "/bin/sh", "-c", - "mkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\"/workspace-scripts/gl-run-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" + "#!/bin/sh\n\nmkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running poststart commands for workspace...\"\n\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running internal blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-internal-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\"\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running non-blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-non-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" ] } } @@ -855,8 +944,10 @@ def golden_master_desired_config_with_include_all_resources_true namespace: "gl-rd-ns-991-990-fedcba" }, data: { - "gl-run-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/example-poststart-exec-command...\"\n/workspace-scripts/example-poststart-exec-command || true\n", - "example-poststart-exec-command": "echo 'example poststart exec command'" + "gl-run-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\n", + "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\n", + "gl-internal-example-command-1": "echo 'gl-internal-example-command-1'", + "gl-internal-example-command-2": "echo 'gl-internal-example-command-2'" } }, { @@ -1115,7 +1206,7 @@ def golden_master_desired_config_with_include_all_resources_false command: [ "/bin/sh", "-c", - "mkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\"/workspace-scripts/gl-run-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" + "#!/bin/sh\n\nmkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running poststart commands for workspace...\"\n\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running internal blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-internal-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\"\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running non-blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-non-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" ] } } @@ -1433,8 +1524,589 @@ def golden_master_desired_config_with_include_all_resources_false namespace: "gl-rd-ns-991-990-fedcba" }, data: { - "gl-run-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/example-poststart-exec-command...\"\n/workspace-scripts/example-poststart-exec-command || true\n", - "example-poststart-exec-command": "echo 'example poststart exec command'" + "gl-run-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\n", + "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\n", + "gl-internal-example-command-1": "echo 'gl-internal-example-command-1'", + "gl-internal-example-command-2": "echo 'gl-internal-example-command-2'" + } + } + ] + end + + # @return [Array] + def golden_master_desired_config_from_legacy_devfile_with_poststart_and_with_include_all_resources_true + [ + { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991", + "cli-utils.sigs.k8s.io/inventory-id": "workspace-991-990-fedcba-workspace-inventory" + }, + name: "workspace-991-990-fedcba-workspace-inventory", + namespace: "gl-rd-ns-991-990-fedcba" + } + }, + { + apiVersion: "apps/v1", + kind: "Deployment", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + creationTimestamp: nil, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba", + namespace: "gl-rd-ns-991-990-fedcba" + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + } + }, + strategy: { + type: "Recreate" + }, + template: { + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + creationTimestamp: nil, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba", + namespace: "gl-rd-ns-991-990-fedcba" + }, + spec: + { + containers: [ + { + args: [ + "echo 'tooling container args'" + ], + command: [ + "/bin/sh", + "-c" + ], + env: [ + { + name: "GL_ENV_NAME", + value: "gl-env-value" + }, + { + name: "PROJECTS_ROOT", + value: "/projects" + }, + { + name: "PROJECT_SOURCE", + value: "/projects" + } + ], + envFrom: [ + { + secretRef: { + name: "workspace-991-990-fedcba-env-var" + } + } + ], + image: "quay.io/mloriedo/universal-developer-image:ubi8-dw-demo", + imagePullPolicy: "Always", + name: "tooling-container", + ports: [ + { + containerPort: 60001, + name: "server", + protocol: "TCP" + } + ], + resources: { + limits: { + cpu: "1", + memory: "1Gi" + }, + requests: { + cpu: "0.5", + memory: "512Mi" + } + }, + securityContext: { + allowPrivilegeEscalation: false, + privileged: false, + runAsNonRoot: true, + runAsUser: 5001 + }, + volumeMounts: [ + { + mountPath: "/projects", + name: "gl-workspace-data" + }, + { + mountPath: "/.workspace-data/variables/file", + name: "gl-workspace-variables" + }, + { + name: "gl-workspace-scripts", + mountPath: "/workspace-scripts" + } + ], + lifecycle: { + postStart: { + exec: { + command: [ + "/bin/sh", + "-c", + "#!/bin/sh\n\nmkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\"/workspace-scripts/gl-run-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\"\n" + ] + } + } + } + } + ], + initContainers: [ + { + args: [ + "echo 'sidecar container args'" + ], + command: [ + "/bin/sh", + "-c" + ], + env: [ + { + name: "GL_ENV2_NAME", + value: "gl-env2-value" + }, + { + name: "PROJECTS_ROOT", + value: "/projects" + }, + { + name: "PROJECT_SOURCE", + value: "/projects" + } + ], + envFrom: [ + { + secretRef: { + name: "workspace-991-990-fedcba-env-var" + } + } + ], + image: "sidecar-container:latest", + imagePullPolicy: "Always", + name: "sidecar-container-example-prestart-apply-command-1", + resources: { + limits: { + cpu: "500m", + memory: "1000Mi" + }, + requests: { + cpu: "100m", + memory: "500Mi" + } + }, + securityContext: { + allowPrivilegeEscalation: false, + privileged: false, + runAsNonRoot: true, + runAsUser: 5001 + }, + volumeMounts: [ + { + mountPath: "/projects", + name: "gl-workspace-data" + }, + { + mountPath: "/.workspace-data/variables/file", + name: "gl-workspace-variables" + } + ] + } + ], + runtimeClassName: "standard", + securityContext: { + fsGroup: 0, + fsGroupChangePolicy: "OnRootMismatch", + runAsNonRoot: true, + runAsUser: 5001 + }, + serviceAccountName: "workspace-991-990-fedcba", + volumes: [ + { + name: "gl-workspace-data", + persistentVolumeClaim: { + claimName: "workspace-991-990-fedcba-gl-workspace-data" + } + }, + { + name: "gl-workspace-variables", + projected: { + defaultMode: 0o774, + sources: [ + { + secret: { + name: "workspace-991-990-fedcba-file" + } + } + ] + } + }, + { + name: "gl-workspace-scripts", + projected: { + defaultMode: 0o555, + sources: [ + { + configMap: { + name: "workspace-991-990-fedcba-scripts-configmap" + } + } + ] + } + } + ] + } + } + }, + status: {} + }, + { + apiVersion: "v1", + kind: "Service", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + creationTimestamp: nil, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba", + namespace: "gl-rd-ns-991-990-fedcba" + }, + spec: { + ports: [ + { + name: "server", + port: 60001, + targetPort: 60001 + } + ], + selector: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + } + }, + status: { + loadBalancer: {} + } + }, + { + apiVersion: "v1", + kind: "PersistentVolumeClaim", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + creationTimestamp: nil, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba-gl-workspace-data", + namespace: "gl-rd-ns-991-990-fedcba" + }, + spec: { + accessModes: [ + "ReadWriteOnce" + ], + resources: { + requests: { + storage: "50Gi" + } + } + }, + status: {} + }, + { + apiVersion: "v1", + automountServiceAccountToken: false, + imagePullSecrets: [ + { + name: "registry-secret" + } + ], + kind: "ServiceAccount", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba", + namespace: "gl-rd-ns-991-990-fedcba" + } + }, + { + apiVersion: "networking.k8s.io/v1", + kind: "NetworkPolicy", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba", + namespace: "gl-rd-ns-991-990-fedcba" + }, + spec: { + egress: [ + { + ports: [ + { + port: 53, + protocol: "TCP" + }, + { + port: 53, + protocol: "UDP" + } + ], + to: [ + { + namespaceSelector: { + matchLabels: { + "kubernetes.io/metadata.name": "kube-system" + } + } + } + ] + }, + { + to: [ + { + ipBlock: { + cidr: "0.0.0.0/0", + except: [ + "10.0.0.0/8", + "172.16.0.0/12", + "192.168.0.0/16" + ] + } + } + ] + } + ], + ingress: [ + { + from: [ + { + namespaceSelector: { + matchLabels: { + "kubernetes.io/metadata.name": "gitlab-workspaces" + } + }, + podSelector: { + matchLabels: { + "app.kubernetes.io/name": "gitlab-workspaces-proxy" + } + } + } + ] + } + ], + podSelector: {}, + policyTypes: [ + "Ingress", + "Egress" + ] + } + }, + { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba-scripts-configmap", + namespace: "gl-rd-ns-991-990-fedcba" + }, + data: { + "gl-run-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\n", + "gl-internal-example-command-1": "echo 'gl-internal-example-command-1'", + "gl-internal-example-command-2": "echo 'gl-internal-example-command-2'" + } + }, + { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991", + "cli-utils.sigs.k8s.io/inventory-id": "workspace-991-990-fedcba-secrets-inventory" + }, + name: "workspace-991-990-fedcba-secrets-inventory", + namespace: "gl-rd-ns-991-990-fedcba" + } + }, + { + apiVersion: "v1", + kind: "ResourceQuota", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-workspace-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba", + namespace: "gl-rd-ns-991-990-fedcba" + }, + spec: { + hard: { + "limits.cpu": "2", + "limits.memory": "4Gi", + "requests.cpu": "1", + "requests.memory": "1Gi" + } + } + }, + { + apiVersion: "v1", + data: { + ENV_VAR1: "ZW52LXZhci12YWx1ZTE=" + }, + kind: "Secret", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-secrets-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba-env-var", + namespace: "gl-rd-ns-991-990-fedcba" + } + }, + { + apiVersion: "v1", + data: { + FILE_VAR1: "ZmlsZS12YXItdmFsdWUx", + "gl_workspace_reconciled_actual_state.txt": "UnVubmluZw==" + }, + kind: "Secret", + metadata: { + annotations: { + environment: "production", + team: "engineering", + "config.k8s.io/owning-inventory": "workspace-991-990-fedcba-secrets-inventory", + "workspaces.gitlab.com/host-template": "{{.port}}-workspace-991-990-fedcba.workspaces.localdev.me", + "workspaces.gitlab.com/id": "993", + "workspaces.gitlab.com/max-resources-per-workspace-sha256": "24aefc317e11db538ede450d1773e273966b9801b988d49e1219f2a9bf8e7f66" + }, + labels: { + app: "workspace", + tier: "development", + "agent.gitlab.com/id": "991" + }, + name: "workspace-991-990-fedcba-file", + namespace: "gl-rd-ns-991-990-fedcba" } } ] @@ -2169,7 +2841,7 @@ def golden_master_desired_config_for_shared_namespace_with_include_all_resources command: [ "/bin/sh", "-c", - "mkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\"/workspace-scripts/gl-run-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" + "#!/bin/sh\n\nmkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running poststart commands for workspace...\"\n\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running internal blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-internal-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\"\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running non-blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-non-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" ] } } @@ -2497,8 +3169,10 @@ def golden_master_desired_config_for_shared_namespace_with_include_all_resources namespace: "default" }, data: { - "gl-run-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/example-poststart-exec-command...\"\n/workspace-scripts/example-poststart-exec-command || true\n", - "example-poststart-exec-command": "echo 'example poststart exec command'" + "gl-run-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\n", + "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\n", + "gl-internal-example-command-1": "echo 'gl-internal-example-command-1'", + "gl-internal-example-command-2": "echo 'gl-internal-example-command-2'" } }, { @@ -2735,7 +3409,7 @@ def golden_master_desired_config_for_shared_namespace_with_include_all_resources command: [ "/bin/sh", "-c", - "mkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\"/workspace-scripts/gl-run-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" + "#!/bin/sh\n\nmkdir -p \"${GL_WORKSPACE_LOGS_DIR}\"\nln -sf \"${GL_WORKSPACE_LOGS_DIR}\" /tmp\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running poststart commands for workspace...\"\n\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running internal blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-internal-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\"\n\n{\n echo \"$(date -Iseconds): ----------------------------------------\"\n echo \"$(date -Iseconds): Running non-blocking poststart commands script...\"\n} >> \"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\"\n\n\"/workspace-scripts/gl-run-non-blocking-poststart-commands.sh\" 1>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stdout.log\" 2>>\"${GL_WORKSPACE_LOGS_DIR}/poststart-stderr.log\" &\n" ] } } @@ -3063,8 +3737,10 @@ def golden_master_desired_config_for_shared_namespace_with_include_all_resources namespace: "default" }, data: { - "gl-run-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/example-poststart-exec-command...\"\n/workspace-scripts/example-poststart-exec-command || true\n", - "example-poststart-exec-command": "echo 'example poststart exec command'" + "gl-run-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\n", + "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\n", + "gl-internal-example-command-1": "echo 'gl-internal-example-command-1'", + "gl-internal-example-command-2": "echo 'gl-internal-example-command-2'" } } ] diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_spec.rb index ee6e6b582a72c295dc5a455f40ac15a847b69fa5..871c71e3474a212507fbf4a0a85bda10acaa752d 100644 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/desired_config_generator_spec.rb @@ -16,7 +16,8 @@ let(:desired_state_is_terminated) { false } let(:include_all_resources) { false } let(:include_scripts_resources) { true } - let(:legacy_scripts_in_container_command) { false } + let(:legacy_no_poststart_container_command) { false } + let(:legacy_poststart_container_command) { false } let(:deployment_resource_version_from_agent) { workspace.deployment_resource_version } let(:network_policy_enabled) { true } let(:gitlab_workspaces_proxy_namespace) { 'gitlab-workspaces' } @@ -59,7 +60,8 @@ include_network_policy: workspace.workspaces_agent_config.network_policy_enabled, include_all_resources: include_all_resources, include_scripts_resources: include_scripts_resources, - legacy_scripts_in_container_command: legacy_scripts_in_container_command, + legacy_no_poststart_container_command: legacy_no_poststart_container_command, + legacy_poststart_container_command: legacy_poststart_container_command, egress_ip_rules: workspace.workspaces_agent_config.network_policy_egress.map(&:deep_symbolize_keys), max_resources_per_workspace: max_resources_per_workspace, default_resources_per_workspace_container: default_resources_per_workspace_container, @@ -245,11 +247,22 @@ end end + context "when legacy postStart events are present in devfile" do + let(:legacy_poststart_container_command) { true } + let(:processed_devfile_yaml) do + read_devfile_yaml("example.legacy-poststart-in-container-command-processed-devfile.yaml.erb") + end + + it 'returns expected config without script resources' do + expect(workspace_resources).to eq(expected_config) + end + end + context "when postStart events are not present in devfile" do let(:include_scripts_resources) { false } - let(:legacy_scripts_in_container_command) { true } + let(:legacy_no_poststart_container_command) { true } let(:processed_devfile_yaml) do - read_devfile_yaml("example.legacy-scripts-in-container-command-processed-devfile.yaml.erb") + read_devfile_yaml("example.legacy-no-poststart-in-container-command-processed-devfile.yaml.erb") end it 'returns expected config without script resources' do diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter_spec.rb index c562a5a17c82d1bb0cbc6642358a1a2b59e44211..de667b3c3fde197ba8b2cd6c92d0bdb219b4dfbf 100644 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/kubernetes_poststart_hook_inserter_spec.rb @@ -8,8 +8,12 @@ let(:processed_devfile) { example_processed_devfile } let(:devfile_commands) { processed_devfile.fetch(:commands) } let(:devfile_events) { processed_devfile.fetch(:events) } + let(:legacy_poststart_container_command) { false } let(:input_containers) do - deployment = create_deployment(include_scripts_resources: false) + deployment = create_deployment( + include_scripts_resources: false, + legacy_poststart_container_command: legacy_poststart_container_command + ) deployment => { spec: { template: { @@ -23,7 +27,10 @@ end let(:expected_containers) do - deployment = create_deployment(include_scripts_resources: true) + deployment = create_deployment( + include_scripts_resources: true, + legacy_poststart_container_command: legacy_poststart_container_command + ) deployment => { spec: { template: { @@ -45,41 +52,58 @@ ) end + shared_examples "successful insertion of postStart lifecycle hooks" do + it "inserts postStart lifecycle hooks", :unlimited_max_formatted_output_length do + invoke_insert + + expected_containers => [ + *_, + { + lifecycle: Hash => first_container_expected_lifecycle_hooks + }, + *_ + ] + + input_containers => [ + *_, + { + lifecycle: Hash => first_container_updated_lifecycle_hooks + }, + *_ + ] + + expect(first_container_updated_lifecycle_hooks).to eq(first_container_expected_lifecycle_hooks) + end + end + it "has valid fixtures with no lifecycle in any input_containers" do expect(input_containers.any? { |c| c[:lifecycle] }).to be false end - it "inserts postStart lifecycle hooks", :unlimited_max_formatted_output_length do - invoke_insert - - expected_containers => [ - *_, - { - lifecycle: Hash => first_container_expected_lifecycle_hooks - }, - *_ - ] + it_behaves_like "successful insertion of postStart lifecycle hooks" - input_containers => [ - *_, - { - lifecycle: Hash => first_container_updated_lifecycle_hooks - }, - *_ - ] + context "when legacy poststart scripts are used" do + let(:legacy_poststart_container_command) { true } + let(:processed_devfile) do + yaml_safe_load_symbolized( + read_devfile_yaml("example.legacy-poststart-in-container-command-processed-devfile.yaml.erb") + ) + end - expect(first_container_updated_lifecycle_hooks).to eq(first_container_expected_lifecycle_hooks) + it_behaves_like "successful insertion of postStart lifecycle hooks" end private # @param [Boolean] include_scripts_resources + # # @param [Boolean] legacy_poststart_container_command # @return [Hash] - def create_deployment(include_scripts_resources:) + def create_deployment(include_scripts_resources:, legacy_poststart_container_command:) workspace_deployment( workspace_name: "name", workspace_namespace: "namespace", - include_scripts_resources: include_scripts_resources + include_scripts_resources: include_scripts_resources, + legacy_poststart_container_command: legacy_poststart_container_command ) end end diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender_spec.rb index f9e81477315d17aefdec09fdc6630b8abac26e2f..23c9eca6be6a3cc184f48c107118150f9de1bde0 100644 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/scripts_configmap_appender_spec.rb @@ -52,11 +52,48 @@ expect(data).to eq( "gl-clone-project-command": clone_project_script, "gl-init-tools-command": files::INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, - reconcile_constants_module::RUN_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => - postart_commands_script, + reconcile_constants_module::RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => + internal_blocking_poststart_commands_script, + reconcile_constants_module::RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => + non_blocking_poststart_commands_script, "gl-sleep-until-container-is-running-command": sleep_until_container_is_running_script, "gl-start-sshd-command": files::INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT ) end + + context "when legacy poststart scripts are used" do + let(:processed_devfile) do + yaml_safe_load_symbolized( + read_devfile_yaml("example.legacy-poststart-in-container-command-processed-devfile.yaml.erb") + ) + end + + it "appends ConfigMap to desired_config" do + expect(updated_desired_config.length).to eq(2) + + updated_desired_config => [ + {}, # existing fake element + { + apiVersion: api_version, + metadata: { + name: configmap_name + }, + data: data + }, + ] + + expect(api_version).to eq("v1") + expect(configmap_name).to eq(name) + expect(data).to eq( + "gl-clone-project-command": clone_project_script, + "gl-init-tools-command": files::INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, + reconcile_constants_module::LEGACY_RUN_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => + legacy_poststart_commands_script, + "gl-sleep-until-container-is-running-command": + sleep_until_container_is_running_script, + "gl-start-sshd-command": files::INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT + ) + end + end end diff --git a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb index 8f96456bef6160288021e3066f00ca66ee6dc2e0..95232f6bc5ec62950487c0bea98b5f9481b7ffda 100644 --- a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb +++ b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb @@ -354,7 +354,7 @@ def create_config_to_apply(workspace:, **args) # @param [String] namespace_path # @param [Array] image_pull_secrets # @param [Boolean] include_scripts_resources - # @param [Boolean] legacy_scripts_in_container_command + # @param [Boolean] legacy_no_poststart_container_command # @param [String] shared_namespace # @param [Boolean] core_resources_only # @return [Array] @@ -384,7 +384,8 @@ def create_config_to_apply_v3( namespace_path: "test-group", image_pull_secrets: [], include_scripts_resources: true, - legacy_scripts_in_container_command: false, + legacy_no_poststart_container_command: false, + legacy_poststart_container_command: false, shared_namespace: "", core_resources_only: false ) @@ -436,7 +437,8 @@ def create_config_to_apply_v3( use_kubernetes_user_namespaces: use_kubernetes_user_namespaces, default_runtime_class: default_runtime_class, include_scripts_resources: include_scripts_resources, - legacy_scripts_in_container_command: legacy_scripts_in_container_command + legacy_no_poststart_container_command: legacy_no_poststart_container_command, + legacy_poststart_container_command: legacy_poststart_container_command ) workspace_service = workspace_service( @@ -473,7 +475,8 @@ def create_config_to_apply_v3( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: workspace_inventory_annotations + annotations: workspace_inventory_annotations, + legacy_poststart_container_command: legacy_poststart_container_command ) secrets_inventory_config_map = secrets_inventory_config_map( @@ -580,7 +583,8 @@ def workspace_inventory_config_map(workspace_name:, workspace_namespace:, labels # @param [Hash] default_resources_per_workspace_container # @param [String] default_runtime_class # @param [Boolean] include_scripts_resources - # @param [Boolean] legacy_scripts_in_container_command + # @param [Boolean] legacy_no_poststart_container_command + # @param [Boolean] legacy_poststart_container_command # @param [Hash] labels # @param [Integer] spec_replicas # @param [Boolean] use_kubernetes_user_namespaces @@ -593,7 +597,8 @@ def workspace_deployment( default_resources_per_workspace_container: {}, default_runtime_class: "", include_scripts_resources: true, - legacy_scripts_in_container_command: false, + legacy_no_poststart_container_command: false, + legacy_poststart_container_command: false, labels: {}, spec_replicas: 1, use_kubernetes_user_namespaces: false @@ -715,9 +720,12 @@ def workspace_deployment( "-c", format( files_module::KUBERNETES_POSTSTART_HOOK_COMMAND, - run_poststart_commands_script_file_path: + run_internal_blocking_poststart_commands_script_file_path: + "#{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/" \ + "#{reconcile_constants_module::RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME}", # rubocop:disable Layout/LineEndStringConcatenationIndentation -- Match default RubyMine formatting + run_non_blocking_poststart_commands_script_file_path: "#{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/" \ - "#{reconcile_constants_module::RUN_POSTSTART_COMMANDS_SCRIPT_NAME}" # rubocop:disable Layout/LineEndStringConcatenationIndentation -- Match default RubyMien formatting + "#{reconcile_constants_module::RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME}" # rubocop:disable Layout/LineEndStringConcatenationIndentation -- Match default RubyMine formatting ) ] } @@ -876,7 +884,26 @@ def workspace_deployment( deployment[:spec][:template][:spec][:containers][0].delete(:lifecycle) end - if legacy_scripts_in_container_command + if legacy_poststart_container_command + deployment[:spec][:template][:spec][:containers][0][:lifecycle] = { + postStart: { + exec: { + command: [ + "/bin/sh", + "-c", + format( + files_module::KUBERNETES_LEGACY_POSTSTART_HOOK_COMMAND, + run_internal_blocking_poststart_commands_script_file_path: + "#{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/" \ + "#{reconcile_constants_module::LEGACY_RUN_POSTSTART_COMMANDS_SCRIPT_NAME}" # rubocop:disable Layout/LineEndStringConcatenationIndentation -- Match default RubyMine formatting + ) + ] + } + } + } + end + + if legacy_no_poststart_container_command # Add the container args for the container where tools are injected deployment[:spec][:template][:spec][:containers][0][:args][0] = <<~YAML.chomp @@ -1130,7 +1157,28 @@ def workspace_network_policy( end # @return [String] - def postart_commands_script + def internal_blocking_poststart_commands_script + <<~SCRIPT + #!/bin/sh + echo "$(date -Iseconds): Running #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-clone-project-command..." + #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-clone-project-command || true + echo "$(date -Iseconds): Running #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-start-sshd-command..." + #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-start-sshd-command || true + echo "$(date -Iseconds): Running #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-init-tools-command..." + #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-init-tools-command || true + SCRIPT + end + + # @return [String] + def non_blocking_poststart_commands_script + <<~SCRIPT + #!/bin/sh + echo "$(date -Iseconds): Running #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-sleep-until-container-is-running-command..." + #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-sleep-until-container-is-running-command || true + SCRIPT + end + + def legacy_poststart_commands_script <<~SCRIPT #!/bin/sh echo "$(date -Iseconds): Running #{reconcile_constants_module::WORKSPACE_SCRIPTS_VOLUME_PATH}/gl-clone-project-command..." @@ -1173,8 +1221,33 @@ def sleep_until_container_is_running_script # @param [String] workspace_namespace # @param [Hash] labels # @param [Hash] annotations + # @param [Boolean] legacy_poststart_container_command # @return [Hash] - def scripts_configmap(workspace_name:, workspace_namespace:, labels:, annotations:) + def scripts_configmap( + workspace_name:, + workspace_namespace:, + labels:, + annotations:, + legacy_poststart_container_command: + ) + data = { + "gl-clone-project-command": clone_project_script, + "gl-init-tools-command": files_module::INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, + reconcile_constants_module::RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => + internal_blocking_poststart_commands_script, + reconcile_constants_module::RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => + non_blocking_poststart_commands_script, + "gl-sleep-until-container-is-running-command": sleep_until_container_is_running_script, + "gl-start-sshd-command": files_module::INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT + } + + if legacy_poststart_container_command + data.delete(reconcile_constants_module::RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym) + data.delete(reconcile_constants_module::RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym) + data[reconcile_constants_module::LEGACY_RUN_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym] = + legacy_poststart_commands_script + end + { apiVersion: "v1", kind: "ConfigMap", @@ -1184,13 +1257,7 @@ def scripts_configmap(workspace_name:, workspace_namespace:, labels:, annotation name: "#{workspace_name}-scripts-configmap", namespace: workspace_namespace }, - data: { - "gl-clone-project-command": clone_project_script, - "gl-init-tools-command": files_module::INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, - reconcile_constants_module::RUN_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => postart_commands_script, - "gl-sleep-until-container-is-running-command": sleep_until_container_is_running_script, - "gl-start-sshd-command": files_module::INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT - } + data: data } end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4c99d733850ec074ada237e4898304113a8febfc..a7e347d09f4706f385f95197dde5f4732b97e160 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -35791,6 +35791,9 @@ msgstr[1] "" msgid "Label %{labelName} was not found" msgstr "" +msgid "Label '%{command_label}' for command id '%{command}' must not start with '%{prefix}'" +msgstr "" + msgid "Label actions dropdown" msgstr ""