summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/action/custom_spec.rb136
-rw-r--r--spec/gitlab_shell_spec.rb23
-rw-r--r--spec/vcr_cassettes/custom-action-not-ok-json.yml40
-rw-r--r--spec/vcr_cassettes/custom-action-not-ok-not-json.yml40
-rw-r--r--spec/vcr_cassettes/custom-action-ok-not-json.yml51
-rw-r--r--spec/vcr_cassettes/custom-action-ok.yml99
6 files changed, 389 insertions, 0 deletions
diff --git a/spec/action/custom_spec.rb b/spec/action/custom_spec.rb
new file mode 100644
index 0000000..e85df71
--- /dev/null
+++ b/spec/action/custom_spec.rb
@@ -0,0 +1,136 @@
+require_relative '../spec_helper'
+require_relative '../../lib/action/custom'
+
+describe Action::Custom do
+ let(:repo_name) { 'gitlab-ci.git' }
+ let(:gl_id) { 'key-1' }
+ let(:secret) { "0a3938d9d95d807e94d937af3a4fbbea" }
+ let(:base_url) { 'http://localhost:3000' }
+
+ subject { described_class.new(gl_id, payload) }
+
+ describe '#execute' do
+ context 'with an empty payload' do
+ let(:payload) { {} }
+
+ it 'raises a MissingPayloadError exception' do
+ expect { subject.execute }.to raise_error(Action::Custom::MissingPayloadError)
+ end
+ end
+
+ context 'with api_endpoints defined' do
+ before do
+ allow(subject).to receive(:base_url).and_return(base_url)
+ allow(subject).to receive(:secret_token).and_return(secret)
+ allow($stdin).to receive(:read).and_return('')
+ end
+
+ context 'that are valid' do
+ let(:payload) do
+ {
+ 'action' => 'geo_proxy_to_primary',
+ 'data' => {
+ 'api_endpoints' => %w{/api/v4/fake/info_refs /api/v4/fake/push},
+ 'gl_username' => 'user1',
+ 'primary_repo' => 'http://localhost:3001/user1/repo1.git'
+ }
+ }
+ end
+
+ context 'and responds correctly' do
+ it 'returns an instance of Net::HTTPCreated' do
+ VCR.use_cassette("custom-action-ok") do
+ expect(subject.execute).to be_instance_of(Net::HTTPCreated)
+ end
+ end
+ end
+
+ context 'but responds incorrectly' do
+ it 'raises an UnsuccessfulError exception' do
+ VCR.use_cassette("custom-action-ok-not-json") do
+ expect {
+ subject.execute
+ }.to raise_error(Action::Custom::UnsuccessfulError, 'Response was not valid JSON')
+ end
+ end
+ end
+ end
+
+ context 'that are invalid' do
+ context 'where api_endpoints gl_id is missing' do
+ let(:payload) do
+ {
+ 'action' => 'geo_proxy_to_primary',
+ 'data' => {
+ 'gl_username' => 'user1',
+ 'primary_repo' => 'http://localhost:3001/user1/repo1.git'
+ }
+ }
+ end
+
+ it 'raises a MissingAPIEndpointsError exception' do
+ expect { subject.execute }.to raise_error(Action::Custom::MissingAPIEndpointsError)
+ end
+ end
+
+ context 'where api_endpoints are empty' do
+ let(:payload) do
+ {
+ 'action' => 'geo_proxy_to_primary',
+ 'data' => {
+ 'api_endpoints' => [],
+ 'gl_username' => 'user1',
+ 'primary_repo' => 'http://localhost:3001/user1/repo1.git'
+ }
+ }
+ end
+
+ it 'raises a MissingAPIEndpointsError exception' do
+ expect { subject.execute }.to raise_error(Action::Custom::MissingAPIEndpointsError)
+ end
+ end
+
+ context 'where data gl_id is missing' do
+ let(:payload) { { 'api_endpoints' => %w{/api/v4/fake/info_refs /api/v4/fake/push} } }
+
+ it 'raises a MissingDataError exception' do
+ expect { subject.execute }.to raise_error(Action::Custom::MissingDataError)
+ end
+ end
+
+ context 'where API endpoints are bad' do
+ let(:payload) do
+ {
+ 'action' => 'geo_proxy_to_primary',
+ 'data' => {
+ 'api_endpoints' => %w{/api/v4/fake/info_refs_bad /api/v4/fake/push_bad},
+ 'gl_username' => 'user1',
+ 'primary_repo' => 'http://localhost:3001/user1/repo1.git'
+ }
+ }
+ end
+
+ context 'and response is JSON' do
+ it 'raises an UnsuccessfulError exception' do
+ VCR.use_cassette("custom-action-not-ok-json") do
+ expect {
+ subject.execute
+ }.to raise_error(Action::Custom::UnsuccessfulError, 'You cannot perform write operations on a read-only instance (403)')
+ end
+ end
+ end
+
+ context 'and response is not JSON' do
+ it 'raises an UnsuccessfulError exception' do
+ VCR.use_cassette("custom-action-not-ok-not-json") do
+ expect {
+ subject.execute
+ }.to raise_error(Action::Custom::UnsuccessfulError, 'No message (403)')
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/gitlab_shell_spec.rb b/spec/gitlab_shell_spec.rb
index 24fe151..77fb6cd 100644
--- a/spec/gitlab_shell_spec.rb
+++ b/spec/gitlab_shell_spec.rb
@@ -256,6 +256,29 @@ describe GitlabShell do
user_string = "user with id #{gl_id}"
expect($logger).to receive(:info).with(message, command: "gitaly-receive-pack unix:gitaly.socket #{gitaly_message}", user: user_string)
end
+
+ context 'with a custom action' do
+ let(:fake_payload) { { 'api_endpoints' => [ '/fake/api/endpoint' ], 'data' => {} } }
+ let(:custom_action_gitlab_access_status) do
+ GitAccessStatus.new(
+ true,
+ HTTPCodes::HTTP_MULTIPLE_CHOICES,
+ 'Multiple Choices',
+ payload: fake_payload
+ )
+ end
+ let(:action_custom) { double(Action::Custom) }
+
+ before do
+ allow(api).to receive(:check_access).and_return(custom_action_gitlab_access_status)
+ end
+
+ it "should not process the command" do
+ expect(subject).to_not receive(:process_cmd).with(%w(git-receive-pack gitlab-ci.git))
+ expect(Action::Custom).to receive(:new).with(gl_id, fake_payload).and_return(action_custom)
+ expect(action_custom).to receive(:execute)
+ end
+ end
end
context 'gitaly-receive-pack' do
diff --git a/spec/vcr_cassettes/custom-action-not-ok-json.yml b/spec/vcr_cassettes/custom-action-not-ok-json.yml
new file mode 100644
index 0000000..e50719d
--- /dev/null
+++ b/spec/vcr_cassettes/custom-action-not-ok-json.yml
@@ -0,0 +1,40 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: http://localhost:3000/api/v4/fake/info_refs_bad
+ body:
+ encoding: UTF-8
+ string: '{"data":{"gl_username":"user1","primary_repo":"http://localhost:3001/user1/repo1.git","gl_id":"key-11"},"output":"","secret_token":"0a3938d9d95d807e94d937af3a4fbbea\n"}'
+ headers:
+ Content-Type:
+ - application/json
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ Host:
+ - localhost
+ response:
+ status:
+ code: 403
+ message: Forbidden
+ headers:
+ Date:
+ - Fri, 20 Jul 2018 06:54:21 GMT
+ Connection:
+ - close
+ Content-Type:
+ - application/json
+ X-Request-Id:
+ - ea0644ac-e1ad-45f6-aa72-cc7910274318
+ X-Runtime:
+ - '1.236672'
+ body:
+ encoding: UTF-8
+ string: '{"message":"You cannot perform write operations on a read-only instance"}'
+ http_version:
+ recorded_at: Fri, 20 Jul 2018 06:54:21 GMT
+recorded_with: VCR 2.4.0
diff --git a/spec/vcr_cassettes/custom-action-not-ok-not-json.yml b/spec/vcr_cassettes/custom-action-not-ok-not-json.yml
new file mode 100644
index 0000000..b60a93a
--- /dev/null
+++ b/spec/vcr_cassettes/custom-action-not-ok-not-json.yml
@@ -0,0 +1,40 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: http://localhost:3000/api/v4/fake/info_refs_bad
+ body:
+ encoding: UTF-8
+ string: '{"data":{"gl_username":"user1","primary_repo":"http://localhost:3001/user1/repo1.git","gl_id":"key-11"},"output":"","secret_token":"0a3938d9d95d807e94d937af3a4fbbea\n"}'
+ headers:
+ Content-Type:
+ - application/json
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ Host:
+ - localhost
+ response:
+ status:
+ code: 403
+ message: Forbidden
+ headers:
+ Date:
+ - Fri, 20 Jul 2018 06:54:21 GMT
+ Connection:
+ - close
+ Content-Type:
+ - application/json
+ X-Request-Id:
+ - ea0644ac-e1ad-45f6-aa72-cc7910274318
+ X-Runtime:
+ - '1.236672'
+ body:
+ encoding: UTF-8
+ string: '""'
+ http_version:
+ recorded_at: Fri, 20 Jul 2018 06:54:21 GMT
+recorded_with: VCR 2.4.0
diff --git a/spec/vcr_cassettes/custom-action-ok-not-json.yml b/spec/vcr_cassettes/custom-action-ok-not-json.yml
new file mode 100644
index 0000000..3bfb390
--- /dev/null
+++ b/spec/vcr_cassettes/custom-action-ok-not-json.yml
@@ -0,0 +1,51 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: http://localhost:3000/api/v4/fake/info_refs
+ body:
+ encoding: UTF-8
+ string: '{"data":{"gl_username":"user1","primary_repo":"http://localhost:3001/user1/repo1.git","gl_id":"key-1"},"output":"","secret_token":"0a3938d9d95d807e94d937af3a4fbbea"}'
+ headers:
+ Content-Type:
+ - application/json
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ Host:
+ - localhost
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Fri, 20 Jul 2018 06:18:58 GMT
+ Connection:
+ - close
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Content-Type-Options:
+ - nosniff
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '172'
+ Vary:
+ - Origin
+ Etag:
+ - W/"7d01e1e3dbcbe7cca9607461352f8244"
+ Cache-Control:
+ - max-age=0, private, must-revalidate
+ X-Request-Id:
+ - 03afa234-b6be-49ab-9392-4aa35c5dee25
+ X-Runtime:
+ - '1.436040'
+ body:
+ encoding: UTF-8
+ string: '""'
+ http_version:
+ recorded_at: Fri, 20 Jul 2018 06:18:58 GMT
diff --git a/spec/vcr_cassettes/custom-action-ok.yml b/spec/vcr_cassettes/custom-action-ok.yml
new file mode 100644
index 0000000..a057441
--- /dev/null
+++ b/spec/vcr_cassettes/custom-action-ok.yml
@@ -0,0 +1,99 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: http://localhost:3000/api/v4/fake/info_refs
+ body:
+ encoding: UTF-8
+ string: '{"data":{"gl_username":"user1","primary_repo":"http://localhost:3001/user1/repo1.git","gl_id":"key-1"},"output":"","secret_token":"0a3938d9d95d807e94d937af3a4fbbea"}'
+ headers:
+ Content-Type:
+ - application/json
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ Host:
+ - localhost
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Fri, 20 Jul 2018 06:18:58 GMT
+ Connection:
+ - close
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Content-Type-Options:
+ - nosniff
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '172'
+ Vary:
+ - Origin
+ Etag:
+ - W/"7d01e1e3dbcbe7cca9607461352f8244"
+ Cache-Control:
+ - max-age=0, private, must-revalidate
+ X-Request-Id:
+ - 03afa234-b6be-49ab-9392-4aa35c5dee25
+ X-Runtime:
+ - '1.436040'
+ body:
+ encoding: UTF-8
+ string: '{"result":"info_refs-result"}'
+ http_version:
+ recorded_at: Fri, 20 Jul 2018 06:18:58 GMT
+- request:
+ method: post
+ uri: http://localhost:3000/api/v4/fake/push
+ body:
+ encoding: UTF-8
+ string: '{"data":{"gl_username":"user1","primary_repo":"http://localhost:3001/user1/repo1.git","gl_id":"key-1"},"output":"info_refs-result","secret_token":"0a3938d9d95d807e94d937af3a4fbbea"}'
+ headers:
+ Content-Type:
+ - application/json
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ User-Agent:
+ - Ruby
+ Host:
+ - localhost
+ response:
+ status:
+ code: 201
+ message: Created
+ headers:
+ Date:
+ - Fri, 20 Jul 2018 06:19:08 GMT
+ Connection:
+ - close
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Content-Type-Options:
+ - nosniff
+ Content-Type:
+ - application/json
+ Content-Length:
+ - '13'
+ Vary:
+ - Origin
+ Cache-Control:
+ - no-cache
+ X-Request-Id:
+ - 0c6894ac-7f8e-4cdb-871f-4cb64d3731ca
+ X-Runtime:
+ - '0.786754'
+ body:
+ encoding: UTF-8
+ string: '{"result":"push-result"}'
+ http_version:
+ recorded_at: Fri, 20 Jul 2018 06:19:08 GMT
+recorded_with: VCR 2.4.0