Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2019-12-24 00:07:31 +00:00
parent 33e1622bfe
commit 3888bc4261
29 changed files with 343 additions and 111 deletions

View file

@ -23,7 +23,7 @@ module Projects
private private
def prometheus_adapter def prometheus_adapter
@prometheus_adapter ||= ::Prometheus::AdapterService.new(project).prometheus_adapter @prometheus_adapter ||= ::Prometheus::AdapterService.new(project, project.deployment_platform&.cluster).prometheus_adapter
end end
def require_prometheus_metrics! def require_prometheus_metrics!

View file

@ -719,8 +719,8 @@ module Ci
end end
end end
def has_expiring_archive_artifacts? def has_expiring_artifacts?
has_expiring_artifacts? && artifacts_file&.exists? artifacts_expire_at.present? && artifacts_expire_at > Time.now
end end
def keep_artifacts! def keep_artifacts!
@ -935,10 +935,6 @@ module Ci
value.with_indifferent_access value.with_indifferent_access
end end
end end
def has_expiring_artifacts?
artifacts_expire_at.present? && artifacts_expire_at > Time.now
end
end end
end end

View file

@ -62,6 +62,8 @@ module Ci
has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline
has_one :source_job, through: :source_pipeline, source: :source_job has_one :source_job, through: :source_pipeline, source: :source_job
has_one :pipeline_config, class_name: 'Ci::PipelineConfig', inverse_of: :pipeline
accepts_nested_attributes_for :variables, reject_if: :persisted? accepts_nested_attributes_for :variables, reject_if: :persisted?
delegate :id, to: :project, prefix: true delegate :id, to: :project, prefix: true

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
module Ci
class PipelineConfig < ApplicationRecord
extend Gitlab::Ci::Model
self.table_name = 'ci_pipelines_config'
self.primary_key = :pipeline_id
belongs_to :pipeline, class_name: "Ci::Pipeline", inverse_of: :pipeline_config
validates :pipeline, presence: true
validates :content, presence: true
end
end

View file

@ -223,7 +223,7 @@ class Environment < ApplicationRecord
# rubocop: disable CodeReuse/ServiceClass # rubocop: disable CodeReuse/ServiceClass
def prometheus_adapter def prometheus_adapter
@prometheus_adapter ||= Prometheus::AdapterService.new(project, deployment_platform).prometheus_adapter @prometheus_adapter ||= Prometheus::AdapterService.new(project, deployment_platform&.cluster).prometheus_adapter
end end
# rubocop: enable CodeReuse/ServiceClass # rubocop: enable CodeReuse/ServiceClass

View file

@ -14,7 +14,7 @@ class BuildArtifactEntity < Grape::Entity
download_project_job_artifacts_path(project, job) download_project_job_artifacts_path(project, job)
end end
expose :keep_path, if: -> (*) { job.has_expiring_archive_artifacts? } do |job| expose :keep_path, if: -> (*) { job.has_expiring_artifacts? } do |job|
keep_project_job_artifacts_path(project, job) keep_project_job_artifacts_path(project, job)
end end

View file

@ -31,7 +31,7 @@ class BuildDetailsEntity < JobEntity
browse_project_job_artifacts_path(project, build) browse_project_job_artifacts_path(project, build)
end end
expose :keep_path, if: -> (*) { build.has_expiring_archive_artifacts? && can?(current_user, :update_build, build) } do |build| expose :keep_path, if: -> (*) { build.has_expiring_artifacts? && can?(current_user, :update_build, build) } do |build|
keep_project_job_artifacts_path(project, build) keep_project_job_artifacts_path(project, build)
end end

View file

@ -2,18 +2,13 @@
module Prometheus module Prometheus
class AdapterService class AdapterService
def initialize(project, deployment_platform = nil) attr_reader :project, :cluster
def initialize(project, cluster)
@project = project @project = project
@cluster = cluster
@deployment_platform = if deployment_platform
deployment_platform
else
project.deployment_platform
end
end end
attr_reader :deployment_platform, :project
def prometheus_adapter def prometheus_adapter
@prometheus_adapter ||= if service_prometheus_adapter.can_query? @prometheus_adapter ||= if service_prometheus_adapter.can_query?
service_prometheus_adapter service_prometheus_adapter
@ -27,7 +22,7 @@ module Prometheus
end end
def cluster_prometheus_adapter def cluster_prometheus_adapter
application = deployment_platform&.cluster&.application_prometheus application = cluster&.application_prometheus
application if application&.available? application if application&.available?
end end

View file

@ -0,0 +1,5 @@
---
title: Add Gitlab version and revision to export
merge_request: 22108
author:
type: added

View file

@ -0,0 +1,5 @@
---
title: Implement saving config content for pipelines in a new table 'ci_pipelines_config'
merge_request: 21827
author:
type: other

View file

@ -1,5 +0,0 @@
---
title: Remove keep button for non archive artifacts
merge_request: 21553
author:
type: fixed

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
class CreateCiPipelinesConfig < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
create_table :ci_pipelines_config, id: false do |t|
t.references :pipeline,
primary_key: true,
foreign_key: { to_table: :ci_pipelines, on_delete: :cascade }
t.text :content, null: false
end
end
end

View file

@ -876,6 +876,11 @@ ActiveRecord::Schema.define(version: 2019_12_18_225624) do
t.index ["user_id"], name: "index_ci_pipelines_on_user_id" t.index ["user_id"], name: "index_ci_pipelines_on_user_id"
end end
create_table "ci_pipelines_config", primary_key: "pipeline_id", force: :cascade do |t|
t.text "content", null: false
t.index ["pipeline_id"], name: "index_ci_pipelines_config_on_pipeline_id"
end
create_table "ci_resource_groups", force: :cascade do |t| create_table "ci_resource_groups", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false t.datetime_with_timezone "updated_at", null: false
@ -4438,6 +4443,7 @@ ActiveRecord::Schema.define(version: 2019_12_18_225624) do
add_foreign_key "ci_pipelines", "external_pull_requests", name: "fk_190998ef09", on_delete: :nullify add_foreign_key "ci_pipelines", "external_pull_requests", name: "fk_190998ef09", on_delete: :nullify
add_foreign_key "ci_pipelines", "merge_requests", name: "fk_a23be95014", on_delete: :cascade add_foreign_key "ci_pipelines", "merge_requests", name: "fk_a23be95014", on_delete: :cascade
add_foreign_key "ci_pipelines", "projects", name: "fk_86635dbd80", on_delete: :cascade add_foreign_key "ci_pipelines", "projects", name: "fk_86635dbd80", on_delete: :cascade
add_foreign_key "ci_pipelines_config", "ci_pipelines", column: "pipeline_id", on_delete: :cascade
add_foreign_key "ci_resource_groups", "projects", name: "fk_774722d144", on_delete: :cascade add_foreign_key "ci_resource_groups", "projects", name: "fk_774722d144", on_delete: :cascade
add_foreign_key "ci_resources", "ci_builds", column: "build_id", name: "fk_e169a8e3d5", on_delete: :nullify add_foreign_key "ci_resources", "ci_builds", column: "build_id", name: "fk_e169a8e3d5", on_delete: :nullify
add_foreign_key "ci_resources", "ci_resource_groups", column: "resource_group_id", on_delete: :cascade add_foreign_key "ci_resources", "ci_resource_groups", column: "resource_group_id", on_delete: :cascade

View file

