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
7266edd2
Commit
7266edd2
authored
Aug 07, 2018
by
Thong Kuah
Committed by
Dmitriy Zaporozhets
Aug 07, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EE port for: 48098 Mutual auth cluster applications
parent
ad606ea6
Changes
44
Show whitespace changes
Inline
Side-by-side
Showing
44 changed files
with
647 additions
and
278 deletions
+647
-278
app/models/clusters/applications/helm.rb
app/models/clusters/applications/helm.rb
+48
-1
app/models/clusters/applications/ingress.rb
app/models/clusters/applications/ingress.rb
+2
-2
app/models/clusters/applications/jupyter.rb
app/models/clusters/applications/jupyter.rb
+2
-2
app/models/clusters/applications/prometheus.rb
app/models/clusters/applications/prometheus.rb
+2
-2
app/models/clusters/applications/runner.rb
app/models/clusters/applications/runner.rb
+2
-2
app/models/clusters/concerns/application_data.rb
app/models/clusters/concerns/application_data.rb
+26
-0
changelogs/unreleased/48098-mutual-auth-cluster-applications.yml
...ogs/unreleased/48098-mutual-auth-cluster-applications.yml
+6
-0
db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb
...0180612103626_add_columns_for_helm_tiller_certificates.rb
+12
-0
db/schema.rb
db/schema.rb
+3
-0
ee/app/models/ee/clusters/applications/prometheus.rb
ee/app/models/ee/clusters/applications/prometheus.rb
+9
-6
ee/app/services/clusters/applications/prometheus_update_service.rb
...rvices/clusters/applications/prometheus_update_service.rb
+6
-2
ee/lib/ee/gitlab/kubernetes/helm/api.rb
ee/lib/ee/gitlab/kubernetes/helm/api.rb
+3
-5
ee/lib/gitlab/kubernetes/helm/get_command.rb
ee/lib/gitlab/kubernetes/helm/get_command.rb
+0
-17
ee/lib/gitlab/kubernetes/helm/upgrade_command.rb
ee/lib/gitlab/kubernetes/helm/upgrade_command.rb
+23
-16
ee/spec/lib/ee/gitlab/kubernetes/helm/api_spec.rb
ee/spec/lib/ee/gitlab/kubernetes/helm/api_spec.rb
+5
-7
ee/spec/lib/gitlab/kubernetes/helm/get_command_spec.rb
ee/spec/lib/gitlab/kubernetes/helm/get_command_spec.rb
+0
-19
ee/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
ee/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
+20
-10
ee/spec/models/ee/clusters/applications/prometheus_spec.rb
ee/spec/models/ee/clusters/applications/prometheus_spec.rb
+40
-15
ee/spec/services/clusters/applications/prometheus_update_service_spec.rb
...s/clusters/applications/prometheus_update_service_spec.rb
+3
-3
lib/gitlab/kubernetes/config_map.rb
lib/gitlab/kubernetes/config_map.rb
+4
-4
lib/gitlab/kubernetes/helm/api.rb
lib/gitlab/kubernetes/helm/api.rb
+1
-1
lib/gitlab/kubernetes/helm/base_command.rb
lib/gitlab/kubernetes/helm/base_command.rb
+21
-11
lib/gitlab/kubernetes/helm/certificate.rb
lib/gitlab/kubernetes/helm/certificate.rb
+73
-0
lib/gitlab/kubernetes/helm/init_command.rb
lib/gitlab/kubernetes/helm/init_command.rb
+16
-2
lib/gitlab/kubernetes/helm/install_command.rb
lib/gitlab/kubernetes/helm/install_command.rb
+20
-15
lib/gitlab/kubernetes/helm/pod.rb
lib/gitlab/kubernetes/helm/pod.rb
+3
-5
qa/qa/factory/resource/kubernetes_cluster.rb
qa/qa/factory/resource/kubernetes_cluster.rb
+3
-2
qa/qa/page/project/operations/kubernetes/show.rb
qa/qa/page/project/operations/kubernetes/show.rb
+1
-0
spec/factories/clusters/applications/helm.rb
spec/factories/clusters/applications/helm.rb
+13
-3
spec/factories/clusters/clusters.rb
spec/factories/clusters/clusters.rb
+4
-0
spec/features/projects/clusters/applications_spec.rb
spec/features/projects/clusters/applications_spec.rb
+14
-2
spec/lib/gitlab/kubernetes/config_map_spec.rb
spec/lib/gitlab/kubernetes/config_map_spec.rb
+2
-2
spec/lib/gitlab/kubernetes/helm/api_spec.rb
spec/lib/gitlab/kubernetes/helm/api_spec.rb
+1
-1
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
+20
-8
spec/lib/gitlab/kubernetes/helm/certificate_spec.rb
spec/lib/gitlab/kubernetes/helm/certificate_spec.rb
+28
-0
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
+2
-2
spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+34
-35
spec/lib/gitlab/kubernetes/helm/pod_spec.rb
spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+4
-25
spec/models/clusters/applications/helm_spec.rb
spec/models/clusters/applications/helm_spec.rb
+24
-2
spec/models/clusters/applications/ingress_spec.rb
spec/models/clusters/applications/ingress_spec.rb
+34
-8
spec/models/clusters/applications/jupyter_spec.rb
spec/models/clusters/applications/jupyter_spec.rb
+35
-11
spec/models/clusters/applications/prometheus_spec.rb
spec/models/clusters/applications/prometheus_spec.rb
+33
-9
spec/models/clusters/applications/runner_spec.rb
spec/models/clusters/applications/runner_spec.rb
+44
-20
spec/services/clusters/applications/install_service_spec.rb
spec/services/clusters/applications/install_service_spec.rb
+1
-1
No files found.
app/models/clusters/applications/helm.rb
View file @
7266edd2
# frozen_string_literal: true
require
'openssl'
module
Clusters
module
Applications
class
Helm
<
ActiveRecord
::
Base
self
.
table_name
=
'clusters_applications_helm'
attr_encrypted
:ca_key
,
mode: :per_attribute_iv
,
key:
Settings
.
attr_encrypted_db_key_base_truncated
,
algorithm:
'aes-256-cbc'
include
::
Clusters
::
Concerns
::
ApplicationCore
include
::
Clusters
::
Concerns
::
ApplicationStatus
default_value_for
:version
,
Gitlab
::
Kubernetes
::
Helm
::
HELM_VERSION
before_create
:create_keys_and_certs
def
issue_client_cert
ca_cert_obj
.
issue
end
def
set_initial_status
return
unless
not_installable?
...
...
@@ -17,7 +30,41 @@ module Clusters
end
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
.
new
(
name
)
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
.
new
(
name:
name
,
files:
files
)
end
def
has_ssl?
ca_key
.
present?
&&
ca_cert
.
present?
end
private
def
files
{
'ca.pem'
:
ca_cert
,
'cert.pem'
:
tiller_cert
.
cert_string
,
'key.pem'
:
tiller_cert
.
key_string
}
end
def
create_keys_and_certs
ca_cert
=
Gitlab
::
Kubernetes
::
Helm
::
Certificate
.
generate_root
self
.
ca_key
=
ca_cert
.
key_string
self
.
ca_cert
=
ca_cert
.
cert_string
end
def
tiller_cert
@tiller_cert
||=
ca_cert_obj
.
issue
(
expires_in:
Gitlab
::
Kubernetes
::
Helm
::
Certificate
::
INFINITE_EXPIRY
)
end
def
ca_cert_obj
return
unless
has_ssl?
Gitlab
::
Kubernetes
::
Helm
::
Certificate
.
from_strings
(
ca_key
,
ca_cert
)
end
end
end
...
...
app/models/clusters/applications/ingress.rb
View file @
7266edd2
...
...
@@ -37,10 +37,10 @@ module Clusters
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name
,
name
:
name
,
version:
VERSION
,
chart:
chart
,
values:
valu
es
files:
fil
es
)
end
...
...
app/models/clusters/applications/jupyter.rb
View file @
7266edd2
...
...
@@ -38,10 +38,10 @@ module Clusters
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name
,
name
:
name
,
version:
VERSION
,
chart:
chart
,
values:
valu
es
,
files:
fil
es
,
repository:
repository
)
end
...
...
app/models/clusters/applications/prometheus.rb
View file @
7266edd2
...
...
@@ -48,10 +48,10 @@ module Clusters
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name
,
name
:
name
,
version:
VERSION
,
chart:
chart
,
values:
valu
es
files:
fil
es
)
end
...
...
app/models/clusters/applications/runner.rb
View file @
7266edd2
...
...
@@ -31,10 +31,10 @@ module Clusters
def
install_command
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
.
new
(
name
,
name
:
name
,
version:
VERSION
,
chart:
chart
,
values:
valu
es
,
files:
fil
es
,
repository:
repository
)
end
...
...
app/models/clusters/concerns/application_data.rb
View file @
7266edd2
...
...
@@ -14,8 +14,34 @@ module Clusters
File
.
read
(
chart_values_file
)
end
def
files
@files
||=
begin
files
=
{
'values.yaml'
:
values
}
files
.
merge!
(
certificate_files
)
if
cluster
.
application_helm
.
has_ssl?
files
end
end
private
def
certificate_files
{
'ca.pem'
:
ca_cert
,
'cert.pem'
:
helm_cert
.
cert_string
,
'key.pem'
:
helm_cert
.
key_string
}
end
def
ca_cert
cluster
.
application_helm
.
ca_cert
end
def
helm_cert
@helm_cert
||=
cluster
.
application_helm
.
issue_client_cert
end
def
chart_values_file
"
#{
Rails
.
root
}
/vendor/
#{
name
}
/values.yaml"
end
...
...
changelogs/unreleased/48098-mutual-auth-cluster-applications.yml
0 → 100644
View file @
7266edd2
---
title
:
Ensure installed Helm Tiller For GitLab Managed Apps Is protected by mutual
auth
merge_request
:
20928
author
:
type
:
changed
db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb
0 → 100644
View file @
7266edd2
# frozen_string_literal: true
class
AddColumnsForHelmTillerCertificates
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
add_column
:clusters_applications_helm
,
:encrypted_ca_key
,
:text
add_column
:clusters_applications_helm
,
:encrypted_ca_key_iv
,
:text
add_column
:clusters_applications_helm
,
:ca_cert
,
:text
end
end
db/schema.rb
View file @
7266edd2
...
...
@@ -749,6 +749,9 @@ ActiveRecord::Schema.define(version: 20180803001726) do
t
.
integer
"status"
,
null:
false
t
.
string
"version"
,
null:
false
t
.
text
"status_reason"
t
.
text
"encrypted_ca_key"
t
.
text
"encrypted_ca_key_iv"
t
.
text
"ca_cert"
end
create_table
"clusters_applications_ingress"
,
force: :cascade
do
|
t
|
...
...
ee/app/models/ee/clusters/applications/prometheus.rb
View file @
7266edd2
...
...
@@ -30,19 +30,22 @@ module EE
status_name
==
:update_errored
end
def
get_command
::
Gitlab
::
Kubernetes
::
Helm
::
GetCommand
.
new
(
name
)
end
# TODO allow users to chose which version to upgrade to.
def
upgrade_command
(
values
)
::
Gitlab
::
Kubernetes
::
Helm
::
UpgradeCommand
.
new
(
name
,
version:
self
.
class
.
const_get
(
:VERSION
),
chart:
chart
,
values:
values
files:
files_with_replaced_values
(
values
)
)
end
# Returns a copy of files where the values of 'values.yaml'
# are replaced by the argument.
#
# See #values for the data format required
def
files_with_replaced_values
(
replaced_values
)
files
.
merge
(
'values.yaml'
:
replaced_values
)
end
end
end
end
...
...
ee/app/services/clusters/applications/prometheus_update_service.rb
View file @
7266edd2
...
...
@@ -11,7 +11,7 @@ module Clusters
def
execute
app
.
make_updating!
response
=
helm_api
.
get_config_map
(
app
.
get_command
)
response
=
helm_api
.
get_config_map
(
config_map_name
)
config
=
extract_config
(
response
)
data
=
...
...
@@ -32,6 +32,10 @@ module Clusters
private
def
config_map_name
::
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
app
.
name
,
app
.
files
).
config_map_name
end
def
reset_alert_manager
(
config
)
config
=
set_alert_manager_enabled
(
config
,
false
)
config
.
delete
(
"alertmanagerFiles"
)
...
...
@@ -117,7 +121,7 @@ module Clusters
end
def
extract_config
(
response
)
YAML
.
safe_load
(
response
.
data
.
values
)
YAML
.
safe_load
(
response
.
data
[
:'values.yaml'
]
)
end
def
has_alerts?
...
...
ee/lib/ee/gitlab/kubernetes/helm/api.rb
View file @
7266edd2
...
...
@@ -3,17 +3,15 @@ module EE
module
Kubernetes
module
Helm
module
Api
def
get_config_map
(
co
mmand
)
def
get_config_map
(
co
nfig_map_name
)
namespace
.
ensure_exists!
return
unless
command
.
config_map?
kubeclient
.
get_config_map
(
command
.
config_map_name
,
namespace
.
name
)
kubeclient
.
get_config_map
(
config_map_name
,
namespace
.
name
)
end
def
update
(
command
)
namespace
.
ensure_exists!
update_config_map
(
command
)
if
command
.
config_map?
update_config_map
(
command
)
kubeclient
.
create_pod
(
command
.
pod_resource
)
end
...
...
ee/lib/gitlab/kubernetes/helm/get_command.rb
deleted
100644 → 0
View file @
ad606ea6
require_dependency
'gitlab/kubernetes/helm.rb'
module
Gitlab
module
Kubernetes
module
Helm
class
GetCommand
<
BaseCommand
def
config_map?
true
end
def
config_map_name
::
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
name
).
config_map_name
end
end
end
end
end
ee/lib/gitlab/kubernetes/helm/upgrade_command.rb
View file @
7266edd2
...
...
@@ -3,14 +3,16 @@ require_dependency 'gitlab/kubernetes/helm.rb'
module
Gitlab
module
Kubernetes
module
Helm
class
UpgradeCommand
<
BaseCommand
attr_reader
:chart
,
:version
,
:repository
,
:values
class
UpgradeCommand
include
BaseCommand
def
initialize
(
name
,
chart
:,
values
:,
version:
nil
,
repository:
nil
)
super
(
name
)
attr_reader
:name
,
:chart
,
:version
,
:repository
,
:files
def
initialize
(
name
,
chart
:,
files
:,
version:
nil
,
repository:
nil
)
@name
=
name
@chart
=
chart
@version
=
version
@
values
=
valu
es
@
files
=
fil
es
@repository
=
repository
end
...
...
@@ -22,14 +24,6 @@ module Gitlab
].
compact
.
join
(
"
\n
"
)
end
def
config_map?
true
end
def
config_map_resource
::
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
name
,
values
).
generate
end
def
pod_name
"upgrade-
#{
name
}
"
end
...
...
@@ -45,14 +39,27 @@ module Gitlab
end
def
script_command
<<~
HEREDOC
helm upgrade
#{
name
}#{
optional_version_flag
}
#{
chart
}
--reset-values --install --namespace
#{
::
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
-f /data/helm/
#{
name
}
/config/values.yaml >/dev/null
HEREDOC
upgrade_flags
=
"
#{
optional_version_flag
}#{
optional_tls_flags
}
"
\
" --reset-values"
\
" --install"
\
" --namespace
#{
::
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
"
\
" -f /data/helm/
#{
name
}
/config/values.yaml"
"helm upgrade
#{
name
}
#{
chart
}#{
upgrade_flags
}
>/dev/null
\n
"
end
def
optional_version_flag
" --version
#{
version
}
"
if
version
end
def
optional_tls_flags
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"
end
end
end
end
...
...
ee/spec/lib/ee/gitlab/kubernetes/helm/api_spec.rb
View file @
7266edd2
...
...
@@ -15,20 +15,18 @@ describe Gitlab::Kubernetes::Helm::Api do
end
describe
'#get_config_map'
do
let
(
:command
)
{
Gitlab
::
Kubernetes
::
Helm
::
GetCommand
.
new
(
application
.
name
)
}
it
'ensures the namespace exists before retrieving the config map'
do
expect
(
namespace
).
to
receive
(
:ensure_exists!
).
once
subject
.
get_config_map
(
command
)
subject
.
get_config_map
(
application
.
name
)
end
it
'gets the config map on kubeclient'
do
expect
(
kubeclient
).
to
receive
(
:get_config_map
)
.
with
(
command
.
config_map_name
,
namespace
.
name
)
.
with
(
"example-config-map-name"
,
namespace
.
name
)
.
once
subject
.
get_config_map
(
command
)
subject
.
get_config_map
(
"example-config-map-name"
)
end
end
...
...
@@ -37,7 +35,7 @@ describe Gitlab::Kubernetes::Helm::Api do
Gitlab
::
Kubernetes
::
Helm
::
UpgradeCommand
.
new
(
application
.
name
,
chart:
application
.
chart
,
values:
application
.
valu
es
files:
application
.
fil
es
)
end
...
...
@@ -50,7 +48,7 @@ describe Gitlab::Kubernetes::Helm::Api do
it
'updates the config map on kubeclient when one exists'
do
resource
=
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
application
.
name
,
application
.
valu
es
application
.
name
,
application
.
fil
es
).
generate
expect
(
kubeclient
).
to
receive
(
:update_config_map
).
with
(
resource
).
once
...
...
ee/spec/lib/gitlab/kubernetes/helm/get_command_spec.rb
deleted
100644 → 0
View file @
ad606ea6
require
'rails_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
GetCommand
do
let
(
:application
)
{
build
(
:clusters_applications_prometheus
)
}
subject
(
:get_command
)
{
described_class
.
new
(
application
.
name
)
}
describe
'#config_map?'
do
it
'returns true'
do
expect
(
get_command
.
config_map?
).
to
be
true
end
end
describe
'#config_map_name'
do
it
'returns the ConfigMap name'
do
expect
(
get_command
.
config_map_name
).
to
eq
(
"values-content-configuration-
#{
application
.
name
}
"
)
end
end
end
ee/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
View file @
7266edd2
...
...
@@ -2,13 +2,14 @@ require 'rails_helper'
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
described_class
.
new
(
application
.
name
,
chart:
application
.
chart
,
values:
application
.
valu
es
files:
fil
es
)
end
...
...
@@ -16,7 +17,7 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm upgrade
#{
application
.
name
}
#{
application
.
chart
}
--reset-values --install --namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/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
...
...
@@ -29,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
described_class
.
new
(
application
.
name
,
chart:
application
.
chart
,
values:
application
.
valu
es
,
files:
fil
es
,
repository:
application
.
repository
)
end
...
...
@@ -39,27 +40,36 @@ describe Gitlab::Kubernetes::Helm::UpgradeCommand do
<<~
EOS
helm init --client-only >/dev/null
helm repo add
#{
application
.
name
}
#{
application
.
repository
}
helm upgrade
#{
application
.
name
}
#{
application
.
chart
}
--reset-values --install --namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/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
describe
'#config_map?'
do
it
'returns true'
do
expect
(
subject
.
config_map?
).
to
be_truthy
context
'when there is no ca.pem file'
do
let
(
:files
)
{
{
'file.txt'
:
'some content'
}
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm upgrade
#{
application
.
name
}
#{
application
.
chart
}
--reset-values --install --namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/dev/null
EOS
end
end
end
describe
'#config_map_resource'
do
it
'returns a KubeClient resource with config map content for the application'
do
metadata
=
{
let
(
:metadata
)
do
{
name:
"values-content-configuration-
#{
application
.
name
}
"
,
namespace:
namespace
,
labels:
{
name:
"values-content-configuration-
#{
application
.
name
}
"
}
}
resource
=
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
{
values:
application
.
values
})
end
let
(
:resource
)
{
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
files
)
}
it
'returns a KubeClient resource with config map content for the application'
do
expect
(
subject
.
config_map_resource
).
to
eq
(
resource
)
end
end
...
...
ee/spec/models/ee/clusters/applications/prometheus_spec.rb
View file @
7266edd2
...
...
@@ -101,35 +101,60 @@ describe Clusters::Applications::Prometheus do
end
end
describe
'#
get
_command'
do
describe
'#
upgrade
_command'
do
let
(
:prometheus
)
{
build
(
:clusters_applications_prometheus
)
}
let
(
:values
)
{
prometheus
.
values
}
it
'returns an instance of Gitlab::Kubernetes::Helm::GetCommand'
do
expect
(
prometheus
.
get_command
).
to
be_an_instance_of
(
::
Gitlab
::
Kubernetes
::
Helm
::
Get
Command
)
expect
(
prometheus
.
upgrade_command
(
values
)).
to
be_an_instance_of
(
::
Gitlab
::
Kubernetes
::
Helm
::
Upgrade
Command
)
end
it
'should be initialized with
1 argument
'
do
command
=
prometheus
.
get_command
it
'should be initialized with
3 arguments
'
do
command
=
prometheus
.
upgrade_command
(
values
)
expect
(
command
.
name
).
to
eq
(
'prometheus'
)
expect
(
command
.
chart
).
to
eq
(
'stable/prometheus'
)
expect
(
command
.
version
).
to
eq
(
'6.7.3'
)
expect
(
command
.
files
).
to
eq
(
prometheus
.
files
)
end
end
describe
'#
upgrade_command
'
do
let
(
:
prometheus
)
{
build
(
:clusters_applications_prometheus
)
}
let
(
:
values
)
{
{
foo:
'bar'
}
}
describe
'#
files_with_replaced_values
'
do
let
(
:
application
)
{
build
(
:clusters_applications_prometheus
)
}
let
(
:
files
)
{
application
.
files
}
it
'returns an instance of Gitlab::Kubernetes::Helm::GetCommand'
do
expect
(
prometheus
.
upgrade_command
(
values
)).
to
be_an_instance_of
(
::
Gitlab
::
Kubernetes
::
Helm
::
UpgradeCommand
)
subject
{
application
.
files_with_replaced_values
({
hello: :world
})
}
it
'does not modify #files'
do
expect
(
subject
[
:'values.yaml'
]).
not_to
eq
(
files
)
expect
(
files
[
:'values.yaml'
]).
to
eq
(
application
.
values
)
end
it
'should be initialized with 3 arguments'
do
command
=
prometheus
.
upgrade_command
(
values
)
it
'returns values.yaml with replaced values'
do
expect
(
subject
[
:'values.yaml'
]).
to
eq
({
hello: :world
})
end
expect
(
command
.
name
).
to
eq
(
'prometheus'
)
expect
(
command
.
chart
).
to
eq
(
'stable/prometheus'
)
expect
(
command
.
version
).
to
eq
(
'6.7.3'
)
expect
(
command
.
values
).
to
eq
(
values
)
it
'should include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
to
be_present
expect
(
subject
[
:'ca.pem'
]).
to
eq
(
application
.
cluster
.
application_helm
.
ca_cert
)
expect
(
subject
[
:'cert.pem'
]).
to
be_present
expect
(
subject
[
:'key.pem'
]).
to
be_present
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
<
60
.
minutes
.
from_now
end
context
'when the helm application does not have a ca_cert'
do
before
do
application
.
cluster
.
application_helm
.
ca_cert
=
nil
end
it
'should not include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
not_to
be_present
expect
(
subject
[
:'cert.pem'
]).
not_to
be_present
expect
(
subject
[
:'key.pem'
]).
not_to
be_present
end
end
end
end
ee/spec/services/clusters/applications/prometheus_update_service_spec.rb
View file @
7266edd2
...
...
@@ -4,9 +4,9 @@ describe Clusters::Applications::PrometheusUpdateService do
describe
'#execute'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:environment
)
{
create
(
:environment
,
project:
project
)
}
let
(
:cluster
)
{
create
(
:cluster
,
projects:
[
project
])
}
let
(
:cluster
)
{
create
(
:cluster
,
:with_installed_helm
,
projects:
[
project
])
}
let
(
:application
)
{
create
(
:clusters_applications_prometheus
,
:installed
,
cluster:
cluster
)
}
let!
(
:get_command_values
)
{
OpenStruct
.
new
(
data:
OpenStruct
.
new
(
values
:
application
.
values
))
}
let!
(
:get_command_values
)
{
OpenStruct
.
new
(
data:
OpenStruct
.
new
(
'values.yaml'
:
application
.
values
))
}
let!
(
:upgrade_command
)
{
application
.
upgrade_command
(
""
)
}
let
(
:helm_client
)
{
instance_double
(
::
Gitlab
::
Kubernetes
::
Helm
::
Api
)
}
...
...
@@ -19,7 +19,7 @@ describe Clusters::Applications::PrometheusUpdateService do
context
'when there are no errors'
do
before
do
expect
(
helm_client
).
to
receive
(
:get_config_map
).
and_return
(
get_command_values
)
expect
(
helm_client
).
to
receive
(
:get_config_map
).
with
(
"values-content-configuration-prometheus"
).
and_return
(
get_command_values
)
expect
(
helm_client
).
to
receive
(
:update
).
with
(
upgrade_command
)
allow
(
::
ClusterWaitForAppUpdateWorker
).
to
receive
(
:perform_in
).
and_return
(
nil
)
end
...
...
lib/gitlab/kubernetes/config_map.rb
View file @
7266edd2
module
Gitlab
module
Kubernetes
class
ConfigMap
def
initialize
(
name
,
values
=
""
)
def
initialize
(
name
,
files
)
@name
=
name
@
values
=
valu
es
@
files
=
fil
es
end
def
generate
resource
=
::
Kubeclient
::
Resource
.
new
resource
.
metadata
=
metadata
resource
.
data
=
{
values:
values
}
resource
.
data
=
files
resource
end
...
...
@@ -19,7 +19,7 @@ module Gitlab
private
attr_reader
:name
,
:
valu
es
attr_reader
:name
,
:
fil
es
def
metadata
{
...
...
lib/gitlab/kubernetes/helm/api.rb
View file @
7266edd2
...
...
@@ -11,7 +11,7 @@ module Gitlab
def
install
(
command
)
namespace
.
ensure_exists!
create_config_map
(
command
)
if
command
.
config_map?
create_config_map
(
command
)
kubeclient
.
create_pod
(
command
.
pod_resource
)
end
...
...
lib/gitlab/kubernetes/helm/base_command.rb
View file @
7266edd2
module
Gitlab
module
Kubernetes
module
Helm
class
BaseCommand
attr_reader
:name
def
initialize
(
name
)
@name
=
name
end
module
BaseCommand
def
pod_resource
Gitlab
::
Kubernetes
::
Helm
::
Pod
.
new
(
self
,
namespace
).
generate
end
...
...
@@ -24,16 +18,32 @@ module Gitlab
HEREDOC
end
def
config_map?
false
end
def
pod_name
"install-
#{
name
}
"
end
def
config_map_resource
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
name
,
files
).
generate
end
def
file_names
files
.
keys
end
def
name
raise
"Not implemented"
end
def
files
raise
"Not implemented"
end
private
def
files_dir
"/data/helm/
#{
name
}
/config"
end
def
namespace
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
end
...
...
lib/gitlab/kubernetes/helm/certificate.rb
0 → 100644
View file @
7266edd2
# frozen_string_literal: true
module
Gitlab
module
Kubernetes
module
Helm
class
Certificate
INFINITE_EXPIRY
=
1000
.
years
SHORT_EXPIRY
=
30
.
minutes
attr_reader
:key
,
:cert
def
key_string
@key
.
to_s
end
def
cert_string
@cert
.
to_pem
end
def
self
.
from_strings
(
key_string
,
cert_string
)
key
=
OpenSSL
::
PKey
::
RSA
.
new
(
key_string
)
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
cert_string
)
new
(
key
,
cert
)
end
def
self
.
generate_root
_issue
(
signed_by:
nil
,
expires_in:
INFINITE_EXPIRY
,
certificate_authority:
true
)
end
def
issue
(
expires_in:
SHORT_EXPIRY
)
self
.
class
.
_issue
(
signed_by:
self
,
expires_in:
expires_in
,
certificate_authority:
false
)
end
private
def
self
.
_issue
(
signed_by
:,
expires_in
:,
certificate_authority
:)
key
=
OpenSSL
::
PKey
::
RSA
.
new
(
4096
)
public_key
=
key
.
public_key
subject
=
OpenSSL
::
X509
::
Name
.
parse
(
"/C=US"
)
cert
=
OpenSSL
::
X509
::
Certificate
.
new
cert
.
subject
=
subject
cert
.
issuer
=
signed_by
&
.
cert
&
.
subject
||
subject
cert
.
not_before
=
Time
.
now
cert
.
not_after
=
expires_in
.
from_now
cert
.
public_key
=
public_key
cert
.
serial
=
0x0
cert
.
version
=
2
if
certificate_authority
extension_factory
=
OpenSSL
::
X509
::
ExtensionFactory
.
new
extension_factory
.
subject_certificate
=
cert
extension_factory
.
issuer_certificate
=
cert
cert
.
add_extension
(
extension_factory
.
create_extension
(
'subjectKeyIdentifier'
,
'hash'
))
cert
.
add_extension
(
extension_factory
.
create_extension
(
'basicConstraints'
,
'CA:TRUE'
,
true
))
cert
.
add_extension
(
extension_factory
.
create_extension
(
'keyUsage'
,
'cRLSign,keyCertSign'
,
true
))
end
cert
.
sign
(
signed_by
&
.
key
||
key
,
OpenSSL
::
Digest
::
SHA256
.
new
)
new
(
key
,
cert
)
end
def
initialize
(
key
,
cert
)
@key
=
key
@cert
=
cert
end
end
end
end
end
lib/gitlab/kubernetes/helm/init_command.rb
View file @
7266edd2
module
Gitlab
module
Kubernetes
module
Helm
class
InitCommand
<
BaseCommand
class
InitCommand
include
BaseCommand
attr_reader
:name
,
:files
def
initialize
(
name
:,
files
:)
@name
=
name
@files
=
files
end
def
generate_script
super
+
[
init_helm_command
...
...
@@ -11,7 +20,12 @@ module Gitlab
private
def
init_helm_command
"helm init >/dev/null"
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"
"helm init
#{
tls_flags
}
>/dev/null"
end
end
end
...
...
lib/gitlab/kubernetes/helm/install_command.rb
View file @
7266edd2
module
Gitlab
module
Kubernetes
module
Helm
class
InstallCommand
<
BaseCommand
attr_reader
:name
,
:chart
,
:version
,
:repository
,
:values
class
InstallCommand
include
BaseCommand
def
initialize
(
name
,
chart
:,
values
:,
version:
nil
,
repository:
nil
)
attr_reader
:name
,
:files
,
:chart
,
:version
,
:repository
def
initialize
(
name
:,
chart
:,
files
:,
version:
nil
,
repository:
nil
)
@name
=
name
@chart
=
chart
@version
=
version
@
values
=
valu
es
@
files
=
fil
es
@repository
=
repository
end
...
...
@@ -20,14 +22,6 @@ module Gitlab
].
compact
.
join
(
"
\n
"
)
end
def
config_map?
true
end
def
config_map_resource
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
name
,
values
).
generate
end
private
def
init_command
...
...
@@ -39,14 +33,25 @@ module Gitlab
end
def
script_command
<<~
HEREDOC
helm install
#{
chart
}
--name
#{
name
}#{
optional_version_flag
}
--namespace
#{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
-f /data/helm/
#{
name
}
/config/values.yaml >/dev/null
HEREDOC
init_flags
=
"--name
#{
name
}#{
optional_tls_flags
}#{
optional_version_flag
}
"
\
" --namespace
#{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
"
\
" -f /data/helm/
#{
name
}
/config/values.yaml"
"helm install
#{
chart
}
#{
init_flags
}
>/dev/null
\n
"
end
def
optional_version_flag
" --version
#{
version
}
"
if
version
end
def
optional_tls_flags
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"
end
end
end
end
...
...
lib/gitlab/kubernetes/helm/pod.rb
View file @
7266edd2
...
...
@@ -10,10 +10,8 @@ module Gitlab
def
generate
spec
=
{
containers:
[
container_specification
],
restartPolicy:
'Never'
}
if
command
.
config_map?
spec
[
:volumes
]
=
volumes_specification
spec
[
:containers
][
0
][
:volumeMounts
]
=
volume_mounts_specification
end
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
spec:
spec
)
end
...
...
@@ -61,7 +59,7 @@ module Gitlab
name:
'configuration-volume'
,
configMap:
{
name:
"values-content-configuration-
#{
command
.
name
}
"
,
items:
[{
key:
'values'
,
path:
'values.yaml'
}]
items:
command
.
file_names
.
map
{
|
name
|
{
key:
name
,
path:
name
}
}
}
}
]
...
...
qa/qa/factory/resource/kubernetes_cluster.rb
View file @
7266edd2
...
...
@@ -44,10 +44,11 @@ module QA
page
.
await_installed
(
:helm
)
page
.
install!
(
:ingress
)
if
@install_ingress
page
.
await_installed
(
:ingress
)
if
@install_ingress
page
.
install!
(
:prometheus
)
if
@install_prometheus
page
.
await_installed
(
:prometheus
)
if
@install_prometheus
page
.
install!
(
:runner
)
if
@install_runner
page
.
await_installed
(
:ingress
)
if
@install_ingress
page
.
await_installed
(
:prometheus
)
if
@install_prometheus
page
.
await_installed
(
:runner
)
if
@install_runner
end
end
...
...
qa/qa/page/project/operations/kubernetes/show.rb
View file @
7266edd2
...
...
@@ -16,6 +16,7 @@ module QA
def
install!
(
application_name
)
within
(
".js-cluster-application-row-
#{
application_name
}
"
)
do
page
.
has_button?
(
'Install'
,
wait:
30
)
click_on
'Install'
end
end
...
...
spec/factories/clusters/applications/helm.rb
View file @
7266edd2
...
...
@@ -45,11 +45,21 @@ FactoryBot.define do
updated_at
ClusterWaitForAppInstallationWorker
::
TIMEOUT
.
ago
end
factory
:clusters_applications_ingress
,
class:
Clusters
::
Applications
::
Ingress
factory
:clusters_applications_prometheus
,
class:
Clusters
::
Applications
::
Prometheus
factory
:clusters_applications_runner
,
class:
Clusters
::
Applications
::
Runner
factory
:clusters_applications_ingress
,
class:
Clusters
::
Applications
::
Ingress
do
cluster
factory:
%i(cluster with_installed_helm provided_by_gcp)
end
factory
:clusters_applications_prometheus
,
class:
Clusters
::
Applications
::
Prometheus
do
cluster
factory:
%i(cluster with_installed_helm provided_by_gcp)
end
factory
:clusters_applications_runner
,
class:
Clusters
::
Applications
::
Runner
do
cluster
factory:
%i(cluster with_installed_helm provided_by_gcp)
end
factory
:clusters_applications_jupyter
,
class:
Clusters
::
Applications
::
Jupyter
do
oauth_application
factory: :oauth_application
cluster
factory:
%i(cluster with_installed_helm provided_by_gcp)
end
end
end
spec/factories/clusters/clusters.rb
View file @
7266edd2
...
...
@@ -36,5 +36,9 @@ FactoryBot.define do
trait
:production_environment
do
sequence
(
:environment_scope
)
{
|
n
|
"production
#{
n
}
/*"
}
end
trait
:with_installed_helm
do
application_helm
factory:
%i(clusters_applications_helm installed)
end
end
end
spec/features/projects/clusters/applications_spec.rb
View file @
7266edd2
...
...
@@ -46,12 +46,14 @@ describe 'Clusters Applications', :js do
end
end
it
'
he sees
status transition'
do
it
'
they see
status transition'
do
page
.
within
(
'.js-cluster-application-row-helm'
)
do
# FE sends request and gets the response, then the buttons is "Install"
expect
(
page
.
find
(
:css
,
'.js-cluster-application-install-button'
)[
'disabled'
]).
to
eq
(
'true'
)
expect
(
page
).
to
have_css
(
'.js-cluster-application-install-button'
,
exact_text:
'Install'
)
wait_until_helm_created!
Clusters
::
Cluster
.
last
.
application_helm
.
make_installing!
# FE starts polling and update the buttons to "Installing"
...
...
@@ -83,7 +85,7 @@ describe 'Clusters Applications', :js do
end
end
it
'
he sees
status transition'
do
it
'
they see
status transition'
do
page
.
within
(
'.js-cluster-application-row-ingress'
)
do
# FE sends request and gets the response, then the buttons is "Install"
expect
(
page
).
to
have_css
(
'.js-cluster-application-install-button[disabled]'
)
...
...
@@ -116,4 +118,14 @@ describe 'Clusters Applications', :js do
end
end
end
def
wait_until_helm_created!
retries
=
0
while
Clusters
::
Cluster
.
last
.
application_helm
.
nil?
raise
"Timed out waiting for helm application to be created in DB"
if
(
retries
+=
1
)
>
3
sleep
(
1
)
end
end
end
spec/lib/gitlab/kubernetes/config_map_spec.rb
View file @
7266edd2
...
...
@@ -3,7 +3,7 @@ require 'spec_helper'
describe
Gitlab
::
Kubernetes
::
ConfigMap
do
let
(
:kubeclient
)
{
double
(
'kubernetes client'
)
}
let
(
:application
)
{
create
(
:clusters_applications_prometheus
)
}
let
(
:config_map
)
{
described_class
.
new
(
application
.
name
,
application
.
valu
es
)
}
let
(
:config_map
)
{
described_class
.
new
(
application
.
name
,
application
.
fil
es
)
}
let
(
:namespace
)
{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
let
(
:metadata
)
do
...
...
@@ -15,7 +15,7 @@ describe Gitlab::Kubernetes::ConfigMap do
end
describe
'#generate'
do
let
(
:resource
)
{
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
{
values:
application
.
values
}
)
}
let
(
:resource
)
{
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
application
.
files
)
}
subject
{
config_map
.
generate
}
it
'should build a Kubeclient Resource'
do
...
...
spec/lib/gitlab/kubernetes/helm/api_spec.rb
View file @
7266edd2
...
...
@@ -39,7 +39,7 @@ describe Gitlab::Kubernetes::Helm::Api do
end
context
'with a ConfigMap'
do
let
(
:resource
)
{
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
application
.
name
,
application
.
valu
es
).
generate
}
let
(
:resource
)
{
Gitlab
::
Kubernetes
::
ConfigMap
.
new
(
application
.
name
,
application
.
fil
es
).
generate
}
it
'creates a ConfigMap on kubeclient'
do
expect
(
client
).
to
receive
(
:create_config_map
).
with
(
resource
).
once
...
...
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
View file @
7266edd2
...
...
@@ -2,7 +2,25 @@ require 'spec_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
BaseCommand
do
let
(
:application
)
{
create
(
:clusters_applications_helm
)
}
let
(
:base_command
)
{
described_class
.
new
(
application
.
name
)
}
let
(
:test_class
)
do
Class
.
new
do
include
Gitlab
::
Kubernetes
::
Helm
::
BaseCommand
def
name
"test-class-name"
end
def
files
{
some:
'value'
}
end
end
end
let
(
:base_command
)
do
test_class
.
new
end
subject
{
base_command
}
...
...
@@ -18,15 +36,9 @@ describe Gitlab::Kubernetes::Helm::BaseCommand do
end
end
describe
'#config_map?'
do
subject
{
base_command
.
config_map?
}
it
{
is_expected
.
to
be_falsy
}
end
describe
'#pod_name'
do
subject
{
base_command
.
pod_name
}
it
{
is_expected
.
to
eq
(
'install-
helm
'
)
}
it
{
is_expected
.
to
eq
(
'install-
test-class-name
'
)
}
end
end
spec/lib/gitlab/kubernetes/helm/certificate_spec.rb
0 → 100644
View file @
7266edd2
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
Certificate
do
describe
'.generate_root'
do
subject
{
described_class
.
generate_root
}
it
'should generate a root CA that expires a long way in the future'
do
expect
(
subject
.
cert
.
not_after
).
to
be
>
999
.
years
.
from_now
end
end
describe
'#issue'
do
subject
{
described_class
.
generate_root
.
issue
}
it
'should generate a cert that expires soon'
do
expect
(
subject
.
cert
.
not_after
).
to
be
<
60
.
minutes
.
from_now
end
context
'passing in INFINITE_EXPIRY'
do
subject
{
described_class
.
generate_root
.
issue
(
expires_in:
described_class
::
INFINITE_EXPIRY
)
}
it
'should generate a cert that expires a long way in the future'
do
expect
(
subject
.
cert
.
not_after
).
to
be
>
999
.
years
.
from_now
end
end
end
end
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
View file @
7266edd2
...
...
@@ -2,9 +2,9 @@ require 'spec_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
InitCommand
do
let
(
:application
)
{
create
(
:clusters_applications_helm
)
}
let
(
:commands
)
{
'helm init >/dev/null'
}
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'
}
subject
{
described_class
.
new
(
application
.
name
)
}
subject
{
described_class
.
new
(
name:
application
.
name
,
files:
{}
)
}
it_behaves_like
'helm commands'
end
spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
View file @
7266edd2
require
'rails_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
InstallCommand
do
let
(
:
application
)
{
create
(
:clusters_applications_prometheus
)
}
let
(
:
namespace
)
{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
let
(
:
install_command
)
{
application
.
install_command
}
let
(
:
files
)
{
{
'ca.pem'
:
'some file content'
}
}
let
(
:
repository
)
{
'https://repository.example.com'
}
let
(
:
version
)
{
'1.2.3'
}
subject
{
install_command
}
let
(
:install_command
)
do
described_class
.
new
(
name:
'app-name'
,
chart:
'chart-name'
,
files:
files
,
version:
version
,
repository:
repository
)
end
context
'for ingress'
do
let
(
:application
)
{
create
(
:clusters_applications_ingress
)
}
subject
{
install_command
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm install
#{
application
.
chart
}
--name
#{
application
.
name
}
--version
#{
application
.
version
}
--namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/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
EOS
end
end
end
context
'
for prometheus
'
do
let
(
:
application
)
{
create
(
:clusters_applications_prometheus
)
}
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
#{
application
.
chart
}
--name
#{
application
.
name
}
--version
#{
application
.
version
}
--namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/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
EOS
end
end
end
context
'for runner'
do
let
(
:ci_runner
)
{
create
(
:ci_runner
)
}
let
(
:application
)
{
create
(
:clusters_applications_runner
,
runner:
ci_runner
)
}
context
'when there is no ca.pem file'
do
let
(
:files
)
{
{
'file.txt'
:
'some content'
}
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm repo add
#{
application
.
name
}
#{
application
.
repository
}
helm install
#{
application
.
chart
}
--name
#{
application
.
name
}
--version
#{
application
.
version
}
--namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/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
EOS
end
end
end
context
'
for jupyter
'
do
let
(
:
application
)
{
create
(
:clusters_applications_jupyter
)
}
context
'
when there is no version
'
do
let
(
:
version
)
{
nil
}
it_behaves_like
'helm commands'
do
let
(
:commands
)
do
<<~
EOS
helm init --client-only >/dev/null
helm repo add
#{
application
.
name
}
#{
application
.
repository
}
helm install
#{
application
.
chart
}
--name
#{
application
.
name
}
--version
#{
application
.
version
}
--namespace
#{
namespace
}
-f /data/helm/
#{
application
.
name
}
/config/values.yaml >/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
EOS
end
end
end
describe
'#config_map?'
do
subject
{
install_command
.
config_map?
}
it
{
is_expected
.
to
be_truthy
}
end
describe
'#config_map_resource'
do
let
(
:metadata
)
do
{
name:
"values-content-configuration-
#{
application
.
name
}
"
,
namespace:
namespace
,
labels:
{
name:
"values-content-configuration-
#{
application
.
name
}
"
}
name:
"values-content-configuration-
app-name
"
,
namespace:
'gitlab-managed-apps'
,
labels:
{
name:
"values-content-configuration-
app-name
"
}
}
end
let
(
:resource
)
{
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
{
values:
application
.
values
}
)
}
let
(
:resource
)
{
::
Kubeclient
::
Resource
.
new
(
metadata:
metadata
,
data:
files
)
}
subject
{
install_command
.
config_map_resource
}
...
...
spec/lib/gitlab/kubernetes/helm/pod_spec.rb
View file @
7266edd2
...
...
@@ -2,14 +2,13 @@ require 'rails_helper'
describe
Gitlab
::
Kubernetes
::
Helm
::
Pod
do
describe
'#generate'
do
let
(
:cluster
)
{
create
(
:cluster
)
}
let
(
:app
)
{
create
(
:clusters_applications_prometheus
,
cluster:
cluster
)
}
let
(
:app
)
{
create
(
:clusters_applications_prometheus
)
}
let
(
:command
)
{
app
.
install_command
}
let
(
:namespace
)
{
Gitlab
::
Kubernetes
::
Helm
::
NAMESPACE
}
subject
{
described_class
.
new
(
command
,
namespace
)
}
shared_examples
'helm po
d'
do
context
'with a comman
d'
do
it
'should generate a Kubeclient::Resource'
do
expect
(
subject
.
generate
).
to
be_a_kind_of
(
Kubeclient
::
Resource
)
end
...
...
@@ -41,10 +40,6 @@ describe Gitlab::Kubernetes::Helm::Pod do
spec
=
subject
.
generate
.
spec
expect
(
spec
.
restartPolicy
).
to
eq
(
'Never'
)
end
end
context
'with a install command'
do
it_behaves_like
'helm pod'
it
'should include volumes for the container'
do
container
=
subject
.
generate
.
spec
.
containers
.
first
...
...
@@ -60,24 +55,8 @@ describe Gitlab::Kubernetes::Helm::Pod do
it
'should mount configMap specification in the volume'
do
volume
=
subject
.
generate
.
spec
.
volumes
.
first
expect
(
volume
.
configMap
[
'name'
]).
to
eq
(
"values-content-configuration-
#{
app
.
name
}
"
)
expect
(
volume
.
configMap
[
'items'
].
first
[
'key'
]).
to
eq
(
'values'
)
expect
(
volume
.
configMap
[
'items'
].
first
[
'path'
]).
to
eq
(
'values.yaml'
)
end
end
context
'with a init command'
do
let
(
:app
)
{
create
(
:clusters_applications_helm
,
cluster:
cluster
)
}
it_behaves_like
'helm pod'
it
'should not include volumeMounts inside the container'
do
container
=
subject
.
generate
.
spec
.
containers
.
first
expect
(
container
.
volumeMounts
).
to
be_nil
end
it
'should not a volume inside the specification'
do
spec
=
subject
.
generate
.
spec
expect
(
spec
.
volumes
).
to
be_nil
expect
(
volume
.
configMap
[
'items'
].
first
[
'key'
]).
to
eq
(
:'values.yaml'
)
expect
(
volume
.
configMap
[
'items'
].
first
[
'path'
]).
to
eq
(
:'values.yaml'
)
end
end
end
...
...
spec/models/clusters/applications/helm_spec.rb
View file @
7266edd2
...
...
@@ -6,13 +6,24 @@ describe Clusters::Applications::Helm do
describe
'.installed'
do
subject
{
described_class
.
installed
}
let!
(
:cluster
)
{
create
(
:clusters_applications_helm
,
:installed
)
}
let!
(
:
installed_
cluster
)
{
create
(
:clusters_applications_helm
,
:installed
)
}
before
do
create
(
:clusters_applications_helm
,
:errored
)
end
it
{
is_expected
.
to
contain_exactly
(
cluster
)
}
it
{
is_expected
.
to
contain_exactly
(
installed_cluster
)
}
end
describe
'#issue_client_cert'
do
let
(
:application
)
{
create
(
:clusters_applications_helm
)
}
subject
{
application
.
issue_client_cert
}
it
'returns a new cert'
do
is_expected
.
to
be_kind_of
(
Gitlab
::
Kubernetes
::
Helm
::
Certificate
)
expect
(
subject
.
cert_string
).
not_to
eq
(
application
.
ca_cert
)
expect
(
subject
.
key_string
).
not_to
eq
(
application
.
ca_key
)
end
end
describe
'#install_command'
do
...
...
@@ -25,5 +36,16 @@ describe Clusters::Applications::Helm do
it
'should be initialized with 1 arguments'
do
expect
(
subject
.
name
).
to
eq
(
'helm'
)
end
it
'should have cert files'
do
expect
(
subject
.
files
[
:'ca.pem'
]).
to
be_present
expect
(
subject
.
files
[
:'ca.pem'
]).
to
eq
(
helm
.
ca_cert
)
expect
(
subject
.
files
[
:'cert.pem'
]).
to
be_present
expect
(
subject
.
files
[
:'key.pem'
]).
to
be_present
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
.
files
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
>
999
.
years
.
from_now
end
end
end
spec/models/clusters/applications/ingress_spec.rb
View file @
7266edd2
...
...
@@ -88,7 +88,7 @@ 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
.
values
).
to
eq
(
ingress
.
valu
es
)
expect
(
subject
.
files
).
to
eq
(
ingress
.
fil
es
)
end
context
'application failed to install previously'
do
...
...
@@ -100,14 +100,40 @@ describe Clusters::Applications::Ingress do
end
end
describe
'#values'
do
subject
{
ingress
.
values
}
describe
'#files'
do
let
(
:application
)
{
ingress
}
let
(
:values
)
{
subject
[
:'values.yaml'
]
}
it
'should include ingress valid keys'
do
is_expected
.
to
include
(
'image'
)
is_expected
.
to
include
(
'repository'
)
is_expected
.
to
include
(
'stats'
)
is_expected
.
to
include
(
'podAnnotations'
)
subject
{
application
.
files
}
it
'should include ingress valid keys in values'
do
expect
(
values
).
to
include
(
'image'
)
expect
(
values
).
to
include
(
'repository'
)
expect
(
values
).
to
include
(
'stats'
)
expect
(
values
).
to
include
(
'podAnnotations'
)
end
context
'when the helm application does not have a ca_cert'
do
before
do
application
.
cluster
.
application_helm
.
ca_cert
=
nil
end
it
'should not include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
not_to
be_present
expect
(
subject
[
:'cert.pem'
]).
not_to
be_present
expect
(
subject
[
:'key.pem'
]).
not_to
be_present
end
end
it
'should include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
to
be_present
expect
(
subject
[
:'ca.pem'
]).
to
eq
(
application
.
cluster
.
application_helm
.
ca_cert
)
expect
(
subject
[
:'cert.pem'
]).
to
be_present
expect
(
subject
[
:'key.pem'
]).
to
be_present
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
<
60
.
minutes
.
from_now
end
end
end
spec/models/clusters/applications/jupyter_spec.rb
View file @
7266edd2
...
...
@@ -52,7 +52,7 @@ describe Clusters::Applications::Jupyter do
expect
(
subject
.
chart
).
to
eq
(
'jupyter/jupyterhub'
)
expect
(
subject
.
version
).
to
eq
(
'v0.6'
)
expect
(
subject
.
repository
).
to
eq
(
'https://jupyterhub.github.io/helm-chart/'
)
expect
(
subject
.
values
).
to
eq
(
jupyter
.
valu
es
)
expect
(
subject
.
files
).
to
eq
(
jupyter
.
fil
es
)
end
context
'application failed to install previously'
do
...
...
@@ -64,19 +64,43 @@ describe Clusters::Applications::Jupyter do
end
end
describe
'#values'
do
let
(
:jupyter
)
{
create
(
:clusters_applications_jupyter
)
}
describe
'#files'
do
let
(
:application
)
{
create
(
:clusters_applications_jupyter
)
}
let
(
:values
)
{
subject
[
:'values.yaml'
]
}
subject
{
jupyter
.
values
}
subject
{
application
.
files
}
it
'should include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
to
be_present
expect
(
subject
[
:'ca.pem'
]).
to
eq
(
application
.
cluster
.
application_helm
.
ca_cert
)
expect
(
subject
[
:'cert.pem'
]).
to
be_present
expect
(
subject
[
:'key.pem'
]).
to
be_present
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
<
60
.
minutes
.
from_now
end
context
'when the helm application does not have a ca_cert'
do
before
do
application
.
cluster
.
application_helm
.
ca_cert
=
nil
end
it
'should not include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
not_to
be_present
expect
(
subject
[
:'cert.pem'
]).
not_to
be_present
expect
(
subject
[
:'key.pem'
]).
not_to
be_present
end
end
it
'should include valid values'
do
is_expected
.
to
include
(
'ingress'
)
is_expected
.
to
include
(
'hub'
)
is_expected
.
to
include
(
'rbac'
)
is_expected
.
to
include
(
'proxy'
)
is_expected
.
to
include
(
'auth'
)
is_expected
.
to
include
(
"clientId:
#{
jupyter
.
oauth_application
.
uid
}
"
)
is_expected
.
to
include
(
"callbackUrl:
#{
jupyter
.
callback_url
}
"
)
expect
(
values
)
.
to
include
(
'ingress'
)
expect
(
values
)
.
to
include
(
'hub'
)
expect
(
values
)
.
to
include
(
'rbac'
)
expect
(
values
)
.
to
include
(
'proxy'
)
expect
(
values
)
.
to
include
(
'auth'
)
expect
(
values
).
to
match
(
/clientId: '?
#{
application
.
oauth_application
.
uid
}
/
)
expect
(
values
).
to
match
(
/callbackUrl: '?
#{
application
.
callback_url
}
/
)
end
end
end
spec/models/clusters/applications/prometheus_spec.rb
View file @
7266edd2
...
...
@@ -167,7 +167,7 @@ describe Clusters::Applications::Prometheus do
expect
(
command
.
name
).
to
eq
(
'prometheus'
)
expect
(
command
.
chart
).
to
eq
(
'stable/prometheus'
)
expect
(
command
.
version
).
to
eq
(
'6.7.3'
)
expect
(
command
.
values
).
to
eq
(
prometheus
.
valu
es
)
expect
(
command
.
files
).
to
eq
(
prometheus
.
fil
es
)
end
context
'application failed to install previously'
do
...
...
@@ -179,17 +179,41 @@ describe Clusters::Applications::Prometheus do
end
end
describe
'#values'
do
let
(
:prometheus
)
{
create
(
:clusters_applications_prometheus
)
}
describe
'#files'
do
let
(
:application
)
{
create
(
:clusters_applications_prometheus
)
}
let
(
:values
)
{
subject
[
:'values.yaml'
]
}
subject
{
application
.
files
}
it
'should include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
to
be_present
expect
(
subject
[
:'ca.pem'
]).
to
eq
(
application
.
cluster
.
application_helm
.
ca_cert
)
expect
(
subject
[
:'cert.pem'
]).
to
be_present
expect
(
subject
[
:'key.pem'
]).
to
be_present
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
<
60
.
minutes
.
from_now
end
subject
{
prometheus
.
values
}
context
'when the helm application does not have a ca_cert'
do
before
do
application
.
cluster
.
application_helm
.
ca_cert
=
nil
end
it
'should not include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
not_to
be_present
expect
(
subject
[
:'cert.pem'
]).
not_to
be_present
expect
(
subject
[
:'key.pem'
]).
not_to
be_present
end
end
it
'should include prometheus valid values'
do
is_expected
.
to
include
(
'alertmanager'
)
is_expected
.
to
include
(
'kubeStateMetrics'
)
is_expected
.
to
include
(
'nodeExporter'
)
is_expected
.
to
include
(
'pushgateway'
)
is_expected
.
to
include
(
'serverFiles'
)
expect
(
values
)
.
to
include
(
'alertmanager'
)
expect
(
values
)
.
to
include
(
'kubeStateMetrics'
)
expect
(
values
)
.
to
include
(
'nodeExporter'
)
expect
(
values
)
.
to
include
(
'pushgateway'
)
expect
(
values
)
.
to
include
(
'serverFiles'
)
end
end
end
spec/models/clusters/applications/runner_spec.rb
View file @
7266edd2
...
...
@@ -47,7 +47,7 @@ describe Clusters::Applications::Runner do
expect
(
subject
.
chart
).
to
eq
(
'runner/gitlab-runner'
)
expect
(
subject
.
version
).
to
eq
(
'0.1.31'
)
expect
(
subject
.
repository
).
to
eq
(
'https://charts.gitlab.io'
)
expect
(
subject
.
values
).
to
eq
(
gitlab_runner
.
valu
es
)
expect
(
subject
.
files
).
to
eq
(
gitlab_runner
.
fil
es
)
end
context
'application failed to install previously'
do
...
...
@@ -59,27 +59,51 @@ describe Clusters::Applications::Runner do
end
end
describe
'#values'
do
let
(
:gitlab_runner
)
{
create
(
:clusters_applications_runner
,
runner:
ci_runner
)
}
describe
'#files'
do
let
(
:application
)
{
create
(
:clusters_applications_runner
,
runner:
ci_runner
)
}
let
(
:values
)
{
subject
[
:'values.yaml'
]
}
subject
{
application
.
files
}
it
'should include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
to
be_present
expect
(
subject
[
:'ca.pem'
]).
to
eq
(
application
.
cluster
.
application_helm
.
ca_cert
)
expect
(
subject
[
:'cert.pem'
]).
to
be_present
expect
(
subject
[
:'key.pem'
]).
to
be_present
cert
=
OpenSSL
::
X509
::
Certificate
.
new
(
subject
[
:'cert.pem'
])
expect
(
cert
.
not_after
).
to
be
<
60
.
minutes
.
from_now
end
subject
{
gitlab_runner
.
values
}
context
'when the helm application does not have a ca_cert'
do
before
do
application
.
cluster
.
application_helm
.
ca_cert
=
nil
end
it
'should not include cert files'
do
expect
(
subject
[
:'ca.pem'
]).
not_to
be_present
expect
(
subject
[
:'cert.pem'
]).
not_to
be_present
expect
(
subject
[
:'key.pem'
]).
not_to
be_present
end
end
it
'should include runner valid values'
do
is_expected
.
to
include
(
'concurrent'
)
is_expected
.
to
include
(
'checkInterval'
)
is_expected
.
to
include
(
'rbac'
)
is_expected
.
to
include
(
'runners'
)
is_expected
.
to
include
(
'privileged: true'
)
is_expected
.
to
include
(
'image: ubuntu:16.04'
)
is_expected
.
to
include
(
'resources'
)
is_expected
.
to
include
(
"runnerToken:
#{
ci_runner
.
token
}
"
)
is_expected
.
to
include
(
"gitlabUrl:
#{
Gitlab
::
Routing
.
url_helpers
.
root_url
}
"
)
expect
(
values
)
.
to
include
(
'concurrent'
)
expect
(
values
)
.
to
include
(
'checkInterval'
)
expect
(
values
)
.
to
include
(
'rbac'
)
expect
(
values
)
.
to
include
(
'runners'
)
expect
(
values
)
.
to
include
(
'privileged: true'
)
expect
(
values
)
.
to
include
(
'image: ubuntu:16.04'
)
expect
(
values
)
.
to
include
(
'resources'
)
expect
(
values
).
to
match
(
/runnerToken: '?
#{
ci_runner
.
token
}
/
)
expect
(
values
).
to
match
(
/gitlabUrl: '?
#{
Gitlab
::
Routing
.
url_helpers
.
root_url
}
/
)
end
context
'without a runner'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:cluster
)
{
create
(
:cluster
,
projects:
[
project
])
}
let
(
:
gitlab_runner
)
{
create
(
:clusters_applications_runner
,
cluster:
cluster
)
}
let
(
:cluster
)
{
create
(
:cluster
,
:with_installed_helm
,
projects:
[
project
])
}
let
(
:
application
)
{
create
(
:clusters_applications_runner
,
cluster:
cluster
)
}
it
'creates a runner'
do
expect
do
...
...
@@ -88,18 +112,18 @@ describe Clusters::Applications::Runner do
end
it
'uses the new runner token'
do
expect
(
subject
).
to
include
(
"runnerToken:
#{
gitlab_runner
.
reload
.
runner
.
token
}
"
)
expect
(
values
).
to
match
(
/runnerToken: '?
#{
application
.
reload
.
runner
.
token
}
/
)
end
it
'assigns the new runner to runner'
do
subject
expect
(
gitlab_runner
.
reload
.
runner
).
to
be_project_type
expect
(
application
.
reload
.
runner
).
to
be_project_type
end
end
context
'with duplicated values on vendor/runner/values.yaml'
do
let
(
:values
)
do
let
(
:
stub_
values
)
do
{
"concurrent"
=>
4
,
"checkInterval"
=>
3
,
...
...
@@ -118,11 +142,11 @@ describe Clusters::Applications::Runner do
end
before
do
allow
(
gitlab_runner
).
to
receive
(
:chart_values
).
and_return
(
values
)
allow
(
application
).
to
receive
(
:chart_values
).
and_return
(
stub_
values
)
end
it
'should overwrite values.yaml'
do
is_expected
.
to
include
(
"privileged:
#{
gitlab_runner
.
privileged
}
"
)
expect
(
values
).
to
match
(
/privileged: '?
#{
application
.
privileged
}
/
)
end
end
end
...
...
spec/services/clusters/applications/install_service_spec.rb
View file @
7266edd2
...
...
@@ -47,7 +47,7 @@ describe Clusters::Applications::InstallService do
end
context
'when application cannot be persisted'
do
let
(
:application
)
{
build
(
:clusters_applications_helm
,
:scheduled
)
}
let
(
:application
)
{
create
(
:clusters_applications_helm
,
:scheduled
)
}
it
'make the application errored'
do
expect
(
application
).
to
receive
(
:make_installing!
).
once
.
and_raise
(
ActiveRecord
::
RecordInvalid
)
...
...
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