diff options
author | Dylan Griffith <dyl.griffith@gmail.com> | 2018-12-06 21:08:49 +0300 |
---|---|---|
committer | Mike Greiling <mike@pixelcog.com> | 2018-12-06 21:08:49 +0300 |
commit | 2c80a1c0de07877e6e2bf7ab20de2d4f43a0d97c (patch) | |
tree | afa7f5f54e2491e0c08168b6f4ce47511da3012b /spec | |
parent | e80f89337b4be31c5531448861cedb556d02c01e (diff) |
Introduce Knative Serverless Tab
Diffstat (limited to 'spec')
5 files changed, 289 insertions, 0 deletions
diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb new file mode 100644 index 00000000000..284b582b1f5 --- /dev/null +++ b/spec/controllers/projects/serverless/functions_controller_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::Serverless::FunctionsController do + include KubernetesHelpers + include ReactiveCachingHelpers + + let(:user) { create(:user) } + let(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } + let(:service) { cluster.platform_kubernetes } + let(:project) { cluster.project} + + let(:namespace) do + create(:cluster_kubernetes_namespace, + cluster: cluster, + cluster_project: cluster.cluster_project, + project: cluster.cluster_project.project) + end + + before do + project.add_maintainer(user) + sign_in(user) + end + + def params(opts = {}) + opts.reverse_merge(namespace_id: project.namespace.to_param, + project_id: project.to_param) + end + + describe 'GET #index' do + context 'empty cache' do + it 'has no data' do + get :index, params({ format: :json }) + + expect(response).to have_gitlab_http_status(204) + end + + it 'renders an html page' do + get :index, params + + expect(response).to have_gitlab_http_status(200) + end + end + end + + describe 'GET #index with data', :use_clean_rails_memory_store_caching do + before do + stub_reactive_cache(knative, services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"]) + end + + it 'has data' do + get :index, params({ format: :json }) + + expect(response).to have_gitlab_http_status(200) + + expect(json_response).to contain_exactly( + a_hash_including( + "name" => project.name, + "url" => "http://#{project.name}.#{namespace.namespace}.example.com" + ) + ) + end + + it 'has data in html' do + get :index, params + + expect(response).to have_gitlab_http_status(200) + end + end +end diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb new file mode 100644 index 00000000000..766c63725b3 --- /dev/null +++ b/spec/features/projects/serverless/functions_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe 'Functions', :js do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + project.add_maintainer(user) + gitlab_sign_in(user) + end + + context 'when user does not have a cluster and visits the serverless page' do + before do + visit project_serverless_functions_path(project) + end + + it 'sees an empty state' do + expect(page).to have_link('Install Knative') + expect(page).to have_selector('.empty-state') + end + end + + context 'when the user does have a cluster and visits the serverless page' do + let(:cluster) { create(:cluster, :project, :provided_by_gcp) } + + before do + visit project_serverless_functions_path(project) + end + + it 'sees an empty state' do + expect(page).to have_link('Install Knative') + expect(page).to have_selector('.empty-state') + end + end + + context 'when the user has a cluster and knative installed and visits the serverless page' do + let!(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } + let(:project) { knative.cluster.project } + + before do + visit project_serverless_functions_path(project) + end + + it 'sees an empty listing of serverless functions' do + expect(page).to have_selector('.gl-responsive-table-row') + end + end +end diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb new file mode 100644 index 00000000000..60d02b12054 --- /dev/null +++ b/spec/finders/projects/serverless/functions_finder_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::Serverless::FunctionsFinder do + include KubernetesHelpers + include ReactiveCachingHelpers + + let(:user) { create(:user) } + let(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:service) { cluster.platform_kubernetes } + let(:project) { cluster.project} + + let(:namespace) do + create(:cluster_kubernetes_namespace, + cluster: cluster, + cluster_project: cluster.cluster_project, + project: cluster.cluster_project.project) + end + + before do + project.add_maintainer(user) + end + + describe 'retrieve data from knative' do + it 'does not have knative installed' do + expect(described_class.new(project.clusters).execute).to be_empty + end + + context 'has knative installed' do + let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } + + it 'there are no functions' do + expect(described_class.new(project.clusters).execute).to be_empty + end + + it 'there are functions', :use_clean_rails_memory_store_caching do + stub_reactive_cache(knative, services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"]) + + expect(described_class.new(project.clusters).execute).not_to be_empty + end + end + end + + describe 'verify if knative is installed' do + context 'knative is not installed' do + it 'does not have knative installed' do + expect(described_class.new(project.clusters).installed?).to be false + end + end + + context 'knative is installed' do + let!(:knative) { create(:clusters_applications_knative, :installed, cluster: cluster) } + + it 'does have knative installed' do + expect(described_class.new(project.clusters).installed?).to be true + end + end + end +end diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb index d43d88c2924..a1579b90436 100644 --- a/spec/models/clusters/applications/knative_spec.rb +++ b/spec/models/clusters/applications/knative_spec.rb @@ -1,6 +1,9 @@ require 'rails_helper' describe Clusters::Applications::Knative do + include KubernetesHelpers + include ReactiveCachingHelpers + let(:knative) { create(:clusters_applications_knative) } include_examples 'cluster application core specs', :clusters_applications_knative @@ -121,4 +124,43 @@ describe Clusters::Applications::Knative do describe 'validations' do it { is_expected.to validate_presence_of(:hostname) } end + + describe '#services' do + let(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:service) { cluster.platform_kubernetes } + let(:knative) { create(:clusters_applications_knative, cluster: cluster) } + + let(:namespace) do + create(:cluster_kubernetes_namespace, + cluster: cluster, + cluster_project: cluster.cluster_project, + project: cluster.cluster_project.project) + end + + subject { knative.services } + + before do + stub_kubeclient_discover(service.api_url) + stub_kubeclient_knative_services + end + + it 'should have an unintialized cache' do + is_expected.to be_nil + end + + context 'when using synchronous reactive cache' do + before do + stub_reactive_cache(knative, services: kube_response(kube_knative_services_body)) + synchronous_reactive_cache(knative) + end + + it 'should have cached services' do + is_expected.not_to be_nil + end + + it 'should match our namespace' do + expect(knative.services_for(ns: namespace)).not_to be_nil + end + end + end end diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb index bef951e1517..39bd305d88a 100644 --- a/spec/support/helpers/kubernetes_helpers.rb +++ b/spec/support/helpers/kubernetes_helpers.rb @@ -34,6 +34,17 @@ module KubernetesHelpers WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response) end + def stub_kubeclient_knative_services(**options) + options[:name] ||= "kubetest" + options[:namespace] ||= "default" + options[:domain] ||= "example.com" + + stub_kubeclient_discover(service.api_url) + knative_url = service.api_url + "/apis/serving.knative.dev/v1alpha1/services" + + WebMock.stub_request(:get, knative_url).to_return(kube_response(kube_knative_services_body(options))) + end + def stub_kubeclient_get_secret(api_url, **options) options[:metadata_name] ||= "default-token-1" options[:namespace] ||= "default" @@ -181,6 +192,13 @@ module KubernetesHelpers } end + def kube_knative_services_body(**options) + { + "kind" => "List", + "items" => [kube_service(options)] + } + end + # This is a partial response, it will have many more elements in reality but # these are the ones we care about at the moment def kube_pod(name: "kube-pod", app: "valid-pod-label", status: "Running", track: nil) @@ -224,6 +242,54 @@ module KubernetesHelpers } end + def kube_service(name: "kubetest", namespace: "default", domain: "example.com") + { + "metadata" => { + "creationTimestamp" => "2018-11-21T06:16:33Z", + "name" => name, + "namespace" => namespace, + "selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}" + }, + "spec" => { + "generation" => 2 + }, + "status" => { + "domain" => "#{name}.#{namespace}.#{domain}", + "domainInternal" => "#{name}.#{namespace}.svc.cluster.local", + "latestCreatedRevisionName" => "#{name}-00002", + "latestReadyRevisionName" => "#{name}-00002", + "observedGeneration" => 2 + } + } + end + + def kube_service_full(name: "kubetest", namespace: "kube-ns", domain: "example.com") + { + "metadata" => { + "creationTimestamp" => "2018-11-21T06:16:33Z", + "name" => name, + "namespace" => namespace, + "selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}", + "annotation" => { + "description" => "This is a test description" + } + }, + "spec" => { + "generation" => 2, + "build" => { + "template" => "go-1.10.3" + } + }, + "status" => { + "domain" => "#{name}.#{namespace}.#{domain}", + "domainInternal" => "#{name}.#{namespace}.svc.cluster.local", + "latestCreatedRevisionName" => "#{name}-00002", + "latestReadyRevisionName" => "#{name}-00002", + "observedGeneration" => 2 + } + } + end + def kube_terminals(service, pod) pod_name = pod['metadata']['name'] containers = pod['spec']['containers'] |