Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
db535764
Commit
db535764
authored
Sep 06, 2018
by
Thong Kuah
Committed by
Kamil Trzciński
Sep 06, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EE port for 29398 support kubernetes rbac for gitlab managed apps
parent
f14cfc3f
Changes
49
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
1370 additions
and
101 deletions
+1370
-101
app/controllers/projects/clusters_controller.rb
app/controllers/projects/clusters_controller.rb
+2
-1
app/helpers/clusters_helper.rb
app/helpers/clusters_helper.rb
+4
-0
app/models/clusters/applications/helm.rb
app/models/clusters/applications/helm.rb
+2
-1
app/models/clusters/applications/ingress.rb
app/models/clusters/applications/ingress.rb
+1
-0
app/models/clusters/applications/jupyter.rb
app/models/clusters/applications/jupyter.rb
+1
-0
app/models/clusters/applications/prometheus.rb
app/models/clusters/applications/prometheus.rb
+2
-1
app/models/clusters/applications/runner.rb
app/models/clusters/applications/runner.rb
+1
-0
app/models/clusters/cluster.rb
app/models/clusters/cluster.rb
+1
-0
app/models/clusters/platforms/kubernetes.rb
app/models/clusters/platforms/kubernetes.rb
+13
-14
app/models/project_services/kubernetes_service.rb
app/models/project_services/kubernetes_service.rb
+9
-17
app/views/projects/clusters/user/_form.html.haml
app/views/projects/clusters/user/_form.html.haml
+9
-0
app/views/projects/clusters/user/_show.html.haml
app/views/projects/clusters/user/_show.html.haml
+9
-0
changelogs/unreleased/29398-support-kubernetes-rbac-for-gitlab-managed-apps.yml
...29398-support-kubernetes-rbac-for-gitlab-managed-apps.yml
+5
-0
db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb
...add_authorization_type_to_cluster_platforms_kubernetes.rb
+11
-0
db/schema.rb
db/schema.rb
+1
-0
ee/app/models/concerns/ee/kubernetes_service.rb
ee/app/models/concerns/ee/kubernetes_service.rb
+1
-1
ee/app/models/ee/clusters/applications/prometheus.rb
ee/app/models/ee/clusters/applications/prometheus.rb
+1
-0
ee/lib/gitlab/kubernetes/helm/upgrade_command.rb
ee/lib/gitlab/kubernetes/helm/upgrade_command.rb
+6
-1
ee/spec/lib/ee/gitlab/kubernetes/helm/api_spec.rb
ee/spec/lib/ee/gitlab/kubernetes/helm/api_spec.rb
+3
-1
ee/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
ee/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
+57
-5
lib/gitlab/kubernetes/cluster_role_binding.rb
lib/gitlab/kubernetes/cluster_role_binding.rb
+37
-0
lib/gitlab/kubernetes/helm.rb
lib/gitlab/kubernetes/helm.rb
+3
-0
lib/gitlab/kubernetes/helm/api.rb
lib/gitlab/kubernetes/helm/api.rb
+48
-0
lib/gitlab/kubernetes/helm/base_command.rb
lib/gitlab/kubernetes/helm/base_command.rb
+19
-1
lib/gitlab/kubernetes/helm/init_command.rb
lib/gitlab/kubernetes/helm/init_command.rb
+54
-6
lib/gitlab/kubernetes/helm/install_command.rb
lib/gitlab/kubernetes/helm/install_command.rb
+40
-12
lib/gitlab/kubernetes/helm/pod.rb
lib/gitlab/kubernetes/helm/pod.rb
+4
-2
lib/gitlab/kubernetes/kube_client.rb
lib/gitlab/kubernetes/kube_client.rb
+110
-0
lib/gitlab/kubernetes/service_account.rb
lib/gitlab/kubernetes/service_account.rb
+27
-0
locale/gitlab.pot
locale/gitlab.pot
+9
-0
spec/controllers/projects/clusters_controller_spec.rb
spec/controllers/projects/clusters_controller_spec.rb
+32
-0
spec/factories/clusters/platforms/kubernetes.rb
spec/factories/clusters/platforms/kubernetes.rb
+4
-0
spec/features/projects/clusters/user_spec.rb
spec/features/projects/clusters/user_spec.rb
+22
-0
spec/lib/gitlab/kubernetes/cluster_role_binding_spec.rb
spec/lib/gitlab/kubernetes/cluster_role_binding_spec.rb
+35
-0
spec/lib/gitlab/kubernetes/helm/api_spec.rb
spec/lib/gitlab/kubernetes/helm/api_spec.rb
+105
-4
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
+19
-1
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
+128
-2
spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+145
-10
spec/lib/gitlab/kubernetes/helm/pod_spec.rb
spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+16
-1
spec/lib/gitlab/kubernetes/kube_client_spec.rb
spec/lib/gitlab/kubernetes/kube_client_spec.rb
+247
-0
spec/lib/gitlab/kubernetes/service_account_spec.rb
spec/lib/gitlab/kubernetes/service_account_spec.rb
+24
-0
spec/models/clusters/applications/helm_spec.rb
spec/models/clusters/applications/helm_spec.rb
+14
-0
spec/models/clusters/applications/ingress_spec.rb
spec/models/clusters/applications/ingress_spec.rb
+9
-0
spec/models/clusters/applications/jupyter_spec.rb
spec/models/clusters/applications/jupyter_spec.rb
+9
-0
spec/models/clusters/applications/prometheus_spec.rb
spec/models/clusters/applications/prometheus_spec.rb
+17
-18
spec/models/clusters/applications/runner_spec.rb
spec/models/clusters/applications/runner_spec.rb
+9
-0
spec/models/clusters/cluster_spec.rb
spec/models/clusters/cluster_spec.rb
+4
-0
spec/models/clusters/platforms/kubernetes_spec.rb
spec/models/clusters/platforms/kubernetes_spec.rb
+24
-0
spec/support/helpers/kubernetes_helpers.rb
spec/support/helpers/kubernetes_helpers.rb
+17
-2
No files found.
app/controllers/projects/clusters_controller.rb
View file @
db535764
...
...
@@ -159,7 +159,8 @@ class Projects::ClustersController < Projects::ApplicationController
:namespace
,
:api_url
,
:token
,
:ca_cert
:ca_cert
,
:authorization_type
]).
merge
(
provider_type: :user
,
platform_type: :kubernetes
...
...
app/helpers/clusters_helper.rb
View file @
db535764
...
...
@@ -11,4 +11,8 @@ module ClustersHelper
render
'projects/clusters/gcp_signup_offer_banner'
end
end
def
rbac_clusters_feature_enabled?
Feature
.
enabled?
(
:rbac_clusters
)
end
end
app/models/clusters/applications/helm.rb
View file @
db535764
...
...
@@ -32,7 +32,8 @@ module Clusters
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
.
new
(
name:
name
,
files:
files
files:
files
,
rbac:
cluster
.
platform_kubernetes_rbac?
)
end
...
...
app/models/clusters/applications/ingress.rb
View file @
db535764
...
...
@@ -39,6 +39,7 @@ module Clusters
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
)
...
...
app/models/clusters/applications/jupyter.rb
View file @
db535764
...
...
@@ -40,6 +40,7 @@ module Clusters
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
,
repository:
repository
...
...
app/models/clusters/applications/prometheus.rb
View file @
db535764
...
...
@@ -50,6 +50,7 @@ module Clusters
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
)
...
...
@@ -73,7 +74,7 @@ module Clusters
private
def
kube_client
cluster
&
.
kubeclient
cluster
&
.
kubeclient
&
.
core_client
end
end
end
...
...
app/models/clusters/applications/runner.rb
View file @
db535764
...
...
@@ -33,6 +33,7 @@ module Clusters
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
name
,
version:
VERSION
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
chart:
chart
,
files:
files
,
repository:
repository
...
...
app/models/clusters/cluster.rb
View file @
db535764
...
...
@@ -44,6 +44,7 @@ module Clusters
delegate
:on_creation?
,
to: :provider
,
allow_nil:
true
delegate
:active?
,
to: :platform_kubernetes
,
prefix:
true
,
allow_nil:
true
delegate
:rbac?
,
to: :platform_kubernetes
,
prefix:
true
,
allow_nil:
true
delegate
:installed?
,
to: :application_helm
,
prefix:
true
,
allow_nil:
true
delegate
:installed?
,
to: :application_ingress
,
prefix:
true
,
allow_nil:
true
...
...
app/models/clusters/platforms/kubernetes.rb
View file @
db535764
...
...
@@ -5,6 +5,7 @@ module Clusters
class
Kubernetes
<
ActiveRecord
::
Base
include
Gitlab
::
Kubernetes
include
ReactiveCaching
include
EnumWithNil
prepend
EE
::
KubernetesService
...
...
@@ -49,6 +50,12 @@ module Clusters
alias_method
:active?
,
:enabled?
enum_with_nil
authorization_type:
{
unknown_authorization:
nil
,
rbac:
1
,
abac:
2
}
def
actual_namespace
if
namespace
.
present?
namespace
...
...
@@ -97,7 +104,7 @@ module Clusters
end
def
kubeclient
@kubeclient
||=
build_kube
client!
@kubeclient
||=
build_kube
_client!
(
api_groups:
[
'api'
,
'apis/rbac.authorization.k8s.io'
])
end
private
...
...
@@ -117,15 +124,16 @@ module Clusters
slug
.
gsub
(
/[^-a-z0-9]/
,
'-'
).
gsub
(
/^-+/
,
''
)
end
def
build_kube
client!
(
api_path:
'api'
,
api_version:
'v1'
)
def
build_kube
_client!
(
api_groups:
[
'api'
]
,
api_version:
'v1'
)
raise
"Incomplete settings"
unless
api_url
&&
actual_namespace
unless
(
username
&&
password
)
||
token
raise
"Either username/password or token is required to access API"
end
::
Kubeclient
::
Client
.
new
(
join_api_url
(
api_path
),
Gitlab
::
Kubernetes
::
KubeClient
.
new
(
api_url
,
api_groups
,
api_version
,
auth_options:
kubeclient_auth_options
,
ssl_options:
kubeclient_ssl_options
,
...
...
@@ -135,7 +143,7 @@ module Clusters
# Returns a hash of all pods in the namespace
def
read_pods
kubeclient
=
build_kubeclient!
kubeclient
=
build_kube
_
client!
kubeclient
.
get_pods
(
namespace:
actual_namespace
).
as_json
rescue
Kubeclient
::
HttpError
=>
err
...
...
@@ -159,15 +167,6 @@ module Clusters
{
bearer_token:
token
}
end
def
join_api_url
(
api_path
)
url
=
URI
.
parse
(
api_url
)
prefix
=
url
.
path
.
sub
(
%r{/+
\z
}
,
''
)
url
.
path
=
[
prefix
,
api_path
].
join
(
"/"
)
url
.
to_s
end
def
terminal_auth
{
token:
token
,
...
...
app/models/project_services/kubernetes_service.rb
View file @
db535764
...
...
@@ -98,10 +98,10 @@ class KubernetesService < DeploymentService
# Check we can connect to the Kubernetes API
def
test
(
*
args
)
kubeclient
=
build_kubeclient!
kubeclient
=
build_kube
_
client!
kubeclient
.
discover
{
success:
kubeclient
.
discovered
,
result:
"Checked API discovery endpoint"
}
kubeclient
.
core_client
.
discover
{
success:
kubeclient
.
core_client
.
discovered
,
result:
"Checked API discovery endpoint"
}
rescue
=>
err
{
success:
false
,
result:
err
}
end
...
...
@@ -146,7 +146,7 @@ class KubernetesService < DeploymentService
end
def
kubeclient
@kubeclient
||=
build_kube
client!
@kubeclient
||=
build_kube
_client!
(
api_groups:
[
'api'
,
'apis/rbac.authorization.k8s.io'
])
end
def
deprecated?
...
...
@@ -184,11 +184,12 @@ class KubernetesService < DeploymentService
slug
.
gsub
(
/[^-a-z0-9]/
,
'-'
).
gsub
(
/^-+/
,
''
)
end
def
build_kube
client!
(
api_path:
'api'
,
api_version:
'v1'
)
def
build_kube
_client!
(
api_groups:
[
'api'
]
,
api_version:
'v1'
)
raise
"Incomplete settings"
unless
api_url
&&
actual_namespace
&&
token
::
Kubeclient
::
Client
.
new
(
join_api_url
(
api_path
),
Gitlab
::
Kubernetes
::
KubeClient
.
new
(
api_url
,
api_groups
,
api_version
,
auth_options:
kubeclient_auth_options
,
ssl_options:
kubeclient_ssl_options
,
...
...
@@ -198,7 +199,7 @@ class KubernetesService < DeploymentService
# Returns a hash of all pods in the namespace
def
read_pods
kubeclient
=
build_kubeclient!
kubeclient
=
build_kube
_
client!
kubeclient
.
get_pods
(
namespace:
actual_namespace
).
as_json
rescue
Kubeclient
::
HttpError
=>
err
...
...
@@ -222,15 +223,6 @@ class KubernetesService < DeploymentService
{
bearer_token:
token
}
end
def
join_api_url
(
api_path
)
url
=
URI
.
parse
(
api_url
)
prefix
=
url
.
path
.
sub
(
%r{/+
\z
}
,
''
)
url
.
path
=
[
prefix
,
api_path
].
join
(
"/"
)
url
.
to_s
end
def
terminal_auth
{
token:
token
,
...
...
app/views/projects/clusters/user/_form.html.haml
View file @
db535764
...
...
@@ -25,5 +25,14 @@
=
platform_kubernetes_field
.
label
:namespace
,
s_
(
'ClusterIntegration|Project namespace (optional, unique)'
),
class:
'label-bold'
=
platform_kubernetes_field
.
text_field
:namespace
,
class:
'form-control'
,
placeholder:
s_
(
'ClusterIntegration|Project namespace'
)
-
if
rbac_clusters_feature_enabled?
.form-group
.form-check
=
platform_kubernetes_field
.
check_box
:authorization_type
,
{
class:
'form-check-input'
},
'rbac'
,
'abac'
=
platform_kubernetes_field
.
label
:authorization_type
,
s_
(
'ClusterIntegration|RBAC-enabled cluster (experimental)'
),
class:
'form-check-label label-bold'
.form-text.text-muted
=
s_
(
'ClusterIntegration|Enable this setting if using role-based access control (RBAC).'
)
=
s_
(
'ClusterIntegration|This option will allow you to install applications on RBAC clusters.'
)
.form-group
=
field
.
submit
s_
(
'ClusterIntegration|Add Kubernetes cluster'
),
class:
'btn btn-success'
app/views/projects/clusters/user/_show.html.haml
View file @
db535764
...
...
@@ -26,5 +26,14 @@
=
platform_kubernetes_field
.
label
:namespace
,
s_
(
'ClusterIntegration|Project namespace (optional, unique)'
),
class:
'label-bold'
=
platform_kubernetes_field
.
text_field
:namespace
,
class:
'form-control'
,
placeholder:
s_
(
'ClusterIntegration|Project namespace'
)
-
if
rbac_clusters_feature_enabled?
.form-group
.form-check
=
platform_kubernetes_field
.
check_box
:authorization_type
,
{
class:
'form-check-input'
,
disabled:
true
},
'rbac'
,
'abac'
=
platform_kubernetes_field
.
label
:authorization_type
,
s_
(
'ClusterIntegration|RBAC-enabled cluster (experimental)'
),
class:
'form-check-label label-bold'
.form-text.text-muted
=
s_
(
'ClusterIntegration|Enable this setting if using role-based access control (RBAC).'
)
=
s_
(
'ClusterIntegration|This option will allow you to install applications on RBAC clusters.'
)
.form-group
=
field
.
submit
s_
(
'ClusterIntegration|Save changes'
),
class:
'btn btn-success'
changelogs/unreleased/29398-support-kubernetes-rbac-for-gitlab-managed-apps.yml
0 → 100644
View file @
db535764
---
title
:
Support Kubernetes RBAC for GitLab Managed Apps when adding a existing cluster
merge_request
:
21127
author
:
type
:
changed
db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
class
AddAuthorizationTypeToClusterPlatformsKubernetes
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
add_column
:cluster_platforms_kubernetes
,
:authorization_type
,
:integer
,
limit:
2
end
end
db/schema.rb
View file @
db535764
...
...
@@ -706,6 +706,7 @@ ActiveRecord::Schema.define(version: 20180831152625) do
t
.
string
"encrypted_password_iv"
t
.
text
"encrypted_token"
t
.
string
"encrypted_token_iv"
t
.
integer
"authorization_type"
,
limit:
2
end
add_index
"cluster_platforms_kubernetes"
,
[
"cluster_id"
],
name:
"index_cluster_platforms_kubernetes_on_cluster_id"
,
unique:
true
,
using: :btree
...
...
ee/app/models/concerns/ee/kubernetes_service.rb
View file @
db535764
...
...
@@ -31,7 +31,7 @@ module EE
end
def
read_deployments
kubeclient
=
build_kube
client!
(
api_path:
'apis/extensions'
,
api_version:
'v1beta1'
)
kubeclient
=
build_kube
_client!
(
api_groups:
[
'apis/extensions'
]
,
api_version:
'v1beta1'
)
kubeclient
.
get_deployments
(
namespace:
actual_namespace
).
as_json
rescue
KubeException
=>
err
...
...
ee/app/models/ee/clusters/applications/prometheus.rb
View file @
db535764
...
...
@@ -35,6 +35,7 @@ module EE
name
,
version:
self
.
class
.
const_get
(
:VERSION
),
chart:
chart
,
rbac:
cluster
.
platform_kubernetes_rbac?
,
files:
files_with_replaced_values
(
values
)
)
end
...
...
ee/lib/gitlab/kubernetes/helm/upgrade_command.rb
View file @
db535764
...
...
@@ -8,9 +8,10 @@ module Gitlab
attr_reader
:name
,
:chart
,
:version
,
:repository
,
:files
def
initialize
(
name
,
chart
:,
files
:,
version:
nil
,
repository:
nil
)
def
initialize
(
name
,
chart
:,
files
:,
rbac
:,
version:
nil
,
repository:
nil
)
@name
=
name
@chart
=
chart
@rbac
=
rbac
@version
=
version
@files
=
files
@repository
=
repository
...
...
@@ -24,6 +25,10 @@ module Gitlab
].
compact
.
join
(
"
\n
"
)
end
def
rbac?
@rbac
end
def
pod_name
"upgrade-
#{
name
}
"
end
...
...
ee/spec/lib/ee/gitlab/kubernetes/helm/api_spec.rb
View file @
db535764
...
...
@@ -31,11 +31,13 @@ describe Gitlab::Kubernetes::Helm::Api do
end
describe
'#update'
do
let
(
:rbac
)
{
false
}
let
(
:command
)
do
Gitlab
::
Kubernetes
::
Helm
::
UpgradeCommand
.
new
(
application
.
name
,
chart:
application
.
chart
,
files:
application
.
files
files:
application
.
files
,
rbac:
rbac
)
end
...
...
ee/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
View file @
db535764
...
...
@@ -4,15 +4,18 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
let
(
:application
)
{
build
(
:clusters_applications_prometheus
)
}
let
(
:files
)
{
{
'ca.pem'
:
'some file content'
}
}
let
(
:namespace
)
{
::
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
subject
do
let
(
:rbac
)
{
false
}
let
(
:upgrade_command
)
do
described_class
.
new
(
application
.
name
,
chart:
application
.
chart
,
files:
files
files:
files
,
rbac:
rbac
)
end
subject
{
upgrade_command
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
...
...
@@ -22,15 +25,28 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
end
end
context
'rbac is true'
do
let
(
:rbac
)
{
true
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm upgrade
#{
application
.
name
}
#{
application
.
chart
}
--tls --tls-ca-cert /data/helm/
#{
application
.
name
}
/config/ca.pem --tls-cert /data/helm/
#{
application
.
name
}
/config/cert.pem --tls-key /data/helm/
#{
application
.
name
}
/config/key.pem --reset-values --install --namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/dev/null
EOS
end
end
end
context
'with an application with a repository'
do
let
(
:ci_runner
)
{
create
(
:ci_runner
)
}
let
(
:application
)
{
build
(
:clusters_applications_runner
,
runner:
ci_runner
)
}
subject
do
let
(
:upgrade_command
)
do
described_class
.
new
(
application
.
name
,
chart:
application
.
chart
,
files:
files
,
rbac:
rbac
,
repository:
application
.
repository
)
end
...
...
@@ -59,6 +75,26 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
end
end
describe
'#pod_resource'
do
subject
{
upgrade_command
.
pod_resource
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
'generates a pod that uses the tiller serviceAccountName'
do
expect
(
subject
.
spec
.
serviceAccountName
).
to
eq
(
'tiller'
)
end
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
'generates a pod that uses the default serviceAccountName'
do
expect
(
subject
.
spec
.
serviceAcccountName
).
to
be_nil
end
end
end
describe
'#config_map_resource'
do
let
(
:metadata
)
do
{
...
...
@@ -74,6 +110,22 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
end
end
describe
'#rbac?'
do
subject
{
upgrade_command
.
rbac?
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
{
is_expected
.
to
be_truthy
}
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#pod_name'
do
it
'returns the pod name'
do
expect
(
subject
.
pod_name
).
to
eq
(
"upgrade-
#{
application
.
name
}
"
)
...
...
lib/gitlab/kubernetes/cluster_role_binding.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
module
Gitlab
module
Kubernetes
class
ClusterRoleBinding
attr_reader
:name
,
:cluster_role_name
,
:subjects
def
initialize
(
name
,
cluster_role_name
,
subjects
)
@name
=
name
@cluster_role_name
=
cluster_role_name
@subjects
=
subjects
end
def
generate
::
Kubeclient
::
Resource
.
new
.
tap
do
|
resource
|
resource
.
metadata
=
metadata
resource
.
roleRef
=
role_ref
resource
.
subjects
=
subjects
end
end
private
def
metadata
{
name:
name
}
end
def
role_ref
{
apiGroup:
'rbac.authorization.k8s.io'
,
kind:
'ClusterRole'
,
name:
cluster_role_name
}
end
end
end
end
lib/gitlab/kubernetes/helm.rb
View file @
db535764
...
...
@@ -3,6 +3,9 @@ module Gitlab
module
Helm
HELM_VERSION
=
'2.7.2'
.
freeze
NAMESPACE
=
'gitlab-managed-apps'
.
freeze
SERVICE_ACCOUNT
=
'tiller'
.
freeze
CLUSTER_ROLE_BINDING
=
'tiller-admin'
.
freeze
CLUSTER_ROLE
=
'cluster-admin'
.
freeze
end
end
end
lib/gitlab/kubernetes/helm/api.rb
View file @
db535764
...
...
@@ -11,7 +11,11 @@ module Gitlab
def
install
(
command
)
namespace
.
ensure_exists!
create_service_account
(
command
)
create_cluster_role_binding
(
command
)
create_config_map
(
command
)
kubeclient
.
create_pod
(
command
.
pod_resource
)
end
...
...
@@ -43,6 +47,50 @@ module Gitlab
kubeclient
.
create_config_map
(
config_map_resource
)
end
end
def
create_service_account
(
command
)
command
.
service_account_resource
.
tap
do
|
service_account_resource
|
break
unless
service_account_resource
if
service_account_exists?
(
service_account_resource
)
kubeclient
.
update_service_account
(
service_account_resource
)
else
kubeclient
.
create_service_account
(
service_account_resource
)
end
end
end
def
create_cluster_role_binding
(
command
)
command
.
cluster_role_binding_resource
.
tap
do
|
cluster_role_binding_resource
|
break
unless
cluster_role_binding_resource
if
cluster_role_binding_exists?
(
cluster_role_binding_resource
)
kubeclient
.
update_cluster_role_binding
(
cluster_role_binding_resource
)
else
kubeclient
.
create_cluster_role_binding
(
cluster_role_binding_resource
)
end
end
end
def
service_account_exists?
(
resource
)
resource_exists?
do
kubeclient
.
get_service_account
(
resource
.
metadata
.
name
,
resource
.
metadata
.
namespace
)
end
end
def
cluster_role_binding_exists?
(
resource
)
resource_exists?
do
kubeclient
.
get_cluster_role_binding
(
resource
.
metadata
.
name
)
end
end
def
resource_exists?
yield
rescue
::
Kubeclient
::
HttpError
=>
e
raise
e
unless
e
.
error_code
==
404
false
end
end
end
end
...
...
lib/gitlab/kubernetes/helm/base_command.rb
View file @
db535764
...
...
@@ -3,7 +3,9 @@ module Gitlab
module
Helm
module
BaseCommand
def
pod_resource
Gitlab
::
Kubernetes
::
Helm
::
Pod
.
new
(
self
,
namespace
).
generate
pod_service_account_name
=
rbac?
?
service_account_name
:
nil
Gitlab
::
Kubernetes
::
Helm
::
Pod
.
new
(
self
,
namespace
,
service_account_name:
pod_service_account_name
).
generate
end
def
generate_script
...
...
@@ -26,6 +28,14 @@ module Gitlab
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
name
,
files
).
generate
end
def
service_account_resource
nil
end
def
cluster_role_binding_resource
nil
end
def
file_names
files
.
keys
end
...
...
@@ -34,6 +44,10 @@ module Gitlab
raise
"Not implemented"
end
def
rbac?
raise
"Not implemented"
end
def
files
raise
"Not implemented"
end
...
...
@@ -47,6 +61,10 @@ module Gitlab
def
namespace
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
end
def
service_account_name
Gitlab
::
Kubernetes
::
Helm
::
SERVICE_ACCOUNT
end
end
end
end
...
...
lib/gitlab/kubernetes/helm/init_command.rb
View file @
db535764
...
...
@@ -6,9 +6,10 @@ module Gitlab
attr_reader
:name
,
:files
def
initialize
(
name
:,
files
:)
def
initialize
(
name
:,
files
:
,
rbac
:
)
@name
=
name
@files
=
files
@rbac
=
rbac
end
def
generate_script
...
...
@@ -17,15 +18,62 @@ module Gitlab
].
join
(
"
\n
"
)
end
def
rbac?
@rbac
end
def
service_account_resource
return
unless
rbac?
Gitlab
::
Kubernetes
::
ServiceAccount
.
new
(
service_account_name
,
namespace
).
generate
end
def
cluster_role_binding_resource
return
unless
rbac?
subjects
=
[{
kind:
'ServiceAccount'
,
name:
service_account_name
,
namespace:
namespace
}]
Gitlab
::
Kubernetes
::
ClusterRoleBinding
.
new
(
cluster_role_binding_name
,
cluster_role_name
,
subjects
).
generate
end
private
def
init_helm_command
tls_flags
=
"--tiller-tls"
\
" --tiller-tls-verify --tls-ca-cert
#{
files_dir
}
/ca.pem"
\
" --tiller-tls-cert
#{
files_dir
}
/cert.pem"
\
" --tiller-tls-key
#{
files_dir
}
/key.pem"
command
=
%w[helm init]
+
init_command_flags
command
.
shelljoin
+
" >/dev/null
\n
"
end
def
init_command_flags
tls_flags
+
optional_service_account_flag
end
def
tls_flags
[
'--tiller-tls'
,
'--tiller-tls-verify'
,
'--tls-ca-cert'
,
"
#{
files_dir
}
/ca.pem"
,
'--tiller-tls-cert'
,
"
#{
files_dir
}
/cert.pem"
,
'--tiller-tls-key'
,
"
#{
files_dir
}
/key.pem"
]
end
def
optional_service_account_flag
return
[]
unless
rbac?
[
'--service-account'
,
service_account_name
]
end
def
cluster_role_binding_name
Gitlab
::
Kubernetes
::
Helm
::
CLUSTER_ROLE_BINDING
end
"helm init
#{
tls_flags
}
>/dev/null"
def
cluster_role_name
Gitlab
::
Kubernetes
::
Helm
::
CLUSTER_ROLE
end
end
end
...
...
lib/gitlab/kubernetes/helm/install_command.rb
View file @
db535764
...
...
@@ -6,10 +6,11 @@ module Gitlab
attr_reader
:name
,
:files
,
:chart
,
:version
,
:repository
def
initialize
(
name
:,
chart
:,
files
:,
version:
nil
,
repository:
nil
)
def
initialize
(
name
:,
chart
:,
files
:,
rbac
:,
version:
nil
,
repository:
nil
)
@name
=
name
@chart
=
chart
@version
=
version
@rbac
=
rbac
@files
=
files
@repository
=
repository
end
...
...
@@ -22,6 +23,10 @@ module Gitlab
].
compact
.
join
(
"
\n
"
)
end
def
rbac?
@rbac
end
private
def
init_command
...
...
@@ -29,28 +34,51 @@ module Gitlab
end
def
repository_command
"helm repo add
#{
name
}
#{
repository
}
"
if
repository
[
'helm'
,
'repo'
,
'add'
,
name
,
repository
].
shelljoin
if
repository
end
def
script_command
init_flags
=
"--name
#{
name
}#{
optional_tls_flags
}#{
optional_version_flag
}
"
\
" --namespace
#{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
"
\
" -f /data/helm/
#{
name
}
/config/values.yaml"
command
=
[
'helm'
,
'install'
,
chart
]
+
install_command_flags
command
.
shelljoin
+
" >/dev/null
\n
"
end
def
install_command_flags
name_flag
=
[
'--name'
,
name
]
namespace_flag
=
[
'--namespace'
,
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
]
value_flag
=
[
'-f'
,
"/data/helm/
#{
name
}
/config/values.yaml"
]
"helm install
#{
chart
}
#{
init_flags
}
>/dev/null
\n
"
name_flag
+
optional_tls_flags
+
optional_version_flag
+
optional_rbac_create_flag
+
namespace_flag
+
value_flag
end
def
optional_rbac_create_flag
return
[]
unless
rbac?
# jupyterhub helm chart is using rbac.enabled
# https://github.com/jupyterhub/zero-to-jupyterhub-k8s/tree/master/jupyterhub
%w[--set rbac.create=true,rbac.enabled=true]
end
def
optional_version_flag
" --version
#{
version
}
"
if
version
return
[]
unless
version
[
'--version'
,
version
]
end
def
optional_tls_flags
return
unless
files
.
key?
(
:'ca.pem'
)
return
[]
unless
files
.
key?
(
:'ca.pem'
)
" --tls"
\
" --tls-ca-cert
#{
files_dir
}
/ca.pem"
\
" --tls-cert
#{
files_dir
}
/cert.pem"
\
" --tls-key
#{
files_dir
}
/key.pem"
[
'--tls'
,
'--tls-ca-cert'
,
"
#{
files_dir
}
/ca.pem"
,
'--tls-cert'
,
"
#{
files_dir
}
/cert.pem"
,
'--tls-key'
,
"
#{
files_dir
}
/key.pem"
]
end
end
end
...
...
lib/gitlab/kubernetes/helm/pod.rb
View file @
db535764
...
...
@@ -2,9 +2,10 @@ module Gitlab
module
Kubernetes
module
Helm
class
Pod
def
initialize
(
command
,
namespace_name
)
def
initialize
(
command
,
namespace_name
,
service_account_name:
nil
)
@command
=
command
@namespace_name
=
namespace_name
@service_account_name
=
service_account_name
end
def
generate
...
...
@@ -12,13 +13,14 @@ module Gitlab
spec
[
:volumes
]
=
volumes_specification
spec
[
:containers
][
0
][
:volumeMounts
]
=
volume_mounts_specification
spec
[
:serviceAccountName
]
=
service_account_name
if
service_account_name
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
spec:
spec
)
end
private
attr_reader
:command
,
:namespace_name
,
:
kubeclient
,
:config_map
attr_reader
:command
,
:namespace_name
,
:
service_account_name
def
container_specification
{
...
...
lib/gitlab/kubernetes/kube_client.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
require
'uri'
module
Gitlab
module
Kubernetes
# Wrapper around Kubeclient::Client to dispatch
# the right message to the client that can respond to the message.
# We must have a kubeclient for each ApiGroup as there is no
# other way to use the Kubeclient gem.
#
# See https://github.com/abonas/kubeclient/issues/348.
class
KubeClient
include
Gitlab
::
Utils
::
StrongMemoize
SUPPORTED_API_GROUPS
=
[
'api'
,
'apis/rbac.authorization.k8s.io'
,
'apis/extensions'
].
freeze
# Core API methods delegates to the core api group client
delegate
:get_pods
,
:get_secrets
,
:get_config_map
,
:get_namespace
,
:get_pod
,
:get_service
,
:get_service_account
,
:delete_pod
,
:create_config_map
,
:create_namespace
,
:create_pod
,
:create_service_account
,
:update_config_map
,
:update_service_account
,
to: :core_client
# RBAC methods delegates to the apis/rbac.authorization.k8s.io api
# group client
delegate
:create_cluster_role_binding
,
:get_cluster_role_binding
,
:update_cluster_role_binding
,
to: :rbac_client
# Deployments resource is currently on the apis/extensions api group
delegate
:get_deployments
,
to: :extensions_client
# non-entity methods that can only work with the core client
# as it uses the pods/log resource
delegate
:get_pod_log
,
:watch_pod_log
,
to: :core_client
def
initialize
(
api_prefix
,
api_groups
=
[
'api'
],
api_version
=
'v1'
,
**
kubeclient_options
)
raise
ArgumentError
unless
check_api_groups_supported?
(
api_groups
)
@api_prefix
=
api_prefix
@api_groups
=
api_groups
@api_version
=
api_version
@kubeclient_options
=
kubeclient_options
end
def
discover!
clients
.
each
(
&
:discover
)
end
def
clients
hashed_clients
.
values
end
def
core_client
hashed_clients
[
'api'
]
end
def
rbac_client
hashed_clients
[
'apis/rbac.authorization.k8s.io'
]
end
def
extensions_client
hashed_clients
[
'apis/extensions'
]
end
def
hashed_clients
strong_memoize
(
:hashed_clients
)
do
@api_groups
.
map
do
|
api_group
|
api_url
=
join_api_url
(
@api_prefix
,
api_group
)
[
api_group
,
::
Kubeclient
::
Client
.
new
(
api_url
,
@api_version
,
**
@kubeclient_options
)]
end
.
to_h
end
end
private
def
check_api_groups_supported?
(
api_groups
)
api_groups
.
all?
{
|
api_group
|
SUPPORTED_API_GROUPS
.
include?
(
api_group
)
}
end
def
join_api_url
(
api_prefix
,
api_path
)
url
=
URI
.
parse
(
api_prefix
)
prefix
=
url
.
path
.
sub
(
%r{/+
\z
}
,
''
)
url
.
path
=
[
prefix
,
api_path
].
join
(
"/"
)
url
.
to_s
end
end
end
end
lib/gitlab/kubernetes/service_account.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
module
Gitlab
module
Kubernetes
class
ServiceAccount
attr_reader
:name
,
:namespace_name
def
initialize
(
name
,
namespace_name
)
@name
=
name
@namespace_name
=
namespace_name
end
def
generate
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
)
end
private
def
metadata
{
name:
name
,
namespace:
namespace_name
}
end
end
end
end
locale/gitlab.pot
View file @
db535764
...
...
@@ -1646,6 +1646,9 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
msgstr ""
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
...
...
@@ -1844,6 +1847,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
msgid "ClusterIntegration|RBAC-enabled cluster (experimental)"
msgstr ""
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
...
...
@@ -1922,6 +1928,9 @@ msgstr ""
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes Cluster"
msgstr ""
...
...
spec/controllers/projects/clusters_controller_spec.rb
View file @
db535764
...
...
@@ -274,11 +274,43 @@ describe Projects::ClustersController do
context
'when creates a cluster'
do
it
'creates a new cluster'
do
expect
(
ClusterProvisionWorker
).
to
receive
(
:perform_async
)
expect
{
go
}.
to
change
{
Clusters
::
Cluster
.
count
}
.
and
change
{
Clusters
::
Platforms
::
Kubernetes
.
count
}
expect
(
response
).
to
redirect_to
(
project_cluster_path
(
project
,
project
.
clusters
.
first
))
expect
(
project
.
clusters
.
first
).
to
be_user
expect
(
project
.
clusters
.
first
).
to
be_kubernetes
end
end
context
'when creates a RBAC-enabled cluster'
do
let
(
:params
)
do
{
cluster:
{
name:
'new-cluster'
,
platform_kubernetes_attributes:
{
api_url:
'http://my-url'
,
token:
'test'
,
namespace:
'aaa'
,
authorization_type:
'rbac'
}
}
}
end
it
'creates a new cluster'
do
expect
(
ClusterProvisionWorker
).
to
receive
(
:perform_async
)
expect
{
go
}.
to
change
{
Clusters
::
Cluster
.
count
}
.
and
change
{
Clusters
::
Platforms
::
Kubernetes
.
count
}
expect
(
response
).
to
redirect_to
(
project_cluster_path
(
project
,
project
.
clusters
.
first
))
expect
(
project
.
clusters
.
first
).
to
be_user
expect
(
project
.
clusters
.
first
).
to
be_kubernetes
expect
(
project
.
clusters
.
first
).
to
be_platform_kubernetes_rbac
end
end
end
...
...
spec/factories/clusters/platforms/kubernetes.rb
View file @
db535764
...
...
@@ -16,5 +16,9 @@ FactoryBot.define do
platform_kubernetes
.
ca_cert
=
File
.
read
(
pem_file
)
end
end
trait
:rbac_enabled
do
authorization_type
:rbac
end
end
end
spec/features/projects/clusters/user_spec.rb
View file @
db535764
...
...
@@ -38,6 +38,28 @@ describe 'User Cluster', :js do
end
end
context
'rbac_clusters feature flag is enabled'
do
before
do
stub_feature_flags
(
rbac_clusters:
true
)
fill_in
'cluster_name'
,
with:
'dev-cluster'
fill_in
'cluster_platform_kubernetes_attributes_api_url'
,
with:
'http://example.com'
fill_in
'cluster_platform_kubernetes_attributes_token'
,
with:
'my-token'
check
'cluster_platform_kubernetes_attributes_authorization_type'
click_button
'Add Kubernetes cluster'
end
it
'user sees a cluster details page'
do
expect
(
page
).
to
have_content
(
'Kubernetes cluster integration'
)
expect
(
page
.
find_field
(
'cluster[name]'
).
value
).
to
eq
(
'dev-cluster'
)
expect
(
page
.
find_field
(
'cluster[platform_kubernetes_attributes][api_url]'
).
value
)
.
to
have_content
(
'http://example.com'
)
expect
(
page
.
find_field
(
'cluster[platform_kubernetes_attributes][token]'
).
value
)
.
to
have_content
(
'my-token'
)
expect
(
page
.
find_field
(
'cluster[platform_kubernetes_attributes][authorization_type]'
,
disabled:
true
)).
to
be_checked
end
end
context
'when user filled form with invalid parameters'
do
before
do
click_button
'Add Kubernetes cluster'
...
...
spec/lib/gitlab/kubernetes/cluster_role_binding_spec.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Kubernetes
::
ClusterRoleBinding
do
let
(
:cluster_role_binding
)
{
described_class
.
new
(
name
,
cluster_role_name
,
subjects
)
}
let
(
:name
)
{
'cluster-role-binding-name'
}
let
(
:cluster_role_name
)
{
'cluster-admin'
}
let
(
:subjects
)
{
[{
kind:
'ServiceAccount'
,
name:
'sa'
,
namespace:
'ns'
}]
}
describe
'#generate'
do
let
(
:role_ref
)
do
{
apiGroup:
'rbac.authorization.k8s.io'
,
kind:
'ClusterRole'
,
name:
cluster_role_name
}
end
let
(
:resource
)
do
::
Kubeclient
::
Resource
.
new
(
metadata:
{
name:
name
},
roleRef:
role_ref
,
subjects:
subjects
)
end
subject
{
cluster_role_binding
.
generate
}
it
'should build a Kubeclient Resource'
do
is_expected
.
to
eq
(
resource
)
end
end
end
spec/lib/gitlab/kubernetes/helm/api_spec.rb
View file @
db535764
...
...
@@ -5,9 +5,18 @@ describe Gitlab::Kubernetes::Helm::Api do
let
(
:helm
)
{
described_class
.
new
(
client
)
}
let
(
:gitlab_namespace
)
{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
let
(
:namespace
)
{
Gitlab
::
Kubernetes
::
Namespace
.
new
(
gitlab_namespace
,
client
)
}
let
(
:application
)
{
create
(
:clusters_applications_prometheus
)
}
let
(
:command
)
{
application
.
install_command
}
let
(
:application_name
)
{
'app-name'
}
let
(
:rbac
)
{
false
}
let
(
:files
)
{
{}
}
let
(
:command
)
do
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name:
application_name
,
chart:
'chart-name'
,
rbac:
rbac
,
files:
files
)
end
subject
{
helm
}
...
...
@@ -28,6 +37,8 @@ describe Gitlab::Kubernetes::Helm::Api do
before
do
allow
(
client
).
to
receive
(
:create_pod
).
and_return
(
nil
)
allow
(
client
).
to
receive
(
:create_config_map
).
and_return
(
nil
)
allow
(
client
).
to
receive
(
:create_service_account
).
and_return
(
nil
)
allow
(
client
).
to
receive
(
:create_cluster_role_binding
).
and_return
(
nil
)
allow
(
namespace
).
to
receive
(
:ensure_exists!
).
once
end
...
...
@@ -39,7 +50,7 @@ describe Gitlab::Kubernetes::Helm::Api do
end
context
'with a ConfigMap'
do
let
(
:resource
)
{
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
application
.
name
,
application
.
files
).
generate
}
let
(
:resource
)
{
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
application
_name
,
files
).
generate
}
it
'creates a ConfigMap on kubeclient'
do
expect
(
client
).
to
receive
(
:create_config_map
).
with
(
resource
).
once
...
...
@@ -47,6 +58,96 @@ describe Gitlab::Kubernetes::Helm::Api do
subject
.
install
(
command
)
end
end
context
'without a service account'
do
it
'does not create a service account on kubeclient'
do
expect
(
client
).
not_to
receive
(
:create_service_account
)
expect
(
client
).
not_to
receive
(
:create_cluster_role_binding
)
subject
.
install
(
command
)
end
end
context
'with a service account'
do
let
(
:command
)
{
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
.
new
(
name:
application_name
,
files:
files
,
rbac:
rbac
)
}
context
'rbac-enabled cluster'
do
let
(
:rbac
)
{
true
}
let
(
:service_account_resource
)
do
Kubeclient
::
Resource
.
new
(
metadata:
{
name:
'tiller'
,
namespace:
'gitlab-managed-apps'
})
end
let
(
:cluster_role_binding_resource
)
do
Kubeclient
::
Resource
.
new
(
metadata:
{
name:
'tiller-admin'
},
roleRef:
{
apiGroup:
'rbac.authorization.k8s.io'
,
kind:
'ClusterRole'
,
name:
'cluster-admin'
},
subjects:
[{
kind:
'ServiceAccount'
,
name:
'tiller'
,
namespace:
'gitlab-managed-apps'
}]
)
end
context
'service account and cluster role binding does not exist'
do
before
do
expect
(
client
).
to
receive
(
'get_service_account'
).
with
(
'tiller'
,
'gitlab-managed-apps'
).
and_raise
(
Kubeclient
::
HttpError
.
new
(
404
,
'Not found'
,
nil
))
expect
(
client
).
to
receive
(
'get_cluster_role_binding'
).
with
(
'tiller-admin'
).
and_raise
(
Kubeclient
::
HttpError
.
new
(
404
,
'Not found'
,
nil
))
end
it
'creates a service account, followed the cluster role binding on kubeclient'
do
expect
(
client
).
to
receive
(
:create_service_account
).
with
(
service_account_resource
).
once
.
ordered
expect
(
client
).
to
receive
(
:create_cluster_role_binding
).
with
(
cluster_role_binding_resource
).
once
.
ordered
subject
.
install
(
command
)
end
end
context
'service account already exists'
do
before
do
expect
(
client
).
to
receive
(
'get_service_account'
).
with
(
'tiller'
,
'gitlab-managed-apps'
).
and_return
(
service_account_resource
)
expect
(
client
).
to
receive
(
'get_cluster_role_binding'
).
with
(
'tiller-admin'
).
and_raise
(
Kubeclient
::
HttpError
.
new
(
404
,
'Not found'
,
nil
))
end
it
'updates the service account, followed by creating the cluster role binding'
do
expect
(
client
).
to
receive
(
:update_service_account
).
with
(
service_account_resource
).
once
.
ordered
expect
(
client
).
to
receive
(
:create_cluster_role_binding
).
with
(
cluster_role_binding_resource
).
once
.
ordered
subject
.
install
(
command
)
end
end
context
'service account and cluster role binding already exists'
do
before
do
expect
(
client
).
to
receive
(
'get_service_account'
).
with
(
'tiller'
,
'gitlab-managed-apps'
).
and_return
(
service_account_resource
)
expect
(
client
).
to
receive
(
'get_cluster_role_binding'
).
with
(
'tiller-admin'
).
and_return
(
cluster_role_binding_resource
)
end
it
'updates the service account, followed by creating the cluster role binding'
do
expect
(
client
).
to
receive
(
:update_service_account
).
with
(
service_account_resource
).
once
.
ordered
expect
(
client
).
to
receive
(
:update_cluster_role_binding
).
with
(
cluster_role_binding_resource
).
once
.
ordered
subject
.
install
(
command
)
end
end
context
'a non-404 error is thrown'
do
before
do
expect
(
client
).
to
receive
(
'get_service_account'
).
with
(
'tiller'
,
'gitlab-managed-apps'
).
and_raise
(
Kubeclient
::
HttpError
.
new
(
401
,
'Unauthorized'
,
nil
))
end
it
'raises an error'
do
expect
{
subject
.
install
(
command
)
}.
to
raise_error
(
Kubeclient
::
HttpError
)
end
end
end
context
'legacy abac cluster'
do
it
'does not create a service account on kubeclient'
do
expect
(
client
).
not_to
receive
(
:create_service_account
)
expect
(
client
).
not_to
receive
(
:create_cluster_role_binding
)
subject
.
install
(
command
)
end
end
end
end
describe
'#status'
do
...
...
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
View file @
db535764
...
...
@@ -2,14 +2,24 @@ require 'spec_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
BaseCommand
do
let
(
:application
)
{
create
(
:clusters_applications_helm
)
}
let
(
:rbac
)
{
false
}
let
(
:test_class
)
do
Class
.
new
do
include
Gitlab
::
Kubernetes
::
Helm
::
BaseCommand
def
initialize
(
rbac
)
@rbac
=
rbac
end
def
name
"test-class-name"
end
def
rbac?
@rbac
end
def
files
{
some:
'value'
...
...
@@ -19,7 +29,7 @@ describe Gitlab::Kubernetes::Helm::BaseCommand do
end
let
(
:base_command
)
do
test_class
.
new
test_class
.
new
(
rbac
)
end
subject
{
base_command
}
...
...
@@ -34,6 +44,14 @@ describe Gitlab::Kubernetes::Helm::BaseCommand do
it
'should returns a kubeclient resoure with pod content for application'
do
is_expected
.
to
be_an_instance_of
::
Kubeclient
::
Resource
end
context
'when rbac is true'
do
let
(
:rbac
)
{
true
}
it
'also returns a kubeclient resource'
do
is_expected
.
to
be_an_instance_of
::
Kubeclient
::
Resource
end
end
end
describe
'#pod_name'
do
...
...
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
View file @
db535764
...
...
@@ -2,9 +2,135 @@ require 'spec_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
do
let
(
:application
)
{
create
(
:clusters_applications_helm
)
}
let
(
:commands
)
{
'helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem >/dev/null'
}
let
(
:rbac
)
{
false
}
let
(
:files
)
{
{}
}
let
(
:init_command
)
{
described_class
.
new
(
name:
application
.
name
,
files:
files
,
rbac:
rbac
)
}
subject
{
described_class
.
new
(
name:
application
.
name
,
files:
{})
}
let
(
:commands
)
do
<<~
EOS
helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem >/dev/null
EOS
end
subject
{
init_command
}
it_behaves_like
'helm commands'
context
'on a rbac-enabled cluster'
do
let
(
:rbac
)
{
true
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller >/dev/null
EOS
end
end
end
describe
'#rbac?'
do
subject
{
init_command
.
rbac?
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
{
is_expected
.
to
be_truthy
}
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#config_map_resource'
do
let
(
:metadata
)
do
{
name:
'values-content-configuration-helm'
,
namespace:
'gitlab-managed-apps'
,
labels:
{
name:
'values-content-configuration-helm'
}
}
end
let
(
:resource
)
{
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
files
)
}
subject
{
init_command
.
config_map_resource
}
it
'returns a KubeClient resource with config map content for the application'
do
is_expected
.
to
eq
(
resource
)
end
end
describe
'#pod_resource'
do
subject
{
init_command
.
pod_resource
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
'generates a pod that uses the tiller serviceAccountName'
do
expect
(
subject
.
spec
.
serviceAccountName
).
to
eq
(
'tiller'
)
end
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
'generates a pod that uses the default serviceAccountName'
do
expect
(
subject
.
spec
.
serviceAcccountName
).
to
be_nil
end
end
end
describe
'#service_account_resource'
do
let
(
:resource
)
do
Kubeclient
::
Resource
.
new
(
metadata:
{
name:
'tiller'
,
namespace:
'gitlab-managed-apps'
})
end
subject
{
init_command
.
service_account_resource
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
'generates a Kubeclient resource for the tiller ServiceAccount'
do
is_expected
.
to
eq
(
resource
)
end
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
'generates nothing'
do
is_expected
.
to
be_nil
end
end
end
describe
'#cluster_role_binding_resource'
do
let
(
:resource
)
do
Kubeclient
::
Resource
.
new
(
metadata:
{
name:
'tiller-admin'
},
roleRef:
{
apiGroup:
'rbac.authorization.k8s.io'
,
kind:
'ClusterRole'
,
name:
'cluster-admin'
},
subjects:
[{
kind:
'ServiceAccount'
,
name:
'tiller'
,
namespace:
'gitlab-managed-apps'
}]
)
end
subject
{
init_command
.
cluster_role_binding_resource
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
'generates a Kubeclient resource for the ClusterRoleBinding for tiller'
do
is_expected
.
to
eq
(
resource
)
end
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
'generates nothing'
do
is_expected
.
to
be_nil
end
end
end
end
spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
View file @
db535764
...
...
@@ -3,14 +3,17 @@ require 'rails_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
do
let
(
:files
)
{
{
'ca.pem'
:
'some file content'
}
}
let
(
:repository
)
{
'https://repository.example.com'
}
let
(
:rbac
)
{
false
}
let
(
:version
)
{
'1.2.3'
}
let
(
:install_command
)
do
described_class
.
new
(
name:
'app-name'
,
chart:
'chart-name'
,
rbac:
rbac
,
files:
files
,
version:
version
,
repository:
repository
version:
version
,
repository:
repository
)
end
...
...
@@ -21,19 +24,76 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
<<~
EOS
helm init --client-only >/dev/null
helm repo add app-name https://repository.example.com
helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml >/dev/null
#{
helm_install_comand
}
EOS
end
let
(
:helm_install_comand
)
do
<<~
EOS
.
squish
helm install chart-name
--name app-name
--tls
--tls-ca-cert /data/helm/app-name/config/ca.pem
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
--version 1.2.3
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml >/dev/null
EOS
end
end
context
'when rbac is true'
do
let
(
:rbac
)
{
true
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm repo add app-name https://repository.example.com
#{
helm_install_command
}
EOS
end
let
(
:helm_install_command
)
do
<<~
EOS
.
squish
helm install chart-name
--name app-name
--tls
--tls-ca-cert /data/helm/app-name/config/ca.pem
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
--version 1.2.3
--set rbac.create
\\
=true,rbac.enabled
\\
=true
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml >/dev/null
EOS
end
end
end
context
'when there is no repository'
do
let
(
:repository
)
{
nil
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml >/dev/null
helm init --client-only >/dev/null
#{
helm_install_command
}
EOS
end
let
(
:helm_install_command
)
do
<<~
EOS
.
squish
helm install chart-name
--name app-name
--tls
--tls-ca-cert /data/helm/app-name/config/ca.pem
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
--version 1.2.3
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml >/dev/null
EOS
end
end
...
...
@@ -45,9 +105,19 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm repo add app-name https://repository.example.com
helm install chart-name --name app-name --version 1.2.3 --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml >/dev/null
helm init --client-only >/dev/null
helm repo add app-name https://repository.example.com
#{
helm_install_command
}
EOS
end
let
(
:helm_install_command
)
do
<<~
EOS
.
squish
helm install chart-name
--name app-name
--version 1.2.3
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml >/dev/null
EOS
end
end
...
...
@@ -59,14 +129,63 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm repo add app-name https://repository.example.com
helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml >/dev/null
helm init --client-only >/dev/null
helm repo add app-name https://repository.example.com
#{
helm_install_command
}
EOS
end
let
(
:helm_install_command
)
do
<<~
EOS
.
squish
helm install chart-name
--name app-name
--tls
--tls-ca-cert /data/helm/app-name/config/ca.pem
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml >/dev/null
EOS
end
end
end
describe
'#rbac?'
do
subject
{
install_command
.
rbac?
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
{
is_expected
.
to
be_truthy
}
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#pod_resource'
do
subject
{
install_command
.
pod_resource
}
context
'rbac is enabled'
do
let
(
:rbac
)
{
true
}
it
'generates a pod that uses the tiller serviceAccountName'
do
expect
(
subject
.
spec
.
serviceAccountName
).
to
eq
(
'tiller'
)
end
end
context
'rbac is not enabled'
do
let
(
:rbac
)
{
false
}
it
'generates a pod that uses the default serviceAccountName'
do
expect
(
subject
.
spec
.
serviceAcccountName
).
to
be_nil
end
end
end
describe
'#config_map_resource'
do
let
(
:metadata
)
do
{
...
...
@@ -84,4 +203,20 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
is_expected
.
to
eq
(
resource
)
end
end
describe
'#service_account_resource'
do
subject
{
install_command
.
service_account_resource
}
it
'returns nothing'
do
is_expected
.
to
be_nil
end
end
describe
'#cluster_role_binding_resource'
do
subject
{
install_command
.
cluster_role_binding_resource
}
it
'returns nothing'
do
is_expected
.
to
be_nil
end
end
end
spec/lib/gitlab/kubernetes/helm/pod_spec.rb
View file @
db535764
...
...
@@ -5,8 +5,9 @@ describe Gitlab::Kubernetes::Helm::Pod do
let
(
:app
)
{
create
(
:clusters_applications_prometheus
)
}
let
(
:command
)
{
app
.
install_command
}
let
(
:namespace
)
{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
let
(
:service_account_name
)
{
nil
}
subject
{
described_class
.
new
(
command
,
namespace
)
}
subject
{
described_class
.
new
(
command
,
namespace
,
service_account_name:
service_account_name
)
}
context
'with a command'
do
it
'should generate a Kubeclient::Resource'
do
...
...
@@ -58,6 +59,20 @@ describe Gitlab::Kubernetes::Helm::Pod do
expect
(
volume
.
configMap
[
'items'
].
first
[
'key'
]).
to
eq
(
:'values.yaml'
)
expect
(
volume
.
configMap
[
'items'
].
first
[
'path'
]).
to
eq
(
:'values.yaml'
)
end
it
'should have no serviceAccountName'
do
spec
=
subject
.
generate
.
spec
expect
(
spec
.
serviceAccountName
).
to
be_nil
end
context
'with a service_account_name'
do
let
(
:service_account_name
)
{
'sa'
}
it
'should use the serviceAccountName provided'
do
spec
=
subject
.
generate
.
spec
expect
(
spec
.
serviceAccountName
).
to
eq
(
service_account_name
)
end
end
end
end
end
spec/lib/gitlab/kubernetes/kube_client_spec.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Kubernetes
::
KubeClient
do
include
KubernetesHelpers
let
(
:api_url
)
{
'https://kubernetes.example.com/prefix'
}
let
(
:api_groups
)
{
[
'api'
,
'apis/rbac.authorization.k8s.io'
]
}
let
(
:api_version
)
{
'v1'
}
let
(
:kubeclient_options
)
{
{
auth_options:
{
bearer_token:
'xyz'
}
}
}
let
(
:client
)
{
described_class
.
new
(
api_url
,
api_groups
,
api_version
,
kubeclient_options
)
}
before
do
stub_kubeclient_discover
(
api_url
)
end
describe
'#hashed_clients'
do
subject
{
client
.
hashed_clients
}
it
'has keys from api groups'
do
expect
(
subject
.
keys
).
to
match_array
api_groups
end
it
'has values of Kubeclient::Client'
do
expect
(
subject
.
values
).
to
all
(
be_an_instance_of
Kubeclient
::
Client
)
end
end
describe
'#clients'
do
subject
{
client
.
clients
}
it
'is not empty'
do
is_expected
.
to
be_present
end
it
'is an array of Kubeclient::Client objects'
do
is_expected
.
to
all
(
be_an_instance_of
Kubeclient
::
Client
)
end
it
'has each API group url'
do
expected_urls
=
api_groups
.
map
{
|
group
|
"
#{
api_url
}
/
#{
group
}
"
}
expect
(
subject
.
map
(
&
:api_endpoint
).
map
(
&
:to_s
)).
to
match_array
(
expected_urls
)
end
it
'has the kubeclient options'
do
subject
.
each
do
|
client
|
expect
(
client
.
auth_options
).
to
eq
({
bearer_token:
'xyz'
})
end
end
it
'has the api_version'
do
subject
.
each
do
|
client
|
expect
(
client
.
instance_variable_get
(
:@api_version
)).
to
eq
(
'v1'
)
end
end
end
describe
'#core_client'
do
subject
{
client
.
core_client
}
it
'is a Kubeclient::Client'
do
is_expected
.
to
be_an_instance_of
Kubeclient
::
Client
end
it
'has the core API endpoint'
do
expect
(
subject
.
api_endpoint
.
to_s
).
to
match
(
%r{
\/
api
\Z
}
)
end
end
describe
'#rbac_client'
do
subject
{
client
.
rbac_client
}
it
'is a Kubeclient::Client'
do
is_expected
.
to
be_an_instance_of
Kubeclient
::
Client
end
it
'has the RBAC API group endpoint'
do
expect
(
subject
.
api_endpoint
.
to_s
).
to
match
(
%r{
\/
apis
\/
rbac.authorization.k8s.io
\Z
}
)
end
end
describe
'#extensions_client'
do
subject
{
client
.
extensions_client
}
let
(
:api_groups
)
{
[
'apis/extensions'
]
}
it
'is a Kubeclient::Client'
do
is_expected
.
to
be_an_instance_of
Kubeclient
::
Client
end
it
'has the extensions API group endpoint'
do
expect
(
subject
.
api_endpoint
.
to_s
).
to
match
(
%r{
\/
apis
\/
extensions
\Z
}
)
end
end
describe
'#discover!'
do
it
'makes a discovery request for each API group'
do
client
.
discover!
api_groups
.
each
do
|
api_group
|
discovery_url
=
api_url
+
'/'
+
api_group
+
'/v1'
expect
(
WebMock
).
to
have_requested
(
:get
,
discovery_url
).
once
end
end
end
describe
'core API'
do
let
(
:core_client
)
{
client
.
core_client
}
[
:get_pods
,
:get_secrets
,
:get_config_map
,
:get_pod
,
:get_namespace
,
:get_service
,
:get_service_account
,
:delete_pod
,
:create_config_map
,
:create_namespace
,
:create_pod
,
:create_service_account
,
:update_config_map
,
:update_service_account
].
each
do
|
method
|
describe
"#
#{
method
}
"
do
it
'delegates to the core client'
do
expect
(
client
).
to
delegate_method
(
method
).
to
(
:core_client
)
end
it
'responds to the method'
do
expect
(
client
).
to
respond_to
method
end
end
end
end
describe
'rbac API group'
do
let
(
:rbac_client
)
{
client
.
rbac_client
}
[
:create_cluster_role_binding
,
:get_cluster_role_binding
,
:update_cluster_role_binding
].
each
do
|
method
|
describe
"#
#{
method
}
"
do
it
'delegates to the rbac client'
do
expect
(
client
).
to
delegate_method
(
method
).
to
(
:rbac_client
)
end
it
'responds to the method'
do
expect
(
client
).
to
respond_to
method
end
context
'no rbac client'
do
let
(
:api_groups
)
{
[
'api'
]
}
it
'throws an error'
do
expect
{
client
.
public_send
(
method
)
}.
to
raise_error
(
Module
::
DelegationError
)
end
end
end
end
end
describe
'extensions API group'
do
let
(
:api_groups
)
{
[
'apis/extensions'
]
}
let
(
:api_version
)
{
'v1beta1'
}
let
(
:extensions_client
)
{
client
.
extensions_client
}
describe
'#get_deployments'
do
it
'delegates to the extensions client'
do
expect
(
client
).
to
delegate_method
(
:get_deployments
).
to
(
:extensions_client
)
end
it
'responds to the method'
do
expect
(
client
).
to
respond_to
:get_deployments
end
context
'no extensions client'
do
let
(
:api_groups
)
{
[
'api'
]
}
let
(
:api_version
)
{
'v1'
}
it
'throws an error'
do
expect
{
client
.
get_deployments
}.
to
raise_error
(
Module
::
DelegationError
)
end
end
end
end
describe
'non-entity methods'
do
it
'does not proxy for non-entity methods'
do
expect
(
client
.
clients
.
first
).
to
respond_to
:proxy_url
expect
(
client
).
not_to
respond_to
:proxy_url
end
it
'throws an error'
do
expect
{
client
.
proxy_url
}.
to
raise_error
(
NoMethodError
)
end
end
describe
'#get_pod_log'
do
let
(
:core_client
)
{
client
.
core_client
}
it
'is delegated to the core client'
do
expect
(
client
).
to
delegate_method
(
:get_pod_log
).
to
(
:core_client
)
end
context
'when no core client'
do
let
(
:api_groups
)
{
[
'apis/extensions'
]
}
it
'throws an error'
do
expect
{
client
.
get_pod_log
(
'pod-name'
)
}.
to
raise_error
(
Module
::
DelegationError
)
end
end
end
describe
'#watch_pod_log'
do
let
(
:core_client
)
{
client
.
core_client
}
it
'is delegated to the core client'
do
expect
(
client
).
to
delegate_method
(
:watch_pod_log
).
to
(
:core_client
)
end
context
'when no core client'
do
let
(
:api_groups
)
{
[
'apis/extensions'
]
}
it
'throws an error'
do
expect
{
client
.
watch_pod_log
(
'pod-name'
)
}.
to
raise_error
(
Module
::
DelegationError
)
end
end
end
describe
'methods that do not exist on any client'
do
it
'throws an error'
do
expect
{
client
.
non_existent_method
}.
to
raise_error
(
NoMethodError
)
end
it
'returns false for respond_to'
do
expect
(
client
.
respond_to?
(
:non_existent_method
)).
to
be_falsey
end
end
end
spec/lib/gitlab/kubernetes/service_account_spec.rb
0 → 100644
View file @
db535764
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Kubernetes
::
ServiceAccount
do
let
(
:name
)
{
'a_service_account'
}
let
(
:namespace_name
)
{
'a_namespace'
}
let
(
:service_account
)
{
described_class
.
new
(
name
,
namespace_name
)
}
it
{
expect
(
service_account
.
name
).
to
eq
(
name
)
}
it
{
expect
(
service_account
.
namespace_name
).
to
eq
(
namespace_name
)
}
describe
'#generate'
do
let
(
:resource
)
do
::
Kubeclient
::
Resource
.
new
(
metadata:
{
name:
name
,
namespace:
namespace_name
})
end
subject
{
service_account
.
generate
}
it
'should build a Kubeclient Resource'
do
is_expected
.
to
eq
(
resource
)
end
end
end
spec/models/clusters/applications/helm_spec.rb
View file @
db535764
...
...
@@ -47,5 +47,19 @@ describe Clusters::Applications::Helm do
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
.
files
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
>
999
.
years
.
from_now
end
describe
'rbac'
do
context
'non rbac cluster'
do
it
{
expect
(
subject
).
not_to
be_rbac
}
end
context
'rbac cluster'
do
before
do
helm
.
cluster
.
platform_kubernetes
.
rbac!
end
it
{
expect
(
subject
).
to
be_rbac
}
end
end
end
end
spec/models/clusters/applications/ingress_spec.rb
View file @
db535764
...
...
@@ -88,9 +88,18 @@ describe Clusters::Applications::Ingress do
expect
(
subject
.
name
).
to
eq
(
'ingress'
)
expect
(
subject
.
chart
).
to
eq
(
'stable/nginx-ingress'
)
expect
(
subject
.
version
).
to
eq
(
'0.23.0'
)
expect
(
subject
).
not_to
be_rbac
expect
(
subject
.
files
).
to
eq
(
ingress
.
files
)
end
context
'on a rbac enabled cluster'
do
before
do
ingress
.
cluster
.
platform_kubernetes
.
rbac!
end
it
{
is_expected
.
to
be_rbac
}
end
context
'application failed to install previously'
do
let
(
:ingress
)
{
create
(
:clusters_applications_ingress
,
:errored
,
version:
'nginx'
)
}
...
...
spec/models/clusters/applications/jupyter_spec.rb
View file @
db535764
...
...
@@ -51,10 +51,19 @@ describe Clusters::Applications::Jupyter do
expect
(
subject
.
name
).
to
eq
(
'jupyter'
)
expect
(
subject
.
chart
).
to
eq
(
'jupyter/jupyterhub'
)
expect
(
subject
.
version
).
to
eq
(
'v0.6'
)
expect
(
subject
).
not_to
be_rbac
expect
(
subject
.
repository
).
to
eq
(
'https://jupyterhub.github.io/helm-chart/'
)
expect
(
subject
.
files
).
to
eq
(
jupyter
.
files
)
end
context
'on a rbac enabled cluster'
do
before
do
jupyter
.
cluster
.
platform_kubernetes
.
rbac!
end
it
{
is_expected
.
to
be_rbac
}
end
context
'application failed to install previously'
do
let
(
:jupyter
)
{
create
(
:clusters_applications_jupyter
,
:errored
,
version:
'0.0.1'
)
}
...
...
spec/models/clusters/applications/prometheus_spec.rb
View file @
db535764
require
'rails_helper'
describe
Clusters
::
Applications
::
Prometheus
do
include
KubernetesHelpers
include_examples
'cluster application core specs'
,
:clusters_applications_prometheus
include_examples
'cluster application status specs'
,
:cluster_application_prometheus
...
...
@@ -107,26 +109,14 @@ describe Clusters::Applications::Prometheus do
end
context
'cluster has kubeclient'
do
let
(
:kubernetes_url
)
{
'http://example.com'
}
let
(
:k8s_discover_response
)
do
{
resources:
[
{
name:
'service'
,
kind:
'Service'
}
]
}
end
let
(
:kube_client
)
{
Kubeclient
::
Client
.
new
(
kubernetes_url
)
}
let
(
:kubernetes_url
)
{
subject
.
cluster
.
platform_kubernetes
.
api_url
}
let
(
:kube_client
)
{
subject
.
cluster
.
kubeclient
.
core_client
}
let
(
:cluster
)
{
create
(
:cluster
)
}
subject
{
create
(
:clusters_applications_prometheus
,
cluster:
cluster
)
}
subject
{
create
(
:clusters_applications_prometheus
)
}
before
do
allow
(
kube_client
.
rest_client
).
to
receive
(
:get
).
and_return
(
k8s_discover_response
.
to_json
)
allow
(
subject
.
cluster
).
to
receive
(
:kubeclient
).
and_return
(
kube_client
)
subject
.
cluster
.
platform_kubernetes
.
namespace
=
'a-namespace'
stub_kubeclient_discover
(
subject
.
cluster
.
platform_kubernetes
.
api_url
)
end
it
'creates proxy prometheus rest client'
do
...
...
@@ -134,7 +124,7 @@ describe Clusters::Applications::Prometheus do
end
it
'creates proper url'
do
expect
(
subject
.
prometheus_client
.
url
).
to
eq
(
'http://example.com/api/v1/namespaces/gitlab-managed-apps/service/prometheus-prometheus-server:80/proxy'
)
expect
(
subject
.
prometheus_client
.
url
).
to
eq
(
"
#{
kubernetes_url
}
/api/v1/namespaces/gitlab-managed-apps/services/prometheus-prometheus-server:80/proxy"
)
end
it
'copies options and headers from kube client to proxy client'
do
...
...
@@ -164,9 +154,18 @@ describe Clusters::Applications::Prometheus do
expect
(
subject
.
name
).
to
eq
(
'prometheus'
)
expect
(
subject
.
chart
).
to
eq
(
'stable/prometheus'
)
expect
(
subject
.
version
).
to
eq
(
'6.7.3'
)
expect
(
subject
).
not_to
be_rbac
expect
(
subject
.
files
).
to
eq
(
prometheus
.
files
)
end
context
'on a rbac enabled cluster'
do
before
do
prometheus
.
cluster
.
platform_kubernetes
.
rbac!
end
it
{
is_expected
.
to
be_rbac
}
end
context
'application failed to install previously'
do
let
(
:prometheus
)
{
create
(
:clusters_applications_prometheus
,
:errored
,
version:
'2.0.0'
)
}
...
...
spec/models/clusters/applications/runner_spec.rb
View file @
db535764
...
...
@@ -46,10 +46,19 @@ describe Clusters::Applications::Runner do
expect
(
subject
.
name
).
to
eq
(
'runner'
)
expect
(
subject
.
chart
).
to
eq
(
'runner/gitlab-runner'
)
expect
(
subject
.
version
).
to
eq
(
'0.1.31'
)
expect
(
subject
).
not_to
be_rbac
expect
(
subject
.
repository
).
to
eq
(
'https://charts.gitlab.io'
)
expect
(
subject
.
files
).
to
eq
(
gitlab_runner
.
files
)
end
context
'on a rbac enabled cluster'
do
before
do
gitlab_runner
.
cluster
.
platform_kubernetes
.
rbac!
end
it
{
is_expected
.
to
be_rbac
}
end
context
'application failed to install previously'
do
let
(
:gitlab_runner
)
{
create
(
:clusters_applications_runner
,
:errored
,
runner:
ci_runner
,
version:
'0.1.13'
)
}
...
...
spec/models/clusters/cluster_spec.rb
View file @
db535764
...
...
@@ -13,6 +13,10 @@ describe Clusters::Cluster do
it
{
is_expected
.
to
delegate_method
(
:status_reason
).
to
(
:provider
)
}
it
{
is_expected
.
to
delegate_method
(
:status_name
).
to
(
:provider
)
}
it
{
is_expected
.
to
delegate_method
(
:on_creation?
).
to
(
:provider
)
}
it
{
is_expected
.
to
delegate_method
(
:active?
).
to
(
:platform_kubernetes
).
with_prefix
}
it
{
is_expected
.
to
delegate_method
(
:rbac?
).
to
(
:platform_kubernetes
).
with_prefix
}
it
{
is_expected
.
to
delegate_method
(
:installed?
).
to
(
:application_helm
).
with_prefix
}
it
{
is_expected
.
to
delegate_method
(
:installed?
).
to
(
:application_ingress
).
with_prefix
}
it
{
is_expected
.
to
respond_to
:project
}
describe
'.enabled'
do
...
...
spec/models/clusters/platforms/kubernetes_spec.rb
View file @
db535764
...
...
@@ -92,6 +92,30 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
end
describe
'#kubeclient'
do
subject
{
kubernetes
.
kubeclient
}
let
(
:kubernetes
)
{
build
(
:cluster_platform_kubernetes
,
:configured
,
namespace:
'a-namespace'
)
}
it
{
is_expected
.
to
be_an_instance_of
(
Gitlab
::
Kubernetes
::
KubeClient
)
}
end
describe
'#rbac?'
do
subject
{
kubernetes
.
rbac?
}
let
(
:kubernetes
)
{
build
(
:cluster_platform_kubernetes
,
:configured
)
}
context
'when authorization type is rbac'
do
let
(
:kubernetes
)
{
build
(
:cluster_platform_kubernetes
,
:rbac_enabled
,
:configured
)
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when authorization type is nil'
do
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#actual_namespace'
do
subject
{
kubernetes
.
actual_namespace
}
...
...
spec/support/helpers/kubernetes_helpers.rb
View file @
db535764
...
...
@@ -20,6 +20,7 @@ module KubernetesHelpers
def
stub_kubeclient_discover
(
api_url
)
WebMock
.
stub_request
(
:get
,
api_url
+
'/api/v1'
).
to_return
(
kube_response
(
kube_v1_discovery_body
))
WebMock
.
stub_request
(
:get
,
api_url
+
'/apis/extensions/v1beta1'
).
to_return
(
kube_response
(
kube_v1beta1_discovery_body
))
WebMock
.
stub_request
(
:get
,
api_url
+
'/apis/rbac.authorization.k8s.io/v1'
).
to_return
(
kube_response
(
kube_v1_rbac_authorization_discovery_body
))
end
def
stub_kubeclient_pods
(
response
=
nil
)
...
...
@@ -77,7 +78,8 @@ module KubernetesHelpers
"resources"
=>
[
{
"name"
=>
"pods"
,
"namespaced"
=>
true
,
"kind"
=>
"Pod"
},
{
"name"
=>
"deployments"
,
"namespaced"
=>
true
,
"kind"
=>
"Deployment"
},
{
"name"
=>
"secrets"
,
"namespaced"
=>
true
,
"kind"
=>
"Secret"
}
{
"name"
=>
"secrets"
,
"namespaced"
=>
true
,
"kind"
=>
"Secret"
},
{
"name"
=>
"services"
,
"namespaced"
=>
true
,
"kind"
=>
"Service"
}
]
}
end
...
...
@@ -88,7 +90,20 @@ module KubernetesHelpers
"resources"
=>
[
{
"name"
=>
"pods"
,
"namespaced"
=>
true
,
"kind"
=>
"Pod"
},
{
"name"
=>
"deployments"
,
"namespaced"
=>
true
,
"kind"
=>
"Deployment"
},
{
"name"
=>
"secrets"
,
"namespaced"
=>
true
,
"kind"
=>
"Secret"
}
{
"name"
=>
"secrets"
,
"namespaced"
=>
true
,
"kind"
=>
"Secret"
},
{
"name"
=>
"services"
,
"namespaced"
=>
true
,
"kind"
=>
"Service"
}
]
}
end
def
kube_v1_rbac_authorization_discovery_body
{
"kind"
=>
"APIResourceList"
,
"resources"
=>
[
{
"name"
=>
"clusterrolebindings"
,
"namespaced"
=>
false
,
"kind"
=>
"ClusterRoleBinding"
},
{
"name"
=>
"clusterroles"
,
"namespaced"
=>
false
,
"kind"
=>
"ClusterRole"
},
{
"name"
=>
"rolebindings"
,
"namespaced"
=>
true
,
"kind"
=>
"RoleBinding"
},
{
"name"
=>
"roles"
,
"namespaced"
=>
true
,
"kind"
=>
"Role"
}
]
}
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment