Commit 1fb87fa9 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch...

Merge branch '34372-serverless-function-description-does-not-show-up-for-newly-created-functions' into 'master'

Resolve "Serverless function description missing on Knative 0.7"

Closes #34372

See merge request gitlab-org/gitlab!18973
parents c7865861 a09a2f30
...@@ -44,28 +44,52 @@ module Projects ...@@ -44,28 +44,52 @@ module Projects
end end
expose :url do |service| expose :url do |service|
service.dig('status', 'url') || "http://#{service.dig('status', 'domain')}" knative_06_07_url(service) || knative_05_url(service)
end end
expose :description do |service| expose :description do |service|
knative_07_description(service) || knative_05_06_description(service)
end
expose :image do |service|
service.dig( service.dig(
'spec', 'spec',
'runLatest', 'runLatest',
'configuration', 'configuration',
'revisionTemplate', 'build',
'template',
'name')
end
private
def knative_07_description(service)
service.dig(
'spec',
'template',
'metadata', 'metadata',
'annotations', 'annotations',
'Description') 'Description'
)
end end
expose :image do |service| def knative_05_url(service)
"http://#{service.dig('status', 'domain')}"
end
def knative_06_07_url(service)
service.dig('status', 'url')
end
def knative_05_06_description(service)
service.dig( service.dig(
'spec', 'spec',
'runLatest', 'runLatest',
'configuration', 'configuration',
'build', 'revisionTemplate',
'template', 'metadata',
'name') 'annotations',
'Description')
end end
end end
end end
......
---
title: Fix serverless function descriptions not showing on Knative 0.7
merge_request: 18973
author:
type: fixed
...@@ -13,6 +13,10 @@ describe Projects::Serverless::FunctionsController do ...@@ -13,6 +13,10 @@ describe Projects::Serverless::FunctionsController do
let(:environment) { create(:environment, project: project) } let(:environment) { create(:environment, project: project) }
let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) } let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) }
let(:knative_services_finder) { environment.knative_services_finder } let(:knative_services_finder) { environment.knative_services_finder }
let(:function_description) { 'A serverless function' }
let(:knative_stub_options) do
{ namespace: namespace.namespace, name: cluster.project.name, description: function_description }
end
let(:namespace) do let(:namespace) do
create(:cluster_kubernetes_namespace, create(:cluster_kubernetes_namespace,
...@@ -114,40 +118,33 @@ describe Projects::Serverless::FunctionsController do ...@@ -114,40 +118,33 @@ describe Projects::Serverless::FunctionsController do
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response).to include( expect(json_response).to include(
"name" => project.name, 'name' => project.name,
"url" => "http://#{project.name}.#{namespace.namespace}.example.com", 'url' => "http://#{project.name}.#{namespace.namespace}.example.com",
"podcount" => 1 'description' => function_description,
'podcount' => 1
) )
end end
end end
context 'on Knative 0.5' do context 'on Knative 0.5.0' do
before do
prepare_knative_stubs(knative_05_service(knative_stub_options))
end
include_examples 'GET #show with valid data'
end
context 'on Knative 0.6.0' do
before do before do
stub_kubeclient_service_pods prepare_knative_stubs(knative_06_service(knative_stub_options))
stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(
legacy_knative: true,
namespace: namespace.namespace,
name: cluster.project.name
)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
*knative_services_finder.cache_args)
end end
include_examples 'GET #show with valid data' include_examples 'GET #show with valid data'
end end
context 'on Knative 0.6 or 0.7' do context 'on Knative 0.7.0' do
before do before do
stub_kubeclient_service_pods prepare_knative_stubs(knative_07_service(knative_stub_options))
stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
*knative_services_finder.cache_args)
end end
include_examples 'GET #show with valid data' include_examples 'GET #show with valid data'
...@@ -172,11 +169,12 @@ describe Projects::Serverless::FunctionsController do ...@@ -172,11 +169,12 @@ describe Projects::Serverless::FunctionsController do
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(json_response).to match({ expect(json_response).to match({
"knative_installed" => "checking", 'knative_installed' => 'checking',
"functions" => [ 'functions' => [
a_hash_including( a_hash_including(
"name" => project.name, 'name' => project.name,
"url" => "http://#{project.name}.#{namespace.namespace}.example.com" 'url' => "http://#{project.name}.#{namespace.namespace}.example.com",
'description' => function_description
) )
] ]
}) })
...@@ -189,36 +187,38 @@ describe Projects::Serverless::FunctionsController do ...@@ -189,36 +187,38 @@ describe Projects::Serverless::FunctionsController do
end end
end end
context 'on Knative 0.5' do context 'on Knative 0.5.0' do
before do before do
stub_kubeclient_service_pods prepare_knative_stubs(knative_05_service(knative_stub_options))
stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(
legacy_knative: true,
namespace: namespace.namespace,
name: cluster.project.name
)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
*knative_services_finder.cache_args)
end end
include_examples 'GET #index with data' include_examples 'GET #index with data'
end end
context 'on Knative 0.6 or 0.7' do context 'on Knative 0.6.0' do
before do before do
stub_kubeclient_service_pods prepare_knative_stubs(knative_06_service(knative_stub_options))
stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
*knative_services_finder.cache_args)
end end
include_examples 'GET #index with data' include_examples 'GET #index with data'
end end
context 'on Knative 0.7.0' do
before do
prepare_knative_stubs(knative_07_service(knative_stub_options))
end
include_examples 'GET #index with data'
end
end
def prepare_knative_stubs(knative_service)
stub_kubeclient_service_pods
stub_reactive_cache(knative_services_finder,
{
services: [knative_service],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
*knative_services_finder.cache_args)
end end
end end
...@@ -319,10 +319,10 @@ module KubernetesHelpers ...@@ -319,10 +319,10 @@ module KubernetesHelpers
} }
end end
def kube_knative_services_body(legacy_knative: false, **options) def kube_knative_services_body(**options)
{ {
"kind" => "List", "kind" => "List",
"items" => [legacy_knative ? knative_05_service(options) : kube_service(options)] "items" => [knative_07_service(options)]
} }
end end
...@@ -398,77 +398,171 @@ module KubernetesHelpers ...@@ -398,77 +398,171 @@ module KubernetesHelpers
} }
end end
def kube_service(name: "kubetest", namespace: "default", domain: "example.com") # noinspection RubyStringKeysInHashInspection
{ def knative_06_service(name: 'kubetest', namespace: 'default', domain: 'example.com', description: 'a knative service', environment: 'production')
"metadata" => { { "apiVersion" => "serving.knative.dev/v1alpha1",
"creationTimestamp" => "2018-11-21T06:16:33Z", "kind" => "Service",
"name" => name, "metadata" =>
"namespace" => namespace, { "annotations" =>
"selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}" { "serving.knative.dev/creator" => "system:serviceaccount:#{namespace}:#{namespace}-service-account",
}, "serving.knative.dev/lastModifier" => "system:serviceaccount:#{namespace}:#{namespace}-service-account" },
"creationTimestamp" => "2019-10-22T21:19:20Z",
"generation" => 1,
"labels" => { "service" => name },
"name" => name,
"namespace" => namespace,
"resourceVersion" => "6042",
"selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}",
"uid" => "9c7f63d0-f511-11e9-8815-42010a80002f" },
"spec" => { "spec" => {
"generation" => 2 "runLatest" => {
"configuration" => {
"revisionTemplate" => {
"metadata" => {
"annotations" => { "Description" => description },
"creationTimestamp" => "2019-10-22T21:19:20Z",
"labels" => { "service" => name }
},
"spec" => {
"container" => {
"env" => [{ "name" => "timestamp", "value" => "2019-10-22 21:19:20" }],
"image" => "image_name",
"name" => "",
"resources" => {}
},
"timeoutSeconds" => 300
}
}
}
}
}, },
"status" => { "status" => {
"url" => "http://#{name}.#{namespace}.#{domain}",
"address" => { "address" => {
"url" => "#{name}.#{namespace}.svc.cluster.local" "hostname" => "#{name}.#{namespace}.svc.cluster.local",
"url" => "http://#{name}.#{namespace}.svc.cluster.local"
}, },
"latestCreatedRevisionName" => "#{name}-00002", "conditions" =>
"latestReadyRevisionName" => "#{name}-00002", [{ "lastTransitionTime" => "2019-10-22T21:20:25Z", "status" => "True", "type" => "ConfigurationsReady" },
"observedGeneration" => 2 { "lastTransitionTime" => "2019-10-22T21:20:25Z", "status" => "True", "type" => "Ready" },
} { "lastTransitionTime" => "2019-10-22T21:20:25Z", "status" => "True", "type" => "RoutesReady" }],
}
end
def knative_05_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}", "domain" => "#{name}.#{namespace}.#{domain}",
"domainInternal" => "#{name}.#{namespace}.svc.cluster.local", "domainInternal" => "#{name}.#{namespace}.svc.cluster.local",
"latestCreatedRevisionName" => "#{name}-00002", "latestCreatedRevisionName" => "#{name}-bskx6",
"latestReadyRevisionName" => "#{name}-00002", "latestReadyRevisionName" => "#{name}-bskx6",
"observedGeneration" => 2 "observedGeneration" => 1,
} "traffic" => [{ "latestRevision" => true, "percent" => 100, "revisionName" => "#{name}-bskx6" }],
} "url" => "http://#{name}.#{namespace}.#{domain}"
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"
}
}, },
"environment_scope" => environment,
"cluster_id" => 9,
"podcount" => 0 }
end
# noinspection RubyStringKeysInHashInspection
def knative_07_service(name: 'kubetest', namespace: 'default', domain: 'example.com', description: 'a knative service', environment: 'production')
{ "apiVersion" => "serving.knative.dev/v1alpha1",
"kind" => "Service",
"metadata" =>
{ "annotations" =>
{ "serving.knative.dev/creator" => "system:serviceaccount:#{namespace}:#{namespace}-service-account",
"serving.knative.dev/lastModifier" => "system:serviceaccount:#{namespace}:#{namespace}-service-account" },
"creationTimestamp" => "2019-10-22T21:19:13Z",
"generation" => 1,
"labels" => { "service" => name },
"name" => name,
"namespace" => namespace,
"resourceVersion" => "289726",
"selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}",
"uid" => "988349fa-f511-11e9-9ea1-42010a80005e" },
"spec" => { "spec" => {
"generation" => 2, "template" => {
"build" => { "metadata" => {
"template" => "go-1.10.3" "annotations" => { "Description" => description },
"creationTimestamp" => "2019-10-22T21:19:12Z",
"labels" => { "service" => name }
},
"spec" => {
"containers" => [{
"env" =>
[{ "name" => "timestamp", "value" => "2019-10-22 21:19:12" }],
"image" => "image_name",
"name" => "user-container",
"resources" => {}
}],
"timeoutSeconds" => 300
}
},
"traffic" => [{ "latestRevision" => true, "percent" => 100 }]
},
"status" =>
{ "address" => { "url" => "http://#{name}.#{namespace}.svc.cluster.local" },
"conditions" =>
[{ "lastTransitionTime" => "2019-10-22T21:20:15Z", "status" => "True", "type" => "ConfigurationsReady" },
{ "lastTransitionTime" => "2019-10-22T21:20:15Z", "status" => "True", "type" => "Ready" },
{ "lastTransitionTime" => "2019-10-22T21:20:15Z", "status" => "True", "type" => "RoutesReady" }],
"latestCreatedRevisionName" => "#{name}-92tsj",
"latestReadyRevisionName" => "#{name}-92tsj",
"observedGeneration" => 1,
"traffic" => [{ "latestRevision" => true, "percent" => 100, "revisionName" => "#{name}-92tsj" }],
"url" => "http://#{name}.#{namespace}.#{domain}" },
"environment_scope" => environment,
"cluster_id" => 5,
"podcount" => 0 }
end
# noinspection RubyStringKeysInHashInspection
def knative_05_service(name: 'kubetest', namespace: 'default', domain: 'example.com', description: 'a knative service', environment: 'production')
{ "apiVersion" => "serving.knative.dev/v1alpha1",
"kind" => "Service",
"metadata" =>
{ "annotations" =>
{ "serving.knative.dev/creator" => "system:serviceaccount:#{namespace}:#{namespace}-service-account",
"serving.knative.dev/lastModifier" => "system:serviceaccount:#{namespace}:#{namespace}-service-account" },
"creationTimestamp" => "2019-10-22T21:19:19Z",
"generation" => 1,
"labels" => { "service" => name },
"name" => name,
"namespace" => namespace,
"resourceVersion" => "330390",
"selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}",
"uid" => "9c710da6-f511-11e9-9ba0-42010a800161" },
"spec" => {
"runLatest" => {
"configuration" => {
"revisionTemplate" => {
"metadata" => {
"annotations" => { "Description" => description },
"creationTimestamp" => "2019-10-22T21:19:19Z",
"labels" => { "service" => name }
},
"spec" => {
"container" => {
"env" => [{ "name" => "timestamp", "value" => "2019-10-22 21:19:19" }],
"image" => "image_name",
"name" => "",
"resources" => { "requests" => { "cpu" => "400m" } }
},
"timeoutSeconds" => 300
}
}
}
} }
}, },
"status" => { "status" =>
"url" => "http://#{name}.#{namespace}.#{domain}", { "address" => { "hostname" => "#{name}.#{namespace}.svc.cluster.local" },
"address" => { "conditions" =>
"url" => "#{name}.#{namespace}.svc.cluster.local" [{ "lastTransitionTime" => "2019-10-22T21:20:24Z", "status" => "True", "type" => "ConfigurationsReady" },
}, { "lastTransitionTime" => "2019-10-22T21:20:24Z", "status" => "True", "type" => "Ready" },
"latestCreatedRevisionName" => "#{name}-00002", { "lastTransitionTime" => "2019-10-22T21:20:24Z", "status" => "True", "type" => "RoutesReady" }],
"latestReadyRevisionName" => "#{name}-00002", "domain" => "#{name}.#{namespace}.#{domain}",
"observedGeneration" => 2 "domainInternal" => "#{name}.#{namespace}.svc.cluster.local",
} "latestCreatedRevisionName" => "#{name}-58qgr",
} "latestReadyRevisionName" => "#{name}-58qgr",
"observedGeneration" => 1,
"traffic" => [{ "percent" => 100, "revisionName" => "#{name}-58qgr" }] },
"environment_scope" => environment,
"cluster_id" => 8,
"podcount" => 0 }
end end
def kube_terminals(service, pod) def kube_terminals(service, pod)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment