Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-12-18 12:07:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-12-18 12:07:38 +0300
commit1a9d9cc14ec54036548824e3ce17da03960f5f81 (patch)
tree4b93fa74f393a1978ea9c2628516eb4a449b8704 /spec
parentdad534d98a3f86bfa079b7ebd980448641cc9c7c (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/environments/prometheus_api_controller_spec.rb34
-rw-r--r--spec/services/prometheus/proxy_variable_substitution_service_spec.rb146
-rw-r--r--spec/services/template_engines/liquid_service_spec.rb126
3 files changed, 305 insertions, 1 deletions
diff --git a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
index 0940fccb431..793c10f0b21 100644
--- a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
+++ b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
@@ -78,6 +78,40 @@ describe Projects::Environments::PrometheusApiController do
end
end
end
+
+ context 'with variables' do
+ let(:pod_name) { "pod1" }
+
+ before do
+ expected_params[:query] = %{up{pod_name="#{pod_name}"}}
+ expected_params[:variables] = ['pod_name', pod_name]
+ end
+
+ it 'replaces variables with values' do
+ get :proxy, params: environment_params.merge(
+ query: 'up{pod_name="{{pod_name}}"}', variables: ['pod_name', pod_name]
+ )
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(Prometheus::ProxyService).to have_received(:new)
+ .with(environment, 'GET', 'query', expected_params)
+ end
+
+ context 'with invalid variables' do
+ let(:params_with_invalid_variables) do
+ environment_params.merge(
+ query: 'up{pod_name="{{pod_name}}"}', variables: ['a']
+ )
+ end
+
+ it 'returns 400' do
+ get :proxy, params: params_with_invalid_variables
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(Prometheus::ProxyService).not_to receive(:new)
+ end
+ end
+ end
end
context 'with nil result' do
diff --git a/spec/services/prometheus/proxy_variable_substitution_service_spec.rb b/spec/services/prometheus/proxy_variable_substitution_service_spec.rb
index b1cdb8fd3ae..9978c631366 100644
--- a/spec/services/prometheus/proxy_variable_substitution_service_spec.rb
+++ b/spec/services/prometheus/proxy_variable_substitution_service_spec.rb
@@ -39,8 +39,12 @@ describe Prometheus::ProxyVariableSubstitutionService do
end
context 'with predefined variables' do
+ let(:params_keys) { { query: 'up{%{environment_filter}}' } }
+
it_behaves_like 'success' do
- let(:expected_query) { %Q[up{environment="#{environment.slug}"}] }
+ let(:expected_query) do
+ %Q[up{container_name!="POD",environment="#{environment.slug}"}]
+ end
end
context 'with nil query' do
@@ -50,6 +54,133 @@ describe Prometheus::ProxyVariableSubstitutionService do
let(:expected_query) { nil }
end
end
+
+ context 'with liquid format' do
+ let(:params_keys) do
+ { query: 'up{environment="{{ci_environment_slug}}"}' }
+ end
+
+ it_behaves_like 'success' do
+ let(:expected_query) { %Q[up{environment="#{environment.slug}"}] }
+ end
+ end
+
+ context 'with ruby and liquid formats' do
+ let(:params_keys) do
+ { query: 'up{%{environment_filter},env2="{{ci_environment_slug}}"}' }
+ end
+
+ it_behaves_like 'success' do
+ let(:expected_query) do
+ %Q[up{container_name!="POD",environment="#{environment.slug}",env2="#{environment.slug}"}]
+ end
+ end
+ end
+ end
+
+ context 'with custom variables' do
+ let(:pod_name) { "pod1" }
+
+ let(:params_keys) do
+ {
+ query: 'up{pod_name="{{pod_name}}"}',
+ variables: ['pod_name', pod_name]
+ }
+ end
+
+ it_behaves_like 'success' do
+ let(:expected_query) { %q[up{pod_name="pod1"}] }
+ end
+
+ context 'with ruby variable interpolation format' do
+ let(:params_keys) do
+ {
+ query: 'up{pod_name="%{pod_name}"}',
+ variables: ['pod_name', pod_name]
+ }
+ end
+
+ it_behaves_like 'success' do
+ # Custom variables cannot be used with the Ruby interpolation format.
+ let(:expected_query) { "up{pod_name=\"%{pod_name}\"}" }
+ end
+ end
+
+ context 'with predefined variables in variables parameter' do
+ let(:params_keys) do
+ {
+ query: 'up{pod_name="{{pod_name}}",env="{{ci_environment_slug}}"}',
+ variables: ['pod_name', pod_name, 'ci_environment_slug', 'custom_value']
+ }
+ end
+
+ it_behaves_like 'success' do
+ # Predefined variable values should not be overwritten by custom variable
+ # values.
+ let(:expected_query) { "up{pod_name=\"#{pod_name}\",env=\"#{environment.slug}\"}" }
+ end
+ end
+
+ context 'with invalid variables parameter' do
+ let(:params_keys) do
+ {
+ query: 'up{pod_name="{{pod_name}}"}',
+ variables: ['a']
+ }
+ end
+
+ it_behaves_like 'error', 'Optional parameter "variables" must be an ' \
+ 'array of keys and values. Ex: [key1, value1, key2, value2]'
+ end
+
+ context 'with nil variables' do
+ let(:params_keys) do
+ {
+ query: 'up{pod_name="{{pod_name}}"}',
+ variables: nil
+ }
+ end
+
+ it_behaves_like 'success' do
+ let(:expected_query) { 'up{pod_name=""}' }
+ end
+ end
+
+ context 'with ruby and liquid variables' do
+ let(:params_keys) do
+ {
+ query: 'up{env1="%{ruby_variable}",env2="{{ liquid_variable }}"}',
+ variables: %w(ruby_variable value liquid_variable env_slug)
+ }
+ end
+
+ it_behaves_like 'success' do
+ # It should replace only liquid variables with their values
+ let(:expected_query) { %q[up{env1="%{ruby_variable}",env2="env_slug"}] }
+ end
+ end
+ end
+
+ context 'with liquid tags and ruby format variables' do
+ let(:params_keys) do
+ {
+ query: 'up{ {% if true %}env1="%{ci_environment_slug}",' \
+ 'env2="{{ci_environment_slug}}"{% endif %} }'
+ }
+ end
+
+ # The following spec will fail and should be changed to a 'success' spec
+ # once we remove support for the Ruby interpolation format.
+ # https://gitlab.com/gitlab-org/gitlab/issues/37990
+ #
+ # Liquid tags `{% %}` cannot be used currently because the Ruby `%`
+ # operator raises an error when it encounters a Liquid `{% %}` tag in the
+ # string.
+ #
+ # Once we remove support for the Ruby format, users can start using
+ # Liquid tags.
+
+ it_behaves_like 'error', 'Malformed string'
end
context 'ruby template rendering' do
@@ -139,5 +270,18 @@ describe Prometheus::ProxyVariableSubstitutionService do
end
end
end
+
+ context 'when liquid template rendering raises error' do
+ before do
+ liquid_service = instance_double(TemplateEngines::LiquidService)
+
+ allow(TemplateEngines::LiquidService).to receive(:new).and_return(liquid_service)
+ allow(liquid_service).to receive(:render).and_raise(
+ TemplateEngines::LiquidService::RenderError, 'error message'
+ )
+ end
+
+ it_behaves_like 'error', 'error message'
+ end
end
end
diff --git a/spec/services/template_engines/liquid_service_spec.rb b/spec/services/template_engines/liquid_service_spec.rb
new file mode 100644
index 00000000000..7c5262bc264
--- /dev/null
+++ b/spec/services/template_engines/liquid_service_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe TemplateEngines::LiquidService do
+ describe '#render' do
+ let(:template) { 'up{env={{ci_environment_slug}}}' }
+ let(:result) { subject }
+
+ let_it_be(:slug) { 'env_slug' }
+
+ let_it_be(:context) do
+ {
+ ci_environment_slug: slug,
+ environment_filter: "container_name!=\"POD\",environment=\"#{slug}\""
+ }
+ end
+
+ subject { described_class.new(template).render(context) }
+
+ it 'with symbol keys in context it substitutes variables' do
+ expect(result).to include("up{env=#{slug}")
+ end
+
+ context 'with multiple occurrences of variable in template' do
+ let(:template) do
+ 'up{env1={{ci_environment_slug}},env2={{ci_environment_slug}}}'
+ end
+
+ it 'substitutes variables' do
+ expect(result).to eq("up{env1=#{slug},env2=#{slug}}")
+ end
+ end
+
+ context 'with multiple variables in template' do
+ let(:template) do
+ 'up{env={{ci_environment_slug}},' \
+ '{{environment_filter}}}'
+ end
+
+ it 'substitutes all variables' do
+ expect(result).to eq(
+ "up{env=#{slug}," \
+ "container_name!=\"POD\",environment=\"#{slug}\"}"
+ )
+ end
+ end
+
+ context 'with unknown variables in template' do
+ let(:template) { 'up{env={{env_slug}}}' }
+
+ it 'does not substitute unknown variables' do
+ expect(result).to eq("up{env=}")
+ end
+ end
+
+ context 'with extra variables in context' do
+ let(:template) { 'up{env={{ci_environment_slug}}}' }
+
+ it 'substitutes variables' do
+ # If context has only 1 key, there is no need for this spec.
+ expect(context.count).to be > 1
+ expect(result).to eq("up{env=#{slug}}")
+ end
+ end
+
+ context 'with unknown and known variables in template' do
+ let(:template) { 'up{env={{ci_environment_slug}},other_env={{env_slug}}}' }
+
+ it 'substitutes known variables' do
+ expect(result).to eq("up{env=#{slug},other_env=}")
+ end
+ end
+
+ context 'Liquid errors' do
+ shared_examples 'raises RenderError' do |message|
+ it do
+ expect { result }.to raise_error(described_class::RenderError, message)
+ end
+ end
+
+ context 'when liquid raises error' do
+ let(:template) { 'up{env={{ci_environment_slug}}' }
+ let(:liquid_template) { Liquid::Template.new }
+
+ before do
+ allow(Liquid::Template).to receive(:parse).with(template).and_return(liquid_template)
+ allow(liquid_template).to receive(:render!).and_raise(exception, message)
+ end
+
+ context 'raises Liquid::MemoryError' do
+ let(:exception) { Liquid::MemoryError }
+ let(:message) { 'Liquid error: Memory limits exceeded' }
+
+ it_behaves_like 'raises RenderError', 'Memory limit exceeded while rendering template'
+ end
+
+ context 'raises Liquid::Error' do
+ let(:exception) { Liquid::Error }
+ let(:message) { 'Liquid error: Generic error message' }
+
+ it_behaves_like 'raises RenderError', 'Error rendering query'
+ end
+ end
+
+ context 'with template that is expensive to render' do
+ let(:template) do
+ '{% assign loop_count = 1000 %}'\
+ '{% assign padStr = "0" %}'\
+ '{% assign number_to_pad = "1" %}'\
+ '{% assign strLength = number_to_pad | size %}'\
+ '{% assign padLength = loop_count | minus: strLength %}'\
+ '{% if padLength > 0 %}'\
+ ' {% assign padded = number_to_pad %}'\
+ ' {% for position in (1..padLength) %}'\
+ ' {% assign padded = padded | prepend: padStr %}'\
+ ' {% endfor %}'\
+ ' {{ padded }}'\
+ '{% endif %}'
+ end
+
+ it_behaves_like 'raises RenderError', 'Memory limit exceeded while rendering template'
+ end
+ end
+ end
+end