diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /spec/services/clusters | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) | |
download | gitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'spec/services/clusters')
8 files changed, 212 insertions, 214 deletions
diff --git a/spec/services/clusters/applications/check_upgrade_progress_service_spec.rb b/spec/services/clusters/applications/check_upgrade_progress_service_spec.rb index c08b618fe6a..29ee897454a 100644 --- a/spec/services/clusters/applications/check_upgrade_progress_service_spec.rb +++ b/spec/services/clusters/applications/check_upgrade_progress_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Clusters::Applications::CheckUpgradeProgressService do - RESCHEDULE_PHASES = ::Gitlab::Kubernetes::Pod::PHASES - + reschedule_phashes = ::Gitlab::Kubernetes::Pod::PHASES - [::Gitlab::Kubernetes::Pod::SUCCEEDED, ::Gitlab::Kubernetes::Pod::FAILED, ::Gitlab].freeze let(:application) { create(:clusters_applications_prometheus, :updating) } @@ -89,6 +89,6 @@ describe Clusters::Applications::CheckUpgradeProgressService do end end - RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated upgrade', phase } + reschedule_phashes.each { |phase| it_behaves_like 'a not yet terminated upgrade', phase } end end diff --git a/spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb b/spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb deleted file mode 100644 index d456284f76a..00000000000 --- a/spec/services/clusters/applications/ingress_modsecurity_usage_service_spec.rb +++ /dev/null @@ -1,196 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Clusters::Applications::IngressModsecurityUsageService do - describe '#execute' do - ADO_MODSEC_KEY = Clusters::Applications::IngressModsecurityUsageService::ADO_MODSEC_KEY - - let(:project_with_ci_var) { create(:environment).project } - let(:project_with_pipeline_var) { create(:environment).project } - - subject { described_class.new.execute } - - context 'with multiple projects' do - let(:pipeline1) { create(:ci_pipeline, :with_job, project: project_with_pipeline_var) } - let(:pipeline2) { create(:ci_pipeline, :with_job, project: project_with_ci_var) } - - let!(:deployment_with_pipeline_var) do - create( - :deployment, - :success, - environment: project_with_pipeline_var.environments.first, - project: project_with_pipeline_var, - deployable: pipeline1.builds.last - ) - end - let!(:deployment_with_project_var) do - create( - :deployment, - :success, - environment: project_with_ci_var.environments.first, - project: project_with_ci_var, - deployable: pipeline2.builds.last - ) - end - - context 'mixed data' do - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, key: ADO_MODSEC_KEY, value: "On") } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline1, key: ADO_MODSEC_KEY, value: "Off") } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(1) - expect(subject[:ingress_modsecurity_disabled]).to eq(1) - end - end - - context 'blocking' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "On" } } - - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, **modsec_values) } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline1, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(2) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - - context 'disabled' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "Off" } } - - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, **modsec_values) } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline1, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(0) - expect(subject[:ingress_modsecurity_disabled]).to eq(2) - end - end - end - - context 'when set as both ci and pipeline variables' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "Off" } } - - let(:pipeline) { create(:ci_pipeline, :with_job, project: project_with_ci_var) } - let!(:deployment) do - create( - :deployment, - :success, - environment: project_with_ci_var.environments.first, - project: project_with_ci_var, - deployable: pipeline.builds.last - ) - end - - let!(:ci_variable) { create(:ci_variable, project: project_with_ci_var, **modsec_values) } - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline, **modsec_values) } - - it 'wont double-count projects' do - expect(subject[:ingress_modsecurity_blocking]).to eq(0) - expect(subject[:ingress_modsecurity_disabled]).to eq(1) - end - - it 'gives precedence to pipeline variable' do - pipeline_variable.update(value: "On") - - expect(subject[:ingress_modsecurity_blocking]).to eq(1) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - - context 'when a project has multiple environments' do - let(:modsec_values) { { key: ADO_MODSEC_KEY, value: "On" } } - - let!(:env1) { project_with_pipeline_var.environments.first } - let!(:env2) { create(:environment, project: project_with_pipeline_var) } - - let!(:pipeline_with_2_deployments) do - create(:ci_pipeline, :with_job, project: project_with_ci_var).tap do |pip| - pip.builds << build(:ci_build, pipeline: pip, project: project_with_pipeline_var) - end - end - - let!(:deployment1) do - create( - :deployment, - :success, - environment: env1, - project: project_with_pipeline_var, - deployable: pipeline_with_2_deployments.builds.last - ) - end - let!(:deployment2) do - create( - :deployment, - :success, - environment: env2, - project: project_with_pipeline_var, - deployable: pipeline_with_2_deployments.builds.last - ) - end - - context 'when set as ci variable' do - let!(:ci_variable) { create(:ci_variable, project: project_with_pipeline_var, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(2) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - - context 'when set as pipeline variable' do - let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline_with_2_deployments, **modsec_values) } - - it 'gathers variable data' do - expect(subject[:ingress_modsecurity_blocking]).to eq(2) - expect(subject[:ingress_modsecurity_disabled]).to eq(0) - end - end - end - - context 'when an environment has multiple deployments' do - let!(:env) { project_with_pipeline_var.environments.first } - - let!(:pipeline_first) do - create(:ci_pipeline, :with_job, project: project_with_pipeline_var).tap do |pip| - pip.builds << build(:ci_build, pipeline: pip, project: project_with_pipeline_var) - end - end - let!(:pipeline_last) do - create(:ci_pipeline, :with_job, project: project_with_pipeline_var).tap do |pip| - pip.builds << build(:ci_build, pipeline: pip, project: project_with_pipeline_var) - end - end - - let!(:deployment_first) do - create( - :deployment, - :success, - environment: env, - project: project_with_pipeline_var, - deployable: pipeline_first.builds.last - ) - end - let!(:deployment_last) do - create( - :deployment, - :success, - environment: env, - project: project_with_pipeline_var, - deployable: pipeline_last.builds.last - ) - end - - context 'when set as pipeline variable' do - let!(:first_pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline_first, key: ADO_MODSEC_KEY, value: "On") } - let!(:last_pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline_last, key: ADO_MODSEC_KEY, value: "Off") } - - it 'gives precedence to latest deployment' do - expect(subject[:ingress_modsecurity_blocking]).to eq(0) - expect(subject[:ingress_modsecurity_disabled]).to eq(1) - end - end - end - end -end diff --git a/spec/services/clusters/applications/schedule_update_service_spec.rb b/spec/services/clusters/applications/schedule_update_service_spec.rb index 0764f5b6a97..eb1006ce8e0 100644 --- a/spec/services/clusters/applications/schedule_update_service_spec.rb +++ b/spec/services/clusters/applications/schedule_update_service_spec.rb @@ -13,10 +13,10 @@ describe Clusters::Applications::ScheduleUpdateService do context 'when application is able to be updated' do context 'when the application was recently scheduled' do it 'schedules worker with a backoff delay' do - application = create(:clusters_applications_prometheus, :installed, last_update_started_at: Time.now + 5.minutes) + application = create(:clusters_applications_prometheus, :installed, last_update_started_at: Time.current + 5.minutes) service = described_class.new(application, project) - expect(::ClusterUpdateAppWorker).to receive(:perform_in).with(described_class::BACKOFF_DELAY, application.name, application.id, project.id, Time.now).once + expect(::ClusterUpdateAppWorker).to receive(:perform_in).with(described_class::BACKOFF_DELAY, application.name, application.id, project.id, Time.current).once service.execute end @@ -27,7 +27,7 @@ describe Clusters::Applications::ScheduleUpdateService do application = create(:clusters_applications_prometheus, :installed) service = described_class.new(application, project) - expect(::ClusterUpdateAppWorker).to receive(:perform_async).with(application.name, application.id, project.id, Time.now).once + expect(::ClusterUpdateAppWorker).to receive(:perform_async).with(application.name, application.id, project.id, Time.current).once service.execute end diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb index 43dbea959a2..4d1548c9786 100644 --- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb +++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb @@ -108,8 +108,7 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do } ) - stub_kubeclient_get_cluster_role_binding_error(api_url, 'gitlab-admin') - stub_kubeclient_create_cluster_role_binding(api_url) + stub_kubeclient_put_cluster_role_binding(api_url, 'gitlab-admin') end end diff --git a/spec/services/clusters/kubernetes/configure_istio_ingress_service_spec.rb b/spec/services/clusters/kubernetes/configure_istio_ingress_service_spec.rb index 9238f7debd0..e9f7f015293 100644 --- a/spec/services/clusters/kubernetes/configure_istio_ingress_service_spec.rb +++ b/spec/services/clusters/kubernetes/configure_istio_ingress_service_spec.rb @@ -120,8 +120,8 @@ describe Clusters::Kubernetes::ConfigureIstioIngressService, '#execute' do expect(certificate.subject.to_s).to include(serverless_domain_cluster.knative.hostname) - expect(certificate.not_before).to be_within(1.minute).of(Time.now) - expect(certificate.not_after).to be_within(1.minute).of(Time.now + 1000.years) + expect(certificate.not_before).to be_within(1.minute).of(Time.current) + expect(certificate.not_after).to be_within(1.minute).of(Time.current + 1000.years) expect(WebMock).to have_requested(:put, api_url + '/api/v1/namespaces/istio-system/secrets/istio-ingressgateway-ca-certs').with( body: hash_including( diff --git a/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb index 3982d2310d8..6d8b1617c17 100644 --- a/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb +++ b/spec/services/clusters/kubernetes/create_or_update_namespace_service_spec.rb @@ -28,7 +28,6 @@ describe Clusters::Kubernetes::CreateOrUpdateNamespaceService, '#execute' do stub_kubeclient_get_secret_error(api_url, 'gitlab-token') stub_kubeclient_create_secret(api_url) - stub_kubeclient_get_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace) stub_kubeclient_put_role_binding(api_url, "gitlab-#{namespace}", namespace: namespace) stub_kubeclient_get_namespace(api_url, namespace: namespace) stub_kubeclient_get_service_account_error(api_url, "#{namespace}-service-account", namespace: namespace) diff --git a/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb b/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb index 8fa22422074..4bcd5c6933e 100644 --- a/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb +++ b/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb @@ -83,8 +83,7 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do before do cluster.platform_kubernetes.rbac! - stub_kubeclient_get_cluster_role_binding_error(api_url, cluster_role_binding_name) - stub_kubeclient_create_cluster_role_binding(api_url) + stub_kubeclient_put_cluster_role_binding(api_url, cluster_role_binding_name) end it_behaves_like 'creates service account and token' @@ -92,9 +91,8 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do it 'creates a cluster role binding with cluster-admin access' do subject - expect(WebMock).to have_requested(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings").with( + expect(WebMock).to have_requested(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings/gitlab-admin").with( body: hash_including( - kind: 'ClusterRoleBinding', metadata: { name: 'gitlab-admin' }, roleRef: { apiGroup: 'rbac.authorization.k8s.io', @@ -143,8 +141,7 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do before do cluster.platform_kubernetes.rbac! - stub_kubeclient_get_role_binding_error(api_url, role_binding_name, namespace: namespace) - stub_kubeclient_create_role_binding(api_url, namespace: namespace) + stub_kubeclient_put_role_binding(api_url, role_binding_name, namespace: namespace) stub_kubeclient_put_role(api_url, Clusters::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_NAME, namespace: namespace) stub_kubeclient_put_role_binding(api_url, Clusters::Kubernetes::GITLAB_KNATIVE_SERVING_ROLE_BINDING_NAME, namespace: namespace) stub_kubeclient_put_role(api_url, Clusters::Kubernetes::GITLAB_CROSSPLANE_DATABASE_ROLE_NAME, namespace: namespace) @@ -166,9 +163,8 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do it 'creates a namespaced role binding with edit access' do subject - expect(WebMock).to have_requested(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings").with( + expect(WebMock).to have_requested(:put, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings/#{role_binding_name}").with( body: hash_including( - kind: 'RoleBinding', metadata: { name: "gitlab-#{namespace}", namespace: "#{namespace}" }, roleRef: { apiGroup: 'rbac.authorization.k8s.io', diff --git a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb b/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb new file mode 100644 index 00000000000..f14c929554a --- /dev/null +++ b/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb @@ -0,0 +1,200 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Clusters::ParseClusterApplicationsArtifactService do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + + before do + project.add_maintainer(user) + end + + describe 'RELEASE_NAMES' do + it 'is included in Cluster application names', :aggregate_failures do + described_class::RELEASE_NAMES.each do |release_name| + expect(Clusters::Cluster::APPLICATIONS).to include(release_name) + end + end + end + + describe '.new' do + let(:job) { build(:ci_build) } + + it 'sets the project and current user', :aggregate_failures do + service = described_class.new(job, user) + + expect(service.project).to eq(job.project) + expect(service.current_user).to eq(user) + end + end + + describe '#execute' do + let_it_be(:cluster, reload: true) { create(:cluster, projects: [project]) } + let_it_be(:deployment, reload: true) { create(:deployment, cluster: cluster) } + + let(:job) { deployment.deployable } + let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job) } + + context 'when cluster_applications_artifact feature flag is disabled' do + before do + stub_feature_flags(cluster_applications_artifact: false) + end + + it 'does not call Gitlab::Kubernetes::Helm::Parsers::ListV2 and returns success immediately' do + expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).not_to receive(:new) + + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:success) + end + end + + context 'when cluster_applications_artifact feature flag is enabled for project' do + before do + stub_feature_flags(cluster_applications_artifact: job.project) + end + + it 'calls Gitlab::Kubernetes::Helm::Parsers::ListV2' do + expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).to receive(:new).and_call_original + + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:success) + end + + context 'artifact is not of cluster_applications type' do + let(:artifact) { create(:ci_job_artifact, :archive) } + let(:job) { artifact.job } + + it 'raise ArgumentError' do + expect do + described_class.new(job, user).execute(artifact) + end.to raise_error(ArgumentError, 'Artifact is not cluster_applications file type') + end + end + + context 'artifact exceeds acceptable size' do + it 'returns an error' do + stub_const("#{described_class}::MAX_ACCEPTABLE_ARTIFACT_SIZE", 1.byte) + + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('Cluster_applications artifact too big. Maximum allowable size: 1 Byte') + end + end + + context 'job has no deployment cluster' do + let(:job) { build(:ci_build) } + + it 'returns an error' do + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('No deployment cluster found for this job') + end + end + + context 'job has deployment cluster' do + context 'current user does not have access to deployment cluster' do + let(:other_user) { create(:user) } + + it 'returns an error' do + result = described_class.new(job, other_user).execute(artifact) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('No deployment cluster found for this job') + end + end + + context 'release is missing' do + let(:fixture) { 'spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz' } + let(:file) { fixture_file_upload(Rails.root.join(fixture)) } + let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } + + context 'application does not exist' do + it 'does not create or destroy an application' do + expect do + described_class.new(job, user).execute(artifact) + end.not_to change(Clusters::Applications::Prometheus, :count) + end + end + + context 'application exists' do + before do + create(:clusters_applications_prometheus, :installed, cluster: cluster) + end + + it 'marks the application as uninstalled' do + described_class.new(job, user).execute(artifact) + + cluster.application_prometheus.reload + expect(cluster.application_prometheus).to be_uninstalled + end + end + end + + context 'release is deployed' do + let(:fixture) { 'spec/fixtures/helm/helm_list_v2_prometheus_deployed.json.gz' } + let(:file) { fixture_file_upload(Rails.root.join(fixture)) } + let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } + + context 'application does not exist' do + it 'creates an application and marks it as installed' do + expect do + described_class.new(job, user).execute(artifact) + end.to change(Clusters::Applications::Prometheus, :count) + + expect(cluster.application_prometheus).to be_persisted + expect(cluster.application_prometheus).to be_installed + end + end + + context 'application exists' do + before do + create(:clusters_applications_prometheus, :errored, cluster: cluster) + end + + it 'marks the application as installed' do + described_class.new(job, user).execute(artifact) + + expect(cluster.application_prometheus).to be_installed + end + end + end + + context 'release is failed' do + let(:fixture) { 'spec/fixtures/helm/helm_list_v2_prometheus_failed.json.gz' } + let(:file) { fixture_file_upload(Rails.root.join(fixture)) } + let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } + + context 'application does not exist' do + it 'creates an application and marks it as errored' do + expect do + described_class.new(job, user).execute(artifact) + end.to change(Clusters::Applications::Prometheus, :count) + + expect(cluster.application_prometheus).to be_persisted + expect(cluster.application_prometheus).to be_errored + expect(cluster.application_prometheus.status_reason).to eq('Helm release failed to install') + end + end + + context 'application exists' do + before do + create(:clusters_applications_prometheus, :installed, cluster: cluster) + end + + it 'marks the application as errored' do + described_class.new(job, user).execute(artifact) + + expect(cluster.application_prometheus).to be_errored + expect(cluster.application_prometheus.status_reason).to eq('Helm release failed to install') + end + end + end + end + end + end +end |