Commit dd5d5571 authored by Thong Kuah's avatar Thong Kuah

Merge branch 'namespace-labels' into 'master'

Assign labels to the GMA and project k8s namespaces

See merge request gitlab-org/gitlab!23027
parents fa86a635 375e1a52
...@@ -21,10 +21,15 @@ module Clusters ...@@ -21,10 +21,15 @@ module Clusters
attr_reader :cluster, :kubernetes_namespace, :platform attr_reader :cluster, :kubernetes_namespace, :platform
def create_project_service_account def create_project_service_account
environment_slug = kubernetes_namespace.environment&.slug
namespace_labels = { 'app.gitlab.com/app' => kubernetes_namespace.project.full_path_slug }
namespace_labels['app.gitlab.com/env'] = environment_slug if environment_slug
Clusters::Kubernetes::CreateOrUpdateServiceAccountService.namespace_creator( Clusters::Kubernetes::CreateOrUpdateServiceAccountService.namespace_creator(
platform.kubeclient, platform.kubeclient,
service_account_name: kubernetes_namespace.service_account_name, service_account_name: kubernetes_namespace.service_account_name,
service_account_namespace: kubernetes_namespace.namespace, service_account_namespace: kubernetes_namespace.namespace,
service_account_namespace_labels: namespace_labels,
rbac: platform.rbac? rbac: platform.rbac?
).execute ).execute
end end
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
module Clusters module Clusters
module Kubernetes module Kubernetes
class CreateOrUpdateServiceAccountService class CreateOrUpdateServiceAccountService
def initialize(kubeclient, service_account_name:, service_account_namespace:, token_name:, rbac:, namespace_creator: false, role_binding_name: nil) def initialize(kubeclient, service_account_name:, service_account_namespace:, service_account_namespace_labels: nil, token_name:, rbac:, namespace_creator: false, role_binding_name: nil)
@kubeclient = kubeclient @kubeclient = kubeclient
@service_account_name = service_account_name @service_account_name = service_account_name
@service_account_namespace = service_account_namespace @service_account_namespace = service_account_namespace
@service_account_namespace_labels = service_account_namespace_labels
@token_name = token_name @token_name = token_name
@rbac = rbac @rbac = rbac
@namespace_creator = namespace_creator @namespace_creator = namespace_creator
...@@ -23,11 +24,12 @@ module Clusters ...@@ -23,11 +24,12 @@ module Clusters
) )
end end
def self.namespace_creator(kubeclient, service_account_name:, service_account_namespace:, rbac:) def self.namespace_creator(kubeclient, service_account_name:, service_account_namespace:, service_account_namespace_labels:, rbac:)
self.new( self.new(
kubeclient, kubeclient,
service_account_name: service_account_name, service_account_name: service_account_name,
service_account_namespace: service_account_namespace, service_account_namespace: service_account_namespace,
service_account_namespace_labels: service_account_namespace_labels,
token_name: "#{service_account_namespace}-token", token_name: "#{service_account_namespace}-token",
rbac: rbac, rbac: rbac,
namespace_creator: true, namespace_creator: true,
...@@ -55,12 +57,13 @@ module Clusters ...@@ -55,12 +57,13 @@ module Clusters
private private
attr_reader :kubeclient, :service_account_name, :service_account_namespace, :token_name, :rbac, :namespace_creator, :role_binding_name attr_reader :kubeclient, :service_account_name, :service_account_namespace, :service_account_namespace_labels, :token_name, :rbac, :namespace_creator, :role_binding_name
def ensure_project_namespace_exists def ensure_project_namespace_exists
Gitlab::Kubernetes::Namespace.new( Gitlab::Kubernetes::Namespace.new(
service_account_namespace, service_account_namespace,
kubeclient kubeclient,
labels: service_account_namespace_labels
).ensure_exists! ).ensure_exists!
end end
......
---
title: Assign labels to the GMA and project k8s namespaces
merge_request: 23027
author:
type: added
...@@ -6,6 +6,7 @@ module Gitlab ...@@ -6,6 +6,7 @@ module Gitlab
HELM_VERSION = '2.16.1' HELM_VERSION = '2.16.1'
KUBECTL_VERSION = '1.13.12' KUBECTL_VERSION = '1.13.12'
NAMESPACE = 'gitlab-managed-apps' NAMESPACE = 'gitlab-managed-apps'
NAMESPACE_LABELS = { 'app.gitlab.com/managed_by' => :gitlab }.freeze
SERVICE_ACCOUNT = 'tiller' SERVICE_ACCOUNT = 'tiller'
CLUSTER_ROLE_BINDING = 'tiller-admin' CLUSTER_ROLE_BINDING = 'tiller-admin'
CLUSTER_ROLE = 'cluster-admin' CLUSTER_ROLE = 'cluster-admin'
......
...@@ -6,7 +6,11 @@ module Gitlab ...@@ -6,7 +6,11 @@ module Gitlab
class Api class Api
def initialize(kubeclient) def initialize(kubeclient)
@kubeclient = kubeclient @kubeclient = kubeclient
@namespace = Gitlab::Kubernetes::Namespace.new(Gitlab::Kubernetes::Helm::NAMESPACE, kubeclient) @namespace = Gitlab::Kubernetes::Namespace.new(
Gitlab::Kubernetes::Helm::NAMESPACE,
kubeclient,
labels: Gitlab::Kubernetes::Helm::NAMESPACE_LABELS
)
end end
def install(command) def install(command)
......
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
module Gitlab module Gitlab
module Kubernetes module Kubernetes
class Namespace class Namespace
attr_accessor :name attr_accessor :name, :labels
def initialize(name, client) def initialize(name, client, labels: nil)
@name = name @name = name
@client = client @client = client
@labels = labels
end end
def exists? def exists?
...@@ -17,7 +18,7 @@ module Gitlab ...@@ -17,7 +18,7 @@ module Gitlab
end end
def create! def create!
resource = ::Kubeclient::Resource.new(metadata: { name: name }) resource = ::Kubeclient::Resource.new(metadata: { name: name, labels: labels })
log_event(:begin_create) log_event(:begin_create)
@client.create_namespace(resource) @client.create_namespace(resource)
......
...@@ -6,7 +6,8 @@ describe Gitlab::Kubernetes::Helm::Api do ...@@ -6,7 +6,8 @@ describe Gitlab::Kubernetes::Helm::Api do
let(:client) { double('kubernetes client') } let(:client) { double('kubernetes client') }
let(:helm) { described_class.new(client) } let(:helm) { described_class.new(client) }
let(:gitlab_namespace) { Gitlab::Kubernetes::Helm::NAMESPACE } let(:gitlab_namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
let(:namespace) { Gitlab::Kubernetes::Namespace.new(gitlab_namespace, client) } let(:gitlab_namespace_labels) { Gitlab::Kubernetes::Helm::NAMESPACE_LABELS }
let(:namespace) { Gitlab::Kubernetes::Namespace.new(gitlab_namespace, client, labels: gitlab_namespace_labels) }
let(:application_name) { 'app-name' } let(:application_name) { 'app-name' }
let(:rbac) { false } let(:rbac) { false }
let(:files) { {} } let(:files) { {} }
...@@ -23,13 +24,17 @@ describe Gitlab::Kubernetes::Helm::Api do ...@@ -23,13 +24,17 @@ describe Gitlab::Kubernetes::Helm::Api do
subject { helm } subject { helm }
before do before do
allow(Gitlab::Kubernetes::Namespace).to receive(:new).with(gitlab_namespace, client).and_return(namespace) allow(Gitlab::Kubernetes::Namespace).to(
receive(:new).with(gitlab_namespace, client, labels: gitlab_namespace_labels).and_return(namespace)
)
allow(client).to receive(:create_config_map) allow(client).to receive(:create_config_map)
end end
describe '#initialize' do describe '#initialize' do
it 'creates a namespace object' do it 'creates a namespace object' do
expect(Gitlab::Kubernetes::Namespace).to receive(:new).with(gitlab_namespace, client) expect(Gitlab::Kubernetes::Namespace).to(
receive(:new).with(gitlab_namespace, client, labels: gitlab_namespace_labels)
)
subject subject
end end
......
...@@ -5,8 +5,9 @@ require 'spec_helper' ...@@ -5,8 +5,9 @@ require 'spec_helper'
describe Gitlab::Kubernetes::Namespace do describe Gitlab::Kubernetes::Namespace do
let(:name) { 'a_namespace' } let(:name) { 'a_namespace' }
let(:client) { double('kubernetes client') } let(:client) { double('kubernetes client') }
let(:labels) { nil }
subject { described_class.new(name, client) } subject { described_class.new(name, client, labels: labels) }
it { expect(subject.name).to eq(name) } it { expect(subject.name).to eq(name) }
...@@ -49,6 +50,17 @@ describe Gitlab::Kubernetes::Namespace do ...@@ -49,6 +50,17 @@ describe Gitlab::Kubernetes::Namespace do
expect { subject.create! }.not_to raise_error expect { subject.create! }.not_to raise_error
end end
context 'with labels' do
let(:labels) { { foo: :bar } }
it 'creates a namespace with labels' do
matcher = have_attributes(metadata: have_attributes(name: name, labels: have_attributes(foo: :bar)))
expect(client).to receive(:create_namespace).with(matcher).once
expect { subject.create! }.not_to raise_error
end
end
end end
describe '#ensure_exists!' do describe '#ensure_exists!' do
......
...@@ -57,11 +57,21 @@ describe Clusters::Kubernetes::CreateOrUpdateNamespaceService, '#execute' do ...@@ -57,11 +57,21 @@ describe Clusters::Kubernetes::CreateOrUpdateNamespaceService, '#execute' do
end.to change(Clusters::KubernetesNamespace, :count).by(1) end.to change(Clusters::KubernetesNamespace, :count).by(1)
end end
it 'creates project service account' do it 'creates project service account and namespace' do
expect_next_instance_of(Clusters::Kubernetes::CreateOrUpdateServiceAccountService) do |instance| account_service = double(Clusters::Kubernetes::CreateOrUpdateServiceAccountService)
expect(instance).to receive(:execute).once expect(Clusters::Kubernetes::CreateOrUpdateServiceAccountService).to(
end receive(:namespace_creator).with(
cluster.platform.kubeclient,
service_account_name: "#{namespace}-service-account",
service_account_namespace: namespace,
service_account_namespace_labels: {
'app.gitlab.com/app' => project.full_path_slug,
'app.gitlab.com/env' => environment.slug
},
rbac: true
).and_return(account_service)
)
expect(account_service).to receive(:execute).once
subject subject
end end
...@@ -73,6 +83,29 @@ describe Clusters::Kubernetes::CreateOrUpdateNamespaceService, '#execute' do ...@@ -73,6 +83,29 @@ describe Clusters::Kubernetes::CreateOrUpdateNamespaceService, '#execute' do
expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account") expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
expect(kubernetes_namespace.encrypted_service_account_token).to be_present expect(kubernetes_namespace.encrypted_service_account_token).to be_present
end end
context 'without environment' do
before do
kubernetes_namespace.environment = nil
end
it 'creates project service account and namespace' do
account_service = double(Clusters::Kubernetes::CreateOrUpdateServiceAccountService)
expect(Clusters::Kubernetes::CreateOrUpdateServiceAccountService).to(
receive(:namespace_creator).with(
cluster.platform.kubeclient,
service_account_name: "#{namespace}-service-account",
service_account_namespace: namespace,
service_account_namespace_labels: {
'app.gitlab.com/app' => project.full_path_slug
},
rbac: true
).and_return(account_service)
)
expect(account_service).to receive(:execute).once
subject
end
end
end end
context 'group clusters' do context 'group clusters' do
......
...@@ -116,6 +116,7 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do ...@@ -116,6 +116,7 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do
describe '.namespace_creator' do describe '.namespace_creator' do
let(:namespace) { "#{project.path}-#{project.id}" } let(:namespace) { "#{project.path}-#{project.id}" }
let(:namespace_labels) { { app: project.full_path_slug, env: "staging" } }
let(:service_account_name) { "#{namespace}-service-account" } let(:service_account_name) { "#{namespace}-service-account" }
let(:token_name) { "#{namespace}-token" } let(:token_name) { "#{namespace}-token" }
...@@ -124,6 +125,7 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do ...@@ -124,6 +125,7 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do
kubeclient, kubeclient,
service_account_name: service_account_name, service_account_name: service_account_name,
service_account_namespace: namespace, service_account_namespace: namespace,
service_account_namespace_labels: namespace_labels,
rbac: rbac rbac: rbac
).execute ).execute
end end
...@@ -149,6 +151,16 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do ...@@ -149,6 +151,16 @@ describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do
stub_kubeclient_put_role_binding(api_url, Clusters::Kubernetes::GITLAB_CROSSPLANE_DATABASE_ROLE_BINDING_NAME, namespace: namespace) stub_kubeclient_put_role_binding(api_url, Clusters::Kubernetes::GITLAB_CROSSPLANE_DATABASE_ROLE_BINDING_NAME, namespace: namespace)
end end
it 'creates a namespace object' do
kubernetes_namespace = double(Gitlab::Kubernetes::Namespace)
expect(Gitlab::Kubernetes::Namespace).to(
receive(:new).with(namespace, kubeclient, labels: namespace_labels).and_return(kubernetes_namespace)
)
expect(kubernetes_namespace).to receive(:ensure_exists!)
subject
end
it_behaves_like 'creates service account and token' it_behaves_like 'creates service account and token'
it 'creates a namespaced role binding with edit access' do it 'creates a namespaced role binding with edit access' 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