Commit 3a3a767c authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'triggermesh-phase2-external-ip' into 'master'

Expose External IP address for Knative's gateway

See merge request gitlab-org/gitlab-ce!23162
parents 195e3371 2937be7b
......@@ -168,6 +168,9 @@ export default {
knativeInstalled() {
return this.applications.knative.status === APPLICATION_STATUS.INSTALLED;
},
knativeExternalIp() {
return this.applications.knative.externalIp;
},
},
created() {
this.helmInstallIllustration = helmInstallIllustration;
......@@ -443,6 +446,49 @@ export default {
/>
</div>
</template>
<template v-if="knativeInstalled">
<div class="form-group">
<label for="knative-ip-address">
{{ s__('ClusterIntegration|Knative IP Address:') }}
</label>
<div v-if="knativeExternalIp" class="input-group">
<input
id="knative-ip-address"
:value="knativeExternalIp"
type="text"
class="form-control js-ip-address"
readonly
/>
<span class="input-group-append">
<clipboard-button
:text="knativeExternalIp"
:title="s__('ClusterIntegration|Copy Knative IP Address to clipboard')"
class="input-group-text js-clipboard-btn"
/>
</span>
</div>
<input v-else type="text" class="form-control js-ip-address" readonly value="?" />
</div>
<p v-if="!knativeExternalIp" class="settings-message js-no-ip-message">
{{
s__(`ClusterIntegration|The IP address is in
the process of being assigned. Please check your Kubernetes
cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
}}
</p>
<p>
{{
s__(`ClusterIntegration|Point a wildcard DNS to this
generated IP address in order to access
your application after it has been deployed.`)
}}
<a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
</template>
</div>
</application-row>
</div>
......
......@@ -60,6 +60,7 @@ export default class ClusterStore {
requestStatus: null,
requestReason: null,
hostname: null,
externalIp: null,
},
},
};
......@@ -111,6 +112,8 @@ export default class ClusterStore {
} else if (appId === KNATIVE) {
this.state.applications.knative.hostname =
serverAppEntry.hostname || this.state.applications.knative.hostname;
this.state.applications.knative.externalIp =
serverAppEntry.external_ip || this.state.applications.knative.externalIp;
}
});
}
......
......@@ -51,6 +51,10 @@ module Clusters
ClusterWaitForIngressIpAddressWorker.perform_async(name, id)
end
def ingress_service
cluster.kubeclient.get_service('ingress-nginx-ingress-controller', Gitlab::Kubernetes::Helm::NAMESPACE)
end
end
end
end
......@@ -6,9 +6,7 @@ module Clusters
VERSION = '0.1.3'.freeze
REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze
# This is required for helm version <= 2.10.x in order to support
# Setting up CRDs
ISTIO_CRDS = 'https://storage.googleapis.com/triggermesh-charts/istio-crds.yaml'.freeze
FETCH_IP_ADDRESS_DELAY = 30.seconds
self.table_name = 'clusters_applications_knative'
......@@ -16,6 +14,16 @@ module Clusters
include ::Clusters::Concerns::ApplicationStatus
include ::Clusters::Concerns::ApplicationVersion
include ::Clusters::Concerns::ApplicationData
include AfterCommitQueue
state_machine :status do
before_transition any => [:installed] do |application|
application.run_after_commit do
ClusterWaitForIngressIpAddressWorker.perform_in(
FETCH_IP_ADDRESS_DELAY, application.name, application.id)
end
end
end
default_value_for :version, VERSION
......@@ -36,19 +44,23 @@ module Clusters
rbac: cluster.platform_kubernetes_rbac?,
chart: chart,
files: files,
repository: REPOSITORY,
preinstall: install_script
repository: REPOSITORY
)
end
def client
cluster.platform_kubernetes.kubeclient.knative_client
def schedule_status_update
return unless installed?
return if external_ip
ClusterWaitForIngressIpAddressWorker.perform_async(name, id)
end
private
def ingress_service
cluster.kubeclient.get_service('knative-ingressgateway', 'istio-system')
end
def install_script
["/usr/bin/kubectl apply -f #{ISTIO_CRDS}"]
def client
cluster.platform_kubernetes.kubeclient.knative_client
end
end
end
......
......@@ -30,7 +30,7 @@ module Clusters
def service
strong_memoize(:ingress_service) do
kubeclient.get_service('ingress-nginx-ingress-controller', Gitlab::Kubernetes::Helm::NAMESPACE)
app.ingress_service
end
end
end
......
---
title: Add an external IP address to the knative cluster application page
merge_request:
author: Chris Baumbauer
type: fixed
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class KnativeExternalIp < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :clusters_applications_knative, :external_ip, :string
end
end
......@@ -698,6 +698,7 @@ ActiveRecord::Schema.define(version: 20181126153547) do
t.string "version", null: false
t.string "hostname"
t.text "status_reason"
t.string "external_ip"
t.index ["cluster_id"], name: "index_clusters_applications_knative_on_cluster_id", unique: true, using: :btree
end
......
......@@ -1451,6 +1451,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
msgstr ""
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
......@@ -1559,6 +1562,9 @@ msgstr ""
msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
msgid "ClusterIntegration|Knative IP Address:"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
......
......@@ -59,6 +59,7 @@ FactoryBot.define do
end
factory :clusters_applications_runner, class: Clusters::Applications::Runner do
runner factory: %i(ci_runner)
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
......
......@@ -107,6 +107,7 @@ describe('Clusters Store', () => {
requestStatus: null,
requestReason: null,
hostname: null,
externalIp: null,
},
cert_manager: {
title: 'Cert-Manager',
......
......@@ -5,7 +5,7 @@ describe Clusters::Applications::Ingress do
include_examples 'cluster application core specs', :clusters_applications_ingress
include_examples 'cluster application status specs', :clusters_applications_ingress
include_examples 'cluster application helm specs', :clusters_applications_knative
include_examples 'cluster application helm specs', :clusters_applications_ingress
before do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
......
......@@ -2,7 +2,7 @@ require 'rails_helper'
describe Clusters::Applications::Jupyter do
include_examples 'cluster application core specs', :clusters_applications_jupyter
include_examples 'cluster application helm specs', :clusters_applications_knative
include_examples 'cluster application helm specs', :clusters_applications_jupyter
it { is_expected.to belong_to(:oauth_application) }
......
......@@ -7,6 +7,11 @@ describe Clusters::Applications::Knative do
include_examples 'cluster application status specs', :clusters_applications_knative
include_examples 'cluster application helm specs', :clusters_applications_knative
before do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
end
describe '.installed' do
subject { described_class.installed }
......@@ -45,6 +50,48 @@ describe Clusters::Applications::Knative do
it { is_expected.to contain_exactly(cluster) }
end
describe 'make_installed with external_ip' do
before do
application.make_installed!
end
let(:application) { create(:clusters_applications_knative, :installing) }
it 'schedules a ClusterWaitForIngressIpAddressWorker' do
expect(ClusterWaitForIngressIpAddressWorker).to have_received(:perform_in)
.with(Clusters::Applications::Knative::FETCH_IP_ADDRESS_DELAY, 'knative', application.id)
end
end
describe '#schedule_status_update with external_ip' do
let(:application) { create(:clusters_applications_knative, :installed) }
before do
application.schedule_status_update
end
it 'schedules a ClusterWaitForIngressIpAddressWorker' do
expect(ClusterWaitForIngressIpAddressWorker).to have_received(:perform_async)
.with('knative', application.id)
end
context 'when the application is not installed' do
let(:application) { create(:clusters_applications_knative, :installing) }
it 'does not schedule a ClusterWaitForIngressIpAddressWorker' do
expect(ClusterWaitForIngressIpAddressWorker).not_to have_received(:perform_async)
end
end
context 'when there is already an external_ip' do
let(:application) { create(:clusters_applications_knative, :installed, external_ip: '111.222.222.111') }
it 'does not schedule a ClusterWaitForIngressIpAddressWorker' do
expect(ClusterWaitForIngressIpAddressWorker).not_to have_received(:perform_in)
end
end
end
describe '#install_command' do
subject { knative.install_command }
......
......@@ -5,7 +5,7 @@ describe Clusters::Applications::Prometheus do
include_examples 'cluster application core specs', :clusters_applications_prometheus
include_examples 'cluster application status specs', :clusters_applications_prometheus
include_examples 'cluster application helm specs', :clusters_applications_knative
include_examples 'cluster application helm specs', :clusters_applications_prometheus
describe '.installed' do
subject { described_class.installed }
......
......@@ -5,7 +5,7 @@ describe Clusters::Applications::Runner do
include_examples 'cluster application core specs', :clusters_applications_runner
include_examples 'cluster application status specs', :clusters_applications_runner
include_examples 'cluster application helm specs', :clusters_applications_knative
include_examples 'cluster application helm specs', :clusters_applications_runner
it { is_expected.to belong_to(:runner) }
......@@ -90,7 +90,7 @@ describe Clusters::Applications::Runner do
context 'without a runner' do
let(:project) { create(:project) }
let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
let(:application) { create(:clusters_applications_runner, cluster: cluster) }
let(:application) { create(:clusters_applications_runner, runner: nil, cluster: cluster) }
it 'creates a runner' do
expect do
......
......@@ -28,41 +28,7 @@ describe Clusters::Applications::CheckIngressIpAddressService do
allow(application.cluster).to receive(:kubeclient).and_return(kubeclient)
end
describe '#execute' do
context 'when the ingress ip address is available' do
it 'updates the external_ip for the app' do
subject
include_examples 'check ingress ip executions', :clusters_applications_ingress
expect(application.external_ip).to eq('111.222.111.222')
end
end
context 'when the ingress ip address is not available' do
let(:ingress) { nil }
it 'does not error' do
subject
end
end
context 'when the exclusive lease cannot be obtained' do
it 'does not call kubeclient' do
stub_exclusive_lease_taken(lease_key, timeout: 15.seconds.to_i)
subject
expect(kubeclient).not_to have_received(:get_service)
end
end
context 'when there is already an external_ip' do
let(:application) { create(:clusters_applications_ingress, :installed, external_ip: '001.111.002.111') }
it 'does not call kubeclient' do
subject
expect(kubeclient).not_to have_received(:get_service)
end
end
end
include_examples 'check ingress ip executions', :clusters_applications_knative
end
shared_examples 'check ingress ip executions' do |app_name|
describe '#execute' do
let(:application) { create(app_name, :installed) }
let(:service) { described_class.new(application) }
let(:kubeclient) { double(::Kubeclient::Client, get_service: kube_service) }
context 'when the ingress ip address is available' do
it 'updates the external_ip for the app' do
subject
expect(application.external_ip).to eq('111.222.111.222')
end
end
context 'when the ingress ip address is not available' do
let(:ingress) { nil }
it 'does not error' do
subject
end
end
context 'when the exclusive lease cannot be obtained' do
it 'does not call kubeclient' do
stub_exclusive_lease_taken(lease_key, timeout: 15.seconds.to_i)
subject
expect(kubeclient).not_to have_received(:get_service)
end
end
end
end
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