diff options
Diffstat (limited to 'spec/models/project_services/kubernetes_service_spec.rb')
-rw-r--r-- | spec/models/project_services/kubernetes_service_spec.rb | 396 |
1 files changed, 0 insertions, 396 deletions
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb deleted file mode 100644 index 5d7d6c34e67..00000000000 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ /dev/null @@ -1,396 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe KubernetesService, :use_clean_rails_memory_store_caching do - include KubernetesHelpers - include ReactiveCachingHelpers - - let(:project) { create(:kubernetes_project) } - let(:service) { create(:kubernetes_service, project: project) } - - describe 'Associations' do - it { is_expected.to belong_to :project } - end - - describe 'Validations' do - context 'when service is active' do - before do - subject.active = true - subject.skip_deprecation_validation = true - end - - it { is_expected.not_to validate_presence_of(:namespace) } - it { is_expected.to validate_presence_of(:api_url) } - it { is_expected.to validate_presence_of(:token) } - - context 'namespace format' do - before do - subject.project = project - subject.api_url = "http://example.com" - subject.token = "test" - end - - { - 'foo' => true, - '1foo' => true, - 'foo1' => true, - 'foo-bar' => true, - '-foo' => false, - 'foo-' => false, - 'a' * 63 => true, - 'a' * 64 => false, - 'a.b' => false, - 'a*b' => false, - 'FOO' => true - }.each do |namespace, validity| - it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do - subject.namespace = namespace - - expect(subject.valid?).to eq(validity) - end - end - end - end - - context 'when service is inactive' do - before do - subject.project = project - subject.active = false - end - - it { is_expected.not_to validate_presence_of(:api_url) } - it { is_expected.not_to validate_presence_of(:token) } - end - - context 'with a deprecated service' do - let(:kubernetes_service) { create(:kubernetes_service) } - - before do - kubernetes_service.update_attribute(:active, false) - kubernetes_service.skip_deprecation_validation = false - kubernetes_service.properties['namespace'] = "foo" - end - - it 'does not update attributes' do - expect(kubernetes_service.save).to be_falsy - end - - it 'includes an error with a deprecation message' do - kubernetes_service.valid? - expect(kubernetes_service.errors[:base].first).to match(/Kubernetes service integration has been disabled/) - end - end - - context 'with an active and deprecated service' do - let(:kubernetes_service) { create(:kubernetes_service) } - - before do - kubernetes_service.skip_deprecation_validation = false - kubernetes_service.active = false - kubernetes_service.properties['namespace'] = 'foo' - kubernetes_service.save - end - - it 'deactivates the service' do - expect(kubernetes_service.active?).to be_falsy - end - - it 'does not include a deprecation message as error' do - expect(kubernetes_service.errors.messages.count).to eq(0) - end - - it 'updates attributes' do - expect(kubernetes_service.properties['namespace']).to eq("foo") - end - end - end - - describe '#initialize_properties' do - context 'without a project' do - it 'leaves the namespace unset' do - expect(described_class.new.namespace).to be_nil - end - end - end - - describe '#fields' do - let(:kube_namespace) do - subject.fields.find { |h| h[:name] == 'namespace' } - end - - context 'as template' do - before do - subject.template = true - end - - it 'sets the namespace to the default' do - expect(kube_namespace).not_to be_nil - expect(kube_namespace[:placeholder]).to eq(subject.class::TEMPLATE_PLACEHOLDER) - end - end - - context 'with associated project' do - before do - subject.project = project - end - - it 'sets the namespace to the default' do - expect(kube_namespace).not_to be_nil - expect(kube_namespace[:placeholder]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/) - end - end - end - - describe '#kubernetes_namespace_for' do - subject { service.kubernetes_namespace_for(project) } - - shared_examples 'a correctly formatted namespace' do - it 'returns a valid Kubernetes namespace name' do - expect(subject).to match(Gitlab::Regex.kubernetes_namespace_regex) - expect(subject).to eq(expected_namespace) - end - end - - it_behaves_like 'a correctly formatted namespace' do - let(:expected_namespace) { service.send(:default_namespace) } - end - - context 'when the project path contains forbidden characters' do - before do - project.path = '-a_Strange.Path--forSure' - end - - it_behaves_like 'a correctly formatted namespace' do - let(:expected_namespace) { "a-strange-path--forsure-#{project.id}" } - end - end - - context 'when namespace is specified' do - before do - service.namespace = 'my-namespace' - end - - it_behaves_like 'a correctly formatted namespace' do - let(:expected_namespace) { 'my-namespace' } - end - end - - context 'when service is not assigned to project' do - before do - service.project = nil - end - - it 'does not return namespace' do - is_expected.to be_nil - end - end - end - - describe '#test' do - let(:discovery_url) { 'https://kubernetes.example.com/api/v1' } - - before do - stub_kubeclient_discover(service.api_url) - end - - context 'with path prefix in api_url' do - let(:discovery_url) { 'https://kubernetes.example.com/prefix/api/v1' } - - it 'tests with the prefix' do - service.api_url = 'https://kubernetes.example.com/prefix' - stub_kubeclient_discover(service.api_url) - - expect(service.test[:success]).to be_truthy - expect(WebMock).to have_requested(:get, discovery_url).once - end - end - - context 'with custom CA certificate' do - it 'is added to the certificate store' do - service.ca_pem = "CA PEM DATA" - - cert = double("certificate") - expect(OpenSSL::X509::Certificate).to receive(:new).with(service.ca_pem).and_return(cert) - expect_any_instance_of(OpenSSL::X509::Store).to receive(:add_cert).with(cert) - - expect(service.test[:success]).to be_truthy - expect(WebMock).to have_requested(:get, discovery_url).once - end - end - - context 'success' do - it 'reads the discovery endpoint' do - expect(service.test[:success]).to be_truthy - expect(WebMock).to have_requested(:get, discovery_url).once - end - end - - context 'failure' do - it 'fails to read the discovery endpoint' do - WebMock.stub_request(:get, service.api_url + '/api/v1').to_return(status: 404) - - expect(service.test[:success]).to be_falsy - expect(WebMock).to have_requested(:get, discovery_url).once - end - end - end - - describe '#predefined_variable' do - let(:kubeconfig) do - config_file = expand_fixture_path('config/kubeconfig.yml') - config = YAML.load(File.read(config_file)) - config.dig('users', 0, 'user')['token'] = 'token' - config.dig('contexts', 0, 'context')['namespace'] = namespace - config.dig('clusters', 0, 'cluster')['certificate-authority-data'] = - Base64.strict_encode64('CA PEM DATA') - - YAML.dump(config) - end - - before do - subject.api_url = 'https://kube.domain.com' - subject.token = 'token' - subject.ca_pem = 'CA PEM DATA' - subject.project = project - end - - shared_examples 'setting variables' do - it 'sets the variables' do - expect(subject.predefined_variables(project: project)).to include( - { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true }, - { key: 'KUBE_TOKEN', value: 'token', public: false, masked: true }, - { key: 'KUBE_NAMESPACE', value: namespace, public: true }, - { key: 'KUBECONFIG', value: kubeconfig, public: false, file: true }, - { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true }, - { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true } - ) - end - end - - context 'namespace is provided' do - let(:namespace) { 'my-project' } - - before do - subject.namespace = namespace - end - - it_behaves_like 'setting variables' - end - - context 'no namespace provided' do - let(:namespace) { subject.kubernetes_namespace_for(project) } - - it_behaves_like 'setting variables' - - it 'sets the KUBE_NAMESPACE' do - kube_namespace = subject.predefined_variables(project: project).find { |h| h[:key] == 'KUBE_NAMESPACE' } - - expect(kube_namespace).not_to be_nil - expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/) - end - end - end - - describe '#terminals' do - let(:environment) { build(:environment, project: project, name: "env", slug: "env-000000") } - - subject { service.terminals(environment) } - - context 'with invalid pods' do - it 'returns no terminals' do - stub_reactive_cache(service, pods: [{ "bad" => "pod" }]) - - is_expected.to be_empty - end - end - - context 'with valid pods' do - let(:pod) { kube_pod(environment_slug: environment.slug, namespace: service.kubernetes_namespace_for(project), project_slug: project.full_path_slug) } - let(:pod_with_no_terminal) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug, status: "Pending") } - let(:terminals) { kube_terminals(service, pod) } - - before do - stub_reactive_cache( - service, - pods: [pod, pod, pod_with_no_terminal, kube_pod(environment_slug: "should-be-filtered-out")] - ) - end - - it 'returns terminals' do - is_expected.to eq(terminals + terminals) - end - - it 'uses max session time from settings' do - stub_application_setting(terminal_max_session_time: 600) - - times = subject.map { |terminal| terminal[:max_session_time] } - expect(times).to eq [600, 600, 600, 600] - end - end - end - - describe '#calculate_reactive_cache' do - subject { service.calculate_reactive_cache } - - let(:namespace) { service.kubernetes_namespace_for(project) } - - context 'when service is inactive' do - before do - service.active = false - end - - it { is_expected.to be_nil } - end - - context 'when kubernetes responds with valid pods' do - before do - stub_kubeclient_pods(namespace) - stub_kubeclient_deployments(namespace) # Used by EE - end - - it { is_expected.to include(pods: [kube_pod]) } - end - - context 'when kubernetes responds with 500s' do - before do - stub_kubeclient_pods(namespace, status: 500) - stub_kubeclient_deployments(namespace, status: 500) # Used by EE - end - - it { expect { subject }.to raise_error(Kubeclient::HttpError) } - end - - context 'when kubernetes responds with 404s' do - before do - stub_kubeclient_pods(namespace, status: 404) - stub_kubeclient_deployments(namespace, status: 404) # Used by EE - end - - it { is_expected.to include(pods: []) } - end - end - - describe "#deprecated?" do - let(:kubernetes_service) { create(:kubernetes_service) } - - it 'returns true' do - expect(kubernetes_service.deprecated?).to be_truthy - end - end - - describe "#deprecation_message" do - let(:kubernetes_service) { create(:kubernetes_service) } - - it 'indicates the service is deprecated' do - expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been disabled/) - end - - context 'if the service is not active' do - it 'returns a message' do - kubernetes_service.update_attribute(:active, false) - expect(kubernetes_service.deprecation_message).to match(/Fields on this page are not used by GitLab/) - end - end - end -end |