diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb index 267dca74f96..f212ae52ecc 100644 --- a/app/controllers/projects/prometheus/metrics_controller.rb +++ b/app/controllers/projects/prometheus/metrics_controller.rb @@ -23,7 +23,7 @@ module Projects private def prometheus_adapter - @prometheus_adapter ||= ::Prometheus::AdapterService.new(project).prometheus_adapter + @prometheus_adapter ||= ::Prometheus::AdapterService.new(project, project.deployment_platform&.cluster).prometheus_adapter end def require_prometheus_metrics! diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index fbf76f2c36a..f0930705a3f 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -719,8 +719,8 @@ module Ci end end - def has_expiring_archive_artifacts? - has_expiring_artifacts? && artifacts_file&.exists? + def has_expiring_artifacts? + artifacts_expire_at.present? && artifacts_expire_at > Time.now end def keep_artifacts! @@ -935,10 +935,6 @@ module Ci value.with_indifferent_access end end - - def has_expiring_artifacts? - artifacts_expire_at.present? && artifacts_expire_at > Time.now - end end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 29ec41ef1a1..42a40e06240 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -62,6 +62,8 @@ module Ci has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline 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? delegate :id, to: :project, prefix: true diff --git a/app/models/ci/pipeline_config.rb b/app/models/ci/pipeline_config.rb new file mode 100644 index 00000000000..d5a8da2bc1e --- /dev/null +++ b/app/models/ci/pipeline_config.rb @@ -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 diff --git a/app/models/environment.rb b/app/models/environment.rb index 84a72fee77b..7ef38ab4cf4 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -223,7 +223,7 @@ class Environment < ApplicationRecord # rubocop: disable CodeReuse/ServiceClass 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 # rubocop: enable CodeReuse/ServiceClass diff --git a/app/serializers/build_artifact_entity.rb b/app/serializers/build_artifact_entity.rb index c173c155edf..414f436e76e 100644 --- a/app/serializers/build_artifact_entity.rb +++ b/app/serializers/build_artifact_entity.rb @@ -14,7 +14,7 @@ class BuildArtifactEntity < Grape::Entity download_project_job_artifacts_path(project, job) 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) end diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb index 0ef71ff8af5..480a8cab6ff 100644 --- a/app/serializers/build_details_entity.rb +++ b/app/serializers/build_details_entity.rb @@ -31,7 +31,7 @@ class BuildDetailsEntity < JobEntity browse_project_job_artifacts_path(project, build) 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) end diff --git a/app/services/prometheus/adapter_service.rb b/app/services/prometheus/adapter_service.rb index 399f4c35d66..5e8357a83f6 100644 --- a/app/services/prometheus/adapter_service.rb +++ b/app/services/prometheus/adapter_service.rb @@ -2,18 +2,13 @@ module Prometheus class AdapterService - def initialize(project, deployment_platform = nil) + attr_reader :project, :cluster + + def initialize(project, cluster) @project = project - - @deployment_platform = if deployment_platform - deployment_platform - else - project.deployment_platform - end + @cluster = cluster end - attr_reader :deployment_platform, :project - def prometheus_adapter @prometheus_adapter ||= if service_prometheus_adapter.can_query? service_prometheus_adapter @@ -27,7 +22,7 @@ module Prometheus end def cluster_prometheus_adapter - application = deployment_platform&.cluster&.application_prometheus + application = cluster&.application_prometheus application if application&.available? end diff --git a/changelogs/unreleased/118640_add_gitlab_version_and_revision_to_export.yml b/changelogs/unreleased/118640_add_gitlab_version_and_revision_to_export.yml new file mode 100644 index 00000000000..416f241a726 --- /dev/null +++ b/changelogs/unreleased/118640_add_gitlab_version_and_revision_to_export.yml @@ -0,0 +1,5 @@ +--- +title: Add Gitlab version and revision to export +merge_request: 22108 +author: +type: added diff --git a/changelogs/unreleased/38242-persisting-pipeline-config_content.yml b/changelogs/unreleased/38242-persisting-pipeline-config_content.yml new file mode 100644 index 00000000000..02c391186f9 --- /dev/null +++ b/changelogs/unreleased/38242-persisting-pipeline-config_content.yml @@ -0,0 +1,5 @@ +--- +title: Implement saving config content for pipelines in a new table 'ci_pipelines_config' +merge_request: 21827 +author: +type: other diff --git a/changelogs/unreleased/eb-no-keep-report-artifacts.yml b/changelogs/unreleased/eb-no-keep-report-artifacts.yml deleted file mode 100644 index c80fbd2c221..00000000000 --- a/changelogs/unreleased/eb-no-keep-report-artifacts.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Remove keep button for non archive artifacts -merge_request: 21553 -author: -type: fixed diff --git a/db/migrate/20191213143656_create_ci_pipelines_config.rb b/db/migrate/20191213143656_create_ci_pipelines_config.rb new file mode 100644 index 00000000000..92636f35d01 --- /dev/null +++ b/db/migrate/20191213143656_create_ci_pipelines_config.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 0f709482884..219ac8c5263 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -876,6 +876,11 @@ ActiveRecord::Schema.define(version: 2019_12_18_225624) do t.index ["user_id"], name: "index_ci_pipelines_on_user_id" 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| t.datetime_with_timezone "created_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", "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_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_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 diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md index 7d07e8f6944..292cddd284b 100644 --- a/doc/integration/elasticsearch.md +++ b/doc/integration/elasticsearch.md @@ -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: -1. Navigate to the **Admin Area** (wrench icon), then **Settings > Integrations** and expand the **Elasticsearch** section. -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: ```sh @@ -212,7 +211,8 @@ To index via the admin area: 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. 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) 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: ```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 ``` +1. [Enable **Elasticsearch indexing**](#enabling-elasticsearch). 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% decrease in indexing time. We'll enable them when indexing is done. This step is optional! diff --git a/lib/gitlab/ci/pipeline/chain/config/content.rb b/lib/gitlab/ci/pipeline/chain/config/content.rb index d4b7444005e..f9fffbcb517 100644 --- a/lib/gitlab/ci/pipeline/chain/config/content.rb +++ b/lib/gitlab/ci/pipeline/chain/config/content.rb @@ -24,8 +24,7 @@ module Gitlab def perform! if config = find_config - # TODO: we should persist config_content - # @pipeline.config_content = config.content + @pipeline.build_pipeline_config(content: config.content) if ci_root_config_content_enabled? @command.config_content = config.content @pipeline.config_source = config.source else @@ -49,11 +48,11 @@ module Gitlab end def sources - if Feature.enabled?(:ci_root_config_content, @command.project, default_enabled: true) - SOURCES - else - LEGACY_SOURCES - end + ci_root_config_content_enabled? ? SOURCES : LEGACY_SOURCES + end + + def ci_root_config_content_enabled? + Feature.enabled?(:ci_root_config_content, @command.project, default_enabled: true) end end end diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index 516e7f54a6e..8ce6549c0c7 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -50,6 +50,14 @@ module Gitlab 'VERSION' end + def gitlab_version_filename + 'GITLAB_VERSION' + end + + def gitlab_revision_filename + 'GITLAB_REVISION' + end + def export_filename(exportable:) basename = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%3N')}_#{exportable.full_path.tr('/', '_')}" diff --git a/lib/gitlab/import_export/group_tree_saver.rb b/lib/gitlab/import_export/group_tree_saver.rb index 8d2fb881cc0..2effcd01e30 100644 --- a/lib/gitlab/import_export/group_tree_saver.rb +++ b/lib/gitlab/import_export/group_tree_saver.rb @@ -3,7 +3,7 @@ module Gitlab module ImportExport class GroupTreeSaver - attr_reader :full_path + attr_reader :full_path, :shared def initialize(group:, current_user:, shared:, params: {}) @params = params diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb index 8230c0f1e77..dab8bbf539d 100644 --- a/lib/gitlab/import_export/version_saver.rb +++ b/lib/gitlab/import_export/version_saver.rb @@ -13,6 +13,8 @@ module Gitlab mkdir_p(@shared.export_path) 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 @shared.error(e) false @@ -20,6 +22,14 @@ module Gitlab 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 File.join(@shared.export_path, Gitlab::ImportExport.version_filename) end diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb index b23ca095414..21d5c9b0eee 100644 --- a/lib/gitlab/kubernetes/kube_client.rb +++ b/lib/gitlab/kubernetes/kube_client.rb @@ -17,6 +17,7 @@ module Gitlab core: { group: 'api', version: 'v1' }, rbac: { group: 'apis/rbac.authorization.k8s.io', version: 'v1' }, extensions: { group: 'apis/extensions', version: 'v1beta1' }, + istio: { group: 'apis/networking.istio.io', version: 'v1alpha3' }, knative: { group: 'apis/serving.knative.dev', version: 'v1alpha1' } }.freeze @@ -91,6 +92,13 @@ module Gitlab :watch_pod_log, 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 # We disable redirects through 'http_max_redirects: 0', diff --git a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb index f84f10bdc46..aaea044595f 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb @@ -29,6 +29,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'repository_source' + expect(pipeline.pipeline_config).to be_nil expect(command.config_content).to eq('the-content') end end @@ -40,6 +41,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' + expect(pipeline.pipeline_config).to be_nil template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') expect(command.config_content).to eq(template.content) end @@ -52,6 +54,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' + expect(pipeline.pipeline_config).to be_nil template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') expect(command.config_content).to eq(template.content) end @@ -71,6 +74,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'repository_source' + expect(pipeline.pipeline_config).to be_nil expect(command.config_content).to eq('the-content') end end @@ -91,6 +95,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' + expect(pipeline.pipeline_config).to be_nil template = Gitlab::Template::GitlabCiYmlTemplate.find('Beta/Auto-DevOps') expect(command.config_content).to eq(template.content) end @@ -105,6 +110,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' + expect(pipeline.pipeline_config).to be_nil template = Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') expect(command.config_content).to eq(template.content) end @@ -122,6 +128,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq('unknown_source') + expect(pipeline.pipeline_config).to be_nil expect(command.config_content).to be_nil expect(pipeline.errors.full_messages).to include('Missing CI config file') 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 let(:ci_config_path) { 'path/to/config.yml' } + let(:config_content_result) do + <<~EOY + --- + include: + - local: #{ci_config_path} + EOY + end before do expect(project.repository) @@ -142,47 +156,59 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'repository_source' - expect(command.config_content).to eq(<<~EOY) - --- - include: - - local: #{ci_config_path} - EOY + expect(pipeline.pipeline_config.content).to eq(config_content_result) + expect(command.config_content).to eq(config_content_result) end end context 'when config is defined remotely' do let(:ci_config_path) { 'http://example.com/path/to/ci/config.yml' } - - it 'builds root config including the remote config' do - subject.perform! - - expect(pipeline.config_source).to eq 'remote_source' - expect(command.config_content).to eq(<<~EOY) + let(:config_content_result) do + <<~EOY --- include: - remote: #{ci_config_path} EOY 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 context 'when config is defined in a separate repository' do let(:ci_config_path) { 'path/to/.gitlab-ci.yml@another-group/another-repo' } - - it 'builds root config including the path to another repository' do - subject.perform! - - expect(pipeline.config_source).to eq 'external_project_source' - expect(command.config_content).to eq(<<~EOY) + let(:config_content_result) do + <<~EOY --- include: - project: another-group/another-repo file: path/to/.gitlab-ci.yml EOY 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 context 'when config is defined in the default .gitlab-ci.yml' do let(:ci_config_path) { nil } + let(:config_content_result) do + <<~EOY + --- + include: + - local: ".gitlab-ci.yml" + EOY + end before do expect(project.repository) @@ -195,16 +221,20 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'repository_source' - expect(command.config_content).to eq(<<~EOY) - --- - include: - - local: ".gitlab-ci.yml" - EOY + expect(pipeline.pipeline_config.content).to eq(config_content_result) + expect(command.config_content).to eq(config_content_result) end end context 'when config is the Auto-Devops template' do let(:ci_config_path) { nil } + let(:config_content_result) do + <<~EOY + --- + include: + - template: Beta/Auto-DevOps.gitlab-ci.yml + EOY + end before do expect(project).to receive(:auto_devops_enabled?).and_return(true) @@ -219,11 +249,8 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq 'auto_devops_source' - expect(command.config_content).to eq(<<~EOY) - --- - include: - - template: Beta/Auto-DevOps.gitlab-ci.yml - EOY + expect(pipeline.pipeline_config.content).to eq(config_content_result) + expect(command.config_content).to eq(config_content_result) end end @@ -232,16 +259,21 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do stub_feature_flags(auto_devops_beta: false) end - it 'builds root config including the auto-devops template' do - subject.perform! - - expect(pipeline.config_source).to eq 'auto_devops_source' - expect(command.config_content).to eq(<<~EOY) + let(:config_content_result) do + <<~EOY --- include: - template: Auto-DevOps.gitlab-ci.yml EOY 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 @@ -256,6 +288,7 @@ describe Gitlab::Ci::Pipeline::Chain::Config::Content do subject.perform! expect(pipeline.config_source).to eq('unknown_source') + expect(pipeline.pipeline_config).to be_nil expect(command.config_content).to be_nil expect(pipeline.errors.full_messages).to include('Missing CI config file') end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 8f0f09bc0be..a625d2f6cce 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -190,6 +190,7 @@ ci_pipelines: - job_artifacts - vulnerabilities_occurrence_pipelines - vulnerability_findings +- pipeline_config pipeline_variables: - pipeline stages: diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb index 59e81d89a50..e08981a3415 100644 --- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb +++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb @@ -136,6 +136,20 @@ describe Gitlab::Kubernetes::KubeClient do 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 subject { client.knative_client } @@ -233,6 +247,29 @@ describe Gitlab::Kubernetes::KubeClient do 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 it 'does not proxy for non-entity methods' do expect(client).not_to respond_to :proxy_url diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index ee8e9805c49..f9c17f732b6 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -2248,24 +2248,14 @@ describe Ci::Build do end end - describe '#has_expiring_archive_artifacts?' do + describe '#has_expiring_artifacts?' do context 'when artifacts have expiration date set' do before do build.update(artifacts_expire_at: 1.day.from_now) end - context 'and job artifacts file exists' do - let!(:archive) { create(:ci_job_artifact, :archive, job: build) } - - 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 + it 'has expiring artifacts' do + expect(build).to have_expiring_artifacts end end @@ -2275,7 +2265,7 @@ describe Ci::Build do end 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 diff --git a/spec/models/ci/pipeline_config_spec.rb b/spec/models/ci/pipeline_config_spec.rb new file mode 100644 index 00000000000..25f514ee5ab --- /dev/null +++ b/spec/models/ci/pipeline_config_spec.rb @@ -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 diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 3f9e882ea52..286d2ac4fe6 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -35,6 +35,7 @@ describe Ci::Pipeline, :mailer do it { is_expected.to have_one(:source_pipeline) } it { is_expected.to have_one(:triggered_by_pipeline) } 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(:status) } diff --git a/spec/serializers/build_artifact_entity_spec.rb b/spec/serializers/build_artifact_entity_spec.rb index 5f1d5093e0a..09fe094fff1 100644 --- a/spec/serializers/build_artifact_entity_spec.rb +++ b/spec/serializers/build_artifact_entity_spec.rb @@ -4,8 +4,6 @@ require 'spec_helper' describe BuildArtifactEntity do 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 described_class.new(job, request: double) diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb index 6fe9eaedfeb..91c5fd6bf2c 100644 --- a/spec/serializers/build_details_entity_spec.rb +++ b/spec/serializers/build_details_entity_spec.rb @@ -176,27 +176,5 @@ describe BuildDetailsEntity do expect(subject[:reports].first[:file_type]).to eq('codequality') 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 diff --git a/spec/services/prometheus/adapter_service_spec.rb b/spec/services/prometheus/adapter_service_spec.rb index 52e035e1f70..3c075fc1581 100644 --- a/spec/services/prometheus/adapter_service_spec.rb +++ b/spec/services/prometheus/adapter_service_spec.rb @@ -3,13 +3,12 @@ require 'spec_helper' 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 - let(:cluster) { create(:cluster, :provided_by_user, environment_scope: '*', projects: [project]) } - context 'prometheus service can execute queries' do let(:prometheus_service) { double(:prometheus_service, can_query?: true) } diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb index b2145ca729f..2fabfb94928 100644 --- a/spec/support/helpers/kubernetes_helpers.rb +++ b/spec/support/helpers/kubernetes_helpers.rb @@ -33,6 +33,14 @@ module KubernetesHelpers .to_return(kube_response(kube_v1_rbac_authorization_discovery_body)) 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) stub_kubeclient_discover_base(api_url) @@ -244,6 +252,16 @@ module KubernetesHelpers .to_return(kube_response({})) 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) { "kind" => "SecretList", @@ -311,6 +329,115 @@ module KubernetesHelpers } 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 { "kind" => "APIResourceList",