diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 4492d650611eb7f4c1430b194588c5cca645a1e5..4483383ec749aa8626067f941176f1794685c940 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/app/models/remote_development/workspaces_agent_config.rb b/ee/app/models/remote_development/workspaces_agent_config.rb index 8f5fd5a559cb892e57054c224c788bd09cda323a..80aa473da4aada02af2991be69cfcff999c8f5a2 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/config/initializers/validate_workspaces_settings.rb b/ee/config/initializers/validate_workspaces_settings.rb new file mode 100644 index 0000000000000000000000000000000000000000..5ec32bfd17db6881ed213b727e22a7fddd2dd1b7 --- /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? 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 e31a93107f30e3af19ee3ebee9b80b0ed9a209b4..289c73cb83e273de956cd68cd25a4b4ba6d5854c 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 6178f42f69a738498fc79f0dc61d21eb72d20c50..e9e12630495bb478469c1a01f70b536c5e7a611c 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 b9113d8f54e1ec266db39f195c38d97693ba3ef5..e98a039508b13034205bb51c20dc3d5eeeff9a6b 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) @@ -29,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/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 a05b3675e6a157625b119ca6e83a9b887f61deb2..2d0026672b38892c5a31ef649f447801313646fb 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 ca88f18f8c1175680926eb5cb7f38ff3e78d8b22..e45e8202ca2adb7bb41e1e474cd71c926b2f2d2a 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/desired_config/config_values_extractor_spec.rb b/ee/spec/lib/remote_development/workspace_operations/create/desired_config/config_values_extractor_spec.rb index 58b6ac5ac69f2881a04db4f19369d962142a994e..85be54f6fccb00cc4422dbc9517d53a1f071cdab 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 a0f87d86aa6c9a79725e400d7066e5f7c0b4e8ad..cedddfe549d230b0a0a163727dca869ba6ddf726 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 a1a7c214c46ab9ad0de045ab28401eab42e1077a..febb547bc5bb9574e8c133ff07f749ca8252f95f 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/create/workspace_variables_creator_spec.rb b/ee/spec/lib/remote_development/workspace_operations/create/workspace_variables_creator_spec.rb index 2b05d8345295f9016423842dfb3c19191e13a83e..c3cf4c32ee0f2241fde3b65bbd4dbaf5c81cc26c 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 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 704b056b94e3160d9e383c10d962b3ad8266e0ed..7070bda90721565ce5e7d54e89cc74965e06e82f 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 b34236ac003cbdf692b56bb1ba3ddccdb9fe994e..e4d5c8ed6ccfa4aca6f1e906a778e4033a7d84fc 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