@@ -379,11 +389,17 @@ export default {
+
+
{{ $options.i18n.submitButton.create }}
-
+
{{ $options.i18n.cancelButton }}
diff --git a/ee/app/controllers/remote_development/workspaces_feature_flag_controller.rb b/ee/app/controllers/remote_development/workspaces_feature_flag_controller.rb
index eb159ef1fd84bb2f346e9998c51d0f3ff1828933..c4313e48fa6f8a2f5c72a2f2a0e1692dc4861496 100644
--- a/ee/app/controllers/remote_development/workspaces_feature_flag_controller.rb
+++ b/ee/app/controllers/remote_development/workspaces_feature_flag_controller.rb
@@ -15,11 +15,11 @@ class WorkspacesFeatureFlagController < ApplicationController
].freeze
def show
- flag = params[:flag]
+ flag = permitted_params[:flag]
return render json: { enabled: false } unless ALLOWED_FLAGS.include?(flag.to_s)
- namespace_id = params[:namespace_id]
+ namespace_id = permitted_params[:namespace_id]
namespace = ::Namespace.find_by_id(namespace_id)
return render json: { enabled: false } unless namespace
@@ -30,5 +30,11 @@ def show
render json: { enabled: false }
end
end
+
+ private
+
+ def permitted_params
+ params.permit(:flag, :namespace_id)
+ end
end
end
diff --git a/ee/app/graphql/mutations/remote_development/workspaces/create.rb b/ee/app/graphql/mutations/remote_development/workspaces/create.rb
index bda19dc4d44aa6b83e503715e2819e01c900582a..623ce4bd9fba2ecadc37dd7a0694bc6cfcbf206b 100644
--- a/ee/app/graphql/mutations/remote_development/workspaces/create.rb
+++ b/ee/app/graphql/mutations/remote_development/workspaces/create.rb
@@ -51,6 +51,12 @@ class Create < BaseMutation
required: true,
description: 'Project repo git path containing the devfile used to configure the workspace.'
+ argument :variables, [::Types::RemoteDevelopment::WorkspaceVariableInput],
+ required: false,
+ default_value: [],
+ replace_null_with_default: true,
+ description: 'Variables to inject into the workspace.'
+
def resolve(args)
unless License.feature_available?(:remote_development)
raise_resource_not_available_error!("'remote_development' licensed feature is not available")
@@ -110,7 +116,13 @@ def resolve(args)
track_usage_event(:users_creating_workspaces, current_user.id)
service = ::RemoteDevelopment::Workspaces::CreateService.new(current_user: current_user)
- params = args.merge(agent: agent, user: current_user, project: project)
+ variables = args.fetch(:variables, []).map(&:to_h)
+ params = args.merge(
+ agent: agent,
+ user: current_user,
+ project: project,
+ variables: variables
+ )
response = service.execute(params: params)
response_object = response.success? ? response.payload[:workspace] : nil
diff --git a/ee/app/graphql/types/remote_development/workspace_variable_input.rb b/ee/app/graphql/types/remote_development/workspace_variable_input.rb
new file mode 100644
index 0000000000000000000000000000000000000000..349bceaaac60600984d11ce07e1579aa9029e18f
--- /dev/null
+++ b/ee/app/graphql/types/remote_development/workspace_variable_input.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Types
+ module RemoteDevelopment
+ class WorkspaceVariableInput < BaseInputObject
+ graphql_name 'WorkspaceVariableInput'
+ description 'Attributes for defining a variable to be injected in a workspace.'
+
+ # do not allow empty values. also validate that the key contains only alphanumeric characters, -, _ or .
+ # https://kubernetes.io/docs/concepts/configuration/secret/#restriction-names-data
+ argument :key, GraphQL::Types::String,
+ description: 'Key of the variable.',
+ validates: {
+ allow_blank: false,
+ format: { with: /\A[a-zA-Z0-9\-_.]+\z/, message: 'must contain only alphanumeric characters, -, _ or .' }
+ }
+ argument :type, Types::RemoteDevelopment::WorkspaceVariableInputTypeEnum,
+ description: 'Type of the variable to be injected in a workspace.'
+ argument :value, GraphQL::Types::String, description: 'Value of the variable.'
+ end
+ end
+end
diff --git a/ee/app/graphql/types/remote_development/workspace_variable_input_type_enum.rb b/ee/app/graphql/types/remote_development/workspace_variable_input_type_enum.rb
new file mode 100644
index 0000000000000000000000000000000000000000..88de95f8c275868a6c2f4dd48e6ff0561748a774
--- /dev/null
+++ b/ee/app/graphql/types/remote_development/workspace_variable_input_type_enum.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Types
+ module RemoteDevelopment
+ class WorkspaceVariableInputTypeEnum < BaseEnum
+ graphql_name 'WorkspaceVariableInputType'
+ description 'Enum for the type of the variable to be injected in a workspace.'
+
+ from_rails_enum(
+ ::RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES_FOR_GRAPHQL,
+ description: "#{%(name).capitalize} type."
+ )
+ end
+ end
+end
diff --git a/ee/app/models/remote_development/enums/workspace.rb b/ee/app/models/remote_development/enums/workspace.rb
new file mode 100644
index 0000000000000000000000000000000000000000..225fa88a004fac7d9235a40f305dfd287f03e623
--- /dev/null
+++ b/ee/app/models/remote_development/enums/workspace.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module RemoteDevelopment
+ module Enums
+ module Workspace
+ extend ActiveSupport::Concern
+
+ WORKSPACE_VARIABLE_TYPES = {
+ environment: 0,
+ file: 1
+ }.freeze
+
+ # TODO: Add support for file variables in GraphQL - https://gitlab.com/gitlab-org/gitlab/-/issues/465979
+ WORKSPACE_VARIABLE_TYPES_FOR_GRAPHQL = WORKSPACE_VARIABLE_TYPES
+ .except(:file)
+ .transform_keys { |key| key.to_s.upcase }
+ .freeze
+ end
+ end
+end
diff --git a/ee/app/models/remote_development/workspace_variable.rb b/ee/app/models/remote_development/workspace_variable.rb
index 5ac49cfc2547e3960acea766284eaf9b33ea3a4a..30466b091159b679cd1d873ad6ea4083d59f9529 100644
--- a/ee/app/models/remote_development/workspace_variable.rb
+++ b/ee/app/models/remote_development/workspace_variable.rb
@@ -5,26 +5,24 @@ class WorkspaceVariable < ApplicationRecord
belongs_to :workspace, class_name: 'RemoteDevelopment::Workspace', inverse_of: :workspace_variables
validates :variable_type, presence: true, inclusion: {
- in: [
- RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
- RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE
- ]
+ in: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES.values
}
validates :encrypted_value, presence: true
validates :key,
presence: true,
length: { maximum: 255 }
- scope :with_variable_type_env_var, -> {
- where(variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR)
+ scope :with_variable_type_environment, -> {
+ where(variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment])
}
scope :with_variable_type_file, -> {
- where(variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE)
+ where(variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file])
}
attr_encrypted :value,
mode: :per_attribute_iv,
key: ::Settings.attr_encrypted_db_key_base_32,
- algorithm: 'aes-256-gcm'
+ algorithm: 'aes-256-gcm',
+ allow_empty_value: true
end
end
diff --git a/ee/lib/remote_development/workspaces/create/workspace_creator.rb b/ee/lib/remote_development/workspaces/create/workspace_creator.rb
index a578fd7cf5fdb4f9812b5b470140862f3070f162..596b6c98f14dce3407a193f0cdd7540728068598 100644
--- a/ee/lib/remote_development/workspaces/create/workspace_creator.rb
+++ b/ee/lib/remote_development/workspaces/create/workspace_creator.rb
@@ -26,25 +26,42 @@ def self.create(context)
path: String => workspace_root,
}
params => {
- project: Project => project,
+ desired_state: String => desired_state,
+ editor: String => editor,
+ max_hours_before_termination: Integer => max_hours_before_termination,
+ devfile_ref: String => devfile_ref,
+ devfile_path: String => devfile_path,
agent: Clusters::Agent => agent,
+ user: User => user,
+ project: Project => project,
}
project_dir = "#{workspace_root}/#{project.path}"
- workspace = RemoteDevelopment::Workspace.new(params)
+ workspace = RemoteDevelopment::Workspace.new
workspace.name = workspace_name
workspace.namespace = workspace_namespace
- workspace.personal_access_token = personal_access_token
- workspace.devfile = devfile_yaml
- workspace.processed_devfile = YAML.dump(processed_devfile.deep_stringify_keys)
+ workspace.desired_state = desired_state
workspace.actual_state = CREATION_REQUESTED
workspace.config_version = RemoteDevelopment::Workspaces::ConfigVersion::LATEST_VERSION
+ workspace.editor = editor
+ workspace.max_hours_before_termination = max_hours_before_termination
+ workspace.devfile_ref = devfile_ref
+ workspace.devfile_path = devfile_path
+ workspace.devfile = devfile_yaml
+ workspace.processed_devfile = YAML.dump(processed_devfile.deep_stringify_keys)
set_workspace_url(
workspace: workspace,
agent_dns_zone: agent.remote_development_agent_config.dns_zone,
project_dir: project_dir
)
+
+ # associations for workspace
+ workspace.user = user
+ workspace.project = project
+ workspace.agent = agent
+ workspace.personal_access_token = personal_access_token
+
workspace.save
if workspace.errors.present?
diff --git a/ee/lib/remote_development/workspaces/create/workspace_variables.rb b/ee/lib/remote_development/workspaces/create/workspace_variables.rb
index ad529b4671517b7dc4452e778dbb4dd34996f23e..fd4eebcc7546cd8e6bd3059694fba219889c5a7e 100644
--- a/ee/lib/remote_development/workspaces/create/workspace_variables.rb
+++ b/ee/lib/remote_development/workspaces/create/workspace_variables.rb
@@ -4,8 +4,6 @@ module RemoteDevelopment
module Workspaces
module Create
class WorkspaceVariables
- VARIABLE_TYPE_ENV_VAR = 0
- VARIABLE_TYPE_FILE = 1
GIT_CREDENTIAL_STORE_SCRIPT = <<~SH.chomp
#!/bin/sh
# This is a readonly store so we can exit cleanly when git attempts a store or erase action
@@ -34,9 +32,10 @@ class WorkspaceVariables
# @param [String] user_email
# @param [Integer] workspace_id
# @param [Hash] settings
+ # @param [Array
] variables
# @return [Array]
def self.variables(
- name:, dns_zone:, personal_access_token_value:, user_name:, user_email:, workspace_id:, settings:
+ name:, dns_zone:, personal_access_token_value:, user_name:, user_email:, workspace_id:, settings:, variables:
)
settings => { vscode_extensions_gallery: Hash => vscode_extensions_gallery }
vscode_extensions_gallery => {
@@ -45,98 +44,109 @@ def self.variables(
resource_url_template: String => vscode_extensions_gallery_resource_url_template,
}
- [
+ static_variables = [
{
key: File.basename(RemoteDevelopment::Workspaces::FileMounts::GITLAB_TOKEN_FILE),
value: personal_access_token_value,
- variable_type: VARIABLE_TYPE_FILE,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file],
workspace_id: workspace_id
},
{
key: File.basename(RemoteDevelopment::Workspaces::FileMounts::GITLAB_GIT_CREDENTIAL_STORE_FILE),
value: GIT_CREDENTIAL_STORE_SCRIPT,
- variable_type: VARIABLE_TYPE_FILE,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_COUNT',
value: '3',
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_KEY_0',
value: "credential.helper",
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_VALUE_0',
value: RemoteDevelopment::Workspaces::FileMounts::GITLAB_GIT_CREDENTIAL_STORE_FILE,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_KEY_1',
value: "user.name",
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_VALUE_1',
value: user_name,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_KEY_2',
value: "user.email",
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GIT_CONFIG_VALUE_2',
value: user_email,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GL_GIT_CREDENTIAL_STORE_FILE_PATH',
value: RemoteDevelopment::Workspaces::FileMounts::GITLAB_GIT_CREDENTIAL_STORE_FILE,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GL_TOKEN_FILE_PATH',
value: RemoteDevelopment::Workspaces::FileMounts::GITLAB_TOKEN_FILE,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GL_WORKSPACE_DOMAIN_TEMPLATE',
value: "${PORT}-#{name}.#{dns_zone}",
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GL_EDITOR_EXTENSIONS_GALLERY_SERVICE_URL',
value: vscode_extensions_gallery_service_url,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GL_EDITOR_EXTENSIONS_GALLERY_ITEM_URL',
value: vscode_extensions_gallery_item_url,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: 'GL_EDITOR_EXTENSIONS_GALLERY_RESOURCE_URL_TEMPLATE',
value: vscode_extensions_gallery_resource_url_template,
- variable_type: VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
}
]
+
+ user_provided_variables = variables.map do |variable|
+ {
+ key: variable.fetch(:key),
+ value: variable.fetch(:value),
+ variable_type: variable.fetch(:type),
+ workspace_id: workspace_id
+ }
+ end
+
+ static_variables + user_provided_variables
end
end
end
diff --git a/ee/lib/remote_development/workspaces/create/workspace_variables_creator.rb b/ee/lib/remote_development/workspaces/create/workspace_variables_creator.rb
index e5cb5a45e27b6cd5139a63860f5dab7e227caf58..f9b6f3b702cb5bb44ceb95d4bfabed3d458dcbe6 100644
--- a/ee/lib/remote_development/workspaces/create/workspace_variables_creator.rb
+++ b/ee/lib/remote_development/workspaces/create/workspace_variables_creator.rb
@@ -13,19 +13,27 @@ def self.create(context)
workspace: RemoteDevelopment::Workspace => workspace,
personal_access_token: PersonalAccessToken => personal_access_token,
current_user: User => user,
- settings: Hash => settings
+ settings: Hash => settings,
+ params: Hash => params
}
- workspace_variables_params = WorkspaceVariables.variables(
+ params => {
+ variables: Array => user_provided_variables
+ }
+ # When we have the ability to define variables for workspaces
+ # at project/group/instance level, add them here.
+ variables = user_provided_variables
+ workspace_variables = WorkspaceVariables.variables(
name: workspace.name,
dns_zone: workspace.dns_zone,
personal_access_token_value: personal_access_token.token,
user_name: user.name,
user_email: user.email,
workspace_id: workspace.id,
- settings: settings
+ settings: settings,
+ variables: variables
)
- workspace_variables_params.each do |workspace_variable_params|
+ workspace_variables.each do |workspace_variable_params|
workspace_variable = RemoteDevelopment::WorkspaceVariable.new(workspace_variable_params)
workspace_variable.save
diff --git a/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator.rb b/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator.rb
index 6ea5007cc740a717065e49787cfa0b4e9143d2da..dd5d1ccb550b6c5a86e53c89393e31e1e83bc44b 100644
--- a/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator.rb
+++ b/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator.rb
@@ -13,6 +13,9 @@ class DesiredConfigGenerator
# @return [Array]
def self.generate_desired_config(workspace:, include_all_resources:, logger:)
desired_config = []
+ # 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"
env_secret_names = [env_secret_name]
@@ -129,16 +132,16 @@ def self.get_k8s_resources_for_secrets(
agent_id: workspace.agent.id
)
- data_for_env_var = workspace.workspace_variables.with_variable_type_env_var
- data_for_env_var = data_for_env_var.each_with_object({}) do |workspace_variable, hash|
+ data_for_environment = workspace.workspace_variables.with_variable_type_environment
+ data_for_environment = data_for_environment.each_with_object({}) do |workspace_variable, hash|
hash[workspace_variable.key] = workspace_variable.value
end
- k8s_secret_for_env_var = get_secret(
+ k8s_secret_for_environment = get_secret(
name: env_secret_name,
namespace: workspace.namespace,
labels: labels,
annotations: annotations,
- data: data_for_env_var
+ data: data_for_environment
)
data_for_file = workspace.workspace_variables.with_variable_type_file
@@ -153,7 +156,7 @@ def self.get_k8s_resources_for_secrets(
data: data_for_file
)
- [k8s_inventory, k8s_secret_for_env_var, k8s_secret_for_file]
+ [k8s_inventory, k8s_secret_for_environment, k8s_secret_for_file]
end
# @param [String] desired_state
diff --git a/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator_v2.rb b/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator_v2.rb
index 61341c477822efe77699a0679e56ed61d582ee73..6caa9f947c7474bf15dbb94ea5da9db1b36a3bc8 100644
--- a/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator_v2.rb
+++ b/ee/lib/remote_development/workspaces/reconcile/output/desired_config_generator_v2.rb
@@ -102,16 +102,16 @@ def self.get_k8s_resources_for_secrets(workspace:, env_secret_name:, file_secret
agent_id: workspace.agent.id
)
- data_for_env_var = workspace.workspace_variables.with_variable_type_env_var
- data_for_env_var = data_for_env_var.each_with_object({}) do |workspace_variable, hash|
+ data_for_environment = workspace.workspace_variables.with_variable_type_environment
+ data_for_environment = data_for_environment.each_with_object({}) do |workspace_variable, hash|
hash[workspace_variable.key] = workspace_variable.value
end
- k8s_secret_for_env_var = get_secret(
+ k8s_secret_for_environment = get_secret(
name: env_secret_name,
namespace: workspace.namespace,
labels: labels,
annotations: annotations,
- data: data_for_env_var
+ data: data_for_environment
)
data_for_file = workspace.workspace_variables.with_variable_type_file
@@ -126,7 +126,7 @@ def self.get_k8s_resources_for_secrets(workspace:, env_secret_name:, file_secret
data: data_for_file
)
- [k8s_inventory, k8s_secret_for_env_var, k8s_secret_for_file]
+ [k8s_inventory, k8s_secret_for_environment, k8s_secret_for_file]
end
# @param [String] desired_state
diff --git a/ee/spec/factories/remote_development/workspace_variables.rb b/ee/spec/factories/remote_development/workspace_variables.rb
index 8f3c64c35c8c7b35c531e9e7a7a231f735c39368..04b4ed3dcbffb188d716e18eefe50fd1efbf1095 100644
--- a/ee/spec/factories/remote_development/workspace_variables.rb
+++ b/ee/spec/factories/remote_development/workspace_variables.rb
@@ -6,6 +6,6 @@
key { 'my_key' }
value { 'my_value' }
- variable_type { RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE }
+ variable_type { RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file] }
end
end
diff --git a/ee/spec/factories/remote_development/workspaces.rb b/ee/spec/factories/remote_development/workspaces.rb
index f9c44c966b427fe42e5b71bdf5681c3eb7476a4e..03870a22d4c972cb0970e9f218000a176c09efea 100644
--- a/ee/spec/factories/remote_development/workspaces.rb
+++ b/ee/spec/factories/remote_development/workspaces.rb
@@ -89,7 +89,8 @@
item_url: "https://open-vsx.org/vscode/item",
resource_url_template: "https://open-vsx.org/api/{publisher}/{name}/{version}/file/{path}"
}
- }
+ },
+ variables: []
)
workspace_variables.each do |workspace_variable|
diff --git a/ee/spec/features/remote_development/workspaces_spec.rb b/ee/spec/features/remote_development/workspaces_spec.rb
index ed2a666e3ffe5ff000e566e97af9e72a52130880..00d00bcccf0e1d018deb9aa44a2a73e63283d8f8 100644
--- a/ee/spec/features/remote_development/workspaces_spec.rb
+++ b/ee/spec/features/remote_development/workspaces_spec.rb
@@ -22,6 +22,8 @@
let_it_be(:agent_token) { create(:cluster_agent_token, agent: agent, created_by_user: user) }
let(:reconcile_url) { capybara_url(api('/internal/kubernetes/modules/remote_development/reconcile', user)) }
+ let(:variable_key) { "VAR1" }
+ let(:variable_value) { "value 1" }
before do
stub_licensed_features(remote_development: true)
@@ -57,6 +59,9 @@
# noinspection RubyMismatchedArgumentType -- Rubymine is finding the wrong `select`
select agent.name, from: 'Cluster agent'
fill_in 'Workspace automatically terminates after', with: '20'
+ click_button 'Add variable'
+ fill_in 'Variable Key', with: variable_key
+ fill_in 'Variable Value', with: variable_value
click_button 'Create workspace'
# We look for the project GID because that's all we know about the workspace at this point. For the new UI,
diff --git a/ee/spec/frontend/workspaces/user/components/workspace_variables_spec.js b/ee/spec/frontend/workspaces/user/components/workspace_variables_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..aa039d5d2646d49166dc67ea12d8eda8fb22d21b
--- /dev/null
+++ b/ee/spec/frontend/workspaces/user/components/workspace_variables_spec.js
@@ -0,0 +1,219 @@
+import { GlCard, GlTable, GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
+import WorkspaceVariables from 'ee/workspaces/user/components/workspace_variables.vue';
+import { stubComponent } from 'helpers/stub_component';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { extendedWrapper, mountExtended } from 'helpers/vue_test_utils_helper';
+import { WORKSPACE_VARIABLE_INPUT_TYPE_ENUM } from 'ee/workspaces/user/constants';
+
+describe('workspaces/user/components/workspace_variables.vue', () => {
+ let wrapper;
+ let mockApollo;
+
+ const buildMockApollo = () => {
+ mockApollo = createMockApollo([]);
+ };
+
+ const GlFormGroupStub = stubComponent(GlFormGroup, {
+ props: {
+ ...GlFormGroup.props,
+ state: {
+ type: Boolean,
+ required: false,
+ default: undefined,
+ },
+ },
+ });
+
+ const buildWrapper = ({ mountFn = mountExtended, variables, showValidations = false } = {}) => {
+ // noinspection JSCheckFunctionSignatures - TODO: Address in https://gitlab.com/gitlab-org/gitlab/-/issues/437600
+ wrapper = mountFn(WorkspaceVariables, {
+ apolloProvider: mockApollo,
+ propsData: {
+ variables,
+ showValidations,
+ },
+ stubs: {
+ GlTable,
+ GlCard,
+ GlButton,
+ GlFormInput,
+ GlFormGroup: GlFormGroupStub,
+ },
+ });
+ };
+
+ const findCard = () => extendedWrapper(wrapper.findComponent(GlCard));
+ const findTable = () => extendedWrapper(wrapper.findComponent(GlTable));
+ const findAddButton = () =>
+ extendedWrapper(wrapper.findByRole('button', { name: /Add variable/i }));
+
+ beforeEach(() => {
+ buildMockApollo();
+ });
+
+ it('renders table with empty state', () => {
+ const variables = [];
+ buildWrapper({ variables });
+ expect(findCard().props()).toMatchObject({
+ bodyClass: expect.stringContaining('gl-new-card-body'),
+ footerClass: expect.stringContaining(''),
+ headerClass: expect.stringContaining(''),
+ });
+ expect(findCard().text()).toContain('Variables');
+ expect(findTable().text()).toContain('No variables');
+ expect(findAddButton().exists()).toBe(true);
+ });
+
+ it('renders table with variables', () => {
+ const variables = [
+ {
+ key: 'foo1',
+ value: 'bar1',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ {
+ key: 'foo2',
+ value: 'bar2',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+ buildWrapper({ variables });
+
+ const keys = wrapper.findAllByTestId('key');
+ const values = wrapper.findAllByTestId('value');
+ const removeButtons = wrapper.findAllByTestId('remove-variable');
+ variables.forEach((variable, index) => {
+ expect(keys.at(index).element.value).toBe(variable.key);
+ expect(values.at(index).element.value).toBe(variable.value);
+ expect(removeButtons.at(index).exists()).toBe(true);
+ });
+ });
+
+ it('adds a new variable', () => {
+ const variables = [
+ {
+ key: 'foo1',
+ value: 'bar1',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+ buildWrapper({ variables });
+
+ findAddButton().vm.$emit('click');
+ const emittedEvents = wrapper.emitted();
+ expect(emittedEvents.addVariable).toHaveLength(1);
+ expect(emittedEvents.input).toMatchObject([
+ [[...variables, { key: '', value: '', valid: false }]],
+ ]);
+ });
+
+ it('removes a variable', () => {
+ const variables = [
+ {
+ key: 'foo1',
+ value: 'bar1',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ {
+ key: 'foo2',
+ value: 'bar2',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ {
+ key: 'foo3',
+ value: 'bar3',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+ buildWrapper({ variables });
+
+ wrapper.findAllByTestId('remove-variable').at(1).vm.$emit('click');
+ const emittedEvents = wrapper.emitted();
+ expect(emittedEvents.input).toMatchObject([[[...variables.toSpliced(1, 1)]]]);
+ });
+
+ it('updates a variable key', async () => {
+ const variables = [
+ {
+ key: '',
+ value: '',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+ const expectedVariables = [
+ {
+ key: 'foo1',
+ value: '',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: true,
+ },
+ ];
+ buildWrapper({ variables });
+
+ const keys = wrapper.findAllByTestId('key');
+ await keys.at(0).vm.$emit('input', 'foo1');
+ const emittedEvents = wrapper.emitted();
+ expect(emittedEvents.input).toMatchObject([[[...expectedVariables]]]);
+ });
+
+ it('updates a variable value', async () => {
+ const variables = [
+ {
+ key: '',
+ value: '',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+ const expectedVariables = [
+ {
+ key: '',
+ value: 'bar1',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+ buildWrapper({ variables });
+
+ const values = wrapper.findAllByTestId('value');
+ await values.at(0).vm.$emit('input', 'bar1');
+ const emittedEvents = wrapper.emitted();
+ expect(emittedEvents.input).toMatchObject([[[...expectedVariables]]]);
+ });
+
+ it('shows validations', () => {
+ const variables = [
+ {
+ key: '',
+ value: '',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ {
+ key: 'foo2',
+ value: '',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: true,
+ },
+ ];
+ const showValidations = true;
+ buildWrapper({ variables, showValidations });
+
+ variables.forEach((variable, index) => {
+ const row = findTable().findAll('tbody tr').at(index);
+ const formGroups = row.findAllComponents(GlFormGroupStub);
+ const [keyFormGroup, valueFormGroup] = formGroups.wrappers;
+
+ expect(keyFormGroup.props().state).toBe(variable.valid);
+ // Value form group is not validated
+ expect(valueFormGroup.props().state).toBe(undefined);
+ });
+ });
+});
diff --git a/ee/spec/frontend/workspaces/user/pages/create_spec.js b/ee/spec/frontend/workspaces/user/pages/create_spec.js
index e01ee32a3c097c6776f698596428064f88335058..4f8e52a4677960fe6c7eae6529fd8f3acc05fd32 100644
--- a/ee/spec/frontend/workspaces/user/pages/create_spec.js
+++ b/ee/spec/frontend/workspaces/user/pages/create_spec.js
@@ -14,6 +14,7 @@ import {
import RefSelector from '~/ref/components/ref_selector.vue';
import SearchProjectsListbox from 'ee/workspaces/user/components/search_projects_listbox.vue';
import GetProjectDetailsQuery from 'ee/workspaces/common/components/get_project_details_query.vue';
+import WorkspaceVariables from 'ee/workspaces/user/components/workspace_variables.vue';
import WorkspaceCreate, { devfileHelpPath, i18n } from 'ee/workspaces/user/pages/create.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
@@ -23,6 +24,7 @@ import {
DEFAULT_DESIRED_STATE,
DEFAULT_EDITOR,
ROUTES,
+ WORKSPACE_VARIABLE_INPUT_TYPE_ENUM,
WORKSPACES_LIST_PAGE_SIZE,
} from 'ee/workspaces/user/constants';
import waitForPromises from 'helpers/wait_for_promises';
@@ -205,6 +207,7 @@ describe('workspaces/user/pages/create.vue', () => {
findClusterAgentsFormSelect().vm.$emit('input', selectedClusterAgentIDFixture);
const submitCreateWorkspaceForm = () =>
wrapper.findComponent(GlForm).vm.$emit('submit', { preventDefault: jest.fn() });
+ const findWorkspaceVariables = () => wrapper.findComponent(WorkspaceVariables);
beforeEach(() => {
buildMockApollo();
@@ -331,6 +334,13 @@ describe('workspaces/user/pages/create.vue', () => {
});
});
+ it('renders workspace variables component', () => {
+ expect(findWorkspaceVariables().props()).toMatchObject({
+ variables: [],
+ showValidations: false,
+ });
+ });
+
describe('when selecting a project again', () => {
beforeEach(async () => {
await selectProject({ nameWithNamespace: 'New Project', fullPath: 'new-project' });
@@ -367,6 +377,7 @@ describe('workspaces/user/pages/create.vue', () => {
devfilePath,
maxHoursBeforeTermination,
devfileRef,
+ variables: findWorkspaceVariables().props().variables,
},
});
});
@@ -377,6 +388,33 @@ describe('workspaces/user/pages/create.vue', () => {
expect(findCreateWorkspaceButton().props().loading).toBe(true);
});
+ it('displays workspace variables validations', async () => {
+ expect(findWorkspaceVariables().props().showValidations).toBe(false);
+
+ await submitCreateWorkspaceForm();
+
+ expect(findWorkspaceVariables().props().showValidations).toBe(true);
+ });
+
+ describe('when workspace variables are not valid', () => {
+ it('does not submit the Create Workspace mutation', async () => {
+ const variables = [
+ {
+ key: '',
+ value: '',
+ type: WORKSPACE_VARIABLE_INPUT_TYPE_ENUM.env,
+ valid: false,
+ },
+ ];
+
+ await findWorkspaceVariables().vm.$emit('input', variables);
+
+ await submitCreateWorkspaceForm();
+
+ expect(workspaceCreateMutationHandler).not.toHaveBeenCalled();
+ });
+ });
+
describe('when the workspaceCreate mutation succeeds', () => {
it('when workspaces are not previously cached, does not update cache', async () => {
await submitCreateWorkspaceForm();
diff --git a/ee/spec/graphql/types/remote_development/workspace_variable_input_spec.rb b/ee/spec/graphql/types/remote_development/workspace_variable_input_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cde8ac890243f2142d035db0000b0d5eb1e56e3d
--- /dev/null
+++ b/ee/spec/graphql/types/remote_development/workspace_variable_input_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['WorkspaceVariableInput'], feature_category: :remote_development do
+ let(:arguments) do
+ %i[
+ key
+ type
+ value
+ ]
+ end
+
+ specify { expect(described_class.graphql_name).to eq('WorkspaceVariableInput') }
+ specify { expect(described_class.arguments.deep_symbolize_keys.keys).to(match_array(arguments)) }
+ specify { expect(described_class).to have_graphql_arguments(arguments) }
+end
diff --git a/ee/spec/lib/remote_development/agent_config/main_spec.rb b/ee/spec/lib/remote_development/agent_config/main_spec.rb
index 3c966d36ffe5b822381da5bb05e60751e9f36c93..f06910fe1990f3dbb4b17cab904e9bb7237e4ab2 100644
--- a/ee/spec/lib/remote_development/agent_config/main_spec.rb
+++ b/ee/spec/lib/remote_development/agent_config/main_spec.rb
@@ -2,7 +2,7 @@
require_relative '../rd_fast_spec_helper'
-RSpec.describe RemoteDevelopment::AgentConfig::Main, :rd_fast, feature_category: :remote_development do # rubocop:disable RSpec/EmptyExampleGroup -- the context blocks are dynamically generated
+RSpec.describe RemoteDevelopment::AgentConfig::Main, :rd_fast, feature_category: :remote_development do
let(:context_passed_along_steps) { {} }
let(:rop_steps) do
@@ -30,7 +30,6 @@
end
end
- # rubocop:disable Style/TrailingCommaInArrayLiteral -- let the last element have a comma for simpler diffs
# rubocop:disable Layout/LineLength -- we want to avoid excessive wrapping for RSpec::Parameterized Nested Array Style so we can have formatting consistency between entries
where(:case_name, :result_for_step, :expected_response) do
[
@@ -43,7 +42,7 @@
{
status: :success,
payload: lazy { ok_message_content }
- },
+ }
],
[
"when Updater returns AgentConfigUpdateSkippedBecauseNoConfigFileEntryFound",
@@ -58,6 +57,7 @@
]
]
end
+ # rubocop:enable Layout/LineLength
with_them do
it_behaves_like "rop invocation with successful response"
end
@@ -81,8 +81,6 @@
end
end
- # rubocop:disable Style/TrailingCommaInArrayLiteral -- let the last element have a comma for simpler diffs
- # rubocop:disable Layout/LineLength -- we want to avoid excessive wrapping for RSpec::Parameterized Nested Array Style so we can have formatting consistency between entries
where(:case_name, :err_result_for_step, :expected_response) do
[
[
@@ -95,7 +93,7 @@
status: :error,
message: lazy { "License check failed: #{error_details}" },
reason: :forbidden
- },
+ }
],
[
"when Updater returns AgentConfigUpdateFailed",
@@ -107,7 +105,7 @@
status: :error,
message: lazy { "Agent config update failed: #{error_details}" },
reason: :bad_request
- },
+ }
],
[
"when an unmatched error is returned, an exception is raised",
@@ -119,8 +117,6 @@
]
]
end
- # rubocop:enable Style/TrailingCommaInArrayLiteral
- # rubocop:enable Layout/LineLength
with_them do
it_behaves_like "rop invocation with error response"
diff --git a/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/create/main_spec.rb b/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/create/main_spec.rb
index 14e23853ad6c8723734b4f7c042c061cba15e3f6..ea6539fd98690d9cf1d6fbd518a42acd519f793e 100644
--- a/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/create/main_spec.rb
+++ b/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/create/main_spec.rb
@@ -2,7 +2,7 @@
require_relative '../../rd_fast_spec_helper'
-RSpec.describe RemoteDevelopment::NamespaceClusterAgentMappings::Create::Main, :rd_fast, feature_category: :remote_development do # rubocop:disable RSpec/EmptyExampleGroup -- the context blocks are dynamically generated
+RSpec.describe RemoteDevelopment::NamespaceClusterAgentMappings::Create::Main, :rd_fast, feature_category: :remote_development do
let(:context_passed_along_steps) { {} }
let(:rop_steps) do
[
diff --git a/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/delete/main_spec.rb b/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/delete/main_spec.rb
index cd3896bfa1a297f3b8347f7617982794fd06af9c..64a1e86500793f95f7023572196b8183a29ce927 100644
--- a/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/delete/main_spec.rb
+++ b/ee/spec/lib/remote_development/namespace_cluster_agent_mappings/delete/main_spec.rb
@@ -2,7 +2,7 @@
require_relative '../../rd_fast_spec_helper'
-RSpec.describe RemoteDevelopment::NamespaceClusterAgentMappings::Delete::Main, :rd_fast, feature_category: :remote_development do # rubocop:disable RSpec/EmptyExampleGroup -- the context blocks are dynamically generated
+RSpec.describe RemoteDevelopment::NamespaceClusterAgentMappings::Delete::Main, :rd_fast, feature_category: :remote_development do
let(:context_passed_along_steps) { {} }
let(:rop_steps) do
[
diff --git a/ee/spec/lib/remote_development/rd_fast_spec_helper.rb b/ee/spec/lib/remote_development/rd_fast_spec_helper.rb
index dc5a5bf406c07d98ca3970f8dfd099dfa65792ee..d860fd46ed965bee1a3895db628a4df80807fa71 100644
--- a/ee/spec/lib/remote_development/rd_fast_spec_helper.rb
+++ b/ee/spec/lib/remote_development/rd_fast_spec_helper.rb
@@ -6,3 +6,4 @@
# EE-specific helper logic
require_relative '../../support/shared_contexts/remote_development/agent_info_status_fixture_not_implemented_error'
require_relative '../../support/shared_contexts/remote_development/remote_development_shared_contexts'
+require_relative '../../../app/models/remote_development/enums/workspace'
diff --git a/ee/spec/lib/remote_development/workspaces/create/creator_spec.rb b/ee/spec/lib/remote_development/workspaces/create/creator_spec.rb
index 718e1207fe385fcece9ccd7f7d598a81fc4e8901..88dada325af331c94cbe801f0f89bb5a145703a3 100644
--- a/ee/spec/lib/remote_development/workspaces/create/creator_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/create/creator_spec.rb
@@ -6,7 +6,7 @@
# rubocop:disable Rails/SaveBang -- method shadowing
Messages = RemoteDevelopment::Messages
-RSpec.describe ::RemoteDevelopment::Workspaces::Create::Creator, feature_category: :remote_development do # rubocop:disable RSpec/EmptyExampleGroup -- the context blocks are dynamically generated
+RSpec.describe ::RemoteDevelopment::Workspaces::Create::Creator, feature_category: :remote_development do
let(:rop_steps) do
[
[RemoteDevelopment::Workspaces::Create::PersonalAccessTokenCreator, :and_then],
@@ -82,8 +82,6 @@
end
end
- # rubocop:disable Style/TrailingCommaInArrayLiteral -- let the last element have a comma for simpler diffs
- # rubocop:disable Layout/LineLength -- we want to avoid excessive wrapping for RSpec::Parameterized Nested Array Style so we can have formatting consistency between entries
where(:case_name, :err_result_for_step, :expected_response) do
[
[
@@ -112,8 +110,6 @@
]
]
end
- # rubocop:enable Style/TrailingCommaInArrayLiteral
- # rubocop:enable Layout/LineLength
# rubocop:enable Rails/SaveBang
with_them do
it_behaves_like "rop invocation with error response"
diff --git a/ee/spec/lib/remote_development/workspaces/create/main_integration_spec.rb b/ee/spec/lib/remote_development/workspaces/create/main_integration_spec.rb
index afbe26b09c9bf9c3b68b0830c9e581b2982b5f71..fd23f054170461453588e00caedab6c03d395e08 100644
--- a/ee/spec/lib/remote_development/workspaces/create/main_integration_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/create/main_integration_spec.rb
@@ -21,6 +21,12 @@
let(:processed_devfile) { YAML.safe_load(example_processed_devfile).to_h }
let(:editor) { 'webide' }
let(:workspace_root) { '/projects' }
+ let(:variables) do
+ [
+ { key: 'VAR1', value: 'value 1', type: 'ENVIRONMENT' },
+ { key: 'VAR2', value: 'value 2', type: 'ENVIRONMENT' }
+ ]
+ end
let(:project) do
files = { devfile_path => devfile_yaml }
@@ -40,7 +46,8 @@
max_hours_before_termination: 24,
desired_state: RemoteDevelopment::Workspaces::States::RUNNING,
devfile_ref: devfile_ref,
- devfile_path: devfile_path
+ devfile_path: devfile_path,
+ variables: variables
}
end
@@ -106,6 +113,16 @@
actual_processed_devfile = YAML.safe_load(workspace.processed_devfile).to_h
expect(actual_processed_devfile).to eq(processed_devfile)
+
+ variables.each do |variable|
+ expect(
+ RemoteDevelopment::WorkspaceVariable.where(
+ workspace: workspace,
+ key: variable[:key],
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES_FOR_GRAPHQL[variable[:type]]
+ ).first&.value
+ ).to eq(variable[:value])
+ end
end
end
diff --git a/ee/spec/lib/remote_development/workspaces/create/workspace_variables_creator_spec.rb b/ee/spec/lib/remote_development/workspaces/create/workspace_variables_creator_spec.rb
index 7f503002fd6ecd51ebe5f36a280b88d7bbdbe9ec..88cb887dcb5454525439fe74586c11cc81506a19 100644
--- a/ee/spec/lib/remote_development/workspaces/create/workspace_variables_creator_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/create/workspace_variables_creator_spec.rb
@@ -11,12 +11,13 @@
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:workspace) { create(:workspace, user: user, personal_access_token: personal_access_token) }
let(:settings) { { some_setting: "context" } }
+ let(:user_provided_variables) { [{ key: "VAR1", value: "value 1" }, { key: "VAR2", value: "value 2" }] }
let(:returned_workspace_variables) do
[
{
key: "key1",
value: "value1",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file],
workspace_id: workspace.id
},
{
@@ -36,7 +37,8 @@
user_name: user.name,
user_email: user.email,
workspace_id: workspace.id,
- settings: settings
+ settings: settings,
+ variables: user_provided_variables
}
end
@@ -45,7 +47,10 @@
workspace: workspace,
personal_access_token: personal_access_token,
current_user: user,
- settings: settings
+ settings: settings,
+ params: {
+ variables: user_provided_variables
+ }
}
end
@@ -59,7 +64,7 @@
end
context 'when workspace variables create is successful' do
- let(:valid_variable_type) { RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR }
+ let(:valid_variable_type) { RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment] }
let(:variable_type) { valid_variable_type }
it 'creates the workspace variable records and returns ok result containing original context' do
diff --git a/ee/spec/lib/remote_development/workspaces/create/workspace_variables_spec.rb b/ee/spec/lib/remote_development/workspaces/create/workspace_variables_spec.rb
index 74471ec5d24e4703f39cf210c80fa4bcd92be274..56a3ab0cd163fc22d23b3e285ab4660a4914af0d 100644
--- a/ee/spec/lib/remote_development/workspaces/create/workspace_variables_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/create/workspace_variables_spec.rb
@@ -41,91 +41,103 @@
{
key: "gl_token",
value: "example-pat-value",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file],
workspace_id: workspace_id
},
{
key: "gl_git_credential_store.sh",
value: git_credential_store_script,
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_COUNT",
value: "3",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_KEY_0",
value: "credential.helper",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_VALUE_0",
value: "/.workspace-data/variables/file/gl_git_credential_store.sh",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_KEY_1",
value: "user.name",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_VALUE_1",
value: "example.user.name",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_KEY_2",
value: "user.email",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GIT_CONFIG_VALUE_2",
value: "example@user.email",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GL_GIT_CREDENTIAL_STORE_FILE_PATH",
value: "/.workspace-data/variables/file/gl_git_credential_store.sh",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GL_TOKEN_FILE_PATH",
value: "/.workspace-data/variables/file/gl_token",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GL_WORKSPACE_DOMAIN_TEMPLATE",
value: "${PORT}-name.example.dns.zone",
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GL_EDITOR_EXTENSIONS_GALLERY_SERVICE_URL",
value: vscode_extensions_gallery_service_url,
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GL_EDITOR_EXTENSIONS_GALLERY_ITEM_URL",
value: vscode_extensions_gallery_item_url,
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
workspace_id: workspace_id
},
{
key: "GL_EDITOR_EXTENSIONS_GALLERY_RESOURCE_URL_TEMPLATE",
value: vscode_extensions_gallery_resource_url_template,
- variable_type: RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR,
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
+ workspace_id: workspace_id
+ },
+ {
+ key: "VAR1",
+ value: "value 1",
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment],
+ workspace_id: workspace_id
+ },
+ {
+ key: "/path/to/file",
+ value: "value 2",
+ variable_type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file],
workspace_id: workspace_id
}
]
@@ -145,7 +157,19 @@
item_url: vscode_extensions_gallery_item_url,
resource_url_template: vscode_extensions_gallery_resource_url_template
}
- }
+ },
+ variables: [
+ {
+ key: "VAR1",
+ value: "value 1",
+ type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment]
+ },
+ {
+ key: "/path/to/file",
+ value: "value 2",
+ type: RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file]
+ }
+ ]
)
end
diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/input/actual_state_calculator_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/input/actual_state_calculator_spec.rb
index 14c823387c1401b50acbf5aadd3a8c62a0ca8a1c..b653a52e243df7fccbc7283b59d5b1ddd488b270 100644
--- a/ee/spec/lib/remote_development/workspaces/reconcile/input/actual_state_calculator_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/reconcile/input/actual_state_calculator_spec.rb
@@ -54,7 +54,7 @@
previous_actual_state: previous_actual_state,
current_actual_state: current_actual_state,
workspace_exists: workspace_exists,
- workspace_variables_env_var: {},
+ workspace_variables_environment: {},
workspace_variables_file: {}
)
workspace_agent_info_hash.fetch(:latest_k8s_deployment_info).to_h
diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/input/factory_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/input/factory_spec.rb
index c9f0b2afa5e4cac78e20baa2967d9f039d6f7381..e6c6f17596beb23d9623fb3878fc53c54e5b625c 100644
--- a/ee/spec/lib/remote_development/workspaces/reconcile/input/factory_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/reconcile/input/factory_spec.rb
@@ -16,7 +16,7 @@
previous_actual_state: previous_actual_state,
current_actual_state: current_actual_state,
workspace_exists: false,
- workspace_variables_env_var: {},
+ workspace_variables_environment: {},
workspace_variables_file: {}
)
end
diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb
index 969ec5c90d7373827f35c1b7cf92e3dbebaa947e..f182a738811b4a9023d8e924ab96c76e7fb4d57c 100644
--- a/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/reconcile/main_integration_spec.rb
@@ -513,7 +513,7 @@
previous_actual_state: RemoteDevelopment::Workspaces::States::STOPPING,
current_actual_state: RemoteDevelopment::Workspaces::States::STOPPED,
workspace_exists: false,
- workspace_variables_env_var: {},
+ workspace_variables_environment: {},
workspace_variables_file: {}
)
end
diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/main_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/main_spec.rb
index 1776985ce7a5ab393f17307d19ceae564227238a..ba5dd6f29125cf93cfe99724846f1972d4e20631 100644
--- a/ee/spec/lib/remote_development/workspaces/reconcile/main_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/reconcile/main_spec.rb
@@ -2,7 +2,7 @@
require_relative '../../rd_fast_spec_helper'
-RSpec.describe RemoteDevelopment::Workspaces::Reconcile::Main, :rd_fast, feature_category: :remote_development do # rubocop:disable RSpec/EmptyExampleGroup -- the context blocks are dynamically generated
+RSpec.describe RemoteDevelopment::Workspaces::Reconcile::Main, :rd_fast, feature_category: :remote_development do
let(:context_passed_along_steps) { {} }
let(:response_payload) do
{
diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_spec.rb
index 46c5e65dcedaf57209d5b6f0c733a07bfc3cf07c..cb3a5c283d99bf80b658d758f20b398c417267aa 100644
--- a/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_spec.rb
@@ -26,7 +26,7 @@
end
let(:domain_template) { "{{.port}}-#{workspace.name}.#{workspace.dns_zone}" }
- let(:env_var_secret_name) { "#{workspace.name}-env-var" }
+ let(:environment_secret_name) { "#{workspace.name}-env-var" }
let(:file_secret_name) { "#{workspace.name}-file" }
let(:egress_ip_rules) { RemoteDevelopment::AgentConfig::Updater::NETWORK_POLICY_EGRESS_DEFAULT }
let(:max_resources_per_workspace) { {} }
@@ -38,7 +38,7 @@
YAML.load_stream(
create_config_to_apply(
workspace: workspace,
- workspace_variables_env_var: {},
+ workspace_variables_environment: {},
workspace_variables_file: {},
started: true,
include_inventory: false,
@@ -70,7 +70,7 @@
'workspaces.gitlab.com/max-resources-per-workspace-sha256' =>
Digest::SHA256.hexdigest(max_resources_per_workspace.sort.to_h.to_s)
},
- env_secret_names: [env_var_secret_name],
+ env_secret_names: [environment_secret_name],
file_secret_names: [file_secret_name],
default_resources_per_workspace_container: default_resources_per_workspace_container,
logger: logger
@@ -101,7 +101,7 @@
domain_template: "",
labels: {},
annotations: {},
- env_secret_names: [env_var_secret_name],
+ env_secret_names: [environment_secret_name],
file_secret_names: [file_secret_name],
default_resources_per_workspace_container: default_resources_per_workspace_container,
logger: logger
diff --git a/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_v2_spec.rb b/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_v2_spec.rb
index 4f266a1f801b5b243d026df32110abdf6c1787e5..43ee5c21c3830932394036fdefa08914ab1c8405 100644
--- a/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_v2_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/reconcile/output/devfile_parser_v2_spec.rb
@@ -27,7 +27,7 @@
end
let(:domain_template) { "{{.port}}-#{workspace.name}.#{workspace.dns_zone}" }
- let(:env_var_secret_name) { "#{workspace.name}-env-var" }
+ let(:environment_secret_name) { "#{workspace.name}-env-var" }
let(:file_secret_name) { "#{workspace.name}-file" }
let(:egress_ip_rules) { RemoteDevelopment::AgentConfig::Updater::NETWORK_POLICY_EGRESS_DEFAULT }
@@ -35,7 +35,7 @@
YAML.load_stream(
create_config_to_apply_v2(
workspace: workspace,
- workspace_variables_env_var: {},
+ workspace_variables_environment: {},
workspace_variables_file: {},
started: true,
include_inventory: false,
@@ -64,7 +64,7 @@
'workspaces.gitlab.com/host-template' => domain_template,
'workspaces.gitlab.com/id' => workspace.id
},
- env_secret_names: [env_var_secret_name],
+ env_secret_names: [environment_secret_name],
file_secret_names: [file_secret_name],
logger: logger
)
@@ -94,7 +94,7 @@
domain_template: "",
labels: {},
annotations: {},
- env_secret_names: [env_var_secret_name],
+ env_secret_names: [environment_secret_name],
file_secret_names: [file_secret_name],
logger: logger
)
diff --git a/ee/spec/lib/remote_development/workspaces/update/main_spec.rb b/ee/spec/lib/remote_development/workspaces/update/main_spec.rb
index e6c2b5c4d4ffbdc10fdc724ff8d70d0001e57786..9e3370a8b057b85763a1126113e9f220436edcb8 100644
--- a/ee/spec/lib/remote_development/workspaces/update/main_spec.rb
+++ b/ee/spec/lib/remote_development/workspaces/update/main_spec.rb
@@ -2,7 +2,7 @@
require_relative '../../rd_fast_spec_helper'
-RSpec.describe RemoteDevelopment::Workspaces::Update::Main, :rd_fast, feature_category: :remote_development do # rubocop:disable RSpec/EmptyExampleGroup -- the context blocks are dynamically generated
+RSpec.describe RemoteDevelopment::Workspaces::Update::Main, :rd_fast, feature_category: :remote_development do
let(:context_passed_along_steps) { {} }
let(:rop_steps) do
@@ -59,8 +59,6 @@
end
end
- # rubocop:disable Style/TrailingCommaInArrayLiteral -- let the last element have a comma for simpler diffs
- # rubocop:disable Layout/LineLength -- we want to avoid excessive wrapping for RSpec::Parameterized Nested Array Style so we can have formatting consistency between entries
where(:case_name, :err_result_for_step, :expected_response) do
[
[
@@ -73,7 +71,7 @@
status: :error,
message: lazy { "Unauthorized: #{error_details}" },
reason: :unauthorized
- },
+ }
],
[
"when Updater returns WorkspaceUpdateFailed",
@@ -85,7 +83,7 @@
status: :error,
message: lazy { "Workspace update failed: #{error_details}" },
reason: :bad_request
- },
+ }
],
[
"when an unmatched error is returned, an exception is raised",
@@ -98,8 +96,6 @@
]
end
- # rubocop:enable Style/TrailingCommaInArrayLiteral
- # rubocop:enable Layout/LineLength
with_them do
it_behaves_like "rop invocation with error response"
diff --git a/ee/spec/models/remote_development/workspace_variable_spec.rb b/ee/spec/models/remote_development/workspace_variable_spec.rb
index dfe5af8f850d69b1f46b7ebe16898938b86b5008..26f3a5ff2a286ee358770762a56e4babe5dedb35 100644
--- a/ee/spec/models/remote_development/workspace_variable_spec.rb
+++ b/ee/spec/models/remote_development/workspace_variable_spec.rb
@@ -4,13 +4,14 @@
RSpec.describe RemoteDevelopment::WorkspaceVariable, feature_category: :remote_development do
let(:key) { 'key_1' }
- let(:value) { 'value_1' }
- let(:variable_type_env_var) { RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_ENV_VAR }
- let(:variable_type_file) { RemoteDevelopment::Workspaces::Create::WorkspaceVariables::VARIABLE_TYPE_FILE }
+ let(:current_value) { 'value_1' }
+ let(:value) { current_value }
+ let(:variable_type_environment) { RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:environment] }
+ let(:variable_type_file) { RemoteDevelopment::Enums::Workspace::WORKSPACE_VARIABLE_TYPES[:file] }
let(:variable_type) { variable_type_file }
let(:variable_type_values) do
[
- variable_type_env_var,
+ variable_type_environment,
variable_type_file
]
end
@@ -40,14 +41,22 @@
it 'can be decrypted' do
expect(workspace_variable.value).to eq(value)
end
+
+ describe 'can be empty' do
+ let(:current_value) { '' }
+
+ it 'is saved' do
+ expect(workspace_variable.value).to eq(value)
+ end
+ end
end
describe 'scopes' do
- describe 'with_variable_type_env_var' do
- let(:variable_type) { variable_type_env_var }
+ describe 'with_variable_type_environment' do
+ let(:variable_type) { variable_type_environment }
it 'returns the record' do
- expect(described_class.with_variable_type_env_var).to eq([workspace_variable])
+ expect(described_class.with_variable_type_environment).to eq([workspace_variable])
end
end
diff --git a/ee/spec/policies/remote_development/group_policy_spec.rb b/ee/spec/policies/remote_development/group_policy_spec.rb
index d667532afd62e4cf371e0ee07cd6dcb105f2ad0f..03270777309bd6ffa2335e39731a6ea218805976 100644
--- a/ee/spec/policies/remote_development/group_policy_spec.rb
+++ b/ee/spec/policies/remote_development/group_policy_spec.rb
@@ -18,7 +18,6 @@
describe ':admin_remote_development_cluster_agent_mapping' do
let(:ability) { :admin_remote_development_cluster_agent_mapping }
- # rubocop:disable Layout/LineLength -- TableSyntax should not be split across lines
where(:policy_class, :user, :result) do
# In the future, there is a possibility that a common policy module may have to be mixed in to multiple
# target policy types for ex. ProjectNamespacePolicy or UserNamespacePolicy. As a result, the policy_class
@@ -35,7 +34,6 @@
GroupPolicy | ref(:admin_in_admin_mode) | true
GroupPolicy | ref(:admin_in_non_admin_mode) | false
end
- # rubocop:enable Layout/LineLength
with_them do
subject(:policy) { policy_class.new(user, group) }
@@ -54,7 +52,6 @@
describe ':read_remote_development_cluster_agent_mapping' do
let(:ability) { :read_remote_development_cluster_agent_mapping }
- # rubocop:disable Layout/LineLength -- TableSyntax should not be split across lines
where(:policy_class, :user, :result) do
# In the future, there is a possibility that a common policy module may have to be mixed in to multiple
# target policy types for ex. ProjectNamespacePolicy or UserNamespacePolicy. As a result, the policy_class
@@ -71,7 +68,6 @@
GroupPolicy | ref(:admin_in_admin_mode) | true
GroupPolicy | ref(:admin_in_non_admin_mode) | false
end
- # rubocop:enable Layout/LineLength
with_them do
subject(:policy) { policy_class.new(user, group) }
diff --git a/ee/spec/requests/api/graphql/mutations/remote_development/workspaces/create_spec.rb b/ee/spec/requests/api/graphql/mutations/remote_development/workspaces/create_spec.rb
index 8390b647fc8fae3a9c6784116ca8711f3f499beb..bacfbc0d1feabb4fd7399ad98cd201ed8ac37206 100644
--- a/ee/spec/requests/api/graphql/mutations/remote_development/workspaces/create_spec.rb
+++ b/ee/spec/requests/api/graphql/mutations/remote_development/workspaces/create_spec.rb
@@ -45,7 +45,11 @@
cluster_agent_id: agent.to_global_id.to_s,
project_id: workspace_project.to_global_id.to_s,
devfile_ref: 'main',
- devfile_path: '.devfile.yaml'
+ devfile_path: '.devfile.yaml',
+ variables: [
+ { key: 'VAR1', value: 'value 1', type: 'ENVIRONMENT' },
+ { key: 'VAR2', value: 'value 2', type: 'ENVIRONMENT' }
+ ]
}
end
diff --git a/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb b/ee/spec/support/shared_contexts/remote_development/remote_development_shared_contexts.rb
index 8b501768acd77847a962fdf4d5df137bdcf87cbf..54174021ba49873c7d0c8758b87ec9e199323449 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
@@ -10,7 +10,7 @@ def create_workspace_agent_info_hash(
current_actual_state:,
# NOTE: workspace_exists is whether the workspace exists in the cluster at the time of the current_actual_state.
workspace_exists:,
- workspace_variables_env_var: nil,
+ workspace_variables_environment: nil,
workspace_variables_file: nil,
resource_version: '1',
dns_zone: 'workspaces.localdev.me',
@@ -241,19 +241,17 @@ def create_workspace_agent_info_hash(
# updatedReplicas: 1
# STATUS_YAML
else
- # rubocop:todo Layout/LineEndStringConcatenationIndentation -- make this cop accept standard 2-character indentation
msg =
'Unsupported state transition passed for create_workspace_agent_info_hash fixture creation: ' \
"actual_state: #{previous_actual_state} -> #{current_actual_state}, " \
"existing_workspace: #{workspace_exists}"
- # rubocop:enable Layout/LineEndStringConcatenationIndentation
raise RemoteDevelopment::AgentInfoStatusFixtureNotImplementedError, msg
end
# rubocop:enable Lint/DuplicateBranch
config_to_apply_yaml = create_config_to_apply(
workspace: workspace,
- workspace_variables_env_var: workspace_variables_env_var,
+ workspace_variables_environment: workspace_variables_environment,
workspace_variables_file: workspace_variables_file,
started: started,
include_inventory: false,
@@ -304,7 +302,7 @@ def create_config_to_apply(workspace:, **args)
def create_config_to_apply_v3(
workspace:,
started:,
- workspace_variables_env_var: nil,
+ workspace_variables_environment: nil,
workspace_variables_file: nil,
include_inventory: true,
include_network_policy: true,
@@ -380,12 +378,12 @@ def create_config_to_apply_v3(
agent_id: workspace.agent.id
)
- workspace_secret_env_var = workspace_secret_env_var(
+ workspace_secret_environment = workspace_secret_environment(
workspace_name: workspace.name,
workspace_namespace: workspace.namespace,
labels: labels,
annotations: secrets_annotations,
- workspace_variables_env_var: workspace_variables_env_var || get_workspace_variables_env_var(
+ workspace_variables_environment: workspace_variables_environment || get_workspace_variables_environment(
workspace_variables: workspace.workspace_variables
)
)
@@ -416,7 +414,7 @@ def create_config_to_apply_v3(
resources << workspace_network_policy if include_network_policy
resources << workspace_resource_quota if include_all_resources && !max_resources_per_workspace.blank?
resources << workspace_secrets_inventory if include_all_resources && include_inventory
- resources << workspace_secret_env_var if include_all_resources
+ resources << workspace_secret_environment if include_all_resources
resources << workspace_secret_file if include_all_resources
resources.map do |resource|
@@ -427,7 +425,7 @@ def create_config_to_apply_v3(
def create_config_to_apply_v2(
workspace:,
started:,
- workspace_variables_env_var: nil,
+ workspace_variables_environment: nil,
workspace_variables_file: nil,
include_inventory: true,
include_network_policy: true,
@@ -494,12 +492,12 @@ def create_config_to_apply_v2(
agent_id: workspace.agent.id
)
- workspace_secret_env_var = workspace_secret_env_var(
+ workspace_secret_environment = workspace_secret_environment(
workspace_name: workspace.name,
workspace_namespace: workspace.namespace,
labels: labels,
annotations: secrets_annotations,
- workspace_variables_env_var: workspace_variables_env_var || get_workspace_variables_env_var(
+ workspace_variables_environment: workspace_variables_environment || get_workspace_variables_environment(
workspace_variables: workspace.workspace_variables
)
)
@@ -521,7 +519,7 @@ def create_config_to_apply_v2(
resources << workspace_pvc
resources << workspace_network_policy if include_network_policy
resources << workspace_secrets_inventory if include_all_resources && include_inventory
- resources << workspace_secret_env_var if include_all_resources
+ resources << workspace_secret_environment if include_all_resources
resources << workspace_secret_file if include_all_resources
resources.map do |resource|
@@ -1035,30 +1033,13 @@ def workspace_secrets_inventory(
}
end
- def workspace_secret_env_var(
+ def workspace_secret_environment(
workspace_name:,
workspace_namespace:,
labels:,
annotations:,
- workspace_variables_env_var:
+ workspace_variables_environment:
)
- git_config_count = workspace_variables_env_var.fetch('GIT_CONFIG_COUNT', '')
- git_config_key_0 = workspace_variables_env_var.fetch('GIT_CONFIG_KEY_0', '')
- git_config_value_0 = workspace_variables_env_var.fetch('GIT_CONFIG_VALUE_0', '')
- git_config_key_1 = workspace_variables_env_var.fetch('GIT_CONFIG_KEY_1', '')
- git_config_value_1 = workspace_variables_env_var.fetch('GIT_CONFIG_VALUE_1', '')
- git_config_key_2 = workspace_variables_env_var.fetch('GIT_CONFIG_KEY_2', '')
- git_config_value_2 = workspace_variables_env_var.fetch('GIT_CONFIG_VALUE_2', '')
- gl_git_credential_store_file_path = workspace_variables_env_var.fetch('GL_GIT_CREDENTIAL_STORE_FILE_PATH', '')
- gl_token_file_path = workspace_variables_env_var.fetch('GL_TOKEN_FILE_PATH', '')
- gl_workspace_domain_template = workspace_variables_env_var.fetch('GL_WORKSPACE_DOMAIN_TEMPLATE', '')
- gl_editor_extensions_gallery_service_url =
- workspace_variables_env_var.fetch('GL_EDITOR_EXTENSIONS_GALLERY_SERVICE_URL', '')
- gl_editor_extensions_gallery_item_url =
- workspace_variables_env_var.fetch('GL_EDITOR_EXTENSIONS_GALLERY_ITEM_URL', '')
- gl_editor_extensions_gallery_resource_url_template =
- workspace_variables_env_var.fetch('GL_EDITOR_EXTENSIONS_GALLERY_RESOURCE_URL_TEMPLATE', '')
-
# TODO: figure out why there is flakiness in the order of the environment variables -- https://gitlab.com/gitlab-org/gitlab/-/issues/451934
{
kind: "Secret",
@@ -1069,22 +1050,7 @@ def workspace_secret_env_var(
labels: labels,
annotations: annotations
},
- data: {
- GIT_CONFIG_COUNT: Base64.strict_encode64(git_config_count).to_s,
- GIT_CONFIG_KEY_0: Base64.strict_encode64(git_config_key_0).to_s,
- GIT_CONFIG_VALUE_0: Base64.strict_encode64(git_config_value_0).to_s,
- GIT_CONFIG_KEY_1: Base64.strict_encode64(git_config_key_1).to_s,
- GIT_CONFIG_VALUE_1: Base64.strict_encode64(git_config_value_1).to_s,
- GIT_CONFIG_KEY_2: Base64.strict_encode64(git_config_key_2).to_s,
- GIT_CONFIG_VALUE_2: Base64.strict_encode64(git_config_value_2).to_s,
- GL_GIT_CREDENTIAL_STORE_FILE_PATH: Base64.strict_encode64(gl_git_credential_store_file_path).to_s,
- GL_TOKEN_FILE_PATH: Base64.strict_encode64(gl_token_file_path).to_s,
- GL_WORKSPACE_DOMAIN_TEMPLATE: Base64.strict_encode64(gl_workspace_domain_template).to_s,
- GL_EDITOR_EXTENSIONS_GALLERY_SERVICE_URL: Base64.strict_encode64(gl_editor_extensions_gallery_service_url).to_s,
- GL_EDITOR_EXTENSIONS_GALLERY_ITEM_URL: Base64.strict_encode64(gl_editor_extensions_gallery_item_url).to_s,
- GL_EDITOR_EXTENSIONS_GALLERY_RESOURCE_URL_TEMPLATE:
- Base64.strict_encode64(gl_editor_extensions_gallery_resource_url_template).to_s
- }
+ data: workspace_variables_environment.transform_values { |v| Base64.strict_encode64(v).to_s }
}
end
@@ -1095,8 +1061,6 @@ def workspace_secret_file(
annotations:,
workspace_variables_file:
)
- gl_git_credential_store = workspace_variables_file.fetch('gl_git_credential_store.sh', '')
- gl_token = workspace_variables_file.fetch('gl_token', '')
{
kind: "Secret",
apiVersion: "v1",
@@ -1106,15 +1070,12 @@ def workspace_secret_file(
labels: labels,
annotations: annotations
},
- data: {
- gl_token: Base64.strict_encode64(gl_token).to_s,
- "gl_git_credential_store.sh": Base64.strict_encode64(gl_git_credential_store).to_s
- }
+ data: workspace_variables_file.transform_values { |v| Base64.strict_encode64(v).to_s }
}
end
- def get_workspace_variables_env_var(workspace_variables:)
- workspace_variables.with_variable_type_env_var.each_with_object({}) do |workspace_variable, hash|
+ def get_workspace_variables_environment(workspace_variables:)
+ workspace_variables.with_variable_type_environment.each_with_object({}) do |workspace_variable, hash|
hash[workspace_variable.key] = workspace_variable.value
end
end
@@ -1129,7 +1090,7 @@ def get_workspace_host_template_annotation(workspace_name, dns_zone)
"{{.port}}-#{workspace_name}.#{dns_zone}"
end
- def get_workspace_host_template_env_var(workspace_name, dns_zone)
+ def get_workspace_host_template_environment(workspace_name, dns_zone)
"${PORT}-#{workspace_name}.#{dns_zone}"
end
diff --git a/lib/remote_development/settings/current_settings_reader.rb b/lib/remote_development/settings/current_settings_reader.rb
index 6870db26f7e410e0aa403a9cb4deb686ba2faa89..9d21ccb76a5a3cec771496a3fe530e049f55c118 100644
--- a/lib/remote_development/settings/current_settings_reader.rb
+++ b/lib/remote_development/settings/current_settings_reader.rb
@@ -22,7 +22,7 @@ def self.read(context)
# err_result will be set to a non-nil Result.err if type check fails
err_result = Result.err(SettingsCurrentSettingsReadFailed.new(
details: "Gitlab::CurrentSettings.#{setting_name} type of '#{current_setting_value.class}' " \
- "did not match initialized Remote Development Settings type of '#{setting_type}'." # rubocop:disable Layout/LineEndStringConcatenationIndentation -- use default RubyMine formatting
+ "did not match initialized Remote Development Settings type of '#{setting_type}'."
))
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8e0fd204c2594d8154ef3c796e1dbc6e74d9e5b2..efc73c603849b5b95b086835c1c089153164cfbd 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3263,6 +3263,9 @@ msgstr ""
msgid "Add topics to projects to help users find them."
msgstr ""
+msgid "Add variable"
+msgstr ""
+
msgid "Add vulnerability finding"
msgstr ""
@@ -34770,6 +34773,9 @@ msgstr ""
msgid "No user provided"
msgstr ""
+msgid "No variables"
+msgstr ""
+
msgid "No vulnerabilities present"
msgstr ""
@@ -43675,6 +43681,9 @@ msgstr ""
msgid "Remove user from project"
msgstr ""
+msgid "Remove variable"
+msgstr ""
+
msgid "Remove weight"
msgstr ""
diff --git a/qa/qa/ee/page/workspace/list.rb b/qa/qa/ee/page/workspace/list.rb
index 5af0593cf52037e8b78a86a1ce88de3c73e1784f..12def2374a9796839ca7d9daf7d08da194707bc1 100644
--- a/qa/qa/ee/page/workspace/list.rb
+++ b/qa/qa/ee/page/workspace/list.rb
@@ -35,6 +35,7 @@ def create_workspace(agent, project)
QA::EE::Page::Workspace::New.perform do |new|
new.select_devfile_project(project)
new.select_cluster_agent(agent)
+ new.add_new_variable('VAR1', 'value 1')
new.save_workspace
end
Support::WaitForRequests.wait_for_requests(skip_finished_loading_check: true)
diff --git a/qa/qa/ee/page/workspace/new.rb b/qa/qa/ee/page/workspace/new.rb
index 1bd4402ab3d5a20593d356f1bbb9e3eda780701b..c04aa5bff1d485f221a7bda923fe7e4872891a3b 100644
--- a/qa/qa/ee/page/workspace/new.rb
+++ b/qa/qa/ee/page/workspace/new.rb
@@ -12,6 +12,10 @@ class New < QA::Page::Base
element 'create-workspace'
end
+ view 'ee/app/assets/javascripts/workspaces/user/components/workspace_variables.vue' do
+ element 'add-variable'
+ end
+
def select_devfile_project(project)
click_element('workspace-devfile-project-id-field')
search_and_select(project)
@@ -26,6 +30,12 @@ def select_cluster_agent(agent)
agent_selector.select agent
end
+ def add_new_variable(key, value)
+ click_element('add-variable')
+ fill_in 'Variable Key', with: key
+ fill_in 'Variable Value', with: value
+ end
+
def save_workspace
click_element('create-workspace', skip_finished_loading_check: true)
end
diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb
index 155a6dba52c9017eb0dde60aa0715fc91ffbb691..3bd1dd102575d3344f7a0586836a2ceaabb3a6eb 100644
--- a/spec/support/matchers/graphql_matchers.rb
+++ b/spec/support/matchers/graphql_matchers.rb
@@ -109,7 +109,7 @@ def expected_field_names
def expected_names(field)
@names ||= Array.wrap(expected).map { |name| GraphqlHelpers.fieldnamerize(name) }
- if field.type.try(:ancestors)&.include?(GraphQL::Types::Relay::BaseConnection)
+ if field.try(:type).try(:ancestors)&.include?(GraphQL::Types::Relay::BaseConnection)
@names | %w[after before first last]
else
@names