@ -200,8 +200,7 @@ To backfill existing data, you can use one of the methods below to index it in b
To index via the admin area: To index via the admin area:
1. Navigate to the **Admin Area** (wrench icon), then **Settings > Integrations** and expand the **Elasticsearch** section. 1. [Configure your Elasticsearch host and port](#enabling-elasticsearch).
1. [Enable **Elasticsearch indexing** and configure your host and port](#enabling-elasticsearch).
1. Create empty indexes using one of the following commands: 1. Create empty indexes using one of the following commands:
```sh ```sh
@ -212,7 +211,8 @@ To index via the admin area:
bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
``` ```
1. Click **Index all projects**. 1. [Enable **Elasticsearch indexing**](#enabling-elasticsearch).
1. Click **Index all projects** in **Admin Area > Settings > Integrations > Elasticsearch**.
1. Click **Check progress** in the confirmation message to see the status of the background jobs. 1. Click **Check progress** in the confirmation message to see the status of the background jobs.
1. Personal snippets need to be indexed manually by running one of these commands: 1. Personal snippets need to be indexed manually by running one of these commands:
@ -255,7 +255,7 @@ Performing asynchronous indexing will generate a lot of Sidekiq jobs.
Make sure to prepare for this task by either [Horizontally Scaling](../administration/high_availability/README.md#basic-scaling) Make sure to prepare for this task by either [Horizontally Scaling](../administration/high_availability/README.md#basic-scaling)
or creating [extra Sidekiq processes](../administration/operations/extra_sidekiq_processes.md) or creating [extra Sidekiq processes](../administration/operations/extra_sidekiq_processes.md)
1. [Enable **Elasticsearch indexing** and configure your host and port](#enabling-elasticsearch). 1. [Configure your Elasticsearch host and port](#enabling-elasticsearch).
1. Create empty indexes using one of the following commands: 1. Create empty indexes using one of the following commands:
```sh ```sh
@ -266,6 +266,7 @@ or creating [extra Sidekiq processes](../administration/operations/extra_sidekiq
bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
``` ```
1. [Enable **Elasticsearch indexing**](#enabling-elasticsearch).
1. Indexing large Git repositories can take a while. To speed up the process, you 1. Indexing large Git repositories can take a while. To speed up the process, you
can temporarily disable auto-refreshing and replicating. In our experience, you can expect a 20% can temporarily disable auto-refreshing and replicating. In our experience, you can expect a 20%
decrease in indexing time. We'll enable them when indexing is done. This step is optional! decrease in indexing time. We'll enable them when indexing is done. This step is optional!

View file

@ -24,8 +24,7 @@ module Gitlab
def perform! def perform!
if config = find_config if config = find_config
# TODO: we should persist config_content @pipeline.build_pipeline_config(content: config.content) if ci_root_config_content_enabled?
# @pipeline.config_content = config.content
@command.config_content = config.content @command.config_content = config.content
@pipeline.config_source = config.source @pipeline.config_source = config.source
else else
@ -49,11 +48,11 @@ module Gitlab
end end
def sources def sources
if Feature.enabled?(:ci_root_config_content, @command.project, default_enabled: true) ci_root_config_content_enabled? ? SOURCES : LEGACY_SOURCES
SOURCES end
else
LEGACY_SOURCES def ci_root_config_content_enabled?
end Feature.enabled?(:ci_root_config_content, @command.project, default_enabled: true)
end end
end end
end end

View file

@ -50,6 +50,14 @@ module Gitlab
'VERSION' 'VERSION'
end end
def gitlab_version_filename
'GITLAB_VERSION'
end
def gitlab_revision_filename
'GITLAB_REVISION'
end
def export_filename(exportable:) def export_filename(exportable:)
basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{exportable.full_path.tr('/', '_')}" basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{exportable.full_path.tr('/', '_')}"

View file

@ -3,7 +3,7 @@
module Gitlab module Gitlab
module ImportExport module ImportExport
class GroupTreeSaver class GroupTreeSaver
attr_reader :full_path attr_reader :full_path, :shared
def initialize(group:, current_user:, shared:, params: {}) def initialize(group:, current_user:, shared:, params: {})
@params = params @params = params

View file

@ -13,6 +13,8 @@ module Gitlab
mkdir_p(@shared.export_path) mkdir_p(@shared.export_path)
File.write(version_file, Gitlab::ImportExport.version, mode: 'w') File.write(version_file, Gitlab::ImportExport.version, mode: 'w')
File.write(gitlab_version_file, Gitlab::VERSION, mode: 'w')
File.write(gitlab_revision_file, Gitlab.revision, mode: 'w')
rescue => e rescue => e
@shared.error(e) @shared.error(e)
false false
@ -20,6 +22,14 @@ module Gitlab
private private
def gitlab_version_file
File.join(@shared.export_path, Gitlab::ImportExport.gitlab_version_filename)
end
def gitlab_revision_file
File.join(@shared.export_path, Gitlab::ImportExport.gitlab_revision_filename)
end
def version_file def version_file
File.join(@shared.export_path, Gitlab::ImportExport.version_filename) File.join(@shared.export_path, Gitlab::ImportExport.version_filename)
end end

View file

@ -17,6 +17,7 @@ module Gitlab
core: { group: 'api', version: 'v1' }, core: { group: 'api', version: 'v1' },
rbac: { group: 'apis/rbac.authorization.k8s.io', version: 'v1' }, rbac: { group: 'apis/rbac.authorization.k8s.io', version: 'v1' },
extensions: { group: 'apis/extensions', version: 'v1beta1' }, extensions: { group: 'apis/extensions', version: 'v1beta1' },
istio: { group: 'apis/networking.istio.io', version: 'v1alpha3' },
knative: { group: 'apis/serving.knative.dev', version: 'v1alpha1' } knative: { group: 'apis/serving.knative.dev', version: 'v1alpha1' }
}.freeze }.freeze
@ -91,6 +92,13 @@ module Gitlab
:watch_pod_log, :watch_pod_log,
to: :core_client to: :core_client
# Gateway methods delegate to the apis/networking.istio.io api
# group client
delegate :create_gateway,
:get_gateway,
:update_gateway,
to: :istio_client
attr_reader :api_prefix, :kubeclient_options attr_reader :api_prefix, :kubeclient_options
# We disable redirects through 'http_max_redirects: 0', # We disable redirects through 'http_max_redirects: 0',

View file

@ -29,6 +29,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'repository_source' expect(pipeline.config_source).to eq 'repository_source'
expect(pipeline.pipeline_config).to be_nil
expect(command.config_content).to eq('the-content') expect(command.config_content).to eq('the-content')
end end
end end
@ -40,6 +41,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source' expect(pipeline.config_source).to eq 'auto_devops_source'
expect(pipeline.pipeline_config).to be_nil
template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps')
expect(command.config_content).to eq(template.content) expect(command.config_content).to eq(template.content)
end end
@ -52,6 +54,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source' expect(pipeline.config_source).to eq 'auto_devops_source'
expect(pipeline.pipeline_config).to be_nil
template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps')
expect(command.config_content).to eq(template.content) expect(command.config_content).to eq(template.content)
end end
@ -71,6 +74,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'repository_source' expect(pipeline.config_source).to eq 'repository_source'
expect(pipeline.pipeline_config).to be_nil
expect(command.config_content).to eq('the-content') expect(command.config_content).to eq('the-content')
end end
end end
@ -91,6 +95,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source' expect(pipeline.config_source).to eq 'auto_devops_source'
expect(pipeline.pipeline_config).to be_nil
template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps')
expect(command.config_content).to eq(template.content) expect(command.config_content).to eq(template.content)
end end
@ -105,6 +110,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source' expect(pipeline.config_source).to eq 'auto_devops_source'
expect(pipeline.pipeline_config).to be_nil
template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps')
expect(command.config_content).to eq(template.content) expect(command.config_content).to eq(template.content)
end end
@ -122,6 +128,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq('unknown_source') expect(pipeline.config_source).to eq('unknown_source')
expect(pipeline.pipeline_config).to be_nil
expect(command.config_content).to be_nil expect(command.config_content).to be_nil
expect(pipeline.errors.full_messages).to include('Missing CI config file') expect(pipeline.errors.full_messages).to include('Missing CI config file')
end end
@ -130,6 +137,13 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
context 'when config is defined in a custom path in the repository' do context 'when config is defined in a custom path in the repository' do
let(:ci_config_path) { 'path/to/config.yml' } let(:ci_config_path) { 'path/to/config.yml' }
let(:config_content_result) do
<<~EOY
---
include:
- local: #{ci_config_path}
EOY
end
before do before do
expect(project.repository) expect(project.repository)
@ -142,47 +156,59 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'repository_source' expect(pipeline.config_source).to eq 'repository_source'
expect(command.config_content).to eq(<<~EOY) expect(pipeline.pipeline_config.content).to eq(config_content_result)
--- expect(command.config_content).to eq(config_content_result)
include:
- local: #{ci_config_path}
EOY
end end
end end
context 'when config is defined remotely' do context 'when config is defined remotely' do
let(:ci_config_path) { 'http://example.com/path/to/ci/config.yml' } let(:ci_config_path) { 'http://example.com/path/to/ci/config.yml' }
let(:config_content_result) do
it 'builds root config including the remote config' do <<~EOY
subject.perform!
expect(pipeline.config_source).to eq 'remote_source'
expect(command.config_content).to eq(<<~EOY)
--- ---
include: include:
- remote: #{ci_config_path} - remote: #{ci_config_path}
EOY EOY
end end
it 'builds root config including the remote config' do
subject.perform!
expect(pipeline.config_source).to eq 'remote_source'
expect(pipeline.pipeline_config.content).to eq(config_content_result)
expect(command.config_content).to eq(config_content_result)
end
end end
context 'when config is defined in a separate repository' do context 'when config is defined in a separate repository' do
let(:ci_config_path) { 'path/to/.gitlab-ci.yml@another-group/another-repo' } let(:ci_config_path) { 'path/to/.gitlab-ci.yml@another-group/another-repo' }
let(:config_content_result) do
it 'builds root config including the path to another repository' do <<~EOY
subject.perform!
expect(pipeline.config_source).to eq 'external_project_source'
expect(command.config_content).to eq(<<~EOY)
--- ---
include: include:
- project: another-group/another-repo - project: another-group/another-repo
file: path/to/.gitlab-ci.yml file: path/to/.gitlab-ci.yml
EOY EOY
end end
it 'builds root config including the path to another repository' do
subject.perform!
expect(pipeline.config_source).to eq 'external_project_source'
expect(pipeline.pipeline_config.content).to eq(config_content_result)
expect(command.config_content).to eq(config_content_result)
end
end end
context 'when config is defined in the default .gitlab-ci.yml' do context 'when config is defined in the default .gitlab-ci.yml' do
let(:ci_config_path) { nil } let(:ci_config_path) { nil }
let(:config_content_result) do
<<~EOY
---
include:
- local: ".gitlab-ci.yml"
EOY
end
before do before do
expect(project.repository) expect(project.repository)
@ -195,16 +221,20 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'repository_source' expect(pipeline.config_source).to eq 'repository_source'
expect(command.config_content).to eq(<<~EOY) expect(pipeline.pipeline_config.content).to eq(config_content_result)
--- expect(command.config_content).to eq(config_content_result)
include:
- local: ".gitlab-ci.yml"
EOY
end end
end end
context 'when config is the Auto-Devops template' do context 'when config is the Auto-Devops template' do
let(:ci_config_path) { nil } let(:ci_config_path) { nil }
let(:config_content_result) do
<<~EOY
---
include:
- template: Beta/Auto-DevOps.gitlab-ci.yml
EOY
end
before do before do
expect(project).to receive(:auto_devops_enabled?).and_return(true) expect(project).to receive(:auto_devops_enabled?).and_return(true)
@ -219,11 +249,8 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source' expect(pipeline.config_source).to eq 'auto_devops_source'
expect(command.config_content).to eq(<<~EOY) expect(pipeline.pipeline_config.content).to eq(config_content_result)
--- expect(command.config_content).to eq(config_content_result)
include:
- template: Beta/Auto-DevOps.gitlab-ci.yml
EOY
end end
end end
@ -232,16 +259,21 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
stub_feature_flags(auto_devops_beta: false) stub_feature_flags(auto_devops_beta: false)
end end
it 'builds root config including the auto-devops template' do let(:config_content_result) do
subject.perform! <<~EOY
expect(pipeline.config_source).to eq 'auto_devops_source'
expect(command.config_content).to eq(<<~EOY)
--- ---
include: include:
- template: Auto-DevOps.gitlab-ci.yml - template: Auto-DevOps.gitlab-ci.yml
EOY EOY
end end
it 'builds root config including the auto-devops template' do
subject.perform!
expect(pipeline.config_source).to eq 'auto_devops_source'
expect(pipeline.pipeline_config.content).to eq(config_content_result)
expect(command.config_content).to eq(config_content_result)
end
end end
end end
@ -256,6 +288,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do
subject.perform! subject.perform!
expect(pipeline.config_source).to eq('unknown_source') expect(pipeline.config_source).to eq('unknown_source')
expect(pipeline.pipeline_config).to be_nil
expect(command.config_content).to be_nil expect(command.config_content).to be_nil
expect(pipeline.errors.full_messages).to include('Missing CI config file') expect(pipeline.errors.full_messages).to include('Missing CI config file')
end end

View file

@ -190,6 +190,7 @@ ci_pipelines:
- job_artifacts - job_artifacts
- vulnerabilities_occurrence_pipelines - vulnerabilities_occurrence_pipelines
- vulnerability_findings - vulnerability_findings
- pipeline_config
pipeline_variables: pipeline_variables:
- pipeline - pipeline
stages: stages:

View file

@ -136,6 +136,20 @@ describe Gitlab::Kubernetes::KubeClient do
end end
end end
describe '#istio_client' do
subject { client.istio_client }
it_behaves_like 'a Kubeclient'
it 'has the Istio API group endpoint' do
expect(subject.api_endpoint.to_s).to match(%r{\/apis\/networking.istio.io\Z})
end
it 'has the api_version' do
expect(subject.instance_variable_get(:@api_version)).to eq('v1alpha3')
end
end
describe '#knative_client' do describe '#knative_client' do
subject { client.knative_client } subject { client.knative_client }
@ -233,6 +247,29 @@ describe Gitlab::Kubernetes::KubeClient do
end end
end end
describe 'istio API group' do
let(:istio_client) { client.istio_client }
[
:create_gateway,
:get_gateway,
:update_gateway
].each do |method|
describe "##{method}" do
include_examples 'redirection not allowed', method
include_examples 'dns rebinding not allowed', method
it 'delegates to the istio client' do
expect(client).to delegate_method(method).to(:istio_client)
end
it 'responds to the method' do
expect(client).to respond_to method
end
end
end
end
describe 'non-entity methods' do describe 'non-entity methods' do
it 'does not proxy for non-entity methods' do it 'does not proxy for non-entity methods' do
expect(client).not_to respond_to :proxy_url expect(client).not_to respond_to :proxy_url

View file

@ -2248,24 +2248,14 @@ describe Ci::Build do
end end
end end
describe '#has_expiring_archive_artifacts?' do describe '#has_expiring_artifacts?' do
context 'when artifacts have expiration date set' do context 'when artifacts have expiration date set' do
before do before do
build.update(artifacts_expire_at: 1.day.from_now) build.update(artifacts_expire_at: 1.day.from_now)
end end
context 'and job artifacts file exists' do it 'has expiring artifacts' do
let!(:archive) { create(:ci_job_artifact, :archive, job: build) } expect(build).to have_expiring_artifacts
it 'has expiring artifacts' do
expect(build).to have_expiring_archive_artifacts
end
end
context 'and job artifacts file does not exist' do
it 'does not have expiring artifacts' do
expect(build).not_to have_expiring_archive_artifacts
end
end end
end end
@ -2275,7 +2265,7 @@ describe Ci::Build do
end end
it 'does not have expiring artifacts' do it 'does not have expiring artifacts' do
expect(build).not_to have_expiring_archive_artifacts expect(build).not_to have_expiring_artifacts
end end
end end
end end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
require 'spec_helper'
describe Ci::PipelineConfig, type: :model do
it { is_expected.to belong_to(:pipeline) }
it { is_expected.to validate_presence_of(:pipeline) }
it { is_expected.to validate_presence_of(:content) }
end

View file

@ -35,6 +35,7 @@ describe Ci::Pipeline, :mailer do
it { is_expected.to have_one(:source_pipeline) } it { is_expected.to have_one(:source_pipeline) }
it { is_expected.to have_one(:triggered_by_pipeline) } it { is_expected.to have_one(:triggered_by_pipeline) }
it { is_expected.to have_one(:source_job) } it { is_expected.to have_one(:source_job) }
it { is_expected.to have_one(:pipeline_config) }
it { is_expected.to validate_presence_of(:sha) } it { is_expected.to validate_presence_of(:sha) }
it { is_expected.to validate_presence_of(:status) } it { is_expected.to validate_presence_of(:status) }

View file

@ -4,8 +4,6 @@ require 'spec_helper'
describe BuildArtifactEntity do describe BuildArtifactEntity do
let(:job) { create(:ci_build, name: 'test:job', artifacts_expire_at: 1.hour.from_now) } let(:job) { create(:ci_build, name: 'test:job', artifacts_expire_at: 1.hour.from_now) }
let!(:archive) { create(:ci_job_artifact, :archive, job: job) }
let!(:metadata) { create(:ci_job_artifact, :metadata, job: job) }
let(:entity) do let(:entity) do
described_class.new(job, request: double) described_class.new(job, request: double)

View file

@ -176,27 +176,5 @@ describe BuildDetailsEntity do
expect(subject[:reports].first[:file_type]).to eq('codequality') expect(subject[:reports].first[:file_type]).to eq('codequality')
end end
end end
context 'when the build has no archive type artifacts' do
let!(:report) { create(:ci_job_artifact, :codequality, job: build) }
it 'does not expose any artifact actions path' do
expect(subject[:artifact].keys).not_to include(:download_path, :browse_path, :keep_path)
end
end
context 'when the build has archive type artifacts' do
let!(:report) { create(:ci_job_artifact, :codequality, job: build) }
let!(:archive) { create(:ci_job_artifact, :archive, job: build) }
let!(:metadata) { create(:ci_job_artifact, :metadata, job: build) }
before do
build.update(artifacts_expire_at: 7.days.from_now)
end
it 'exposes artifact details' do
expect(subject[:artifact].keys).to include(:download_path, :browse_path, :keep_path, :expire_at, :expired)
end
end
end end
end end

View file

@ -3,13 +3,12 @@
require 'spec_helper' require 'spec_helper'
describe Prometheus::AdapterService do describe Prometheus::AdapterService do
let(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:cluster, reload: true) { create(:cluster, :provided_by_user, environment_scope: '*', projects: [project]) }
subject { described_class.new(project) } subject { described_class.new(project, cluster) }
describe '#prometheus_adapter' do describe '#prometheus_adapter' do
let(:cluster) { create(:cluster, :provided_by_user, environment_scope: '*', projects: [project]) }
context 'prometheus service can execute queries' do context 'prometheus service can execute queries' do
let(:prometheus_service) { double(:prometheus_service, can_query?: true) } let(:prometheus_service) { double(:prometheus_service, can_query?: true) }

View file

@ -33,6 +33,14 @@ module KubernetesHelpers
.to_return(kube_response(kube_v1_rbac_authorization_discovery_body)) .to_return(kube_response(kube_v1_rbac_authorization_discovery_body))
end end
def stub_kubeclient_discover_istio(api_url)
stub_kubeclient_discover_base(api_url)
WebMock
.stub_request(:get, api_url + '/apis/networking.istio.io/v1alpha3')
.to_return(kube_response(kube_istio_discovery_body))
end
def stub_kubeclient_discover(api_url) def stub_kubeclient_discover(api_url)
stub_kubeclient_discover_base(api_url) stub_kubeclient_discover_base(api_url)
@ -244,6 +252,16 @@ module KubernetesHelpers
.to_return(kube_response({})) .to_return(kube_response({}))
end end
def stub_kubeclient_get_gateway(api_url, name, namespace: 'default')
WebMock.stub_request(:get, api_url + "/apis/networking.istio.io/v1alpha3/namespaces/#{namespace}/gateways/#{name}")
.to_return(kube_response(kube_istio_gateway_body(name, namespace)))
end
def stub_kubeclient_put_gateway(api_url, name, namespace: 'default')
WebMock.stub_request(:put, api_url + "/apis/networking.istio.io/v1alpha3/namespaces/#{namespace}/gateways/#{name}")
.to_return(kube_response({}))
end
def kube_v1_secret_body(**options) def kube_v1_secret_body(**options)
{ {
"kind" => "SecretList", "kind" => "SecretList",
@ -311,6 +329,115 @@ module KubernetesHelpers
} }
end end
def kube_istio_discovery_body
{
"kind" => "APIResourceList",
"apiVersion" => "v1",
"groupVersion" => "networking.istio.io/v1alpha3",
"resources" => [
{
"name" => "gateways",
"singularName" => "gateway",
"namespaced" => true,
"kind" => "Gateway",
"verbs" => %w[delete deletecollection get list patch create update watch],
"shortNames" => %w[gw],
"categories" => %w[istio-io networking-istio-io]
},
{
"name" => "serviceentries",
"singularName" => "serviceentry",
"namespaced" => true,
"kind" => "ServiceEntry",
"verbs" => %w[delete deletecollection get list patch create update watch],
"shortNames" => %w[se],
"categories" => %w[istio-io networking-istio-io]
},
{
"name" => "destinationrules",
"singularName" => "destinationrule",
"namespaced" => true,
"kind" => "DestinationRule",
"verbs" => %w[delete deletecollection get list patch create update watch],
"shortNames" => %w[dr],
"categories" => %w[istio-io networking-istio-io]
},
{
"name" => "envoyfilters",
"singularName" => "envoyfilter",
"namespaced" => true,
"kind" => "EnvoyFilter",
"verbs" => %w[delete deletecollection get list patch create update watch],
"categories" => %w[istio-io networking-istio-io]
},
{
"name" => "sidecars",
"singularName" => "sidecar",
"namespaced" => true,
"kind" => "Sidecar",
"verbs" => %w[delete deletecollection get list patch create update watch],
"categories" => %w[istio-io networking-istio-io]
},
{
"name" => "virtualservices",
"singularName" => "virtualservice",
"namespaced" => true,
"kind" => "VirtualService",
"verbs" => %w[delete deletecollection get list patch create update watch],
"shortNames" => %w[vs],
"categories" => %w[istio-io networking-istio-io]
}
]
}
end
def kube_istio_gateway_body(name, namespace)
{
"apiVersion" => "networking.istio.io/v1alpha3",
"kind" => "Gateway",
"metadata" => {
"generation" => 1,
"labels" => {
"networking.knative.dev/ingress-provider" => "istio",
"serving.knative.dev/release" => "v0.7.0"
},
"name" => name,
"namespace" => namespace,
"selfLink" => "/apis/networking.istio.io/v1alpha3/namespaces/#{namespace}/gateways/#{name}"
},
"spec" => {
"selector" => {
"istio" => "ingressgateway"
},
"servers" => [
{
"hosts" => [
"*"
],
"port" => {
"name" => "http",
"number" => 80,
"protocol" => "HTTP"
}
},
{
"hosts" => [
"*"
],
"port" => {
"name" => "https",
"number" => 443,
"protocol" => "HTTPS"
},
"tls" => {
"mode" => "PASSTHROUGH"
}
}
]
}
}
end
def kube_v1alpha1_serving_knative_discovery_body def kube_v1alpha1_serving_knative_discovery_body
{ {
"kind" => "APIResourceList", "kind" => "APIResourceList",