Commit d4762348 authored by charlie ablett's avatar charlie ablett

Merge branch 'merge-injected-kubeconfigs' into 'master'

Merge injected KUBECONFIGs for clusters and agents

See merge request gitlab-org/gitlab!82246
parents 22ae4726 bc2b67cf
......@@ -19,8 +19,7 @@ module Gitlab
variables.concat(project.predefined_variables)
variables.concat(pipeline.predefined_variables)
variables.concat(job.runner.predefined_variables) if job.runnable? && job.runner
variables.concat(kubernetes_variables(job))
variables.concat(deployment_variables(environment: environment, job: job))
variables.concat(kubernetes_variables(environment: environment, job: job))
variables.concat(job.yaml_variables)
variables.concat(user_variables(job.user))
variables.concat(job.dependency_variables) if dependencies
......@@ -33,11 +32,15 @@ module Gitlab
end
end
def kubernetes_variables(job)
def kubernetes_variables(environment:, job:)
::Gitlab::Ci::Variables::Collection.new.tap do |collection|
# Should get merged with the cluster kubeconfig in deployment_variables, see
# https://gitlab.com/gitlab-org/gitlab/-/issues/335089
# NOTE: deployment_variables will be removed as part of cleanup for
# https://gitlab.com/groups/gitlab-org/configure/-/epics/8
# Until then, we need to make both the old and the new KUBECONFIG contexts available
collection.concat(deployment_variables(environment: environment, job: job))
template = ::Ci::GenerateKubeconfigService.new(job).execute
kubeconfig_yaml = collection['KUBECONFIG']&.value
template.merge_yaml(kubeconfig_yaml) if kubeconfig_yaml.present?
if template.valid?
collection.append(key: 'KUBECONFIG', value: template.to_yaml, public: false, file: true)
......
......@@ -14,6 +14,7 @@ module Gitlab
@clusters = []
@users = []
@contexts = []
@current_context = nil
end
def valid?
......@@ -32,14 +33,45 @@ module Gitlab
contexts << new_entry(:context, **args)
end
def merge_yaml(kubeconfig_yaml)
return unless kubeconfig_yaml
kubeconfig_yaml = YAML.safe_load(kubeconfig_yaml, symbolize_names: true)
kubeconfig_yaml[:users].each do |user|
add_user(
name: user[:name],
token: user.dig(:user, :token)
)
end
kubeconfig_yaml[:clusters].each do |cluster|
ca_pem = cluster.dig(:cluster, :'certificate-authority-data')&.yield_self do |data|
Base64.strict_decode64(data)
end
add_cluster(
name: cluster[:name],
url: cluster.dig(:cluster, :server),
ca_pem: ca_pem
)
end
kubeconfig_yaml[:contexts].each do |context|
add_context(
name: context[:name],
**context[:context]&.slice(:cluster, :user, :namespace)
)
end
@current_context = kubeconfig_yaml[:'current-context']
end
def to_h
{
apiVersion: 'v1',
kind: 'Config',
clusters: clusters.map(&:to_h),
users: users.map(&:to_h),
contexts: contexts.map(&:to_h)
}
contexts: contexts.map(&:to_h),
'current-context': current_context
}.compact
end
def to_yaml
......@@ -48,7 +80,7 @@ module Gitlab
private
attr_reader :clusters, :users, :contexts
attr_reader :clusters, :users, :contexts, :current_context
def new_entry(entry, **args)
ENTRIES.fetch(entry).new(**args)
......
......@@ -158,7 +158,6 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
allow(pipeline).to receive(:predefined_variables) { [var('C', 3), var('D', 3)] }
allow(job).to receive(:runner) { double(predefined_variables: [var('D', 4), var('E', 4)]) }
allow(builder).to receive(:kubernetes_variables) { [var('E', 5), var('F', 5)] }
allow(builder).to receive(:deployment_variables) { [var('F', 6), var('G', 6)] }
allow(job).to receive(:yaml_variables) { [var('G', 7), var('H', 7)] }
allow(builder).to receive(:user_variables) { [var('H', 8), var('I', 8)] }
allow(job).to receive(:dependency_variables) { [var('I', 9), var('J', 9)] }
......@@ -177,7 +176,6 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
var('C', 3), var('D', 3),
var('D', 4), var('E', 4),
var('E', 5), var('F', 5),
var('F', 6), var('G', 6),
var('G', 7), var('H', 7),
var('H', 8), var('I', 8),
var('I', 9), var('J', 9),
......@@ -193,7 +191,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
expect(subject.to_hash).to match(
'A' => '1', 'B' => '2',
'C' => '3', 'D' => '4',
'E' => '5', 'F' => '6',
'E' => '5', 'F' => '5',
'G' => '7', 'H' => '8',
'I' => '9', 'J' => '10',
'K' => '11', 'L' => '12',
......@@ -231,7 +229,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
let(:template) { double(to_yaml: 'example-kubeconfig', valid?: template_valid) }
let(:template_valid) { true }
subject { builder.kubernetes_variables(job) }
subject { builder.kubernetes_variables(environment: nil, job: job) }
before do
allow(Ci::GenerateKubeconfigService).to receive(:new).with(job).and_return(service)
......@@ -244,6 +242,16 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
end
it 'includes #deployment_variables and merges the KUBECONFIG values', :aggregate_failures do
expect(builder).to receive(:deployment_variables).and_return([
{ key: 'KUBECONFIG', value: 'deployment-kubeconfig' },
{ key: 'OTHER', value: 'some value' }
])
expect(template).to receive(:merge_yaml).with('deployment-kubeconfig')
expect(subject['KUBECONFIG'].value).to eq('example-kubeconfig')
expect(subject['OTHER'].value).to eq('some value')
end
end
describe '#deployment_variables' do
......
......@@ -39,6 +39,51 @@ RSpec.describe Gitlab::Kubernetes::Kubeconfig::Template do
it { is_expected.to eq(YAML.dump(template.to_h.deep_stringify_keys)) }
end
describe '#merge_yaml' do
it 'appends to the configuration and overwrites the current context' do
template.add_cluster(name: 'hello-cluster', url: 'hello-url')
template.add_context(name: 'hello-context', cluster: 'hello-cluster', user: 'hello-user')
template.add_user(name: 'hello-user', token: 'hello-token')
ca_pem = Base64.strict_encode64('a certificate')
template.merge_yaml(<<~YAML)
apiVersion: v1
kind: Config
clusters:
- name: 'gitlab-deploy'
cluster:
server: url
certificate-authority-data: #{ca_pem.inspect}
contexts:
- name: gitlab-deploy
context:
cluster: gitlab-deploy
namespace: namespace
user: gitlab-deploy
current-context: gitlab-deploy
users:
- name: 'gitlab-deploy'
user: { token: token }
YAML
expect(template.to_h).to eq({
apiVersion: 'v1',
kind: 'Config',
clusters: [
{ name: 'hello-cluster', cluster: { server: 'hello-url' } },
{ name: 'gitlab-deploy', cluster: { server: 'url', 'certificate-authority-data': ca_pem } }
],
contexts: [
{ name: 'hello-context', context: { cluster: 'hello-cluster', user: 'hello-user' } },
{ name: 'gitlab-deploy', context: { cluster: 'gitlab-deploy', namespace: 'namespace', user: 'gitlab-deploy' } }
],
users: [
{ name: 'hello-user', user: { token: 'hello-token' } },
{ name: 'gitlab-deploy', user: { token: 'token' } }
],
'current-context': 'gitlab-deploy'
})
end
end
describe 'adding entries' do
let(:entry) { instance_double(entry_class, to_h: attributes) }
let(:attributes) do
......
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