From a3fd8e6d21f8f788600a03a8875d220d1e514002 Mon Sep 17 00:00:00 2001 From: Vishal Tak Date: Mon, 15 Sep 2025 10:56:53 +0530 Subject: [PATCH 1/3] Add workspace variable creator spec --- .../workspace_url_helper.rb | 2 + .../workspace_host_parser.rb | 3 ++ .../remote_development/workspaces.rb | 2 +- .../workspace_variables_creator_spec.rb | 40 +++++++++++++++++-- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb b/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb index b9113d8f54e1ec..0afedd2c65d5c3 100644 --- a/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb +++ b/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb @@ -2,6 +2,8 @@ module RemoteDevelopment module WorkspaceOperations + # NOTE: If any changes are made to the URL structure, ensure the same is reflected in + # `ee/lib/remote_development/workspaces_server_operations/authorize_user_access/workspace_host_parser.rb`. class WorkspaceUrlHelper # @return [String] def self.url_template(name, dns_zone, gitlab_workspaces_proxy_http_enabled) diff --git a/ee/lib/remote_development/workspaces_server_operations/authorize_user_access/workspace_host_parser.rb b/ee/lib/remote_development/workspaces_server_operations/authorize_user_access/workspace_host_parser.rb index a05b3675e6a157..2d0026672b3889 100644 --- a/ee/lib/remote_development/workspaces_server_operations/authorize_user_access/workspace_host_parser.rb +++ b/ee/lib/remote_development/workspaces_server_operations/authorize_user_access/workspace_host_parser.rb @@ -7,6 +7,9 @@ class WorkspaceHostParser include Messages extend Gitlab::Fp::MessageSupport + # NOTE: If any changes are made to the URL parsing, ensure the same is reflected in + # `ee/lib/remote_development/workspace_operations/workspace_url_helper.rb`. + # Parse the workspace host to extract port and workspace name # @param [Hash] context # @return [Gitlab::Fp::Result] diff --git a/ee/spec/factories/remote_development/workspaces.rb b/ee/spec/factories/remote_development/workspaces.rb index ca88f18f8c1175..e45e8202ca2adb 100644 --- a/ee/spec/factories/remote_development/workspaces.rb +++ b/ee/spec/factories/remote_development/workspaces.rb @@ -119,7 +119,7 @@ workspace_token = "" # The model's before_save and after_save ensures that the token is only associated for workspaces who are # in the running state. - if common_host_prefix && desired_state == RemoteDevelopment::WorkspaceOperations::States::RUNNING + if common_host_prefix && workspace.desired_state == RemoteDevelopment::WorkspaceOperations::States::RUNNING workspace_token = workspace.workspace_token.token end diff --git a/ee/spec/lib/remote_development/workspace_operations/create/workspace_variables_creator_spec.rb b/ee/spec/lib/remote_development/workspace_operations/create/workspace_variables_creator_spec.rb index 2b05d8345295f9..c3cf4c32ee0f22 100644 --- a/ee/spec/lib/remote_development/workspace_operations/create/workspace_variables_creator_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/create/workspace_variables_creator_spec.rb @@ -12,8 +12,11 @@ let_it_be(:user) { create(:user) } let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } # The desired state of the workspace is set to running so that a workspace token gets associated to it. - let_it_be(:workspace) do - create(:workspace, user: user, personal_access_token: personal_access_token, desired_state: states_module::RUNNING) + let_it_be(:workspace, refind: true) do + create( + :workspace, :without_workspace_variables, + user: user, personal_access_token: personal_access_token, desired_state: states_module::RUNNING + ) end let(:vscode_extension_marketplace) do @@ -53,6 +56,12 @@ described_class.create(context) # rubocop:disable Rails/SaveBang -- this is not an ActiveRecord method end + it "has fixture sanity check" do + # We must ensure the workspace fixture, which simulates a workspace in the ROP create chain in the process of being + # created, does not contain any pre-existing associated workspace_variable records + expect(workspace.workspace_variables.count).to eq(0) + end + context "when workspace variables create is successful" do let(:valid_variable_type) { RemoteDevelopment::Enums::WorkspaceVariable::ENVIRONMENT_TYPE } let(:variable_type) { valid_variable_type } @@ -61,11 +70,34 @@ it "creates the workspace variable records and returns ok result containing original context" do expect { result }.to change { workspace.workspace_variables.count }.by(expected_number_of_records_saved) - expect(RemoteDevelopment::WorkspaceVariable.find_by_key("key1").value).to eq("value 1") - expect(RemoteDevelopment::WorkspaceVariable.find_by_key("key2").value).to eq("value 2") + expect(workspace.workspace_variables.find_by_key("key1").value).to eq("value 1") + expect(workspace.workspace_variables.find_by_key("key2").value).to eq("value 2") expect(result).to be_ok_result(context) end + + context "when workspace url helper's common_workspace_host_suffix? returns true" do + let(:workspace_host_suffix) { "workspaces.host.suffix" } + let(:agentw_token_file_name) do + RemoteDevelopment::WorkspaceOperations::Create::CreateConstants::AGENTW_TOKEN_FILE_NAME + end + + before do + stub_config(workspaces: { host: workspace_host_suffix }) + + allow(RemoteDevelopment::WorkspaceOperations::WorkspaceUrlHelper) + .to receive(:common_workspace_host_suffix?) + .and_return(true) + end + + it "creates the workspace variable records and returns ok result containing original context" do + expect { result }.to change { workspace.workspace_variables.count }.by(expected_number_of_records_saved) + + expect(workspace.workspace_variables.find_by_key(agentw_token_file_name).value).to match(/glwt-.*/) + + expect(result).to be_ok_result(context) + end + end end context "when workspace create fails" do -- GitLab From 64a9f79c5087a3038f9b103b97b4c9e49ed6e6eb Mon Sep 17 00:00:00 2001 From: Vishal Tak Date: Wed, 17 Sep 2025 12:14:02 +0530 Subject: [PATCH 2/3] Add workspaces initializer --- config/initializers/1_settings.rb | 9 +++++++++ ee/config/initializers/validate_workspaces_settings.rb | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 ee/config/initializers/validate_workspaces_settings.rb diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 4492d650611eb7..4483383ec749aa 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -1174,6 +1174,15 @@ Settings.gitlab_kas['client_timeout_seconds'] ||= 5 # Settings.gitlab_kas['external_k8s_proxy_url'] ||= 'grpc://localhost:8154' # NOTE: Do not set a default until all distributions have been updated with a correct value +# +# Workspaces +# +Gitlab.ee do + Settings['workspaces'] ||= {} + Settings.workspaces['enabled'] ||= false + Settings.workspaces['host'] ||= nil +end + # # Suggested Reviewers # diff --git a/ee/config/initializers/validate_workspaces_settings.rb b/ee/config/initializers/validate_workspaces_settings.rb new file mode 100644 index 00000000000000..5ec32bfd17db68 --- /dev/null +++ b/ee/config/initializers/validate_workspaces_settings.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +raise "Workspaces host is not set" if Gitlab.config.workspaces.enabled && Gitlab.config.workspaces.host.blank? -- GitLab From 5a9823e1d3956131aaa7b55e9c996b3e2ceed015 Mon Sep 17 00:00:00 2001 From: Vishal Tak Date: Mon, 15 Sep 2025 12:50:21 +0530 Subject: [PATCH 3/3] Update workspace network policy If the workspace agent config has gitlab workspace proxy http and ssh enabled set to false, we don't need to add ingress attributes in the network policy of the workspace which allows incoming traffic from the GitLab Workspaces Proxy in the Kubernetes cluster because the traffic will be routed without it. --- .../workspaces_agent_config.rb | 18 +++++ .../desired_config/config_values_extractor.rb | 2 + .../devfile_resource_appender.rb | 42 +++++++---- .../workspace_url_helper.rb | 6 +- .../config_values_extractor_spec.rb | 58 +++++++++++++++- .../devfile_resource_appender_spec.rb | 42 +++++++++++ .../desired_config/main_integeration_spec.rb | 2 + .../workspace_url_helper_spec.rb | 25 ++----- .../remote_development_shared_contexts.rb | 69 +++++++++++-------- 9 files changed, 197 insertions(+), 67 deletions(-) diff --git a/ee/app/models/remote_development/workspaces_agent_config.rb b/ee/app/models/remote_development/workspaces_agent_config.rb index 8f5fd5a559cb89..80aa473da4aada 100644 --- a/ee/app/models/remote_development/workspaces_agent_config.rb +++ b/ee/app/models/remote_development/workspaces_agent_config.rb @@ -76,6 +76,24 @@ class WorkspacesAgentConfig < ApplicationRecord scope :by_cluster_agent_ids, ->(ids) { where(cluster_agent_id: ids) } + # The papertrail versioned records before the column gitlab_workspaces_proxy_http_enabled was introduced would not + # have the field gitlab_workspaces_proxy_http_enabled present. Hence, we override the attribute reader to + # consolidate/handle this in the model itself. + def gitlab_workspaces_proxy_http_enabled + return true if read_attribute(:gitlab_workspaces_proxy_http_enabled).nil? + + super + end + + # The papertrail versioned records before the column gitlab_workspaces_proxy_ssh_enabled was introduced would not + # have the field gitlab_workspaces_proxy_ssh_enabled present. Hence, we override the attribute reader to + # consolidate/handle this in the model itself. + def gitlab_workspaces_proxy_ssh_enabled + return true if read_attribute(:gitlab_workspaces_proxy_ssh_enabled).nil? + + super + end + private # @return [void] diff --git a/ee/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor.rb b/ee/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor.rb index e31a93107f30e3..289c73cb83e273 100644 --- a/ee/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor.rb +++ b/ee/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor.rb @@ -76,7 +76,9 @@ def self.extract(context) # Update this when a new desired config generator is created for some other reason. env_secret_name: "#{workspace_name}#{ENV_VAR_SECRET_SUFFIX}", file_secret_name: "#{workspace_name}#{FILE_SECRET_SUFFIX}", + gitlab_workspaces_proxy_http_enabled: workspaces_agent_config.gitlab_workspaces_proxy_http_enabled, gitlab_workspaces_proxy_namespace: workspaces_agent_config.gitlab_workspaces_proxy_namespace, + gitlab_workspaces_proxy_ssh_enabled: workspaces_agent_config.gitlab_workspaces_proxy_ssh_enabled, 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, diff --git a/ee/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender.rb b/ee/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender.rb index 6178f42f69a738..e9e12630495bb4 100644 --- a/ee/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender.rb +++ b/ee/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender.rb @@ -16,7 +16,9 @@ def self.append(context) desired_config_array: desired_config_array, env_secret_name: env_secret_name, file_secret_name: file_secret_name, + gitlab_workspaces_proxy_http_enabled: gitlab_workspaces_proxy_http_enabled, gitlab_workspaces_proxy_namespace: gitlab_workspaces_proxy_namespace, + gitlab_workspaces_proxy_ssh_enabled: gitlab_workspaces_proxy_ssh_enabled, image_pull_secrets: image_pull_secrets, labels: labels, max_resources_per_workspace: max_resources_per_workspace, @@ -58,7 +60,9 @@ def self.append(context) desired_config_array: desired_config_array, name: workspace_name, namespace: workspace_namespace, + gitlab_workspaces_proxy_http_enabled: gitlab_workspaces_proxy_http_enabled, gitlab_workspaces_proxy_namespace: gitlab_workspaces_proxy_namespace, + gitlab_workspaces_proxy_ssh_enabled: gitlab_workspaces_proxy_ssh_enabled, network_policy_enabled: network_policy_enabled, network_policy_egress: network_policy_egress, labels: labels, @@ -173,8 +177,11 @@ def self.append_secret(desired_config_array:, name:, namespace:, labels:, annota nil end + # rubocop:disable Metrics/ParameterLists -- Abstracting this further will not help. # @param [Array] desired_config_array + # @param [Boolean] gitlab_workspaces_proxy_http_enabled # @param [String] gitlab_workspaces_proxy_namespace + # @param [Boolean] gitlab_workspaces_proxy_ssh_enabled # @param [String] name # @param [String] namespace # @param [Boolean] network_policy_enabled @@ -186,7 +193,9 @@ def self.append_network_policy( desired_config_array:, name:, namespace:, + gitlab_workspaces_proxy_http_enabled:, gitlab_workspaces_proxy_namespace:, + gitlab_workspaces_proxy_ssh_enabled:, network_policy_enabled:, network_policy_egress:, labels:, @@ -194,22 +203,26 @@ def self.append_network_policy( ) 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 + policy_types = [] + ingress = [] + if gitlab_workspaces_proxy_http_enabled || gitlab_workspaces_proxy_ssh_enabled + policy_types.append("Ingress") + proxy_namespace_selector = { + matchLabels: { + "kubernetes.io/metadata.name": gitlab_workspaces_proxy_namespace + } } - } - proxy_pod_selector = { - matchLabels: { - "app.kubernetes.io/name": "gitlab-workspaces-proxy" + proxy_pod_selector = { + matchLabels: { + "app.kubernetes.io/name": "gitlab-workspaces-proxy" + } } - } - ingress = [{ from: [{ namespaceSelector: proxy_namespace_selector, podSelector: proxy_pod_selector }] }] + ingress.append( + { from: [{ namespaceSelector: proxy_namespace_selector, podSelector: proxy_pod_selector }] } + ) + end + policy_types.append("Egress") kube_system_namespace_selector = { matchLabels: { "kubernetes.io/metadata.name": "kube-system" @@ -221,7 +234,7 @@ def self.append_network_policy( to: [{ namespaceSelector: kube_system_namespace_selector }] } ] - egress_ip_rules.each do |egress_rule| + network_policy_egress.each do |egress_rule| egress.append( { to: [{ ipBlock: { cidr: egress_rule[:allow], except: egress_rule[:except] } }] } ) @@ -258,6 +271,7 @@ def self.append_network_policy( nil end + # rubocop:enable Metrics/ParameterLists # @param [Array] desired_config_array # @param [String] processed_devfile_yaml diff --git a/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb b/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb index 0afedd2c65d5c3..e98a039508b130 100644 --- a/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb +++ b/ee/lib/remote_development/workspace_operations/workspace_url_helper.rb @@ -31,14 +31,16 @@ def self.common_workspace_host_suffix?(gitlab_workspaces_proxy_http_enabled) # @return [String] def self.workspace_host_suffix(dns_zone, gitlab_workspaces_proxy_http_enabled) if common_workspace_host_suffix?(gitlab_workspaces_proxy_http_enabled) - Gitlab.config["workspaces"]["host"] + # We can safely assume these values are set properly because we do that in the initalizers. + Gitlab.config.workspaces.host else dns_zone end end def self.gitlab_config_workspaces_enabled? - !!Gitlab.config["workspaces"]&.fetch("enabled", false) + # We can safely assume these values are set properly because we do that in the initalizers. + Gitlab.config.workspaces.enabled end private_class_method :gitlab_config_workspaces_enabled? diff --git a/ee/spec/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor_spec.rb b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor_spec.rb index 58b6ac5ac69f28..85be54f6fccb00 100644 --- a/ee/spec/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor_spec.rb @@ -10,7 +10,9 @@ let(:dns_zone) { "my.dns-zone.me" } let(:labels) { { "some-label": "value", "other-label": "other-value" } } let(:network_policy_enabled) { true } + let(:gitlab_workspaces_proxy_http_enabled) { nil } let(:gitlab_workspaces_proxy_namespace) { "gitlab-workspaces" } + let(:gitlab_workspaces_proxy_ssh_enabled) { nil } let(:image_pull_secrets) { [{ namespace: "default", name: "secret-name" }] } let(:agent_annotations) { { "some/annotation": "value" } } let(:shared_namespace) { "" } @@ -53,7 +55,7 @@ end let(:workspaces_agent_config) do - instance_double("RemoteDevelopment::WorkspacesAgentConfig", # rubocop:disable RSpec/VerifiedDoubleReference -- We're using the quoted version so we can use fast_spec_helper + record = instance_double("RemoteDevelopment::WorkspacesAgentConfig", # rubocop:disable RSpec/VerifiedDoubleReference -- We're using the quoted version so we can use fast_spec_helper dns_zone: dns_zone, image_pull_secrets: image_pull_secrets, network_policy_enabled: network_policy_enabled, @@ -69,6 +71,16 @@ gitlab_workspaces_proxy_namespace: gitlab_workspaces_proxy_namespace, use_kubernetes_user_namespaces: use_kubernetes_user_namespaces ) + + # Stub the methods separately since they are custom attribute readers on the model. + allow(record).to receive_messages( + gitlab_workspaces_proxy_http_enabled: + gitlab_workspaces_proxy_http_enabled.nil? ? true : gitlab_workspaces_proxy_http_enabled, + gitlab_workspaces_proxy_ssh_enabled: + gitlab_workspaces_proxy_ssh_enabled.nil? ? true : gitlab_workspaces_proxy_ssh_enabled + ) + + record end let(:workspace_id) { 1 } @@ -100,7 +112,9 @@ domain_template env_secret_name file_secret_name + gitlab_workspaces_proxy_http_enabled gitlab_workspaces_proxy_namespace + gitlab_workspaces_proxy_ssh_enabled image_pull_secrets labels max_resources_per_workspace @@ -150,7 +164,9 @@ 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_http_enabled]).to be(true) expect(extracted_values[:gitlab_workspaces_proxy_namespace]).to eq("gitlab-workspaces") + expect(extracted_values[:gitlab_workspaces_proxy_ssh_enabled]).to be(true) expect(extracted_values[:labels]).to eq( { "agent.gitlab.com/id": workspaces_agent_id.to_s, @@ -198,6 +214,46 @@ expect(extracted_values[:workspace_inventory_name]).to eq("#{workspace_name}-workspace-inventory") end + context "when gitlab_workspaces_proxy_http_enabled is set to true" do + let(:gitlab_workspaces_proxy_http_enabled) { true } + + it "sets the value correctly" do + extracted_values = extractor.extract(context) + expect(extracted_values).to be_a(Hash) + expect(extracted_values[:gitlab_workspaces_proxy_http_enabled]).to be(true) + end + end + + context "when gitlab_workspaces_proxy_http_enabled is set to false" do + let(:gitlab_workspaces_proxy_http_enabled) { false } + + it "sets the value correctly" do + extracted_values = extractor.extract(context) + expect(extracted_values).to be_a(Hash) + expect(extracted_values[:gitlab_workspaces_proxy_http_enabled]).to be(false) + end + end + + context "when gitlab_workspaces_proxy_ssh_enabled is set to true" do + let(:gitlab_workspaces_proxy_ssh_enabled) { true } + + it "sets the value correctly" do + extracted_values = extractor.extract(context) + expect(extracted_values).to be_a(Hash) + expect(extracted_values[:gitlab_workspaces_proxy_ssh_enabled]).to be(true) + end + end + + context "when gitlab_workspaces_proxy_ssh_enabled is set to false" do + let(:gitlab_workspaces_proxy_ssh_enabled) { false } + + it "sets the value correctly" do + extracted_values = extractor.extract(context) + expect(extracted_values).to be_a(Hash) + expect(extracted_values[:gitlab_workspaces_proxy_ssh_enabled]).to be(false) + end + end + describe "devfile_parser_params[:replicas]" do subject(:replicas) { extractor.extract(context).fetch(:replicas) } diff --git a/ee/spec/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender_spec.rb b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender_spec.rb index a0f87d86aa6c9a..cedddfe549d230 100644 --- a/ee/spec/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/devfile_resource_appender_spec.rb @@ -2,6 +2,8 @@ require "fast_spec_helper" +# rubocop:disable RSpec/MultipleMemoizedHelpers -- Needed in specs + RSpec.describe RemoteDevelopment::WorkspaceOperations::Create::DesiredConfig::DevfileResourceAppender, :freeze_time, feature_category: :workspaces do include_context "with remote development shared fixtures" include_context "with constant modules" @@ -60,7 +62,9 @@ let(:secrets_inventory_annotations) { { "config.k8s.io/owning-inventory" => secrets_inventory_name } } let(:scripts_configmap_name) { "#{workspace.name}-scripts" } let(:processed_devfile_yaml) { example_processed_devfile_yaml } + let(:gitlab_workspaces_proxy_http_enabled) { true } let(:gitlab_workspaces_proxy_namespace) { "gitlab-workspaces" } + let(:gitlab_workspaces_proxy_ssh_enabled) { true } let(:network_policy_enabled) { true } let(: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] }] } let(:image_pull_secrets) { [] } @@ -114,7 +118,9 @@ secrets_inventory_annotations: secrets_inventory_annotations, scripts_configmap_name: scripts_configmap_name, processed_devfile_yaml: processed_devfile_yaml, + gitlab_workspaces_proxy_http_enabled: gitlab_workspaces_proxy_http_enabled, gitlab_workspaces_proxy_namespace: gitlab_workspaces_proxy_namespace, + gitlab_workspaces_proxy_ssh_enabled: gitlab_workspaces_proxy_ssh_enabled, network_policy_enabled: network_policy_enabled, network_policy_egress: network_policy_egress, image_pull_secrets: image_pull_secrets, @@ -182,6 +188,40 @@ end end + context "when gitlab_workspaces_proxy_http_enabled and gitlab_workspaces_proxy_http_enabled are set to false" do + let(:gitlab_workspaces_proxy_http_enabled) { false } + let(:gitlab_workspaces_proxy_ssh_enabled) { false } + + it "contains empty ingress attributes of the NetworkPolicy resource" do + result = appended_context[:desired_config_array] + np = result.find { |r| r[:kind] == "NetworkPolicy" } + expect(np[:spec][:ingress]).to eq([]) + expect(np[:spec][:policyTypes]).not_to include("Ingress") + end + end + + context "when gitlab_workspaces_proxy_http_enabled is true and gitlab_workspaces_proxy_ssh_enabled is false" do + let(:gitlab_workspaces_proxy_ssh_enabled) { false } + + it "contains empty ingress attributes of the NetworkPolicy resource" do + result = appended_context[:desired_config_array] + np = result.find { |r| r[:kind] == "NetworkPolicy" } + expect(np[:spec][:ingress]).not_to eq([]) + expect(np[:spec][:policyTypes]).to include("Ingress") + end + end + + context "when gitlab_workspaces_proxy_http_enabled is false and gitlab_workspaces_proxy_ssh_enabled is true" do + let(:gitlab_workspaces_proxy_http_enabled) { false } + + it "contains empty ingress attributes of the NetworkPolicy resource" do + result = appended_context[:desired_config_array] + np = result.find { |r| r[:kind] == "NetworkPolicy" } + expect(np[:spec][:ingress]).not_to eq([]) + expect(np[:spec][:policyTypes]).to include("Ingress") + end + end + context "when max_resources_per_workspace is set" do let(:max_resources_per_workspace) do { limits: { cpu: "1.5", memory: "786Mi" }, requests: { cpu: "0.6", memory: "512Mi" } } @@ -214,3 +254,5 @@ end end end + +# rubocop:enable RSpec/MultipleMemoizedHelpers diff --git a/ee/spec/lib/remote_development/workspace_operations/create/desired_config/main_integeration_spec.rb b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/main_integeration_spec.rb index a1a7c214c46ab9..febb547bc5bb95 100644 --- a/ee/spec/lib/remote_development/workspace_operations/create/desired_config/main_integeration_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/main_integeration_spec.rb @@ -70,7 +70,9 @@ except: %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16] } ], + gitlab_workspaces_proxy_http_enabled: true, gitlab_workspaces_proxy_namespace: "gitlab-workspaces", + gitlab_workspaces_proxy_ssh_enabled: true, dns_zone: "workspaces.localdev.me", shared_namespace: shared_namespace ) diff --git a/ee/spec/lib/remote_development/workspace_operations/workspace_url_helper_spec.rb b/ee/spec/lib/remote_development/workspace_operations/workspace_url_helper_spec.rb index 704b056b94e316..7070bda9072156 100644 --- a/ee/spec/lib/remote_development/workspace_operations/workspace_url_helper_spec.rb +++ b/ee/spec/lib/remote_development/workspace_operations/workspace_url_helper_spec.rb @@ -42,14 +42,14 @@ let(:gitlab_workspaces_proxy_http_enabled) { false } before do - allow(Gitlab).to receive(:config).and_return(gitlab_config) + stub_config(workspaces: gitlab_config_workspaces) end context "when gitlab config is set correctly" do - let(:gitlab_config_workspace_host) { "config.workspaces.host:1234" } + let(:gitlab_config_workspaces_host) { "config.workspaces.host:1234" } let(:expected_url_template) { "${PORT}-name.config.workspaces.host:1234" } let(:expected_url) { "https://1234-name.config.workspaces.host:1234/?example=%2Fvalue" } - let(:gitlab_config) { { "workspaces" => { "enabled" => true, "host" => gitlab_config_workspace_host } } } + let(:gitlab_config_workspaces) { { enabled: true, host: gitlab_config_workspaces_host } } it "uses gitlab config workspace host for workspace_url" do expect(returned_value).to eq( @@ -57,29 +57,14 @@ url_template: expected_url_template, url: expected_url, common_workspace_host_suffix: true, - workspace_host_suffix: gitlab_config_workspace_host + workspace_host_suffix: gitlab_config_workspaces_host } ) end end context "when gitlab config is set incorrectly" do - let(:gitlab_config) { { "workspaces" => { "enabled" => false } } } - - it "uses dns_zone for workspace_url" do - expect(returned_value).to eq( - { - url_template: expected_url_template, - url: expected_url, - common_workspace_host_suffix: false, - workspace_host_suffix: dns_zone - } - ) - end - end - - context "when gitlab config is not set" do - let(:gitlab_config) { {} } + let(:gitlab_config_workspaces) { { enabled: false } } it "uses dns_zone for workspace_url" do expect(returned_value).to eq( 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 b34236ac003cbd..e4d5c8ed6ccfa4 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 @@ -339,6 +339,7 @@ def create_config_to_apply_yaml_stream(workspace:, **args) # @param [Boolean] include_all_resources # @param [String] dns_zone # param [Boolean] gitlab_workspaces_proxy_http_enabled + # param [Boolean] gitlab_workspaces_proxy_ssh_enabled # @param [Array] egress_ip_rules # @param [Hash] max_resources_per_workspace # @param [Hash] default_resources_per_workspace_container @@ -369,6 +370,7 @@ def create_config_to_apply( include_all_resources: false, dns_zone: 'workspaces.localdev.me', gitlab_workspaces_proxy_http_enabled: true, + gitlab_workspaces_proxy_ssh_enabled: true, egress_ip_rules: [{ allow: "0.0.0.0/0", except: %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16] @@ -492,7 +494,9 @@ def create_config_to_apply( workspace_namespace: workspace.namespace, labels: labels, annotations: workspace_inventory_annotations_for_partial_reconciliation, - egress_ip_rules: egress_ip_rules + egress_ip_rules: egress_ip_rules, + gitlab_workspaces_proxy_http_enabled: gitlab_workspaces_proxy_http_enabled, + gitlab_workspaces_proxy_ssh_enabled: gitlab_workspaces_proxy_ssh_enabled ) # noinspection RubyMismatchedArgumentType -- RubyMine thinks annotation could be Array | Hash and it expects Hash @@ -1174,28 +1178,50 @@ def workspace_service_account( # @param [Hash] labels # @param [Hash] annotations # @param [Array] egress_ip_rules + # @param [Boolean] gitlab_workspaces_proxy_http_enabled + # @param [Boolean] gitlab_workspaces_proxy_ssh_enabled # @return [Hash] def workspace_network_policy( workspace_name:, workspace_namespace:, labels:, annotations:, - egress_ip_rules: + egress_ip_rules:, + gitlab_workspaces_proxy_http_enabled:, + gitlab_workspaces_proxy_ssh_enabled: ) + policy_types = [] + ingress = [] + if gitlab_workspaces_proxy_http_enabled || gitlab_workspaces_proxy_ssh_enabled + policy_types.append("Ingress") + proxy_namespace_selector = { + matchLabels: { + "kubernetes.io/metadata.name": "gitlab-workspaces" + } + } + proxy_pod_selector = { + matchLabels: { + "app.kubernetes.io/name": "gitlab-workspaces-proxy" + } + } + ingress.append( + { from: [{ namespaceSelector: proxy_namespace_selector, podSelector: proxy_pod_selector }] } + ) + end + + policy_types.append("Egress") + kube_system_namespace_selector = { + matchLabels: { + "kubernetes.io/metadata.name": "kube-system" + } + } egress = [ { ports: [{ port: 53, protocol: "TCP" }, { port: 53, protocol: "UDP" }], - to: [ - { - namespaceSelector: { - matchLabels: { - "kubernetes.io/metadata.name": "kube-system" - } - } - } - ] + to: [{ namespaceSelector: kube_system_namespace_selector }] } ] + egress_ip_rules.each do |egress_rule| symbolized_egress_rule = egress_rule.deep_symbolize_keys egress.append( @@ -1223,26 +1249,9 @@ def workspace_network_policy( }, spec: { egress: egress, - ingress: [ - { - from: [ - { - namespaceSelector: { - matchLabels: { - "kubernetes.io/metadata.name": "gitlab-workspaces" - } - }, - podSelector: { - matchLabels: { - "app.kubernetes.io/name": "gitlab-workspaces-proxy" - } - } - } - ] - } - ], + ingress: ingress, podSelector: pod_selector, - policyTypes: %w[Ingress Egress] + policyTypes: policy_types } } end -- GitLab