Commit e0b3257b authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch '33360-generate-kubeconfig' into 'master'

Generate KUBECONFIG in KubernetesService#predefined_variables

Closes #33360

See merge request !12223
parents a33fb213 dbb313c2
......@@ -96,10 +96,13 @@ class KubernetesService < DeploymentService
end
def predefined_variables
config = YAML.dump(kubeconfig)
variables = [
{ key: 'KUBE_URL', value: api_url, public: true },
{ key: 'KUBE_TOKEN', value: token, public: false },
{ key: 'KUBE_NAMESPACE', value: actual_namespace, public: true }
{ key: 'KUBE_NAMESPACE', value: actual_namespace, public: true },
{ key: 'KUBECONFIG', value: config, public: false, file: true }
]
if ca_pem.present?
......@@ -135,6 +138,14 @@ class KubernetesService < DeploymentService
private
def kubeconfig
to_kubeconfig(
url: api_url,
namespace: actual_namespace,
token: token,
ca_pem: ca_pem)
end
def namespace_placeholder
default_namespace || TEMPLATE_PLACEHOLDER
end
......
---
title: Provide KUBECONFIG from KubernetesService for runners
merge_request: 12223
author:
......@@ -55,6 +55,7 @@ GitLab CI build environment:
- `KUBE_CA_PEM_FILE` - only present if a custom CA bundle was specified. Path
to a file containing PEM data.
- `KUBE_CA_PEM` (deprecated)- only if a custom CA bundle was specified. Raw PEM data.
- `KUBECONFIG` - Path to a file containing kubeconfig for this deployment. CA bundle would be embedded if specified.
## Web terminals
......
......@@ -76,5 +76,44 @@ module Gitlab
url.to_s
end
def to_kubeconfig(url:, namespace:, token:, ca_pem: nil)
config = {
apiVersion: 'v1',
clusters: [
name: 'gitlab-deploy',
cluster: {
server: url
}
],
contexts: [
name: 'gitlab-deploy',
context: {
cluster: 'gitlab-deploy',
namespace: namespace,
user: 'gitlab-deploy'
}
],
'current-context': 'gitlab-deploy',
kind: 'Config',
users: [
{
name: 'gitlab-deploy',
user: { token: token }
}
]
}
kubeconfig_embed_ca_pem(config, ca_pem) if ca_pem
config.deep_stringify_keys
end
private
def kubeconfig_embed_ca_pem(config, ca_pem)
cluster = config.dig(:clusters, 0, :cluster)
cluster[:'certificate-authority-data'] = Base64.encode64(ca_pem)
end
end
end
---
apiVersion: v1
clusters:
- name: gitlab-deploy
cluster:
server: https://kube.domain.com
contexts:
- name: gitlab-deploy
context:
cluster: gitlab-deploy
namespace: NAMESPACE
user: gitlab-deploy
current-context: gitlab-deploy
kind: Config
users:
- name: gitlab-deploy
user:
token: TOKEN
---
apiVersion: v1
clusters:
- name: gitlab-deploy
cluster:
server: https://kube.domain.com
certificate-authority-data: "UEVN\n"
contexts:
- name: gitlab-deploy
context:
cluster: gitlab-deploy
namespace: NAMESPACE
user: gitlab-deploy
current-context: gitlab-deploy
kind: Config
users:
- name: gitlab-deploy
user:
token: TOKEN
......@@ -46,4 +46,28 @@ describe Gitlab::Kubernetes do
expect(filter_by_label(items, app: 'foo')).to eq(matching_items)
end
end
describe '#to_kubeconfig' do
subject do
to_kubeconfig(
url: 'https://kube.domain.com',
namespace: 'NAMESPACE',
token: 'TOKEN',
ca_pem: ca_pem)
end
context 'when CA PEM is provided' do
let(:ca_pem) { 'PEM' }
let(:path) { expand_fixture_path('config/kubeconfig.yml') }
it { is_expected.to eq(YAML.load_file(path)) }
end
context 'when CA PEM is not provided' do
let(:ca_pem) { nil }
let(:path) { expand_fixture_path('config/kubeconfig-without-ca.yml') }
it { is_expected.to eq(YAML.load_file(path)) }
end
end
end
......@@ -201,6 +201,22 @@ describe KubernetesService, models: true, caching: true do
end
describe '#predefined_variables' do
let(:kubeconfig) do
config =
YAML.load(File.read(expand_fixture_path('config/kubeconfig.yml')))
config.dig('users', 0, 'user')['token'] =
'token'
config.dig('clusters', 0, 'cluster')['certificate-authority-data'] =
Base64.encode64('CA PEM DATA')
config.dig('contexts', 0, 'context')['namespace'] =
namespace
YAML.dump(config)
end
before do
subject.api_url = 'https://kube.domain.com'
subject.token = 'token'
......@@ -208,32 +224,34 @@ describe KubernetesService, models: true, caching: true do
subject.project = project
end
context 'namespace is provided' do
before do
subject.namespace = 'my-project'
end
shared_examples 'setting variables' do
it 'sets the variables' do
expect(subject.predefined_variables).to include(
{ key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
{ key: 'KUBE_TOKEN', value: 'token', public: false },
{ key: 'KUBE_NAMESPACE', value: 'my-project', public: 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 'no namespace provided' do
it 'sets the variables' do
expect(subject.predefined_variables).to include(
{ key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
{ key: 'KUBE_TOKEN', value: 'token', public: false },
{ key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true },
{ key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true }
)
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.actual_namespace }
it_behaves_like 'setting variables'
it 'sets the KUBE_NAMESPACE' do
kube_namespace = subject.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
......
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