2016-06-14 11:51:12 +00:00
|
|
|
require 'spec_helper'
|
|
|
|
|
2017-07-10 14:24:02 +00:00
|
|
|
describe Environment do
|
2018-04-18 13:52:55 +00:00
|
|
|
let(:project) { create(:project, :stubbed_repository) }
|
2016-11-22 19:55:56 +00:00
|
|
|
subject(:environment) { create(:environment, project: project) }
|
2016-06-14 11:51:12 +00:00
|
|
|
|
|
|
|
it { is_expected.to belong_to(:project) }
|
|
|
|
it { is_expected.to have_many(:deployments) }
|
|
|
|
|
2016-10-17 21:40:44 +00:00
|
|
|
it { is_expected.to delegate_method(:stop_action).to(:last_deployment) }
|
2016-11-21 16:26:35 +00:00
|
|
|
it { is_expected.to delegate_method(:manual_actions).to(:last_deployment) }
|
2016-10-17 15:10:26 +00:00
|
|
|
|
2016-06-14 11:51:12 +00:00
|
|
|
it { is_expected.to validate_presence_of(:name) }
|
|
|
|
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
|
2016-12-02 12:54:57 +00:00
|
|
|
it { is_expected.to validate_length_of(:name).is_at_most(255) }
|
2016-07-26 07:35:47 +00:00
|
|
|
|
2016-12-08 01:09:18 +00:00
|
|
|
it { is_expected.to validate_uniqueness_of(:slug).scoped_to(:project_id) }
|
|
|
|
it { is_expected.to validate_length_of(:slug).is_at_most(24) }
|
2016-07-26 07:35:47 +00:00
|
|
|
|
2016-12-08 01:09:18 +00:00
|
|
|
it { is_expected.to validate_length_of(:external_url).is_at_most(255) }
|
2016-07-26 12:19:37 +00:00
|
|
|
|
2017-01-31 00:26:40 +00:00
|
|
|
describe '.order_by_last_deployed_at' do
|
2017-08-01 18:51:52 +00:00
|
|
|
let(:project) { create(:project, :repository) }
|
2017-01-30 04:01:31 +00:00
|
|
|
let!(:environment1) { create(:environment, project: project) }
|
|
|
|
let!(:environment2) { create(:environment, project: project) }
|
|
|
|
let!(:environment3) { create(:environment, project: project) }
|
2017-01-31 00:26:40 +00:00
|
|
|
let!(:deployment1) { create(:deployment, environment: environment1) }
|
2017-01-31 16:17:54 +00:00
|
|
|
let!(:deployment2) { create(:deployment, environment: environment2) }
|
|
|
|
let!(:deployment3) { create(:deployment, environment: environment1) }
|
2017-01-30 04:01:31 +00:00
|
|
|
|
2017-01-31 00:26:40 +00:00
|
|
|
it 'returns the environments in order of having been last deployed' do
|
|
|
|
expect(project.environments.order_by_last_deployed_at.to_a).to eq([environment3, environment2, environment1])
|
2017-01-30 04:01:31 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-05-12 13:19:27 +00:00
|
|
|
describe 'state machine' do
|
|
|
|
it 'invalidates the cache after a change' do
|
|
|
|
expect(environment).to receive(:expire_etag_cache)
|
|
|
|
|
|
|
|
environment.stop
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-05-30 21:56:26 +00:00
|
|
|
describe '#expire_etag_cache' do
|
|
|
|
let(:store) { Gitlab::EtagCaching::Store.new }
|
|
|
|
|
|
|
|
it 'changes the cached value' do
|
|
|
|
old_value = store.get(environment.etag_cache_key)
|
|
|
|
|
|
|
|
environment.stop
|
|
|
|
|
|
|
|
expect(store.get(environment.etag_cache_key)).not_to eq(old_value)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-11-06 13:08:33 +00:00
|
|
|
describe '.with_deployment' do
|
|
|
|
subject { described_class.with_deployment(sha) }
|
|
|
|
|
|
|
|
let(:environment) { create(:environment) }
|
|
|
|
let(:sha) { RepoHelpers.sample_commit.id }
|
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
context 'when deployment has the specified sha' do
|
|
|
|
let!(:deployment) { create(:deployment, environment: environment, sha: sha) }
|
2018-11-06 13:08:33 +00:00
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
it { is_expected.to eq([environment]) }
|
2018-11-06 13:08:33 +00:00
|
|
|
end
|
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
context 'when deployment does not have the specified sha' do
|
|
|
|
let!(:deployment) { create(:deployment, environment: environment, sha: 'abc') }
|
2018-11-06 13:08:33 +00:00
|
|
|
|
|
|
|
it { is_expected.to be_empty }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#last_deployed_at' do
|
|
|
|
subject { environment.last_deployed_at }
|
|
|
|
|
|
|
|
let(:environment) { create(:environment) }
|
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
context 'when the latest deployment is successful' do
|
|
|
|
let!(:deployment) { create(:deployment, :success, environment: environment) }
|
2018-11-06 13:08:33 +00:00
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
it { expect(subject).to be_within(1.second).of(deployment.finished_at) }
|
|
|
|
end
|
2018-11-06 13:08:33 +00:00
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
context 'when the latest deployment failed' do
|
|
|
|
let!(:deployment) { create(:deployment, :failed, environment: environment) }
|
2018-11-06 13:08:33 +00:00
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
it { is_expected.to be_nil }
|
2018-11-06 13:08:33 +00:00
|
|
|
end
|
|
|
|
|
2018-11-07 05:29:16 +00:00
|
|
|
context 'when the latest deployment is running' do
|
|
|
|
let!(:deployment) { create(:deployment, :running, environment: environment) }
|
2018-11-06 13:08:33 +00:00
|
|
|
|
|
|
|
it { is_expected.to be_nil }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-08-21 15:46:45 +00:00
|
|
|
describe '#folder_name' do
|
|
|
|
context 'when it is inside a folder' do
|
|
|
|
subject(:environment) do
|
|
|
|
create(:environment, name: 'staging/review-1')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns a top-level folder name' do
|
|
|
|
expect(environment.folder_name).to eq 'staging'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the environment if a top-level item itself' do
|
|
|
|
subject(:environment) do
|
|
|
|
create(:environment, name: 'production')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns an environment name' do
|
|
|
|
expect(environment.folder_name).to eq 'production'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-07-26 12:19:37 +00:00
|
|
|
describe '#nullify_external_url' do
|
|
|
|
it 'replaces a blank url with nil' do
|
|
|
|
env = build(:environment, external_url: "")
|
|
|
|
|
|
|
|
expect(env.save).to be true
|
2016-07-29 10:14:36 +00:00
|
|
|
expect(env.external_url).to be_nil
|
2016-07-26 12:19:37 +00:00
|
|
|
end
|
|
|
|
end
|
2016-08-03 11:37:39 +00:00
|
|
|
|
2016-08-09 13:11:14 +00:00
|
|
|
describe '#includes_commit?' do
|
2017-01-26 22:44:58 +00:00
|
|
|
let(:project) { create(:project, :repository) }
|
2016-11-22 19:55:56 +00:00
|
|
|
|
2016-08-03 11:37:39 +00:00
|
|
|
context 'without a last deployment' do
|
|
|
|
it "returns false" do
|
2016-08-09 13:11:14 +00:00
|
|
|
expect(environment.includes_commit?('HEAD')).to be false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with a last deployment' do
|
|
|
|
let!(:deployment) do
|
2018-11-05 00:37:40 +00:00
|
|
|
create(:deployment, :success, environment: environment, sha: project.commit('master').id)
|
2016-08-09 13:11:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'in the same branch' do
|
|
|
|
it 'returns true' do
|
|
|
|
expect(environment.includes_commit?(RepoHelpers.sample_commit)).to be true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'not in the same branch' do
|
|
|
|
before do
|
|
|
|
deployment.update(sha: project.commit('feature').id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns false' do
|
|
|
|
expect(environment.includes_commit?(RepoHelpers.sample_commit)).to be false
|
|
|
|
end
|
2016-08-03 11:37:39 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-09-14 20:32:11 +00:00
|
|
|
|
2017-01-06 14:51:06 +00:00
|
|
|
describe '#update_merge_request_metrics?' do
|
2017-02-22 17:44:44 +00:00
|
|
|
{
|
|
|
|
'production' => true,
|
2017-01-06 14:51:06 +00:00
|
|
|
'production/eu' => true,
|
|
|
|
'production/www.gitlab.com' => true,
|
|
|
|
'productioneu' => false,
|
|
|
|
'Production' => false,
|
|
|
|
'Production/eu' => false,
|
|
|
|
'test-production' => false
|
|
|
|
}.each do |name, expected_value|
|
|
|
|
it "returns #{expected_value} for #{name}" do
|
|
|
|
env = create(:environment, name: name)
|
|
|
|
|
|
|
|
expect(env.update_merge_request_metrics?).to eq(expected_value)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-14 20:32:11 +00:00
|
|
|
describe '#environment_type' do
|
|
|
|
subject { environment.environment_type }
|
|
|
|
|
|
|
|
it 'sets a environment type if name has multiple segments' do
|
2016-09-19 07:01:04 +00:00
|
|
|
environment.update!(name: 'production/worker.gitlab.com')
|
2016-09-14 20:32:11 +00:00
|
|
|
|
|
|
|
is_expected.to eq('production')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'nullifies a type if it\'s a simple name' do
|
2016-09-19 07:01:04 +00:00
|
|
|
environment.update!(name: 'production')
|
2016-09-14 20:32:11 +00:00
|
|
|
|
|
|
|
is_expected.to be_nil
|
|
|
|
end
|
|
|
|
end
|
2016-10-17 15:10:26 +00:00
|
|
|
|
2018-07-12 10:22:11 +00:00
|
|
|
describe '#stop_action_available?' do
|
|
|
|
subject { environment.stop_action_available? }
|
2016-10-17 15:10:26 +00:00
|
|
|
|
|
|
|
context 'when no other actions' do
|
|
|
|
it { is_expected.to be_falsey }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when matching action is defined' do
|
|
|
|
let(:build) { create(:ci_build) }
|
2018-07-12 10:22:11 +00:00
|
|
|
|
|
|
|
let!(:deployment) do
|
2018-11-05 00:37:40 +00:00
|
|
|
create(:deployment, :success,
|
|
|
|
environment: environment,
|
2018-07-12 10:22:11 +00:00
|
|
|
deployable: build,
|
|
|
|
on_stop: 'close_app')
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:close_action) do
|
|
|
|
create(:ci_build, :manual, pipeline: build.pipeline,
|
|
|
|
name: 'close_app')
|
|
|
|
end
|
2016-10-17 15:10:26 +00:00
|
|
|
|
|
|
|
context 'when environment is available' do
|
|
|
|
before do
|
|
|
|
environment.start
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when environment is stopped' do
|
|
|
|
before do
|
|
|
|
environment.stop
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_falsey }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-10-18 10:02:50 +00:00
|
|
|
|
2017-02-06 15:50:03 +00:00
|
|
|
describe '#stop_with_action!' do
|
2018-04-18 13:52:55 +00:00
|
|
|
let(:user) { create(:user) }
|
2016-10-18 10:02:50 +00:00
|
|
|
|
2017-02-06 15:50:03 +00:00
|
|
|
subject { environment.stop_with_action!(user) }
|
2016-10-18 10:02:50 +00:00
|
|
|
|
|
|
|
before do
|
2016-11-10 12:59:26 +00:00
|
|
|
expect(environment).to receive(:available?).and_call_original
|
2016-10-18 10:02:50 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when no other actions' do
|
2016-11-10 12:59:26 +00:00
|
|
|
context 'environment is available' do
|
|
|
|
before do
|
|
|
|
environment.update(state: :available)
|
|
|
|
end
|
|
|
|
|
|
|
|
it do
|
|
|
|
subject
|
|
|
|
|
|
|
|
expect(environment).to be_stopped
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'environment is already stopped' do
|
|
|
|
before do
|
|
|
|
environment.update(state: :stopped)
|
|
|
|
end
|
|
|
|
|
|
|
|
it do
|
|
|
|
subject
|
|
|
|
|
|
|
|
expect(environment).to be_stopped
|
|
|
|
end
|
|
|
|
end
|
2016-10-18 10:02:50 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when matching action is defined' do
|
2017-04-06 12:28:40 +00:00
|
|
|
let(:pipeline) { create(:ci_pipeline, project: project) }
|
|
|
|
let(:build) { create(:ci_build, pipeline: pipeline) }
|
|
|
|
|
|
|
|
let!(:deployment) do
|
2018-11-05 00:37:40 +00:00
|
|
|
create(:deployment, :success,
|
|
|
|
environment: environment,
|
2017-04-06 12:28:40 +00:00
|
|
|
deployable: build,
|
|
|
|
on_stop: 'close_app')
|
|
|
|
end
|
2016-10-18 10:02:50 +00:00
|
|
|
|
2017-04-06 12:28:40 +00:00
|
|
|
context 'when user is not allowed to stop environment' do
|
|
|
|
let!(:close_action) do
|
|
|
|
create(:ci_build, :manual, pipeline: pipeline, name: 'close_app')
|
|
|
|
end
|
2016-10-18 10:02:50 +00:00
|
|
|
|
2017-04-06 12:28:40 +00:00
|
|
|
it 'raises an exception' do
|
|
|
|
expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
|
2016-10-18 10:02:50 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-06 12:28:40 +00:00
|
|
|
context 'when user is allowed to stop environment' do
|
|
|
|
before do
|
2017-05-31 09:20:36 +00:00
|
|
|
project.add_developer(user)
|
|
|
|
|
|
|
|
create(:protected_branch, :developers_can_merge,
|
|
|
|
name: 'master', project: project)
|
2017-04-06 12:28:40 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when action did not yet finish' do
|
|
|
|
let!(:close_action) do
|
|
|
|
create(:ci_build, :manual, pipeline: pipeline, name: 'close_app')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns the same action' do
|
|
|
|
expect(subject).to eq(close_action)
|
|
|
|
expect(subject.user).to eq(user)
|
|
|
|
end
|
|
|
|
end
|
2016-10-18 10:02:50 +00:00
|
|
|
|
2017-04-06 12:28:40 +00:00
|
|
|
context 'if action did finish' do
|
|
|
|
let!(:close_action) do
|
|
|
|
create(:ci_build, :manual, :success,
|
|
|
|
pipeline: pipeline, name: 'close_app')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns a new action of the same type' do
|
|
|
|
expect(subject).to be_persisted
|
|
|
|
expect(subject.name).to eq(close_action.name)
|
|
|
|
expect(subject.user).to eq(user)
|
|
|
|
end
|
2016-10-18 10:02:50 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-11-16 10:26:36 +00:00
|
|
|
|
|
|
|
describe 'recently_updated_on_branch?' do
|
|
|
|
subject { environment.recently_updated_on_branch?('feature') }
|
|
|
|
|
|
|
|
context 'when last deployment to environment is the most recent one' do
|
|
|
|
before do
|
2018-11-05 00:37:40 +00:00
|
|
|
create(:deployment, :success, environment: environment, ref: 'feature')
|
2016-11-16 10:26:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be true }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when last deployment to environment is not the most recent' do
|
|
|
|
before do
|
2018-11-05 00:37:40 +00:00
|
|
|
create(:deployment, :success, environment: environment, ref: 'feature')
|
|
|
|
create(:deployment, :success, environment: environment, ref: 'master')
|
2016-11-16 10:26:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be false }
|
|
|
|
end
|
|
|
|
end
|
2016-11-21 16:26:35 +00:00
|
|
|
|
|
|
|
describe '#actions_for' do
|
2018-11-05 00:37:40 +00:00
|
|
|
let(:deployment) { create(:deployment, :success, environment: environment) }
|
2016-11-21 16:26:35 +00:00
|
|
|
let(:pipeline) { deployment.deployable.pipeline }
|
2017-03-10 10:20:08 +00:00
|
|
|
let!(:review_action) { create(:ci_build, :manual, name: 'review-apps', pipeline: pipeline, environment: 'review/$CI_COMMIT_REF_NAME' )}
|
2016-11-21 16:26:35 +00:00
|
|
|
let!(:production_action) { create(:ci_build, :manual, name: 'production', pipeline: pipeline, environment: 'production' )}
|
|
|
|
|
|
|
|
it 'returns a list of actions with matching environment' do
|
|
|
|
expect(environment.actions_for('review/master')).to contain_exactly(review_action)
|
|
|
|
end
|
|
|
|
end
|
2016-12-08 01:09:18 +00:00
|
|
|
|
2018-11-05 00:37:40 +00:00
|
|
|
describe '.deployments' do
|
|
|
|
subject { environment.deployments }
|
|
|
|
|
|
|
|
context 'when there is a deployment record with created status' do
|
|
|
|
let(:deployment) { create(:deployment, :created, environment: environment) }
|
|
|
|
|
|
|
|
it 'does not return the record' do
|
|
|
|
is_expected.to be_empty
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is a deployment record with running status' do
|
|
|
|
let(:deployment) { create(:deployment, :running, environment: environment) }
|
|
|
|
|
|
|
|
it 'does not return the record' do
|
|
|
|
is_expected.to be_empty
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is a deployment record with success status' do
|
|
|
|
let(:deployment) { create(:deployment, :success, environment: environment) }
|
|
|
|
|
|
|
|
it 'returns the record' do
|
|
|
|
is_expected.to eq([deployment])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '.last_deployment' do
|
|
|
|
subject { environment.last_deployment }
|
|
|
|
|
|
|
|
before do
|
|
|
|
allow_any_instance_of(Deployment).to receive(:create_ref)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is an old deployment record' do
|
|
|
|
let!(:previous_deployment) { create(:deployment, :success, environment: environment) }
|
|
|
|
|
|
|
|
context 'when there is a deployment record with created status' do
|
|
|
|
let!(:deployment) { create(:deployment, environment: environment) }
|
|
|
|
|
|
|
|
it 'returns the previous deployment' do
|
|
|
|
is_expected.to eq(previous_deployment)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is a deployment record with running status' do
|
|
|
|
let!(:deployment) { create(:deployment, :running, environment: environment) }
|
|
|
|
|
|
|
|
it 'returns the previous deployment' do
|
|
|
|
is_expected.to eq(previous_deployment)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is a deployment record with success status' do
|
|
|
|
let!(:deployment) { create(:deployment, :success, environment: environment) }
|
|
|
|
|
|
|
|
it 'returns the latest successful deployment' do
|
|
|
|
is_expected.to eq(deployment)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-22 19:55:56 +00:00
|
|
|
describe '#has_terminals?' do
|
|
|
|
subject { environment.has_terminals? }
|
|
|
|
|
2018-10-26 15:31:04 +00:00
|
|
|
context 'when the environment is available' do
|
2016-11-22 19:55:56 +00:00
|
|
|
context 'with a deployment service' do
|
2017-11-27 14:19:16 +00:00
|
|
|
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
|
2017-11-27 12:48:54 +00:00
|
|
|
context 'and a deployment' do
|
2018-11-05 00:37:40 +00:00
|
|
|
let!(:deployment) { create(:deployment, :success, environment: environment) }
|
2017-11-27 12:48:54 +00:00
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'but no deployments' do
|
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user configured kubernetes from Integration > Kubernetes' do
|
|
|
|
let(:project) { create(:kubernetes_project) }
|
2016-11-22 19:55:56 +00:00
|
|
|
|
2017-11-27 14:19:16 +00:00
|
|
|
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
|
2016-11-22 19:55:56 +00:00
|
|
|
end
|
|
|
|
|
2017-11-27 12:48:54 +00:00
|
|
|
context 'when user configured kubernetes from CI/CD > Clusters' do
|
|
|
|
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
|
|
|
|
let(:project) { cluster.project }
|
|
|
|
|
2017-11-27 14:19:16 +00:00
|
|
|
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
|
2016-11-22 19:55:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without a deployment service' do
|
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the environment is unavailable' do
|
|
|
|
let(:project) { create(:kubernetes_project) }
|
2017-03-07 16:57:42 +00:00
|
|
|
|
|
|
|
before do
|
|
|
|
environment.stop
|
|
|
|
end
|
|
|
|
|
2016-11-22 19:55:56 +00:00
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-06 10:10:30 +00:00
|
|
|
describe '#deployment_platform' do
|
|
|
|
context 'when there is a deployment platform for environment' do
|
|
|
|
let!(:cluster) do
|
|
|
|
create(:cluster, :provided_by_gcp,
|
|
|
|
environment_scope: '*', projects: [project])
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'finds a deployment platform' do
|
|
|
|
expect(environment.deployment_platform).to eq cluster.platform
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when there is no deployment platform for environment' do
|
|
|
|
it 'returns nil' do
|
|
|
|
expect(environment.deployment_platform).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'checks deployment platforms associated with a project' do
|
|
|
|
expect(project).to receive(:deployment_platform)
|
|
|
|
.with(environment: environment.name)
|
|
|
|
|
|
|
|
environment.deployment_platform
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-22 19:55:56 +00:00
|
|
|
describe '#terminals' do
|
|
|
|
subject { environment.terminals }
|
|
|
|
|
|
|
|
context 'when the environment has terminals' do
|
2017-03-07 16:57:42 +00:00
|
|
|
before do
|
|
|
|
allow(environment).to receive(:has_terminals?).and_return(true)
|
|
|
|
end
|
2016-11-22 19:55:56 +00:00
|
|
|
|
2017-11-27 14:19:16 +00:00
|
|
|
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
|
2017-11-27 13:35:16 +00:00
|
|
|
it 'returns the terminals from the deployment service' do
|
|
|
|
expect(project.deployment_platform)
|
|
|
|
.to receive(:terminals).with(environment)
|
|
|
|
.and_return(:fake_terminals)
|
2016-11-22 19:55:56 +00:00
|
|
|
|
2017-11-27 13:35:16 +00:00
|
|
|
is_expected.to eq(:fake_terminals)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user configured kubernetes from Integration > Kubernetes' do
|
|
|
|
let(:project) { create(:kubernetes_project) }
|
|
|
|
|
2017-11-27 14:19:16 +00:00
|
|
|
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
|
2017-11-27 13:35:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user configured kubernetes from CI/CD > Clusters' do
|
|
|
|
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
|
|
|
|
let(:project) { cluster.project }
|
|
|
|
|
2017-11-27 14:19:16 +00:00
|
|
|
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
|
2016-11-22 19:55:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the environment does not have terminals' do
|
2017-03-07 16:57:42 +00:00
|
|
|
before do
|
|
|
|
allow(environment).to receive(:has_terminals?).and_return(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_nil }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#has_metrics?' do
|
|
|
|
subject { environment.has_metrics? }
|
|
|
|
|
2018-10-26 15:31:04 +00:00
|
|
|
context 'when the environment is available' do
|
2017-03-07 16:57:42 +00:00
|
|
|
context 'with a deployment service' do
|
|
|
|
let(:project) { create(:prometheus_project) }
|
|
|
|
|
|
|
|
context 'and a deployment' do
|
|
|
|
let!(:deployment) { create(:deployment, environment: environment) }
|
|
|
|
it { is_expected.to be_truthy }
|
|
|
|
end
|
|
|
|
|
2018-10-26 15:31:04 +00:00
|
|
|
context 'and no deployments' do
|
|
|
|
it { is_expected.to be_truthy }
|
2017-03-07 16:57:42 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without a monitoring service' do
|
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the environment is unavailable' do
|
|
|
|
let(:project) { create(:prometheus_project) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
environment.stop
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_falsy }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#metrics' do
|
|
|
|
let(:project) { create(:prometheus_project) }
|
|
|
|
subject { environment.metrics }
|
|
|
|
|
|
|
|
context 'when the environment has metrics' do
|
|
|
|
before do
|
|
|
|
allow(environment).to receive(:has_metrics?).and_return(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns the metrics from the deployment service' do
|
2018-02-23 20:33:33 +00:00
|
|
|
expect(environment.prometheus_adapter)
|
|
|
|
.to receive(:query).with(:environment, environment)
|
2017-03-07 16:57:42 +00:00
|
|
|
.and_return(:fake_metrics)
|
|
|
|
|
|
|
|
is_expected.to eq(:fake_metrics)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the environment does not have metrics' do
|
|
|
|
before do
|
|
|
|
allow(environment).to receive(:has_metrics?).and_return(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_nil }
|
2016-11-22 19:55:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-05 16:38:09 +00:00
|
|
|
describe '#additional_metrics' do
|
|
|
|
let(:project) { create(:prometheus_project) }
|
|
|
|
subject { environment.additional_metrics }
|
|
|
|
|
|
|
|
context 'when the environment has additional metrics' do
|
|
|
|
before do
|
2018-02-23 20:33:33 +00:00
|
|
|
allow(environment).to receive(:has_metrics?).and_return(true)
|
2017-06-05 16:38:09 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns the additional metrics from the deployment service' do
|
2018-02-23 20:33:33 +00:00
|
|
|
expect(environment.prometheus_adapter).to receive(:query)
|
|
|
|
.with(:additional_metrics_environment, environment)
|
2017-06-05 16:38:09 +00:00
|
|
|
.and_return(:fake_metrics)
|
|
|
|
|
|
|
|
is_expected.to eq(:fake_metrics)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the environment does not have metrics' do
|
|
|
|
before do
|
2018-02-23 20:33:33 +00:00
|
|
|
allow(environment).to receive(:has_metrics?).and_return(false)
|
2017-06-05 16:38:09 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to be_nil }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-12-08 01:09:18 +00:00
|
|
|
describe '#slug' do
|
|
|
|
it "is automatically generated" do
|
|
|
|
expect(environment.slug).not_to be_nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it "is not regenerated if name changes" do
|
|
|
|
original_slug = environment.slug
|
2018-07-02 10:43:06 +00:00
|
|
|
environment.update!(name: environment.name.reverse)
|
2016-12-08 01:09:18 +00:00
|
|
|
|
|
|
|
expect(environment.slug).to eq(original_slug)
|
|
|
|
end
|
2017-11-02 22:32:22 +00:00
|
|
|
|
|
|
|
it "regenerates the slug if nil" do
|
|
|
|
environment = build(:environment, slug: nil)
|
|
|
|
|
|
|
|
new_slug = environment.slug
|
|
|
|
|
|
|
|
expect(new_slug).not_to be_nil
|
|
|
|
expect(environment.slug).to eq(new_slug)
|
|
|
|
end
|
2016-12-08 01:09:18 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
describe '#generate_slug' do
|
2017-02-21 23:32:18 +00:00
|
|
|
SUFFIX = "-[a-z0-9]{6}".freeze
|
2016-12-08 01:09:18 +00:00
|
|
|
{
|
|
|
|
"staging-12345678901234567" => "staging-123456789" + SUFFIX,
|
|
|
|
"9-staging-123456789012345" => "env-9-staging-123" + SUFFIX,
|
|
|
|
"staging-1234567890123456" => "staging-1234567890123456",
|
|
|
|
"production" => "production",
|
|
|
|
"PRODUCTION" => "production" + SUFFIX,
|
|
|
|
"review/1-foo" => "review-1-foo" + SUFFIX,
|
|
|
|
"1-foo" => "env-1-foo" + SUFFIX,
|
|
|
|
"1/foo" => "env-1-foo" + SUFFIX,
|
|
|
|
"foo-" => "foo" + SUFFIX,
|
2017-01-19 14:42:03 +00:00
|
|
|
"foo--bar" => "foo-bar" + SUFFIX,
|
|
|
|
"foo**bar" => "foo-bar" + SUFFIX,
|
|
|
|
"*-foo" => "env-foo" + SUFFIX,
|
|
|
|
"staging-12345678-" => "staging-12345678" + SUFFIX,
|
2017-05-03 11:22:03 +00:00
|
|
|
"staging-12345678-01234567" => "staging-12345678" + SUFFIX
|
2016-12-08 01:09:18 +00:00
|
|
|
}.each do |name, matcher|
|
|
|
|
it "returns a slug matching #{matcher}, given #{name}" do
|
2016-12-08 15:37:41 +00:00
|
|
|
slug = described_class.new(name: name).generate_slug
|
2016-12-08 01:09:18 +00:00
|
|
|
|
|
|
|
expect(slug).to match(/\A#{matcher}\z/)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-01-30 04:01:31 +00:00
|
|
|
|
2017-10-23 00:57:51 +00:00
|
|
|
describe '#ref_path' do
|
|
|
|
subject(:environment) do
|
|
|
|
create(:environment, name: 'staging / review-1')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns a path that uses the slug and does not have spaces' do
|
|
|
|
expect(environment.ref_path).to start_with('refs/environments/staging-review-1-')
|
|
|
|
end
|
2017-11-02 22:32:22 +00:00
|
|
|
|
|
|
|
it "doesn't change when the slug is nil initially" do
|
|
|
|
environment.slug = nil
|
|
|
|
|
|
|
|
expect(environment.ref_path).to eq(environment.ref_path)
|
|
|
|
end
|
2017-10-23 00:57:51 +00:00
|
|
|
end
|
|
|
|
|
2017-01-30 04:01:31 +00:00
|
|
|
describe '#external_url_for' do
|
|
|
|
let(:source_path) { 'source/file.html' }
|
|
|
|
let(:sha) { RepoHelpers.sample_commit.id }
|
|
|
|
|
|
|
|
before do
|
|
|
|
environment.external_url = 'http://example.com'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the public path is not known' do
|
|
|
|
before do
|
|
|
|
allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return(nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns nil' do
|
|
|
|
expect(environment.external_url_for(source_path, sha)).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when the public path is known' do
|
|
|
|
before do
|
|
|
|
allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return('file.html')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns the full external URL' do
|
|
|
|
expect(environment.external_url_for(source_path, sha)).to eq('http://example.com/file.html')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-02-23 20:33:33 +00:00
|
|
|
|
|
|
|
describe '#prometheus_adapter' do
|
2018-03-05 20:02:26 +00:00
|
|
|
it 'calls prometheus adapter service' do
|
|
|
|
expect_any_instance_of(Prometheus::AdapterService).to receive(:prometheus_adapter)
|
2018-02-23 20:33:33 +00:00
|
|
|
|
2018-03-05 20:02:26 +00:00
|
|
|
subject.prometheus_adapter
|
2018-02-23 20:33:33 +00:00
|
|
|
end
|
|
|
|
end
|
2016-06-14 11:51:12 +00:00
|
|
|
end
|