From 3b36041fdf6957d639ace9f108ea8289ffbb7767 Mon Sep 17 00:00:00 2001 From: Ashvin Sharma Date: Tue, 9 Sep 2025 01:52:23 +0530 Subject: [PATCH] Remove all shadow run related files from reconcile module These files were introduced for shadow run to freeze desired_config in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/194589 and are no longer needed. --- .../create/workspace_agentk_state_creator.rb | 21 +- .../config_to_apply_shadow_run_handler.rb | 72 - .../output/old_config_values_extractor.rb | 111 - .../output/old_desired_config_generator.rb | 526 --- .../reconcile/output/old_devfile_parser.rb | 262 -- .../output/old_scripts_configmap_appender.rb | 165 - .../output/response_payload_builder.rb | 9 - .../remote_development/workspaces.rb | 38 +- ...config_to_apply_shadow_run_handler_spec.rb | 58 - .../old_config_values_extractor_spec.rb | 269 -- ...red_config_generator_golden_master_spec.rb | 3754 ----------------- .../old_desired_config_generator_spec.rb | 374 -- .../output/old_devfile_parser_spec.rb | 247 -- .../old_scripts_configmap_appender_spec.rb | 101 - .../output/response_payload_builder_spec.rb | 12 - .../remote_development_shared_contexts.rb | 29 +- 16 files changed, 50 insertions(+), 5998 deletions(-) delete mode 100644 ee/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler.rb delete mode 100644 ee/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor.rb delete mode 100644 ee/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator.rb delete mode 100644 ee/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser.rb delete mode 100644 ee/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender.rb delete mode 100644 ee/spec/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler_spec.rb delete mode 100644 ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor_spec.rb delete mode 100644 ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_golden_master_spec.rb delete mode 100644 ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_spec.rb delete mode 100644 ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser_spec.rb delete mode 100644 ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender_spec.rb diff --git a/ee/lib/remote_development/workspace_operations/create/workspace_agentk_state_creator.rb b/ee/lib/remote_development/workspace_operations/create/workspace_agentk_state_creator.rb index a722532764f3bf..6e323dd78dc4af 100644 --- a/ee/lib/remote_development/workspace_operations/create/workspace_agentk_state_creator.rb +++ b/ee/lib/remote_development/workspace_operations/create/workspace_agentk_state_creator.rb @@ -25,19 +25,16 @@ def self.create(context) ) end - # TODO: Enable it on production by the end of the epic https://gitlab.com/groups/gitlab-org/-/epics/17483 - if Rails.env.test? - workspace_agentk_state = WorkspaceAgentkState.create!( - workspace: workspace, - project: workspace.project, - desired_config: desired_config.symbolized_desired_config_array - ) + workspace_agentk_state = WorkspaceAgentkState.create!( + workspace: workspace, + project: workspace.project, + desired_config: desired_config.symbolized_desired_config_array + ) - if workspace_agentk_state.errors.present? - return Gitlab::Fp::Result.err( - WorkspaceAgentkStateCreateFailed.new({ errors: workspace_agentk_state.errors, context: context }) - ) - end + if workspace_agentk_state.errors.present? + return Gitlab::Fp::Result.err( + WorkspaceAgentkStateCreateFailed.new({ errors: workspace_agentk_state.errors, context: context }) + ) end Gitlab::Fp::Result.ok(context) diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler.rb deleted file mode 100644 index cebe5800fb7b80..00000000000000 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler.rb +++ /dev/null @@ -1,72 +0,0 @@ -# frozen_string_literal: true - -module RemoteDevelopment - module WorkspaceOperations - module Reconcile - module Output - # TODO This class will be removed after the succesfull shadow run of Create::DesiredConfig::Main - # Epic- https://gitlab.com/groups/gitlab-org/-/epics/17483 - # This class handles the scenarios where the new desired config generator returns a different result - # than the old one. In this case we will log a warning and use the old desired - # config generator instead. - class ConfigToApplyShadowRunHandler - include WorkspaceOperationsConstants - - # @param [RemoteDevelopment::Workspace] workspace - # @param [Array] new_config_to_apply_array - # @param [RemoteDevelopment::Logger] logger - # @param [Boolean] include_all_resources - # @return [Array] - def self.handle(workspace:, new_config_to_apply_array:, logger:, include_all_resources:) - old_config_to_apply_array = OldDesiredConfigGenerator.generate_desired_config( - workspace: workspace, - include_all_resources: include_all_resources, - logger: logger - ) - diffable_new_config_to_apply_array = generate_diffable_new_config_to_apply_array( - new_config_to_apply_array: new_config_to_apply_array - ) - - old_config_to_apply = DesiredConfig.new(desired_config_array: old_config_to_apply_array) - new_config_to_apply = DesiredConfig.new(desired_config_array: diffable_new_config_to_apply_array) - diff = new_config_to_apply.diff(old_config_to_apply) - unless diff.empty? - logger.warn( - message: "The generated config_to_apply from Create::DesiredConfig::Main and " \ - "OldDesiredConfigGenerator differ.", - error_type: "workspaces_reconcile_desired_configs_differ", - workspace_id: workspace.id, - diff: diff - ) - end - - old_config_to_apply_array - end - - # @param [Array] new_config_to_apply_array - # @return [Array] - def self.generate_diffable_new_config_to_apply_array(new_config_to_apply_array:) - new_config_to_apply_array.map do |original_resource| - # Ensure we don't mutate the original resource, to avoid testing confusion - resource = original_resource.deep_dup - - annotations = resource.dig(:metadata, :annotations) - next resource unless annotations - - resource[:metadata][:annotations].delete(ANNOTATION_KEY_INCLUDE_IN_PARTIAL_RECONCILIATION) - - if resource[:kind] == "Deployment" - resource[:spec][:template][:metadata][:annotations].delete( - ANNOTATION_KEY_INCLUDE_IN_PARTIAL_RECONCILIATION) - end - - resource - end - end - - private_class_method :generate_diffable_new_config_to_apply_array - end - end - end - end -end diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor.rb deleted file mode 100644 index de5ec9babd80e1..00000000000000 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor.rb +++ /dev/null @@ -1,111 +0,0 @@ -# frozen_string_literal: true - -module RemoteDevelopment - module WorkspaceOperations - module Reconcile - module Output - class OldConfigValuesExtractor - include States - - # @param [RemoteDevelopment::Workspace] workspace - # @return [Hash] - def self.extract(workspace:) - workspace_name = workspace.name - workspaces_agent_config = workspace.workspaces_agent_config - - domain_template = "{{.port}}-#{workspace_name}.#{workspaces_agent_config.dns_zone}" - - max_resources_per_workspace = - deep_sort_and_symbolize_hashes(workspaces_agent_config.max_resources_per_workspace) - - # NOTE: In order to prevent unwanted restarts of the workspace, we need to ensure that the hexdigest - # of the max_resources_per_workspace is backward compatible, and uses the same sorting as the - # legacy logic of existing running workspaces. This means that only the top level keys are sorted, - # not the nested hashes. But everywhere else we will use the deeply sorted version. This workaround - # can be removed if we move all of this logic from workspace reconcile-time to create-time. - # Also note that the value has always been deep_symbolized before #to_s, so we preserve that as well. - max_resources_per_workspace_sha256_with_legacy_sorting = - OpenSSL::Digest::SHA256.hexdigest( - workspaces_agent_config.max_resources_per_workspace.deep_symbolize_keys.sort.to_h.to_s - ) - - default_resources_per_workspace_container = - deep_sort_and_symbolize_hashes(workspaces_agent_config.default_resources_per_workspace_container) - - shared_namespace = workspaces_agent_config.shared_namespace - # TODO: Fix this as part of https://gitlab.com/gitlab-org/gitlab/-/issues/541902 - shared_namespace = "" if shared_namespace.nil? - - extra_annotations = { - "workspaces.gitlab.com/host-template": domain_template.to_s, - "workspaces.gitlab.com/id": workspace.id.to_s, - # NOTE: This annotation is added to cause the workspace to restart whenever the max resources change - "workspaces.gitlab.com/max-resources-per-workspace-sha256": - max_resources_per_workspace_sha256_with_legacy_sorting - } - agent_annotations = workspaces_agent_config.annotations - common_annotations = agent_annotations.merge(extra_annotations) - - agent_labels = workspaces_agent_config.labels - labels = agent_labels.merge({ "agent.gitlab.com/id": workspace.agent.id.to_s }) - # TODO: Unconditionally add this label in https://gitlab.com/gitlab-org/gitlab/-/issues/535197 - labels["workspaces.gitlab.com/id"] = workspace.id.to_s if shared_namespace.present? - - workspace_inventory_name = "#{workspace_name}-workspace-inventory" - secrets_inventory_name = "#{workspace_name}-secrets-inventory" - scripts_configmap_name = "#{workspace_name}-scripts-configmap" - - { - # Please keep alphabetized - allow_privilege_escalation: workspaces_agent_config.allow_privilege_escalation, - common_annotations: deep_sort_and_symbolize_hashes(common_annotations), - default_resources_per_workspace_container: - default_resources_per_workspace_container, - default_runtime_class: workspaces_agent_config.default_runtime_class, - domain_template: domain_template, - # NOTE: update env_secret_name to "#{workspace.name}-environment". This is to ensure naming consistency. - # Changing it now would require migration from old config version to a new one. - # Update this when a new desired config generator is created for some other reason. - env_secret_name: "#{workspace_name}-env-var", - file_secret_name: "#{workspace_name}-file", - gitlab_workspaces_proxy_namespace: workspaces_agent_config.gitlab_workspaces_proxy_namespace, - image_pull_secrets: deep_sort_and_symbolize_hashes(workspaces_agent_config.image_pull_secrets), - labels: deep_sort_and_symbolize_hashes(labels), - max_resources_per_workspace: max_resources_per_workspace, - network_policy_enabled: workspaces_agent_config.network_policy_enabled, - network_policy_egress: deep_sort_and_symbolize_hashes(workspaces_agent_config.network_policy_egress), - processed_devfile_yaml: workspace.processed_devfile, - replicas: workspace.desired_state_running? ? 1 : 0, - scripts_configmap_name: scripts_configmap_name, - secrets_inventory_annotations: - deep_sort_and_symbolize_hashes( - common_annotations.merge("config.k8s.io/owning-inventory": secrets_inventory_name) - ), - secrets_inventory_name: secrets_inventory_name, - shared_namespace: shared_namespace, - use_kubernetes_user_namespaces: workspaces_agent_config.use_kubernetes_user_namespaces, - workspace_inventory_annotations: - deep_sort_and_symbolize_hashes( - common_annotations.merge("config.k8s.io/owning-inventory": workspace_inventory_name) - ), - workspace_inventory_name: workspace_inventory_name - } - end - - # @param [Array, Hash] collection - # @return [Array, Hash] - def self.deep_sort_and_symbolize_hashes(collection) - collection_to_return = Gitlab::Utils.deep_sort_hashes(collection) - - # NOTE: deep_symbolize_keys! is not available on Array, so we wrap the collection in a - # Hash in case it is an Array. - { to_symbolize: collection_to_return }.deep_symbolize_keys! - collection_to_return - end - - private_class_method :deep_sort_and_symbolize_hashes - end - end - end - end -end diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator.rb deleted file mode 100644 index 80ccb4761278c2..00000000000000 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator.rb +++ /dev/null @@ -1,526 +0,0 @@ -# frozen_string_literal: true - -module RemoteDevelopment - module WorkspaceOperations - module Reconcile - module Output - # TODO this file is marked for deletion by the end of this epic https://gitlab.com/groups/gitlab-org/-/epics/17483 - class OldDesiredConfigGenerator - include Create::CreateConstants - - # @param [RemoteDevelopment::Workspace] workspace - # @param [Boolean] include_all_resources - # @param [RemoteDevelopment::Logger] logger - # @return [Array] - def self.generate_desired_config(workspace:, include_all_resources:, logger:) - config_values_extractor_result = OldConfigValuesExtractor.extract(workspace: workspace) - config_values_extractor_result => { - allow_privilege_escalation: TrueClass | FalseClass => allow_privilege_escalation, - common_annotations: Hash => common_annotations, - default_resources_per_workspace_container: Hash => default_resources_per_workspace_container, - default_runtime_class: String => default_runtime_class, - domain_template: String => domain_template, - env_secret_name: String => env_secret_name, - file_secret_name: String => file_secret_name, - gitlab_workspaces_proxy_namespace: String => gitlab_workspaces_proxy_namespace, - image_pull_secrets: Array => image_pull_secrets, - labels: Hash => labels, - max_resources_per_workspace: Hash => max_resources_per_workspace, - network_policy_enabled: TrueClass | FalseClass => network_policy_enabled, - network_policy_egress: Array => network_policy_egress, - processed_devfile_yaml: String => processed_devfile_yaml, - replicas: Integer => replicas, - scripts_configmap_name: scripts_configmap_name, - secrets_inventory_annotations: Hash => secrets_inventory_annotations, - secrets_inventory_name: String => secrets_inventory_name, - shared_namespace: String => shared_namespace, - use_kubernetes_user_namespaces: TrueClass | FalseClass => use_kubernetes_user_namespaces, - workspace_inventory_annotations: Hash => workspace_inventory_annotations, - workspace_inventory_name: String => workspace_inventory_name, - } - - desired_config = [] - - append_inventory_config_map( - desired_config: desired_config, - name: workspace_inventory_name, - namespace: workspace.namespace, - labels: labels, - annotations: common_annotations - ) - - if workspace.desired_state_terminated? - append_inventory_config_map( - desired_config: desired_config, - name: secrets_inventory_name, - namespace: workspace.namespace, - labels: labels, - annotations: common_annotations - ) - - return desired_config - end - - devfile_parser_params = { - allow_privilege_escalation: allow_privilege_escalation, - annotations: workspace_inventory_annotations, - default_resources_per_workspace_container: default_resources_per_workspace_container, - default_runtime_class: default_runtime_class, - domain_template: domain_template, - env_secret_names: [env_secret_name], - file_secret_names: [file_secret_name], - labels: labels, - name: workspace.name, - namespace: workspace.namespace, - replicas: replicas, - service_account_name: workspace.name, - use_kubernetes_user_namespaces: use_kubernetes_user_namespaces - } - - resources_from_devfile_parser = OldDevfileParser.get_all( - processed_devfile_yaml: processed_devfile_yaml, - params: devfile_parser_params, - logger: logger - ) - - # If we got no resources back from the devfile parser, this indicates some error was encountered in parsing - # the processed_devfile. So we return an empty array which will result in no updates being applied by the - # agent. We should not continue on and try to add anything else to the resources, as this would result - # in an invalid configuration being applied to the cluster. - return [] if resources_from_devfile_parser.empty? - - desired_config.append(*resources_from_devfile_parser) - - append_image_pull_secrets_service_account( - desired_config: desired_config, - name: workspace.name, - namespace: workspace.namespace, - image_pull_secrets: image_pull_secrets, - labels: labels, - annotations: workspace_inventory_annotations - ) - - append_network_policy( - desired_config: desired_config, - name: workspace.name, - namespace: workspace.namespace, - gitlab_workspaces_proxy_namespace: gitlab_workspaces_proxy_namespace, - network_policy_enabled: network_policy_enabled, - network_policy_egress: network_policy_egress, - labels: labels, - annotations: workspace_inventory_annotations - ) - - append_scripts_resources( - desired_config: desired_config, - processed_devfile_yaml: processed_devfile_yaml, - name: scripts_configmap_name, - namespace: workspace.namespace, - labels: labels, - annotations: workspace_inventory_annotations - ) - - return desired_config unless include_all_resources - - append_inventory_config_map( - desired_config: desired_config, - name: secrets_inventory_name, - namespace: workspace.namespace, - labels: labels, - annotations: common_annotations - ) - - append_resource_quota( - desired_config: desired_config, - name: workspace.name, - namespace: workspace.namespace, - labels: labels, - annotations: workspace_inventory_annotations, - max_resources_per_workspace: max_resources_per_workspace, - shared_namespace: shared_namespace - ) - - append_secret( - desired_config: desired_config, - name: env_secret_name, - namespace: workspace.namespace, - labels: labels, - annotations: secrets_inventory_annotations - ) - - append_secret_data_from_variables( - desired_config: desired_config, - secret_name: env_secret_name, - variables: workspace.workspace_variables.with_variable_type_environment - ) - - append_secret( - desired_config: desired_config, - name: file_secret_name, - namespace: workspace.namespace, - labels: labels, - annotations: secrets_inventory_annotations - ) - - append_secret_data_from_variables( - desired_config: desired_config, - secret_name: file_secret_name, - variables: workspace.workspace_variables.with_variable_type_file - ) - - append_secret_data( - desired_config: desired_config, - secret_name: file_secret_name, - data: { WORKSPACE_RECONCILED_ACTUAL_STATE_FILE_NAME.to_sym => workspace.actual_state } - ) - - desired_config - end - - # @param [Array] desired_config - # @param [String] name - # @param [String] namespace - # @param [Hash] labels - # @param [Hash] annotations - # @return [void] - def self.append_inventory_config_map( - desired_config:, - name:, - namespace:, - labels:, - annotations: - ) - extra_labels = { "cli-utils.sigs.k8s.io/inventory-id": name } - - config_map = { - kind: "ConfigMap", - apiVersion: "v1", - metadata: { - name: name, - namespace: namespace, - labels: labels.merge(extra_labels), - annotations: annotations - } - } - - desired_config.append(config_map) - - nil - end - - # @param [Array] desired_config - # @param [String] name - # @param [String] namespace - # @param [Hash] labels - # @param [Hash] annotations - # @return [void] - def self.append_secret(desired_config:, name:, namespace:, labels:, annotations:) - secret = { - kind: "Secret", - apiVersion: "v1", - metadata: { - name: name, - namespace: namespace, - labels: labels, - annotations: annotations - }, - data: {} - } - - desired_config.append(secret) - - nil - end - - # @param [Array] desired_config - # @param [String] secret_name - # @param [ActiveRecord::Relation] variables - # @return [void] - def self.append_secret_data_from_variables(desired_config:, secret_name:, variables:) - data = variables.each_with_object({}) do |workspace_variable, hash| - hash[workspace_variable.key.to_sym] = workspace_variable.value - end - - append_secret_data( - desired_config: desired_config, - secret_name: secret_name, - data: data - ) - - nil - end - - # @param [Array] desired_config - # @param [String] secret_name - # @param [Hash] data - # @return [void] - # noinspection RubyUnusedLocalVariable -- Rubymine doesn't recognize '^' to use a variable in pattern-matching - def self.append_secret_data(desired_config:, secret_name:, data:) - desired_config => [ - *_, - { - metadata: { - name: ^secret_name - }, - data: secret_data - }, - *_ - ] - - transformed_data = data.transform_values { |value| Base64.strict_encode64(value) } - - secret_data.merge!(transformed_data) - - nil - end - - # @param [Array] desired_config - # @param [String] gitlab_workspaces_proxy_namespace - # @param [String] name - # @param [String] namespace - # @param [Boolean] network_policy_enabled - # @param [Array] network_policy_egress - # @param [Hash] labels - # @param [Hash] annotations - # @return [void] - def self.append_network_policy( - desired_config:, - name:, - namespace:, - gitlab_workspaces_proxy_namespace:, - network_policy_enabled:, - network_policy_egress:, - labels:, - annotations: - ) - return unless network_policy_enabled - - egress_ip_rules = network_policy_egress - - policy_types = %w[Ingress Egress] - - proxy_namespace_selector = { - matchLabels: { - "kubernetes.io/metadata.name": gitlab_workspaces_proxy_namespace - } - } - proxy_pod_selector = { - matchLabels: { - "app.kubernetes.io/name": "gitlab-workspaces-proxy" - } - } - ingress = [{ from: [{ namespaceSelector: proxy_namespace_selector, podSelector: proxy_pod_selector }] }] - - kube_system_namespace_selector = { - matchLabels: { - "kubernetes.io/metadata.name": "kube-system" - } - } - egress = [ - { - ports: [{ port: 53, protocol: "TCP" }, { port: 53, protocol: "UDP" }], - to: [{ namespaceSelector: kube_system_namespace_selector }] - } - ] - egress_ip_rules.each do |egress_rule| - egress.append( - { to: [{ ipBlock: { cidr: egress_rule[:allow], except: egress_rule[:except] } }] } - ) - end - - # Use the workspace_id as a pod selector if it is present - workspace_id = labels.fetch(:"workspaces.gitlab.com/id", nil) - pod_selector = {} - # TODO: Unconditionally add this pod selector in https://gitlab.com/gitlab-org/gitlab/-/issues/535197 - if workspace_id.present? - pod_selector[:matchLabels] = { - "workspaces.gitlab.com/id": workspace_id - } - end - - network_policy = { - apiVersion: "networking.k8s.io/v1", - kind: "NetworkPolicy", - metadata: { - annotations: annotations, - labels: labels, - name: name, - namespace: namespace - }, - spec: { - egress: egress, - ingress: ingress, - podSelector: pod_selector, - policyTypes: policy_types - } - } - - desired_config.append(network_policy) - - nil - end - - # @param [Array] desired_config - # @param [String] processed_devfile_yaml - # @param [String] name - # @param [String] namespace - # @param [Hash] labels - # @param [Hash] annotations - # @return [void] - def self.append_scripts_resources( - desired_config:, - processed_devfile_yaml:, - name:, - namespace:, - labels:, - annotations: - ) - desired_config => [ - *_, - { - kind: "Deployment", - spec: { - template: { - spec: { - containers: Array => containers, - volumes: Array => volumes - } - } - } - }, - *_ - ] - - processed_devfile = YAML.safe_load(processed_devfile_yaml).deep_symbolize_keys.to_h - - devfile_commands = processed_devfile.fetch(:commands) - devfile_events = processed_devfile.fetch(:events) - - # NOTE: This guard clause ensures we still support older running workspaces which were started before we - # added support for devfile postStart events. In that case, we don't want to add any resources - # related to the postStart script handling, because that would cause those existing workspaces - # to restart because the deployment would be updated. - return unless devfile_events[:postStart].present? - - OldScriptsConfigmapAppender.append( - desired_config: desired_config, - name: name, - namespace: namespace, - labels: labels, - annotations: annotations, - devfile_commands: devfile_commands, - devfile_events: devfile_events - ) - - Create::DesiredConfig::ScriptsVolumeInserter.insert( - configmap_name: name, - containers: containers, - volumes: volumes - ) - - Create::DesiredConfig::KubernetesPoststartHookInserter.insert( - containers: containers, - devfile_commands: devfile_commands, - devfile_events: devfile_events - ) - - nil - end - - # @param [Array] desired_config - # @param [String] name - # @param [String] namespace - # @param [Hash] labels - # @param [Hash] annotations - # @param [Hash] max_resources_per_workspace - # @return [void] - def self.append_resource_quota( - desired_config:, - name:, - namespace:, - labels:, - annotations:, - max_resources_per_workspace:, - shared_namespace: - ) - return unless max_resources_per_workspace.present? - return if shared_namespace.present? - - max_resources_per_workspace => { - limits: { - cpu: limits_cpu, - memory: limits_memory - }, - requests: { - cpu: requests_cpu, - memory: requests_memory - } - } - - resource_quota = { - apiVersion: "v1", - kind: "ResourceQuota", - metadata: { - annotations: annotations, - labels: labels, - name: name, - namespace: namespace - }, - spec: { - hard: { - "limits.cpu": limits_cpu, - "limits.memory": limits_memory, - "requests.cpu": requests_cpu, - "requests.memory": requests_memory - } - } - } - - desired_config.append(resource_quota) - - nil - end - - # @param [Array] desired_config - # @param [String] name - # @param [String] namespace - # @param [Hash] labels - # @param [Hash] annotations - # @param [Array] image_pull_secrets - # @return [void] - def self.append_image_pull_secrets_service_account( - desired_config:, - name:, - namespace:, - labels:, - annotations:, - image_pull_secrets: - ) - image_pull_secrets_names = image_pull_secrets.map { |secret| { name: secret.fetch(:name) } } - - workspace_service_account_definition = { - apiVersion: "v1", - kind: "ServiceAccount", - metadata: { - name: name, - namespace: namespace, - annotations: annotations, - labels: labels - }, - automountServiceAccountToken: false, - imagePullSecrets: image_pull_secrets_names - } - - desired_config.append(workspace_service_account_definition) - - nil - end - - private_class_method :append_inventory_config_map, - :append_secret, :append_secret_data_from_variables, :append_secret_data, - :append_network_policy, :append_resource_quota, :append_image_pull_secrets_service_account - end - end - end - end -end diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser.rb deleted file mode 100644 index 86a3eafa1670e0..00000000000000 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser.rb +++ /dev/null @@ -1,262 +0,0 @@ -# frozen_string_literal: true - -require 'devfile' - -module RemoteDevelopment - module WorkspaceOperations - module Reconcile - module Output - class OldDevfileParser - include WorkspaceOperationsConstants - include Create::CreateConstants - - # @param [String] processed_devfile_yaml - # @param [Hash] params - # @param [RemoteDevelopment::Logger] logger - # @return [Array] - def self.get_all(processed_devfile_yaml:, params:, logger:) - params => { - name: String => name, - namespace: String => namespace, - replicas: Integer => replicas, - domain_template: String => domain_template, - labels: Hash => labels, - annotations: Hash => annotations, - env_secret_names: Array => env_secret_names, - file_secret_names: Array => file_secret_names, - service_account_name: String => service_account_name, - default_resources_per_workspace_container: Hash => default_resources_per_workspace_container, - allow_privilege_escalation: TrueClass | FalseClass => allow_privilege_escalation, - use_kubernetes_user_namespaces: TrueClass | FalseClass => use_kubernetes_user_namespaces, - default_runtime_class: String => default_runtime_class - } - - begin - workspace_resources_yaml = Devfile::Parser.get_all( - processed_devfile_yaml, - name, - namespace, - YAML.dump(labels.deep_stringify_keys), - YAML.dump(annotations.deep_stringify_keys), - replicas, - domain_template, - 'none' - ) - rescue Devfile::CliError => e - error_message = <<~MSG.squish - #{e.class}: A non zero return code was observed when invoking the devfile CLI - executable from the devfile gem. - MSG - logger.warn( - message: error_message, - error_type: 'reconcile_devfile_parser_error', - workspace_name: name, - workspace_namespace: namespace, - devfile_parser_error: e.message - ) - return [] - rescue StandardError => e - error_message = <<~MSG.squish - #{e.class}: An unrecoverable error occurred when invoking the devfile gem, - this may hint that a gem with a wrong architecture is being used. - MSG - logger.warn( - message: error_message, - error_type: 'reconcile_devfile_parser_error', - workspace_name: name, - workspace_namespace: namespace, - devfile_parser_error: e.message - ) - return [] - end - - workspace_resources = YAML.load_stream(workspace_resources_yaml).map(&:deep_symbolize_keys) - - workspace_resources = set_host_users( - workspace_resources: workspace_resources, - use_kubernetes_user_namespaces: use_kubernetes_user_namespaces - ) - workspace_resources = set_runtime_class( - workspace_resources: workspace_resources, - runtime_class_name: default_runtime_class - ) - workspace_resources = set_security_context( - workspace_resources: workspace_resources, - allow_privilege_escalation: allow_privilege_escalation - ) - workspace_resources = patch_default_resources( - workspace_resources: workspace_resources, - default_resources_per_workspace_container: - default_resources_per_workspace_container - ) - workspace_resources = inject_secrets( - workspace_resources: workspace_resources, - env_secret_names: env_secret_names, - file_secret_names: file_secret_names - ) - - set_service_account( - workspace_resources: workspace_resources, - service_account_name: service_account_name - ) - end - - # @param [Array] workspace_resources - # @param [Boolean] use_kubernetes_user_namespaces - # @return [Array] - def self.set_host_users(workspace_resources:, use_kubernetes_user_namespaces:) - # NOTE: Not setting the use_kubernetes_user_namespaces always since setting it now would require migration - # from old config version to a new one. Set this field always - # when a new devfile parser is created for some other reason. - return workspace_resources unless use_kubernetes_user_namespaces - - workspace_resources.each do |workspace_resource| - next unless workspace_resource[:kind] == 'Deployment' - - workspace_resource[:spec][:template][:spec][:hostUsers] = use_kubernetes_user_namespaces - end - workspace_resources - end - - # @param [Array] workspace_resources - # @param [String] runtime_class_name - # @return [Array] - def self.set_runtime_class(workspace_resources:, runtime_class_name:) - # NOTE: Not setting the runtime_class_name always since changing it now would require migration - # from old config version to a new one. Update this field to `runtime_class_name.presence` - # when a new devfile parser is created for some other reason. - return workspace_resources if runtime_class_name.empty? - - workspace_resources.each do |workspace_resource| - next unless workspace_resource[:kind] == 'Deployment' - - workspace_resource[:spec][:template][:spec][:runtimeClassName] = runtime_class_name - end - workspace_resources - end - - # Devfile library allows specifying the security context of pods/containers as mentioned in - # https://github.com/devfile/api/issues/920 through `pod-overrides` and `container-overrides` attributes. - # However, https://github.com/devfile/library/pull/158 which is implementing this feature, - # is not part of v2.2.0 which is the latest release of the devfile which is being used in the devfile-gem. - # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/409189 - # Once devfile library releases a new version, update the devfile-gem and move - # the logic of setting the security context as part of workspace creation. - - # @param [Array] workspace_resources - # @param [Boolean] allow_privilege_escalation - # @param [Boolean] use_kubernetes_user_namespaces - # @return [Array] - def self.set_security_context( - workspace_resources:, - allow_privilege_escalation: - ) - workspace_resources.each do |workspace_resource| - next unless workspace_resource[:kind] == 'Deployment' - - pod_security_context = { - runAsNonRoot: true, - runAsUser: RUN_AS_USER, - fsGroup: 0, - fsGroupChangePolicy: 'OnRootMismatch' - } - container_security_context = { - allowPrivilegeEscalation: allow_privilege_escalation, - privileged: false, - runAsNonRoot: true, - runAsUser: RUN_AS_USER - } - - pod_spec = workspace_resource[:spec][:template][:spec] - # Explicitly set security context for the pod - pod_spec[:securityContext] = pod_security_context - # Explicitly set security context for all containers - pod_spec[:containers].each do |container| - container[:securityContext] = container_security_context - end - # Explicitly set security context for all init containers - pod_spec[:initContainers].each do |init_container| - init_container[:securityContext] = container_security_context - end - end - workspace_resources - end - - # @param [Array] workspace_resources - # @param [Hash] default_resources_per_workspace_container - # @return [Array] - def self.patch_default_resources(workspace_resources:, default_resources_per_workspace_container:) - workspace_resources.each do |workspace_resource| - next unless workspace_resource.fetch(:kind) == 'Deployment' - - pod_spec = workspace_resource.fetch(:spec).fetch(:template).fetch(:spec) - - container_types = [:initContainers, :containers] - container_types.each do |container_type| - # the purpose of this deep_merge is to ensure - # the values from the devfile override any defaults defined at the agent - pod_spec.fetch(container_type).each do |container| - container - .fetch(:resources, {}) - .deep_merge!(default_resources_per_workspace_container) { |_, val, _| val } - end - end - end - workspace_resources - end - - # @param [Array] workspace_resources - # @param [Array] env_secret_names - # @param [Array] file_secret_names - # @return [Array] - def self.inject_secrets(workspace_resources:, env_secret_names:, file_secret_names:) - workspace_resources.each do |workspace_resource| - next unless workspace_resource.fetch(:kind) == 'Deployment' - - volume = { - name: VARIABLES_VOLUME_NAME, - projected: { - defaultMode: VARIABLES_VOLUME_DEFAULT_MODE, - sources: file_secret_names.map { |name| { secret: { name: name } } } - } - } - - volume_mount = { - name: VARIABLES_VOLUME_NAME, - mountPath: VARIABLES_VOLUME_PATH - } - - env_from = env_secret_names.map { |v| { secretRef: { name: v } } } - - pod_spec = workspace_resource.fetch(:spec).fetch(:template).fetch(:spec) - pod_spec.fetch(:volumes) << volume unless file_secret_names.empty? - - pod_spec.fetch(:initContainers).each do |init_container| - init_container.fetch(:volumeMounts) << volume_mount unless file_secret_names.empty? - init_container[:envFrom] = env_from unless env_secret_names.empty? - end - - pod_spec.fetch(:containers).each do |container| - container.fetch(:volumeMounts) << volume_mount unless file_secret_names.empty? - container[:envFrom] = env_from unless env_secret_names.empty? - end - end - workspace_resources - end - - # @param [Array] workspace_resources - # @param [String] service_account_name - # @return [Array] - def self.set_service_account(workspace_resources:, service_account_name:) - workspace_resources.each do |workspace_resource| - next unless workspace_resource.fetch(:kind) == 'Deployment' - - workspace_resource[:spec][:template][:spec][:serviceAccountName] = service_account_name - end - workspace_resources - end - end - end - end - end -end diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender.rb deleted file mode 100644 index 9e4de02790400e..00000000000000 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender.rb +++ /dev/null @@ -1,165 +0,0 @@ -# frozen_string_literal: true - -module RemoteDevelopment - module WorkspaceOperations - module Reconcile - module Output - class OldScriptsConfigmapAppender - include Create::CreateConstants - include WorkspaceOperationsConstants - - # @param [Array] desired_config - # @param [String] name - # @param [String] namespace - # @param [Hash] labels - # @param [Hash] annotations - # @param [Array] devfile_commands - # @param [Hash] devfile_events - # @return [void] - def self.append(desired_config:, name:, namespace:, labels:, annotations:, devfile_commands:, devfile_events:) - configmap_data = {} - - configmap = - { - kind: "ConfigMap", - apiVersion: "v1", - metadata: { - name: name, - namespace: namespace, - labels: labels, - annotations: annotations - }, - data: configmap_data - } - - add_devfile_command_scripts_to_configmap_data( - configmap_data: configmap_data, - devfile_commands: devfile_commands, - devfile_events: devfile_events - ) - - add_run_poststart_commands_script_to_configmap_data( - configmap_data: configmap_data, - devfile_commands: devfile_commands, - devfile_events: devfile_events - ) - - # noinspection RubyMismatchedArgumentType - RubyMine is misinterpreting types for Hash values - configmap[:data] = Gitlab::Utils.deep_sort_hashes(configmap_data).to_h - - desired_config.append(configmap) - - nil - end - - # @param [Hash] configmap_data - # @param [Array] devfile_commands - # @param [Hash] devfile_events - # @return [void] - def self.add_devfile_command_scripts_to_configmap_data(configmap_data:, devfile_commands:, devfile_events:) - devfile_events => { postStart: Array => poststart_command_ids } - - poststart_command_ids.each do |poststart_command_id| - command = devfile_commands.find { |command| command.fetch(:id) == poststart_command_id } - command => { - exec: { - commandLine: String => command_line - } - } - - configmap_data[poststart_command_id.to_sym] = command_line - end - - nil - end - - # @param [Hash] configmap_data - # @param [Array] devfile_commands - # @param [Hash] devfile_events - # @return [void] - def self.add_run_poststart_commands_script_to_configmap_data( - configmap_data:, - devfile_commands:, - devfile_events: - ) - devfile_events => { postStart: Array => poststart_command_ids } - - 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 - # SAST IGNORE: String interpolation in shell context is safe here - # The interpolated method call returns validated script content - # Future SAST alerts on this heredoc can be safely ignored - # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/547719 - 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. - 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 - - # SAST IGNORE: String interpolation in shell context is safe here - # The interpolated method call returns validated internal script content - # Future SAST alerts on this heredoc can be safely ignored. - # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/547719 - configmap_data[RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym] = - <<~SH.chomp - #!/bin/sh - #{get_poststart_command_script_content(poststart_command_ids: internal_blocking_poststart_command_ids)} - SH - - # SAST IGNORE: String interpolation in shell context is safe here - # The interpolated method call returns validated script content - # Future SAST alerts on this heredoc can be safely ignored. - # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/547719 - 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. - - # SAST IGNORE: String interpolation in shell context is safe here - # Command IDs are validated by the devfile gem, this prevents malicious attacks like path traversal - # Additional validation in ee/lib/remote_development/devfile_operations/restrictions_enforcer.rb - # Future SAST alerts on this heredoc can be safely ignored. - # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/547719 - <<~SH - echo "$(date -Iseconds): ----------------------------------------" - echo "$(date -Iseconds): Running #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id}..." - #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id} || true - echo "$(date -Iseconds): Finished running #{WORKSPACE_SCRIPTS_VOLUME_PATH}/#{poststart_command_id}." - SH - end.join - end - - private_class_method :add_devfile_command_scripts_to_configmap_data, - :add_run_poststart_commands_script_to_configmap_data, :get_poststart_command_script_content - end - end - end - end -end diff --git a/ee/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder.rb b/ee/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder.rb index c7c1182066d6cf..705745dce46593 100644 --- a/ee/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder.rb +++ b/ee/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder.rb @@ -96,15 +96,6 @@ def self.generate_config_to_apply(workspace:, update_type:, logger:) DesiredConfig.new(desired_config_array: config_to_apply_array).validate! end - # TODO: remove this and the above 'if' after a succesful shadow run. Issue - https://gitlab.com/gitlab-org/gitlab/-/issues/551935 - old_config_to_apply = ConfigToApplyShadowRunHandler.handle( - workspace: workspace, - new_config_to_apply_array: config_to_apply_array, - include_all_resources: include_all_resources, - logger: logger - ) - config_to_apply_array = old_config_to_apply - stable_sorted_workspace_resources = config_to_apply_array.map do |resource| Gitlab::Utils.deep_sort_hash(resource) end diff --git a/ee/spec/factories/remote_development/workspaces.rb b/ee/spec/factories/remote_development/workspaces.rb index cba08ed66e2115..ba025846ecf6c7 100644 --- a/ee/spec/factories/remote_development/workspaces.rb +++ b/ee/spec/factories/remote_development/workspaces.rb @@ -102,25 +102,6 @@ responded_to_agent_at: 1.second.ago ) else - unless evaluator.without_workspace_agentk_state - # NOTE: We could attempt to manually build a desired_config_array which has all the correct IDs and values - # agent, namespace, workspace, etc, but this would be a lot of work. For now, we will just use the - # business logic to create a valid one based on the workspace's current state and associations. - result = RemoteDevelopment::WorkspaceOperations::Create::DesiredConfig::Main.main({ - params: { - agent: workspace.agent - }, - workspace: workspace, - logger: nil - }) - desired_config_array = result.fetch(:desired_config).symbolized_desired_config_array - - workspace.create_workspace_agentk_state!( - project: workspace.project, - desired_config: desired_config_array - ) - end - unless evaluator.without_workspace_variables workspace_variables = RemoteDevelopment::WorkspaceOperations::Create::WorkspaceVariablesBuilder.build( name: workspace.name, @@ -164,6 +145,25 @@ ) end + unless evaluator.without_workspace_agentk_state + # NOTE: We could attempt to manually build a desired_config_array which has all the correct IDs and values + # agent, namespace, workspace, etc, but this would be a lot of work. For now, we will just use the + # business logic to create a valid one based on the workspace's current state and associations. + result = RemoteDevelopment::WorkspaceOperations::Create::DesiredConfig::Main.main({ + params: { + agent: workspace.agent + }, + workspace: workspace, + logger: nil + }) + desired_config_array = result.fetch(:desired_config).symbolized_desired_config_array + + workspace.create_workspace_agentk_state!( + project: workspace.project, + desired_config: desired_config_array + ) + end + if evaluator.unprovisioned # if the workspace is unprovisioned, set responded_to_agent_at to nil workspace.update!(responded_to_agent_at: nil) diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler_spec.rb deleted file mode 100644 index 956c30ca4d7a6e..00000000000000 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/config_to_apply_shadow_run_handler_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -# frozen_string_literal: true - -require "fast_spec_helper" - -RSpec.describe RemoteDevelopment::WorkspaceOperations::Reconcile::Output::ConfigToApplyShadowRunHandler, feature_category: :workspaces do - let(:logger) { instance_double("RemoteDevelopment::Logger") } # rubocop:disable RSpec/VerifiedDoubleReference -- We're using the quoted version so we can use fast_spec_helper - let(:workspace) { instance_double("RemoteDevelopment::Workspace", id: 1) } # rubocop:disable RSpec/VerifiedDoubleReference -- We're using the quoted version so we can use fast_spec_helper - - # noinspection RubyMismatchedArgumentType -- We are intentionally passing a double for Workspace and Logger - subject(:result) do - described_class.handle( - workspace: workspace, - new_config_to_apply_array: new_config_to_apply_array, - logger: logger, - include_all_resources: true - ) - end - - before do - allow(RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldDesiredConfigGenerator) - .to(receive(:generate_desired_config)) - .with(workspace: workspace, include_all_resources: true, logger: logger) - .and_return(old_config_to_apply_array) - end - - context "when config_to_apply are same" do - let(:old_config_to_apply_array) { [{ kind: "Deployment" }] } - let(:new_config_to_apply_array) { [{ kind: "Deployment" }] } - - it "returns the value from OldDesiredConfigGenerator" do - expect(logger).not_to receive(:warn) - expect(result).to eq(old_config_to_apply_array) - end - end - - context "when config_to_apply are different" do - let(:old_config_to_apply_array) { [{ kind: "Deployment" }] } - let(:new_config_to_apply_array) { [{ kind: "Service" }] } - - before do - allow(logger).to receive(:warn) - end - - it "logs a warning and returns the value from OldDesiredConfigGenerator" do - # noinspection RubyArgCount -- False positive: Ruby thinks `with` is not supposed to get any argument - expect(logger) - .to(receive(:warn)) - .with({ - diff: [%w[~ [0].kind Service Deployment]], - error_type: "workspaces_reconcile_desired_configs_differ", - message: "The generated config_to_apply from Create::DesiredConfig::Main and OldDesiredConfigGenerator " \ - "differ.", - workspace_id: 1 - }) - expect(result).to eq(old_config_to_apply_array) - end - end -end diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor_spec.rb deleted file mode 100644 index 0ee77aee7ec278..00000000000000 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_config_values_extractor_spec.rb +++ /dev/null @@ -1,269 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -# noinspection RubyArgCount -- Rubymine detecting wrong types, it thinks some #create are from Minitest, not FactoryBot -RSpec.describe RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldConfigValuesExtractor, feature_category: :workspaces do - include_context "with constant modules" - - let_it_be(:user) { create(:user) } - let_it_be(:agent, reload: true) { create(:ee_cluster_agent) } - let_it_be(:workspace_name) { "workspace-name" } - let(:desired_state) { states_module::STOPPED } - let_it_be(:actual_state) { states_module::STOPPED } - let_it_be(:dns_zone) { "my.dns-zone.me" } - let_it_be(:labels) { { "some-label": "value", "other-label": "other-value" } } - let_it_be(:started) { true } - let_it_be(:include_all_resources) { false } - let_it_be(:network_policy_enabled) { true } - let_it_be(:gitlab_workspaces_proxy_namespace) { "gitlab-workspaces" } - let_it_be(:image_pull_secrets) { [{ namespace: "default", name: "secret-name" }] } - let_it_be(:agent_annotations) { { "some/annotation": "value" } } - let_it_be(:shared_namespace) { "" } - let_it_be(:network_policy_egress) do - [ - { - except: %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16], - allow: "0.0.0.0/0" - } - ] - end - - let_it_be(:max_resources_per_workspace) do - { - requests: { - memory: "512Mi", - cpu: "0.6" - }, - limits: { - memory: "786Mi", - cpu: "1.5" - } - } - end - - let_it_be(:default_resources_per_workspace_container) do - { - requests: { - memory: "600Mi", - cpu: "0.5" - }, - limits: { - memory: "700Mi", - cpu: "1.0" - } - } - end - - let_it_be(:workspaces_agent_config) do - config = create( - :workspaces_agent_config, - agent: agent, - dns_zone: dns_zone, - image_pull_secrets: image_pull_secrets, - network_policy_enabled: network_policy_enabled, - # NOTE: We are stringifying all hashes we set here to ensure that the extracted values are converted to symbols - default_resources_per_workspace_container: default_resources_per_workspace_container.deep_stringify_keys, - max_resources_per_workspace: max_resources_per_workspace.deep_stringify_keys, - labels: labels.deep_stringify_keys, - annotations: agent_annotations.deep_stringify_keys, - network_policy_egress: network_policy_egress.map(&:deep_stringify_keys), - shared_namespace: shared_namespace - ) - agent.reload - config - end - - let_it_be(:workspace) do - workspaces_agent_config - create( - :workspace, - name: workspace_name, - agent: agent, - user: user, - actual_state: actual_state - ) - end - - let_it_be(:deployment_resource_version_from_agent) { workspace.deployment_resource_version } - - subject(:extractor) { described_class } - - before do - workspace.update!(desired_state: desired_state) - end - - it "extracts the config values" do - extracted_values = extractor.extract(workspace: workspace) - expect(extracted_values).to be_a(Hash) - expect(extracted_values.keys) - .to eq( - %i[ - allow_privilege_escalation - common_annotations - default_resources_per_workspace_container - default_runtime_class - domain_template - env_secret_name - file_secret_name - gitlab_workspaces_proxy_namespace - image_pull_secrets - labels - max_resources_per_workspace - network_policy_enabled - network_policy_egress - processed_devfile_yaml - replicas - scripts_configmap_name - secrets_inventory_annotations - secrets_inventory_name - shared_namespace - use_kubernetes_user_namespaces - workspace_inventory_annotations - workspace_inventory_name - ] - ) - - # NOTE: We don't explicitly test the values that are returned directly from the agent config without processing. - # Those are covered by the desired_config_generator tests. - - expect(extracted_values[:common_annotations]).to eq( - { - "some/annotation": "value", - "workspaces.gitlab.com/host-template": "{{.port}}-#{workspace.name}.#{dns_zone}", - "workspaces.gitlab.com/id": workspace.id.to_s, - "workspaces.gitlab.com/max-resources-per-workspace-sha256": - "e3dd9c9741b2b3f07cfd341f80ea3a9d4b5a09b29e748cf09b546e93ff98241c" - } - ) - - expect(extracted_values[:default_resources_per_workspace_container]) - .to eq(default_resources_per_workspace_container) - - expect(extracted_values[:env_secret_name]).to eq("#{workspace.name}-env-var") - - expect(extracted_values[:file_secret_name]).to eq("#{workspace.name}-file") - - expect(extracted_values[:image_pull_secrets]).to eq([{ name: "secret-name", namespace: "default" }]) - - expect(extracted_values[:gitlab_workspaces_proxy_namespace]).to eq("gitlab-workspaces") - - expect(extracted_values[:labels]).to eq( - { - "agent.gitlab.com/id": agent.id.to_s, - "other-label": "other-value", - "some-label": "value" - } - ) - - expect(extracted_values[:network_policy_enabled]).to be(true) - - expect(extracted_values[:network_policy_egress]) - .to eq([{ allow: "0.0.0.0/0", except: %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16] }]) - - expect(extracted_values[:max_resources_per_workspace]).to eq(max_resources_per_workspace) - - expect(extracted_values[:processed_devfile_yaml]).to eq(workspace.processed_devfile) - - expect(extracted_values[:scripts_configmap_name]).to eq("#{workspace.name}-scripts-configmap") - - expect(extracted_values[:secrets_inventory_annotations]).to eq( - { - "config.k8s.io/owning-inventory": "#{workspace.name}-secrets-inventory", - "some/annotation": "value", - "workspaces.gitlab.com/host-template": "{{.port}}-#{workspace.name}.#{dns_zone}", - "workspaces.gitlab.com/id": workspace.id.to_s, - "workspaces.gitlab.com/max-resources-per-workspace-sha256": - "e3dd9c9741b2b3f07cfd341f80ea3a9d4b5a09b29e748cf09b546e93ff98241c" - } - ) - - expect(extracted_values[:secrets_inventory_name]).to eq("#{workspace.name}-secrets-inventory") - - expect(extracted_values[:workspace_inventory_annotations]).to eq( - { - "config.k8s.io/owning-inventory": "#{workspace.name}-workspace-inventory", - "some/annotation": "value", - "workspaces.gitlab.com/host-template": "{{.port}}-#{workspace.name}.#{dns_zone}", - "workspaces.gitlab.com/id": workspace.id.to_s, - "workspaces.gitlab.com/max-resources-per-workspace-sha256": - "e3dd9c9741b2b3f07cfd341f80ea3a9d4b5a09b29e748cf09b546e93ff98241c" - } - ) - - expect(extracted_values[:workspace_inventory_name]).to eq("#{workspace.name}-workspace-inventory") - end - - describe "devfile_parser_params[:replicas]" do - subject(:replicas) { extractor.extract(workspace: workspace).fetch(:replicas) } - - context "when desired_state is Running" do - let(:desired_state) { states_module::RUNNING } - let(:expected_replicas) { 1 } - - it { is_expected.to eq(expected_replicas) } - end - - context "when desired_state is not CreationRequested nor Running" do - let(:desired_state) { states_module::STOPPED } - let(:expected_replicas) { 0 } - - it { is_expected.to eq(expected_replicas) } - end - end - - describe "devfile_parser_params[:labels]" do - subject(:actual_labels) { extractor.extract(workspace: workspace).fetch(:labels) } - - context "when shared_namespace is not set" do - let(:expected_labels) do - { - "agent.gitlab.com/id": agent.id.to_s, - "other-label": "other-value", - "some-label": "value" - } - end - - it { is_expected.to eq(expected_labels) } - end - - context "when shared_namespace is set" do - let_it_be(:shared_namespace) { "default" } - let_it_be(:workspace_name) { "workspace-name-shared-namespace" } - let_it_be(:agent, reload: true) { create(:ee_cluster_agent) } - let_it_be(:workspaces_agent_config) do - config = create( - :workspaces_agent_config, - agent: agent, - dns_zone: dns_zone, - labels: labels.deep_stringify_keys, - shared_namespace: shared_namespace - ) - agent.reload - config - end - - let_it_be(:workspace) do - workspaces_agent_config - create( - :workspace, - name: workspace_name, - agent: agent, - user: user, - actual_state: actual_state - ) - end - - let(:expected_labels) do - { - "agent.gitlab.com/id": agent.id.to_s, - "other-label": "other-value", - "some-label": "value", - "workspaces.gitlab.com/id": workspace.id.to_s - } - end - - it { is_expected.to eq(expected_labels) } - end - end -end diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_golden_master_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_golden_master_spec.rb deleted file mode 100644 index 310580cedd628e..00000000000000 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_golden_master_spec.rb +++ /dev/null @@ -1,3754 +0,0 @@ -# frozen_string_literal: true - -require "fast_spec_helper" -# NOTE This explicit "hashdiff" require exists so we can run this spec against historical SHAs, before the require -# existed in ee/spec/fast_spec_helper.rb. It can be removed once there is no longer a need to run it against -# historical SHAs. -require "hashdiff" - -# noinspection RubyLiteralArrayInspection -- Keep original formatting for readability -RSpec.describe RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldDesiredConfigGenerator, "Golden Master for desired_config", feature_category: :workspaces do - # !!!! IMPORTANT NOTE !!!! - # DO NOT ADD - # include_context "with constant modules" - # TO THIS FILE!!! - # THIS FILE SHOULD HAVE ALL THE FIXTURE VALUES HARDCODED, IN ORDER TO PROVIDE PROPER REGRESSION COVERAGE - # !!!!!!!!!!!!!!!!!!!!!!!! - - # rubocop:disable RSpec/VerifiedDoubleReference -- We're using the quoted version of these models, so we can use fast_spec_helper. - let(:logger) { instance_double("Logger", debug: nil) } - let(:agent) { instance_double("Clusters::Agent", id: 991) } - - let(:workspace_variable_environment) do - instance_double( - "RemoteDevelopment::WorkspaceVariable", - key: "ENV_VAR1", - value: "env-var-value1" - ) - end - - let(:workspace_variable_file) do - instance_double( - "RemoteDevelopment::WorkspaceVariable", - key: "FILE_VAR1", - value: "file-var-value1" - ) - end - - # rubocop:disable RSpec/VerifiedDoubles -- This is a scope which is of type ActiveRecord::Associations::CollectionProxy, it can't be a verified double - let(:workspace_variables) do - double( - :workspace_variables, - with_variable_type_environment: [workspace_variable_environment], - with_variable_type_file: [workspace_variable_file] - ) - end - # rubocop:enable RSpec/VerifiedDoubles - - let(:image_pull_secret_stringified) { { "name" => "registry-secret", "namespace" => "default" } } - let(:image_pull_secret_symbolized) { { name: "registry-secret", namespace: "default" } } - let(:image_pull_secret) { image_pull_secret_stringified } - let(:shared_namespace) { "" } - let(:workspace_namespace) { "gl-rd-ns-991-990-fedcba" } - - let(:workspaces_agent_config) do - instance_double( - "RemoteDevelopment::WorkspacesAgentConfig", - allow_privilege_escalation: false, - use_kubernetes_user_namespaces: false, - default_runtime_class: "standard", - default_resources_per_workspace_container: - { requests: { cpu: "0.5", memory: "512Mi" }, limits: { cpu: "1", memory: "1Gi" } }, - # NOTE: This input version of max_resources_per_workspace is deeply UNSORTED, to verify the legacy behavior - # that the "workspaces.gitlab.com/max-resources-per-workspace-sha256" annotation should be calculated - # from the OpenSSL::Digest::SHA256.hexdigest of the #to_s of the SHALLOW sorted version of the hash. In other - # words, the hash is calculated with limits and requests in alphabetical order, but not memory and cpu. - max_resources_per_workspace: { requests: { memory: "1Gi", cpu: "1" }, limits: { memory: "4Gi", cpu: "2" } }, - annotations: { environment: "production", team: "engineering" }, - labels: { app: "workspace", tier: "development" }, - image_pull_secrets: [image_pull_secret], - network_policy_enabled: true, - network_policy_egress: [ - { - allow: "0.0.0.0/0", - except: %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16] - } - ], - gitlab_workspaces_proxy_namespace: "gitlab-workspaces", - dns_zone: "workspaces.localdev.me", - shared_namespace: shared_namespace - ) - end - - let(:input_processed_devfile_yaml) { input_processed_devfile_yaml_with_poststart_event } - - let(:workspace) do - instance_double( - "RemoteDevelopment::Workspace", - id: 993, - agent: agent, - workspaces_agent_config: workspaces_agent_config, - name: "workspace-991-990-fedcba", - namespace: workspace_namespace, - desired_state_running?: desired_state_running, - desired_state_terminated?: desired_state_terminated, - actual_state: 'Running', - workspace_variables: workspace_variables, - processed_devfile: input_processed_devfile_yaml - ) - end - # rubocop:enable RSpec/VerifiedDoubleReference - - subject(:desired_config) do - # noinspection RubyMismatchedArgumentType -- We are intentionally passing a double for Workspace - described_class.generate_desired_config( - workspace: workspace, - include_all_resources: include_all_resources, - logger: logger - ) - end - - shared_examples "generated desired_config golden master checks" do - it "exactly matches the generated desired_config", :unlimited_max_formatted_output_length do - desired_config_object = RemoteDevelopment::WorkspaceOperations::DesiredConfig.new( - desired_config_array: desired_config) - expect(desired_config_object).to be_valid - - desired_config_sorted = desired_config.map(&:deep_symbolize_keys) - - golden_master_desired_config_sorted = golden_master_desired_config.map(&:deep_symbolize_keys) - - # compare the names and kinds of the resources - expect(desired_config_sorted.map { |c| [c.fetch(:kind), c.fetch(:metadata).fetch(:name)] }) - .to eq(golden_master_desired_config_sorted.map { |c| [c.fetch(:kind), c.fetch(:metadata).fetch(:name)] }) - - differences = {} - - # Use Hashdiff on each element to give a more concise and readable diff - desired_config_sorted.each_with_index do |resource, index| - # NOTE: The order of the diff is expected value first, actual value second. This matches the - # "expected ..., got ..." order which RSpec uses by default. - resource_differences = Hashdiff.diff(golden_master_desired_config_sorted[index], resource, use_lcs: false) - - next unless resource_differences.present? - - key = "index=#{index}, kind='#{resource.fetch(:kind)}', name='#{resource.fetch(:metadata).fetch(:name)}'" - value = resource_differences.map(&:inspect).join("\n").to_s - differences[key] = value - end - - expect(differences) - .to be_empty, differences.map { |k, v| "Differences found in resource at #{k} \n#{v}" }.join("\n\n").to_s - end - end - - context "when desired_state is terminated" do - let(:desired_state_running) { false } - let(:desired_state_terminated) { true } - let(:include_all_resources) { true } - let(:golden_master_desired_config) { golden_master_desired_config_with_desired_state_terminated } - - it_behaves_like "generated desired_config golden master checks" - - context "with shared namespace set" do - let(:shared_namespace) { "default" } - let(:workspace_namespace) { shared_namespace } - let(:golden_master_desired_config) do - golden_master_desired_config_for_shared_namespace_with_desired_state_terminated - end - - it_behaves_like "generated desired_config golden master checks" - end - end - - context "when include_all_resources is true" do - let(:desired_state_running) { true } - let(:desired_state_terminated) { false } - let(:include_all_resources) { true } - let(:golden_master_desired_config) { golden_master_desired_config_with_include_all_resources_true } - - 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 - golden_master_desired_config_from_legacy_devfile_with_no_poststart_and_with_include_all_resources_true - end - - it_behaves_like "generated desired_config golden master checks" - end - - context "with shared namespace set" do - let(:shared_namespace) { "default" } - let(:workspace_namespace) { shared_namespace } - let(:golden_master_desired_config) do - golden_master_desired_config_for_shared_namespace_with_include_all_resources_true - end - - it_behaves_like "generated desired_config golden master checks" - end - end - - context "when include_all_resources is false" do - let(:desired_state_running) { true } - let(:desired_state_terminated) { false } - let(:include_all_resources) { false } - let(:golden_master_desired_config) { golden_master_desired_config_with_include_all_resources_false } - - it_behaves_like "generated desired_config golden master checks" - - context "with shared namespace set" do - let(:shared_namespace) { "default" } - let(:workspace_namespace) { shared_namespace } - let(:golden_master_desired_config) do - golden_master_desired_config_for_shared_namespace_with_include_all_resources_false - end - - it_behaves_like "generated desired_config golden master checks" - end - end - - # @return [String] - def input_processed_devfile_yaml_with_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 - 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 '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_without_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: gl-project-cloner - container: - image: alpine/git:2.45.2 - volumeMounts: - - name: gl-workspace-data - path: "/projects" - args: - - "echo 'project cloner container args'" - command: - - "/bin/sh" - - "-c" - memoryLimit: 1000Mi - memoryRequest: 500Mi - cpuLimit: 500m - cpuRequest: 100m - - name: gl-workspace-data - volume: - size: 50Gi - commands: - - id: gl-project-cloner-command - apply: - component: gl-project-cloner - events: - preStart: - - gl-project-cloner-command - variables: {} - YAML - end - - # rubocop:disable Layout/LineLength, Style/WordArray -- Keep original formatting for readability - # noinspection RubyLiteralArrayInspection - # @return [Array] - def golden_master_desired_config_with_desired_state_terminated - [ - { - 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: "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" - } - } - ] - end - - # @return [Array] - def golden_master_desired_config_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\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" - ] - } - } - } - } - ], - 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-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-1.\"\n", - "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-2.\"\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" - } - } - ] - end - - # @return [Array] - def golden_master_desired_config_with_include_all_resources_false - [ - { - 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\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" - ] - } - } - } - } - ], - 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-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-1.\"\n", - "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-2.\"\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): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-1.\"\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-2.\"\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" - } - } - ] - end - - # @return [Array] - def golden_master_desired_config_from_legacy_devfile_with_no_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" - } - ] - } - ], - initContainers: [ - { - args: [ - "echo 'project cloner container args'" - ], - command: [ - "/bin/sh", - "-c" - ], - env: [ - { - name: "PROJECTS_ROOT", - value: "/projects" - }, - { - name: "PROJECT_SOURCE", - value: "/projects" - } - ], - envFrom: [ - { - secretRef: { - name: "workspace-991-990-fedcba-env-var" - } - } - ], - image: "alpine/git:2.45.2", - imagePullPolicy: "Always", - name: "gl-project-cloner-gl-project-cloner-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" - } - } - ] - } - } - ] - } - } - }, - 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", - "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" - } - } - ] - end - - # @return [Array] - def golden_master_desired_config_for_shared_namespace_with_desired_state_terminated - [ - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-workspace-inventory", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-secrets-inventory", - namespace: "default" - } - } - ] - end - - # @return [Array] - def golden_master_desired_config_for_shared_namespace_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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-workspace-inventory", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - spec: { - replicas: 1, - selector: { - matchLabels: { - app: "workspace", - tier: "development", - "agent.gitlab.com/id": "991", - "workspaces.gitlab.com/id": "993" - } - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - 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\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" - ] - } - } - } - } - ], - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - spec: { - ports: [ - { - name: "server", - port: 60001, - targetPort: 60001 - } - ], - selector: { - app: "workspace", - tier: "development", - "agent.gitlab.com/id": "991", - "workspaces.gitlab.com/id": "993" - } - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-gl-workspace-data", - namespace: "default" - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - 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: { - matchLabels: { - "workspaces.gitlab.com/id": "993" - } - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-scripts-configmap", - namespace: "default" - }, - data: { - "gl-run-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-1.\"\n", - "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-2.\"\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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-secrets-inventory", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-env-var", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-file", - namespace: "default" - } - } - ] - end - - # @return [Array] - def golden_master_desired_config_for_shared_namespace_with_include_all_resources_false - [ - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-workspace-inventory", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - spec: { - replicas: 1, - selector: { - matchLabels: { - app: "workspace", - tier: "development", - "agent.gitlab.com/id": "991", - "workspaces.gitlab.com/id": "993" - } - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - 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\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" - ] - } - } - } - } - ], - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - spec: { - ports: [ - { - name: "server", - port: 60001, - targetPort: 60001 - } - ], - selector: { - app: "workspace", - tier: "development", - "agent.gitlab.com/id": "991", - "workspaces.gitlab.com/id": "993" - } - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-gl-workspace-data", - namespace: "default" - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - } - }, - { - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba", - namespace: "default" - }, - 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: { - matchLabels: { - "workspaces.gitlab.com/id": "993" - } - }, - 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", - "workspaces.gitlab.com/id": "993" - }, - name: "workspace-991-990-fedcba-scripts-configmap", - namespace: "default" - }, - data: { - "gl-run-internal-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-1...\"\n/workspace-scripts/gl-internal-example-command-1 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-1.\"\n", - "gl-run-non-blocking-poststart-commands.sh": "#!/bin/sh\necho \"$(date -Iseconds): ----------------------------------------\"\necho \"$(date -Iseconds): Running /workspace-scripts/gl-internal-example-command-2...\"\n/workspace-scripts/gl-internal-example-command-2 || true\necho \"$(date -Iseconds): Finished running /workspace-scripts/gl-internal-example-command-2.\"\n", - "gl-internal-example-command-1": "echo 'gl-internal-example-command-1'", - "gl-internal-example-command-2": "echo 'gl-internal-example-command-2'" - } - } - ] - end - - # rubocop:enable Layout/LineLength, Style/WordArray -end diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_spec.rb deleted file mode 100644 index 369898ac72400e..00000000000000 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_desired_config_generator_spec.rb +++ /dev/null @@ -1,374 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -# noinspection RubyArgCount -- Rubymine detecting wrong types, it thinks some #create are from Minitest, not FactoryBot -RSpec.describe RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldDesiredConfigGenerator, :freeze_time, feature_category: :workspaces do - include_context "with remote development shared fixtures" - - RSpec.shared_examples "includes env and file secrets if the secrets-inventory configmap is present" do - it "verifies that env and file secrets are included when secrets-inventory configmap exists" do - secret_configmap = workspace_resources.find do |resource| - resource.fetch(:kind) == "ConfigMap" && resource.dig(:metadata, :name).match?(/-secrets-inventory$/) - end - - skip "No secrets-inventory configmap found in workspace resources" unless secret_configmap - - secret_configmap_name = secret_configmap.dig(:metadata, :name) - - workspace_secrets = workspace_resources.select { |resource| resource.fetch(:kind) == "Secret" } - - secret_env = workspace_secrets.find do |resource| - resource.dig(:metadata, :name).match?(/-env-var$/) && - resource.dig(:metadata, :annotations, :"config.k8s.io/owning-inventory") == secret_configmap_name - end - - secret_file = workspace_secrets.find do |resource| - resource.dig(:metadata, :name).match?(/-file$/) && - resource.dig(:metadata, :annotations, :"config.k8s.io/owning-inventory") == secret_configmap_name - end - - expect(secret_env).not_to be_nil - expect(secret_file).not_to be_nil - end - end - - describe "#generate_desired_config" do - let(:logger) { instance_double(Logger) } - let(:user) { create(:user) } - let_it_be(:agent, reload: true) { create(:ee_cluster_agent) } - let(:desired_state) { states_module::RUNNING } - let(:actual_state) { states_module::STOPPED } - let(:started) { true } - let(:desired_state_is_terminated) { false } - let(:include_all_resources) { true } - let(:include_scripts_resources) { true } - 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" } - let(:max_resources_per_workspace) { {} } - let(:default_resources_per_workspace_container) { {} } - let(:image_pull_secrets) { [] } - let(:processed_devfile_yaml) { example_processed_devfile_yaml } - let(:shared_namespace) { "" } - let(:workspaces_agent_config) do - config = create( - :workspaces_agent_config, - agent: agent, - image_pull_secrets: image_pull_secrets, - default_resources_per_workspace_container: default_resources_per_workspace_container, - max_resources_per_workspace: max_resources_per_workspace, - network_policy_enabled: network_policy_enabled, - shared_namespace: shared_namespace - ) - agent.reload - config - end - - let(:workspace) do - workspaces_agent_config - create( - :workspace, - agent: agent, - user: user, - desired_state: desired_state, - actual_state: actual_state, - processed_devfile: processed_devfile_yaml - ) - end - - let(:user_defined_commands) do - [ - { - id: "user-defined-command", - exec: { - component: "tooling-container", - commandLine: "echo 'user-defined postStart command'", - hotReloadCapable: false - } - } - ] - end - - let(:expected_config) do - create_config_to_apply( - workspace: workspace, - started: started, - desired_state_is_terminated: desired_state_is_terminated, - include_network_policy: workspace.workspaces_agent_config.network_policy_enabled, - include_all_resources: include_all_resources, - include_scripts_resources: include_scripts_resources, - 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, - allow_privilege_escalation: workspace.workspaces_agent_config.allow_privilege_escalation, - use_kubernetes_user_namespaces: workspace.workspaces_agent_config.use_kubernetes_user_namespaces, - default_runtime_class: workspace.workspaces_agent_config.default_runtime_class, - agent_labels: workspace.workspaces_agent_config.labels.deep_symbolize_keys, - agent_annotations: workspace.workspaces_agent_config.annotations.deep_symbolize_keys, - image_pull_secrets: image_pull_secrets.map(&:deep_symbolize_keys), - shared_namespace: shared_namespace, - user_defined_commands: user_defined_commands - ) - end - - subject(:workspace_resources) do - # noinspection RubyMismatchedArgumentType -- We are passing a test double - described_class.generate_desired_config( - workspace: workspace, - include_all_resources: include_all_resources, - logger: logger - ) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - - it "generates the expected config", :unlimited_max_formatted_output_length do - expect(workspace_resources).to eq(expected_config) - end - - it "includes the workspace name in all resource names" do - resources_without_workspace_name_in_name = workspace_resources.reject do |resource| - resource[:metadata][:name].include?(workspace.name) - end - - expect(resources_without_workspace_name_in_name).to be_empty - end - - context "when desired_state terminated" do - let(:include_all_resources) { true } # Ensure that the terminated behavior overrides the include_all_resources - let(:desired_state_is_terminated) { true } - let(:desired_state) { states_module::TERMINATED } - - it "returns expected config with only inventory config maps", :unlimited_max_formatted_output_length do - actual = workspace_resources - expected = expected_config - expect(actual).to eq(expected) - - workspace_resources.each do |resource| - resource => { - kind: "ConfigMap", - metadata: { - name: String => name - } - } - - expect(name).to end_with("-inventory") - expect(resource).not_to have_key(:data) - end - end - end - - context "when desired_state results in started=true" do - it "returns expected config with the replicas set to one", :unlimited_max_formatted_output_length do - actual = workspace_resources - expected = expected_config - expect(actual).to eq(expected) - workspace_resources => [ - *_, - { - kind: "Deployment", - spec: { - replicas: replicas - } - }, - *_ - ] - - expect(replicas).to eq(1) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when desired_state results in started=false" do - let(:desired_state) { states_module::STOPPED } - let(:started) { false } - - it "returns expected config with the replicas set to zero" do - expect(workspace_resources).to eq(expected_config) - workspace_resources => [ - *_, - { - kind: "Deployment", - spec: { - replicas: replicas - } - }, - *_ - ] - expect(replicas).to eq(0) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when network policy is disabled for agent" do - let(:network_policy_enabled) { false } - - it "returns expected config without network policy" do - expect(workspace_resources).to eq(expected_config) - network_policy_resource = workspace_resources.select { |resource| resource.fetch(:kind) == "NetworkPolicy" } - expect(network_policy_resource).to be_empty - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when default_resources_per_workspace_container is not empty" do - let(:default_resources_per_workspace_container) do - { limits: { cpu: "1.5", memory: "786Mi" }, requests: { cpu: "0.6", memory: "512M" } } - end - - it "returns expected config with defaults for the container resources set" do - expect(workspace_resources).to eq(expected_config) - workspace_resources => [ - *_, - { - kind: "Deployment", - spec: { - template: { - spec: { - containers: containers - } - } - } - }, - *_ - ] - resources_per_workspace_container = containers.map { |container| container.fetch(:resources) } - expect(resources_per_workspace_container).to all(eq(default_resources_per_workspace_container)) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when there are image-pull-secrets" do - let(:image_pull_secrets) { [{ name: "secret-name", namespace: "secret-namespace" }] } - let(:expected_image_pull_secrets_names) { [{ name: "secret-name" }] } - - it "returns expected config with a service account resource configured" do - expect(workspace_resources).to eq(expected_config) - service_account_resource = workspace_resources.find { |resource| resource.fetch(:kind) == "ServiceAccount" } - expect(service_account_resource.to_h.fetch(:imagePullSecrets)).to eq(expected_image_pull_secrets_names) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when shared_namespace is not empty" do - let(:shared_namespace) { "secret-namespace" } - let(:expected_pod_selector_labels) do - { "workspaces.gitlab.com/id": workspace.id.to_s } - end - - it "returns expected config with no resource quota and explicit pod selector in network policy" do - expect(workspace_resources).to eq(expected_config) - resource_quota = workspace_resources.find { |resource| resource.fetch(:kind) == "ResourceQuota" } - expect(resource_quota).to be_nil - workspace_resources => [ - *_, - { - kind: "NetworkPolicy", - spec: { - podSelector: { - matchLabels: pod_selector_labels, - } - } - }, - *_ - ] - expect(pod_selector_labels).to eq(expected_pod_selector_labels) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when max_resources_per_workspace is not empty" do - let(:max_resources_per_workspace) do - { limits: { cpu: "1.5", memory: "786Mi" }, requests: { cpu: "0.6", memory: "512Mi" } } - end - - it "returns expected config with resource quota set" do - expect(workspace_resources).to eq(expected_config) - resource_quota = workspace_resources.find { |resource| resource.fetch(:kind) == "ResourceQuota" } - expect(resource_quota).not_to be_nil - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - 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 - - let(:user_defined_commands) { [] } - - it 'returns expected config without script resources' do - expect(workspace_resources).to eq(expected_config) - end - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when postStart events are not present in devfile" do - let(:include_scripts_resources) { false } - let(:legacy_no_poststart_container_command) { true } - let(:processed_devfile_yaml) do - read_devfile_yaml("example.legacy-no-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 - - it_behaves_like "includes env and file secrets if the secrets-inventory configmap is present" - end - - context "when include_all_resources is false" do - let(:include_all_resources) { false } - - it "does not include secrets inventory config map" do - secret_configmap = workspace_resources.find do |resource| - resource.fetch(:kind) == "ConfigMap" && resource.dig(:metadata, :name).match?(/-secrets-inventory$/) - end - - expect(secret_configmap).to be_nil - end - - it "does not include any secrets" do - secret_env = workspace_resources.find { |resource| resource.fetch(:kind) == "Secret" } - expect(secret_env).to be_nil - end - - context "when max_resources_per_workspace is not empty" do - let(:max_resources_per_workspace) do - { limits: { cpu: "1.5", memory: "786Mi" }, requests: { cpu: "0.6", memory: "512Mi" } } - end - - it "does not include workspace resource quota" do - resource_quota = workspace_resources.find { |resource| resource.fetch(:kind) == "ResourceQuota" } - expect(resource_quota).to be_nil - end - end - end - - context "when DevfileParser returns empty array" do - before do - # rubocop:todo Layout/LineLength -- this line will not be too long once we rename RemoteDevelopment namespace to Workspaces - allow(RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldDevfileParser).to receive(:get_all).and_return([]) - # rubocop:enable Layout/LineLength - end - - it "returns an empty array" do - expect(workspace_resources).to eq([]) - end - end - end -end diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser_spec.rb deleted file mode 100644 index 27dfe74861cceb..00000000000000 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_devfile_parser_spec.rb +++ /dev/null @@ -1,247 +0,0 @@ -# frozen_string_literal: true - -require "fast_spec_helper" - -RSpec.describe RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldDevfileParser, feature_category: :workspaces do - include_context 'with remote development shared fixtures' - - let(:dns_zone) { "workspaces.localdev.me" } - let(:logger) { instance_double(Logger) } - # rubocop:disable RSpec/VerifiedDoubleReference -- We're using the quoted version of these models, so we can use fast_spec_helper. - let(:user) { instance_double("User", name: "name", email: "name@example.com") } - let(:agent) { instance_double("Clusters::Agent", id: 1) } - let(:image_pull_secrets) { [{ name: 'secret-name', namespace: 'secret-namespace' }] } - let(:workspaces_agent_config) do - instance_double("RemoteDevelopment::WorkspacesAgentConfig", image_pull_secrets: image_pull_secrets) - end - - let(:workspace) do - instance_double( - "RemoteDevelopment::Workspace", - id: 1, - name: "name", - namespace: "namespace", - deployment_resource_version: "1", - desired_state: states_module::RUNNING, - actual_state: states_module::STOPPED, - processed_devfile: example_processed_devfile_yaml, - user: user, - agent: agent, - workspaces_agent_config: workspaces_agent_config, - desired_config_generator_version: - ::RemoteDevelopment::WorkspaceOperations::DesiredConfigGeneratorVersion::LATEST_VERSION - ) - end - # rubocop:enable RSpec/VerifiedDoubleReference - - let(:processed_devfile_yaml) do - yaml = example_processed_devfile_yaml - - # Add additional entries to the processed devfile yaml to ensure full coverage of all DevfileParser logic - hash = yaml_safe_load_symbolized(yaml) - - # Add explicit resources to main component container - hash => { - components: [ - *_, - { - name: "tooling-container", - container: tooling_container - }, - *_ - ] - } - tooling_container[:memoryLimit] = "786Mi" - - YAML.dump(hash.deep_stringify_keys) - end - - let(:domain_template) { "" } - let(:egress_ip_rules) do - [{ - allow: "0.0.0.0/0", - except: %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16] - }] - end - - let(:max_resources_per_workspace) { {} } - let(:default_resources_per_workspace_container) do - { limits: { cpu: "1.5", memory: "786Mi" }, requests: { cpu: "0.6", memory: "512Mi" } } - end - - let(:allow_privilege_escalation) { false } - let(:use_kubernetes_user_namespaces) { false } - let(:default_runtime_class) { "test" } - let(:agent_labels) { { a: "1" } } - let(:agent_annotations) { { b: "2" } } - let(:labels) { {} } - let(:annotations) { {} } - - let(:params) do - { - name: workspace.name, - namespace: workspace.namespace, - replicas: 1, - domain_template: domain_template, - labels: labels, - annotations: annotations, - env_secret_names: ["#{workspace.name}-env-var"], - file_secret_names: ["#{workspace.name}-file"], - default_resources_per_workspace_container: default_resources_per_workspace_container, - allow_privilege_escalation: allow_privilege_escalation, - use_kubernetes_user_namespaces: use_kubernetes_user_namespaces, - default_runtime_class: default_runtime_class, - service_account_name: workspace.name - } - end - - let(:expected_workspace_resources) do - create_config_to_apply( - workspace: workspace, - workspace_variables_environment: {}, - workspace_variables_file: {}, - started: true, - include_inventory: false, - include_network_policy: false, - include_all_resources: false, - dns_zone: dns_zone, - egress_ip_rules: egress_ip_rules, - default_resources_per_workspace_container: default_resources_per_workspace_container, - allow_privilege_escalation: allow_privilege_escalation, - use_kubernetes_user_namespaces: use_kubernetes_user_namespaces, - default_runtime_class: default_runtime_class, - agent_labels: agent_labels, - agent_annotations: agent_annotations, - image_pull_secrets: image_pull_secrets, - include_scripts_resources: false, - core_resources_only: true - ) - end - - subject(:resources_from_devfile_parser) do - # noinspection RubyMismatchedArgumentType -- We are passing a test double - described_class.get_all( - processed_devfile_yaml: processed_devfile_yaml, - params: params, - logger: logger - ) - end - - context "when the DevFile parser is successful in parsing k8s core resources" do - let(:domain_template) { "{{.port}}-#{workspace.name}.#{dns_zone}" } - let(:labels) { agent_labels.merge('agent.gitlab.com/id': workspace.agent.id) } - let(:annotations) do - agent_annotations.merge({ - 'config.k8s.io/owning-inventory': "#{workspace.name}-workspace-inventory", - 'workspaces.gitlab.com/host-template': domain_template, - 'workspaces.gitlab.com/id': workspace.id, - 'workspaces.gitlab.com/max-resources-per-workspace-sha256': - Digest::SHA256.hexdigest(max_resources_per_workspace.sort.to_h.to_s) - }) - end - - context "when allow_privilege_escalation is true" do - let(:allow_privilege_escalation) { true } - - it 'returns workspace_resources with allow_privilege_escalation set to true', - :unlimited_max_formatted_output_length do - expect(resources_from_devfile_parser).to eq(expected_workspace_resources) - - resources_from_devfile_parser => [ - *_, - { - kind: "Deployment", - spec: { - template: { - spec: { - containers: containers, - initContainers: init_containers - } - } - } - }, - *_ - ] - - container_privilege_escalation = containers.map do |container| - container.fetch(:securityContext).fetch(:allowPrivilegeEscalation) - end - - init_container_privilege_escalation = init_containers.map do |init_container| - init_container.fetch(:securityContext).fetch(:allowPrivilegeEscalation) - end - - all_containers_privilege_escalation = init_container_privilege_escalation + container_privilege_escalation - - expect(all_containers_privilege_escalation).to all(be true) - end - end - - context "when use_kubernetes_user_namespaces is true" do - let(:use_kubernetes_user_namespaces) { true } - - it 'returns workspace_resources with hostUsers set to true' do - expect(resources_from_devfile_parser).to eq(expected_workspace_resources) - - resources_from_devfile_parser => [ - *_, - { - kind: "Deployment", - spec: { - template: { - spec: { - hostUsers: host_users - } - } - } - }, - *_ - ] - - expect(host_users).to be(true) - end - end - end - - context 'when a runtime error is raised' do - RSpec.shared_examples 'when a runtime error is raised' do - before do - allow(Devfile::Parser).to receive(:get_all).and_raise(error_type.new("some error")) - end - - it 'logs the error' do - expect(logger).to receive(:warn).with( - message: "#{error_type}: #{error_message}", - error_type: 'reconcile_devfile_parser_error', - workspace_name: workspace.name, - workspace_namespace: workspace.namespace, - devfile_parser_error: "some error" - ) - expect(resources_from_devfile_parser).to eq([]) - end - end - - let(:processed_devfile_yaml) { "" } - - context "when Devfile::CliError is raised" do - let(:error_type) { Devfile::CliError } - let(:error_message) do - "A non zero return code was observed when invoking the devfile CLI executable from the devfile gem." - end - - it_behaves_like 'when a runtime error is raised' - end - - context "when StandardError is raised" do - let(:error_type) { StandardError } - let(:error_message) do - <<~MSG.squish - An unrecoverable error occurred when invoking the devfile gem, this may hint that a gem with a wrong - architecture is being used. - MSG - end - - it_behaves_like 'when a runtime error is raised' - end - end -end diff --git a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender_spec.rb deleted file mode 100644 index 775331d34f8d2b..00000000000000 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/old_scripts_configmap_appender_spec.rb +++ /dev/null @@ -1,101 +0,0 @@ -# frozen_string_literal: true - -require "fast_spec_helper" - -RSpec.describe RemoteDevelopment::WorkspaceOperations::Reconcile::Output::OldScriptsConfigmapAppender, feature_category: :workspaces do - include_context 'with remote development shared fixtures' - - let(:files) { RemoteDevelopment::Files } - let(:annotations) { { a: "1" } } - let(:labels) { { b: "2" } } - let(:name) { "workspacename-scripts-configmap" } - let(:namespace) { "namespace" } - let(:processed_devfile) { example_processed_devfile } - let(:devfile_commands) { processed_devfile.fetch(:commands) } - let(:devfile_events) { processed_devfile.fetch(:events) } - - subject(:updated_desired_config) do - # Make a fake desired config with one existing fake element, to prove we are appending - desired_config = [ - {} - ] - - described_class.append( - desired_config: desired_config, - name: name, - namespace: namespace, - labels: labels, - annotations: annotations, - devfile_commands: devfile_commands, - devfile_events: devfile_events - ) - - desired_config - 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-clone-unshallow-command": clone_unshallow_script, - "gl-init-tools-command": files::INTERNAL_POSTSTART_COMMAND_START_VSCODE_SCRIPT, - create_constants_module::RUN_INTERNAL_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => - internal_blocking_poststart_commands_script, - create_constants_module::RUN_NON_BLOCKING_POSTSTART_COMMANDS_SCRIPT_NAME.to_sym => - non_blocking_poststart_commands_script(user_command_ids: ["user-defined-command"]), - "gl-sleep-until-container-is-running-command": - sleep_until_container_is_running_script, - "gl-start-sshd-command": files::INTERNAL_POSTSTART_COMMAND_START_SSHD_SCRIPT, - "user-defined-command": "echo 'user-defined postStart command'" - ) - 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, - create_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/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder_spec.rb b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder_spec.rb index 0709bfa16de361..8c9bbfa03021ad 100644 --- a/ee/spec/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/reconcile/output/response_payload_builder_spec.rb @@ -148,18 +148,6 @@ allow(instance).to receive(:validate!).and_raise("Validation failed") end end - - # TODO: remove this after a successful shadow run. Issue - https://gitlab.com/gitlab-org/gitlab/-/issues/551935 - allow(RemoteDevelopment::WorkspaceOperations::Reconcile::Output::ConfigToApplyShadowRunHandler) - .to receive(:handle) - .with( - hash_including( - workspace: workspace, - new_config_to_apply_array: generated_config_to_apply, - include_all_resources: expected_include_all_resources, - logger: logger - ) - ) { generated_config_to_apply } end context "when update_type is FULL" do 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 f1cf2b5bc73a66..d8e95d73c3724e 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 @@ -418,6 +418,14 @@ def create_config_to_apply( common_annotations.merge({ "config.k8s.io/owning-inventory": "#{workspace.name}-workspace-inventory" }) ).to_h + common_annotations_for_partial_reconciliation = Gitlab::Utils.deep_sort_hashes( + common_annotations.merge({ "workspaces.gitlab.com/include-in-partial-reconciliation" => "true" }) + ) + + workspace_inventory_annotations_for_partial_reconciliation = Gitlab::Utils.deep_sort_hashes( + workspace_inventory_annotations.merge({ "workspaces.gitlab.com/include-in-partial-reconciliation" => "true" }) + ) + labels = agent_labels.merge({ "agent.gitlab.com/id": workspace.agent.id.to_s }) labels["workspaces.gitlab.com/id"] = workspace.id.to_s if shared_namespace.present? labels = Gitlab::Utils.deep_sort_hashes(labels).to_h @@ -427,18 +435,20 @@ def create_config_to_apply( common_annotations.merge({ "config.k8s.io/owning-inventory": "#{workspace.name}-secrets-inventory" }) ).to_h + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash workspace_inventory_config_map = workspace_inventory_config_map( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: common_annotations + annotations: common_annotations_for_partial_reconciliation ) + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash workspace_deployment = workspace_deployment( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: workspace_inventory_annotations, + annotations: workspace_inventory_annotations_for_partial_reconciliation, spec_replicas: spec_replicas, default_resources_per_workspace_container: default_resources_per_workspace_container, allow_privilege_escalation: allow_privilege_escalation, @@ -449,41 +459,46 @@ def create_config_to_apply( legacy_poststart_container_command: legacy_poststart_container_command ) + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash workspace_service = workspace_service( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: workspace_inventory_annotations + annotations: workspace_inventory_annotations_for_partial_reconciliation ) + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash workspace_data_pvc = pvc( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: workspace_inventory_annotations + annotations: workspace_inventory_annotations_for_partial_reconciliation ) + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash workspace_service_account = workspace_service_account( name: workspace.name, namespace: workspace.namespace, image_pull_secrets: image_pull_secrets, labels: labels, - annotations: workspace_inventory_annotations + annotations: workspace_inventory_annotations_for_partial_reconciliation ) + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash workspace_network_policy = workspace_network_policy( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: workspace_inventory_annotations, + annotations: workspace_inventory_annotations_for_partial_reconciliation, egress_ip_rules: egress_ip_rules ) + # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash scripts_configmap = scripts_configmap( workspace_name: workspace.name, workspace_namespace: workspace.namespace, labels: labels, - annotations: workspace_inventory_annotations, + annotations: workspace_inventory_annotations_for_partial_reconciliation, legacy_poststart_container_command: legacy_poststart_container_command, user_defined_commands: user_defined_commands ) -- GitLab