summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-03 00:08:11 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-03 00:08:11 +0000
commitbd8fb5668ae739a83d55ec5ca4a04344eef2167e (patch)
treebaf085c6cd58b3b5e5a192d4d3db360d623bb056 /lib
parent561e1b470f0a99fe6304c8f197348c47a637d594 (diff)
downloadgitlab-ce-bd8fb5668ae739a83d55ec5ca4a04344eef2167e.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib')
-rw-r--r--lib/banzai/filter/inline_grafana_metrics_filter.rb33
-rw-r--r--lib/gitlab/import_export/project/tree_restorer.rb2
-rw-r--r--lib/gitlab/import_export/project/tree_saver.rb2
-rw-r--r--lib/gitlab/import_export/relation_rename_service.rb48
-rw-r--r--lib/grafana/time_window.rb130
5 files changed, 151 insertions, 64 deletions
diff --git a/lib/banzai/filter/inline_grafana_metrics_filter.rb b/lib/banzai/filter/inline_grafana_metrics_filter.rb
index 69ae747333f..60a16b164af 100644
--- a/lib/banzai/filter/inline_grafana_metrics_filter.rb
+++ b/lib/banzai/filter/inline_grafana_metrics_filter.rb
@@ -13,13 +13,16 @@ module Banzai
super
end
+ # @return [Hash<Symbol, String>] with keys :grafana_url, :start, and :end
def embed_params(node)
query_params = Gitlab::Metrics::Dashboard::Url.parse_query(node['href'])
- return unless [:panelId, :from, :to].all? do |param|
- query_params.include?(param)
- end
- { url: node['href'], start: query_params[:from], end: query_params[:to] }
+ return unless query_params.include?(:panelId)
+
+ time_window = Grafana::TimeWindow.new(query_params[:from], query_params[:to])
+ url = url_with_window(node['href'], query_params, time_window.in_milliseconds)
+
+ { grafana_url: url }.merge(time_window.formatted)
end
# Selects any links with an href contains the configured
@@ -44,18 +47,24 @@ module Banzai
Gitlab::Routing.url_helpers.project_grafana_api_metrics_dashboard_url(
project,
embedded: true,
- grafana_url: params[:url],
- start: format_time(params[:start]),
- end: format_time(params[:end])
+ **params
)
end
- # Formats a timestamp from Grafana for compatibility with
- # parsing in JS via `new Date(timestamp)`
+ # If the provided url is missing time window parameters,
+ # this inserts the default window into the url, allowing
+ # the embed service to correctly format prometheus
+ # queries during embed processing.
#
- # @param time [String] Represents miliseconds since epoch
- def format_time(time)
- Time.at(time.to_i / 1000).utc.strftime('%FT%TZ')
+ # @param url [String]
+ # @param query_params [Hash<Symbol, String>]
+ # @param time_window_params [Hash<Symbol, Integer>]
+ # @return [String]
+ def url_with_window(url, query_params, time_window_params)
+ uri = URI(url)
+ uri.query = time_window_params.merge(query_params).to_query
+
+ uri.to_s
end
# Fetches a dashboard and caches the result for the
diff --git a/lib/gitlab/import_export/project/tree_restorer.rb b/lib/gitlab/import_export/project/tree_restorer.rb
index a5123f16dbc..904cb461ac3 100644
--- a/lib/gitlab/import_export/project/tree_restorer.rb
+++ b/lib/gitlab/import_export/project/tree_restorer.rb
@@ -21,8 +21,6 @@ module Gitlab
@tree_hash = read_tree_hash
@project_members = @tree_hash.delete('project_members')
- RelationRenameService.rename(@tree_hash)
-
if relation_tree_restorer.restore
import_failure_service.with_retry(action: 'set_latest_merge_request_diff_ids!') do
@project.merge_requests.set_latest_merge_request_diff_ids!
diff --git a/lib/gitlab/import_export/project/tree_saver.rb b/lib/gitlab/import_export/project/tree_saver.rb
index 58f33a04851..32b3b518ece 100644
--- a/lib/gitlab/import_export/project/tree_saver.rb
+++ b/lib/gitlab/import_export/project/tree_saver.rb
@@ -35,8 +35,6 @@ module Gitlab
end
project_tree['project_members'] += group_members_array
-
- RelationRenameService.add_new_associations(project_tree)
end
def reader
diff --git a/lib/gitlab/import_export/relation_rename_service.rb b/lib/gitlab/import_export/relation_rename_service.rb
deleted file mode 100644
index 03aaa6aefc3..00000000000
--- a/lib/gitlab/import_export/relation_rename_service.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-# This class is intended to help with relation renames within Gitlab versions
-# and allow compatibility between versions.
-# If you have to change one relationship name that is imported/exported,
-# you should add it to the RENAMES constant indicating the old name and the
-# new one.
-# The behavior of these renamed relationships should be transient and it should
-# only last one release until you completely remove the renaming from the list.
-#
-# When importing, this class will check the hash and:
-# - if only the old relationship name is found, it will rename it with the new one
-# - if only the new relationship name is found, it will do nothing
-# - if it finds both, it will use the new relationship data
-#
-# When exporting, this class will duplicate the keys in the resulting file.
-# This way, if we open the file in an old version of the exporter it will work
-# and also it will with the newer versions.
-module Gitlab
- module ImportExport
- class RelationRenameService
- RENAMES = {
- 'pipelines' => 'ci_pipelines' # Added in 11.6, remove in 11.7
- }.freeze
-
- def self.rename(tree_hash)
- return unless tree_hash&.present?
-
- RENAMES.each do |old_name, new_name|
- old_entry = tree_hash.delete(old_name)
-
- next if tree_hash[new_name]
- next unless old_entry
-
- tree_hash[new_name] = old_entry
- end
- end
-
- def self.add_new_associations(tree_hash)
- RENAMES.each do |old_name, new_name|
- next if tree_hash.key?(old_name)
-
- tree_hash[old_name] = tree_hash[new_name]
- end
- end
- end
- end
-end
diff --git a/lib/grafana/time_window.rb b/lib/grafana/time_window.rb
new file mode 100644
index 00000000000..111e3ab7de2
--- /dev/null
+++ b/lib/grafana/time_window.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+module Grafana
+ # Allows for easy formatting and manipulations of timestamps
+ # coming from a Grafana url
+ class TimeWindow
+ include ::Gitlab::Utils::StrongMemoize
+
+ def initialize(from, to)
+ @from = from
+ @to = to
+ end
+
+ def formatted
+ {
+ start: window[:from].formatted,
+ end: window[:to].formatted
+ }
+ end
+
+ def in_milliseconds
+ window.transform_values(&:to_ms)
+ end
+
+ private
+
+ def window
+ strong_memoize(:window) do
+ specified_window
+ rescue Timestamp::Error
+ default_window
+ end
+ end
+
+ def specified_window
+ RangeWithDefaults.new(
+ from: Timestamp.from_ms_since_epoch(@from),
+ to: Timestamp.from_ms_since_epoch(@to)
+ ).to_hash
+ end
+
+ def default_window
+ RangeWithDefaults.new.to_hash
+ end
+ end
+
+ # For incomplete time ranges, adds default parameters to
+ # achieve a complete range. If both full range is provided,
+ # range will be returned.
+ class RangeWithDefaults
+ DEFAULT_RANGE = 8.hours
+
+ # @param from [Grafana::Timestamp, nil] Start of the expected range
+ # @param to [Grafana::Timestamp, nil] End of the expected range
+ def initialize(from: nil, to: nil)
+ @from = from
+ @to = to
+
+ apply_defaults!
+ end
+
+ def to_hash
+ { from: @from, to: @to }.compact
+ end
+
+ private
+
+ def apply_defaults!
+ @to ||= @from ? relative_end : Timestamp.new(Time.now)
+ @from ||= relative_start
+ end
+
+ def relative_start
+ Timestamp.new(DEFAULT_RANGE.before(@to.time))
+ end
+
+ def relative_end
+ Timestamp.new(DEFAULT_RANGE.since(@from.time))
+ end
+ end
+
+ # Offers a consistent API for timestamps originating from
+ # Grafana or other sources, allowing for formatting of timestamps
+ # as consumed by Grafana-related utilities
+ class Timestamp
+ Error = Class.new(StandardError)
+
+ attr_accessor :time
+
+ # @param timestamp [Time]
+ def initialize(time)
+ @time = time
+ end
+
+ # Formats a timestamp from Grafana for compatibility with
+ # parsing in JS via `new Date(timestamp)`
+ def formatted
+ time.utc.strftime('%FT%TZ')
+ end
+
+ # Converts to milliseconds since epoch
+ def to_ms
+ time.to_i * 1000
+ end
+
+ class << self
+ # @param time [String] Representing milliseconds since epoch.
+ # This is what JS "decided" unix is.
+ def from_ms_since_epoch(time)
+ return if time.nil?
+
+ raise Error.new('Expected milliseconds since epoch') unless ms_since_epoch?(time)
+
+ new(cast_ms_to_time(time))
+ end
+
+ private
+
+ def cast_ms_to_time(time)
+ Time.at(time.to_i / 1000.0)
+ end
+
+ def ms_since_epoch?(time)
+ ms = time.to_i
+
+ ms.to_s == time && ms.bit_length < 64
+ end
+ end
+ end
+end