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
0
Merge Requests
0
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
Léo-Paul Géneau
gitlab-ce
Commits
478e59fe
Commit
478e59fe
authored
Oct 30, 2017
by
Shinya Maeda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
specs for models. Improved details.
parent
d0cff7f5
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
838 additions
and
342 deletions
+838
-342
app/models/clusters/cluster.rb
app/models/clusters/cluster.rb
+13
-13
app/models/clusters/platforms/kubernetes.rb
app/models/clusters/platforms/kubernetes.rb
+28
-22
app/models/clusters/project.rb
app/models/clusters/project.rb
+2
-2
app/models/clusters/providers/gcp.rb
app/models/clusters/providers/gcp.rb
+2
-1
app/validators/cluster_name_validator.rb
app/validators/cluster_name_validator.rb
+1
-1
app/views/projects/clusters/_form.html.haml
app/views/projects/clusters/_form.html.haml
+1
-1
spec/factories/clusters/cluster.rb
spec/factories/clusters/cluster.rb
+39
-0
spec/factories/clusters/platforms/gcp.rb
spec/factories/clusters/platforms/gcp.rb
+28
-0
spec/factories/clusters/providers/kubernetes.rb
spec/factories/clusters/providers/kubernetes.rb
+18
-0
spec/factories/gcp/cluster.rb
spec/factories/gcp/cluster.rb
+0
-38
spec/fixtures/clusters/sample_cert.pem
spec/fixtures/clusters/sample_cert.pem
+33
-0
spec/models/clusters/cluster_spec.rb
spec/models/clusters/cluster_spec.rb
+180
-0
spec/models/clusters/platforms/kubernetes_spec.rb
spec/models/clusters/platforms/kubernetes_spec.rb
+304
-0
spec/models/clusters/project_spec.rb
spec/models/clusters/project_spec.rb
+6
-0
spec/models/clusters/providers/gcp_spec.rb
spec/models/clusters/providers/gcp_spec.rb
+183
-0
spec/models/gcp/cluster_spec.rb
spec/models/gcp/cluster_spec.rb
+0
-264
No files found.
app/models/clusters/cluster.rb
View file @
478e59fe
...
...
@@ -6,15 +6,6 @@ module Clusters
belongs_to
:user
enum
platform_type:
{
kubernetes:
1
}
enum
provider_type:
{
user:
0
,
gcp:
1
}
has_many
:cluster_projects
,
class_name:
'Clusters::Project'
has_many
:projects
,
through: :cluster_projects
,
class_name:
'::Project'
...
...
@@ -32,6 +23,18 @@ module Clusters
delegate
:status_name
,
to: :provider
,
allow_nil:
true
delegate
:on_creation?
,
to: :provider
,
allow_nil:
true
enum
platform_type:
{
kubernetes:
1
}
enum
provider_type:
{
user:
0
,
gcp:
1
}
scope
:enabled
,
->
{
where
(
enabled:
true
)
}
scope
:disabled
,
->
{
where
(
enabled:
false
)
}
def
provider
return
provider_gcp
if
gcp?
end
...
...
@@ -40,15 +43,12 @@ module Clusters
return
platform_kubernetes
if
kubernetes?
end
def
project
first_project
end
def
first_project
return
@first_project
if
defined?
(
@first_project
)
@first_project
=
projects
.
first
end
alias_method
:project
,
:first_project
private
...
...
app/models/clusters/platforms/kubernetes.rb
View file @
478e59fe
module
Clusters
module
Platforms
class
Kubernetes
<
ActiveRecord
::
Base
include
Gitlab
::
CurrentSettings
include
Gitlab
::
Kubernetes
include
ReactiveCaching
self
.
table_name
=
'cluster_platforms_kubernetes'
TEMPLATE_PLACEHOLDER
=
'Kubernetes namespace'
.
freeze
self
.
reactive_cache_key
=
->
(
kubernetes
)
{
[
kubernetes
.
class
.
model_name
.
singular
,
kubernetes
.
cluster_id
]
}
belongs_to
:cluster
,
inverse_of: :platform_kubernetes
,
class_name:
'Clusters::Cluster'
...
...
@@ -22,6 +20,8 @@ module Clusters
key:
Gitlab
::
Application
.
secrets
.
db_key_base
,
algorithm:
'aes-256-cbc'
before_validation
:enforce_namespace_to_lower_case
validates
:namespace
,
allow_blank:
true
,
length:
1
..
63
,
...
...
@@ -34,8 +34,19 @@ module Clusters
validates
:token
,
presence:
true
,
on: :update
after_save
:clear_reactive_cache!
before_validation
:enforce_namespace_to_lower_case
alias_attribute
:ca_pem
,
:ca_cert
delegate
:project
,
to: :cluster
,
allow_nil:
true
delegate
:enabled?
,
to: :cluster
,
allow_nil:
true
alias_method
:active?
,
:enabled?
class
<<
self
def
namespace_for_project
(
project
)
"
#{
project
.
path
}
-
#{
project
.
id
}
"
end
end
def
actual_namespace
if
namespace
.
present?
...
...
@@ -45,6 +56,10 @@ module Clusters
end
end
def
default_namespace
self
.
class
.
namespace_for_project
(
project
)
if
project
end
def
predefined_variables
config
=
YAML
.
dump
(
kubeconfig
)
...
...
@@ -55,9 +70,9 @@ module Clusters
{
key:
'KUBECONFIG'
,
value:
config
,
public:
false
,
file:
true
}
]
if
ca_
cert
.
present?
variables
<<
{
key:
'KUBE_CA_PEM'
,
value:
ca_
cert
,
public:
true
}
variables
<<
{
key:
'KUBE_CA_PEM_FILE'
,
value:
ca_
cert
,
public:
true
,
file:
true
}
if
ca_
pem
.
present?
variables
<<
{
key:
'KUBE_CA_PEM'
,
value:
ca_
pem
,
public:
true
}
variables
<<
{
key:
'KUBE_CA_PEM_FILE'
,
value:
ca_
pem
,
public:
true
,
file:
true
}
end
variables
...
...
@@ -78,7 +93,7 @@ module Clusters
# Caches resources in the namespace so other calls don't need to block on
# network access
def
calculate_reactive_cache
return
unless
active?
&&
cluster
.
project
&&
!
cluster
.
project
.
pending_delete?
return
unless
active?
&&
project
&&
!
project
.
pending_delete?
# We may want to cache extra things in the future
{
pods:
read_pods
}
...
...
@@ -89,16 +104,7 @@ module Clusters
url:
api_url
,
namespace:
actual_namespace
,
token:
token
,
ca_pem:
ca_cert
)
end
def
namespace_placeholder
default_namespace
||
TEMPLATE_PLACEHOLDER
end
def
default_namespace
(
project
=
nil
)
project
||=
cluster
&
.
project
"
#{
project
.
path
}
-
#{
project
.
id
}
"
if
project
ca_pem:
ca_pem
)
end
def
read_secrets
...
...
@@ -123,9 +129,9 @@ module Clusters
def
kubeclient_ssl_options
opts
=
{
verify_ssl:
OpenSSL
::
SSL
::
VERIFY_PEER
}
if
ca_
cert
.
present?
if
ca_
pem
.
present?
opts
[
:cert_store
]
=
OpenSSL
::
X509
::
Store
.
new
opts
[
:cert_store
].
add_cert
(
OpenSSL
::
X509
::
Certificate
.
new
(
ca_
cert
))
opts
[
:cert_store
].
add_cert
(
OpenSSL
::
X509
::
Certificate
.
new
(
ca_
pem
))
end
opts
...
...
@@ -166,7 +172,7 @@ module Clusters
def
terminal_auth
{
token:
token
,
ca_pem:
ca_
cert
,
ca_pem:
ca_
pem
,
max_session_time:
current_application_settings
.
terminal_max_session_time
}
end
...
...
app/models/clusters/project.rb
View file @
478e59fe
...
...
@@ -2,7 +2,7 @@ module Clusters
class
Project
<
ActiveRecord
::
Base
self
.
table_name
=
'cluster_projects'
belongs_to
:cluster
,
inverse_of: :projects
,
class_name:
'Clusters::Cluster'
belongs_to
:project
,
inverse_of: :project
,
class_name:
'
Project'
belongs_to
:cluster
,
class_name:
'Clusters::Cluster'
belongs_to
:project
,
class_name:
'::
Project'
end
end
app/models/clusters/providers/gcp.rb
View file @
478e59fe
...
...
@@ -55,7 +55,8 @@ module Clusters
before_transition
any
=>
[
:creating
]
do
|
provider
,
transition
|
operation_id
=
transition
.
args
.
first
provider
.
operation_id
=
operation_id
if
operation_id
raise
'operation_id is required'
unless
operation_id
provider
.
operation_id
=
operation_id
end
before_transition
any
=>
[
:errored
]
do
|
provider
,
transition
|
...
...
app/validators/cluster_name_validator.rb
View file @
478e59fe
...
...
@@ -8,7 +8,7 @@ class ClusterNameValidator < ActiveModel::EachValidator
record
.
errors
.
add
(
attribute
,
" has to be present"
)
end
elsif
record
.
gcp?
if
record
.
persisted?
&&
record
.
name
!=
value
if
record
.
persisted?
&&
record
.
name
_changed?
record
.
errors
.
add
(
attribute
,
" can not be changed because it's synchronized with provider"
)
end
...
...
app/views/projects/clusters/_form.html.haml
View file @
478e59fe
...
...
@@ -35,7 +35,7 @@
=
field
.
fields_for
:platform_kubernetes
,
@cluster
.
platform_kubernetes
do
|
platform_kubernetes_field
|
.form-group
=
platform_kubernetes_field
.
label
:namespace
,
s_
(
'ClusterIntegration|Project namespace (optional, unique)'
)
=
platform_kubernetes_field
.
text_field
:namespace
,
class:
'form-control'
,
placeholder:
@cluster
.
platform_kubernetes
.
default_namespace
(
@project
)
=
platform_kubernetes_field
.
text_field
:namespace
,
class:
'form-control'
,
placeholder:
Clusters
::
Platforms
::
Kubernetes
.
namespace_for_project
(
@project
)
.form-group
=
field
.
submit
s_
(
'ClusterIntegration|Create cluster'
),
class:
'btn btn-save'
spec/factories/clusters/cluster.rb
0 → 100644
View file @
478e59fe
FactoryGirl
.
define
do
factory
:cluster
,
class:
Clusters
::
Cluster
do
user
name
'test-cluster'
provider_type
:user
platform_type
:kubernetes
trait
:project
do
after
(
:create
)
do
|
cluster
,
evaluator
|
cluster
.
projects
<<
create
(
:project
)
end
end
trait
:provided_by_user
do
provider_type
:user
platform_type
:kubernetes
platform_kubernetes
end
trait
:provided_by_gcp
do
provider_type
:gcp
platform_type
:kubernetes
platform_kubernetes
provider_gcp
do
create
(
:provider_gcp
,
:created
)
end
end
trait
:providing_by_gcp
do
provider_type
:gcp
platform_type
:kubernetes
provider_gcp
do
create
(
:provider_gcp
,
:creating
)
end
end
end
end
spec/factories/clusters/platforms/gcp.rb
0 → 100644
View file @
478e59fe
FactoryGirl
.
define
do
factory
:provider_gcp
,
class:
Clusters
::
Providers
::
Gcp
do
cluster
gcp_project_id
'test-gcp-project'
trait
:creating
do
access_token
'access_token_123'
after
(
:build
)
do
|
gcp
,
evaluator
|
gcp
.
make_creating
(
'operation-123'
)
end
end
trait
:created
do
endpoint
'111.111.111.111'
after
(
:build
)
do
|
gcp
,
evaluator
|
gcp
.
make_created
end
end
trait
:errored
do
after
(
:build
)
do
|
gcp
,
evaluator
|
gcp
.
make_errored
(
'Something wrong'
)
end
end
end
end
spec/factories/clusters/providers/kubernetes.rb
0 → 100644
View file @
478e59fe
FactoryGirl
.
define
do
factory
:platform_kubernetes
,
class:
Clusters
::
Platforms
::
Kubernetes
do
cluster
api_url
'https://kubernetes.example.com'
ca_cert
nil
token
'a'
*
40
username
'xxxxxx'
password
'xxxxxx'
namespace
nil
trait
:ca_cert
do
after
(
:create
)
do
|
platform_kubernetes
,
evaluator
|
pem_file
=
File
.
expand_path
(
Rails
.
root
.
join
(
'spec/fixtures/clusters/sample_cert.pem'
))
platform_kubernetes
.
ca_cert
=
File
.
read
(
pem_file
)
end
end
end
end
spec/factories/gcp/cluster.rb
deleted
100644 → 0
View file @
d0cff7f5
# FactoryGirl.define do
# factory :gcp_cluster, class: Gcp::Cluster do
# project
# user
# enabled true
# gcp_project_id 'gcp-project-12345'
# gcp_cluster_name 'test-cluster'
# gcp_cluster_zone 'us-central1-a'
# gcp_cluster_size 1
# gcp_machine_type 'n1-standard-4'
# trait :with_kubernetes_service do
# after(:create) do |cluster, evaluator|
# create(:kubernetes_service, project: cluster.project).tap do |service|
# cluster.update(service: service)
# end
# end
# end
# trait :custom_project_namespace do
# project_namespace 'sample-app'
# end
# trait :created_on_gke do
# status_event :make_created
# endpoint '111.111.111.111'
# ca_cert 'xxxxxx'
# kubernetes_token 'xxxxxx'
# username 'xxxxxx'
# password 'xxxxxx'
# end
# trait :errored do
# status_event :make_errored
# status_reason 'general error'
# end
# end
# end
spec/fixtures/clusters/sample_cert.pem
0 → 100644
View file @
478e59fe
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIJAOutg3Kf2y5dMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcxMDI5MTgxOTU3WhcNMTgxMDI5MTgxOTU3WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEAvQysroM3TLxaavadSPnFIltrYnxCnU4PvCR8971HMWXsq7Z4ShU4BbbE
8yp7oUFjulSwW6DhdIvnQb8ihLKictLmrA0isQqrD/iNpKZ6/lI4DGWw4QzrvMnW
V4yy2QZNpg9tzQHd4+xkeeIoG23RijDU/sPd5dqxF+rPHBfCVInmYvSzLvMhneNj
Bt6gV02gU9e9hsnMatsDvEbvWKp7wcbPot0nWrfZulx2QAWyXy+zG9mJQUds6yc0
4agAeT9JEb/xtRgR/kS0aUHSGnfSnhZiEn17s0PhTmbu7qSHgzgB+7oJrC9jPoUh
S2Wo3n0xykAjHrA8wC/Ddw3L38S41VQ58GEfNchistPswyMmXo/Oenv9P3s/kCOI
fndiksFNdqVo51y9Vjngj589hpOseFDyKmWPIEQZ9kxW/crjP6RZWWLHgz26KtxZ
uJaoYL8VBbYfrk/bucw0Ma2GEOp8rTsBE7SvgejXZa78q+381Kzc/utW6VwSXqzY
xeIitft0rXi17SZ+XoiTkIXtHn0ZwMtOXNDBADTpFmKa6wVACQilvcpOYD8gUHyH
pB+EDRdST3M4Fiq1MBAVhk8Lj3tHSJ/1ymeF1PWSu57AnJlzerzq2fcfPotNNd37
ZPNkPh0kxPLwxbAyrHflzx9qVVdI1irY9055mNSnhzlec4qJ9cECAwEAAaOBpzCB
pDAdBgNVHQ4EFgQUnVa5dYPoIG/3+qXml0bX8+N16GwwdQYDVR0jBG4wbIAUnVa5
dYPoIG/3+qXml0bX8+N16GyhSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDr
rYNyn9suXTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAUg4cyxXi1
VR8ejTpaAruRyJ1pEG9Kc3kiIRXODy60z3hJXnx9LkScPkWGiuL5XacfZ2rMd4bw
oVXIyi8U1UHWfAH8EZdrFKkU92jCiL5soHUONxLAvQEJ/FTR/qijrpzLCxXBdVQE
xFEDWUu6rxLFyjEwzwnRTLgpjR606fdb7qXHkuAMvZ/ezJj8j97hok3Odpn4lr2H
6hMTpK7HmDBX+kmdJJ+yBrm9hG1Pzpl7QU0dkxZ+qJNFjYMLnziiTwkv0c5ZaA9E
NykZUcOv3Sjb6spu1A/E2BSq4WTjkIjrogFlfimE1vmUmObTRJOqUB0Vky1kHEwN
pg7QqIJQmof1EAIaSM/YpUWXyumBwGLDUEud1JUz05In9Q4IZjEwZSJwbQW4fUia
A93m9rk3Lw3xsFcaUdPMFIXk0rPoF1IgmV/oqb0gK95lOWRLbN+AV8qpKPpcKXOc
TkIdFE47ZisEDhIdF6wC1izEMLeMEsPAO7/Y6MY4nRxsinSe95lRaw+yQpzx+mvJ
Q7n1kiHI9Pd5M3+CiQda0d/GO1o5ORJnUGJRvr9HKuNmE7Lif0As/N0AlywjzE7A
6Z8AEiWyRV1ffshu1k2UKmzvZuZeGGKRtrIjbJIRAtpRVtVZZGzhq5/sojCLoJ+u
texqFBUo/4mFRZa4pDItUdyOlDy2/LO/ag==
-----END CERTIFICATE-----
spec/models/clusters/cluster_spec.rb
0 → 100644
View file @
478e59fe
require
'spec_helper'
describe
Clusters
::
Cluster
do
it
{
is_expected
.
to
belong_to
(
:user
)
}
it
{
is_expected
.
to
have_many
(
:projects
)
}
it
{
is_expected
.
to
have_one
(
:provider_gcp
)
}
it
{
is_expected
.
to
have_one
(
:platform_kubernetes
)
}
it
{
is_expected
.
to
delegate_method
(
:status
).
to
(
:provider
)
}
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
respond_to
:project
}
describe
'.enabled'
do
subject
{
described_class
.
enabled
}
let!
(
:cluster
)
{
create
(
:cluster
,
enabled:
true
)
}
before
do
create
(
:cluster
,
enabled:
false
)
end
it
{
is_expected
.
to
contain_exactly
(
cluster
)
}
end
describe
'.disabled'
do
subject
{
described_class
.
disabled
}
let!
(
:cluster
)
{
create
(
:cluster
,
enabled:
false
)
}
before
do
create
(
:cluster
,
enabled:
true
)
end
it
{
is_expected
.
to
contain_exactly
(
cluster
)
}
end
describe
'validation'
do
subject
{
cluster
.
valid?
}
context
'when validates name'
do
context
'when provided by user'
do
let!
(
:cluster
)
{
build
(
:cluster
,
:provided_by_user
,
name:
name
)
}
context
'when name is empty'
do
let
(
:name
)
{
''
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when name is nil'
do
let
(
:name
)
{
nil
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when name is present'
do
let
(
:name
)
{
'cluster-name-1'
}
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when provided by gcp'
do
let!
(
:cluster
)
{
build
(
:cluster
,
:provided_by_gcp
,
name:
name
)
}
context
'when name is shorter than 1'
do
let
(
:name
)
{
''
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when name is longer than 63'
do
let
(
:name
)
{
'a'
*
64
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when name includes invalid character'
do
let
(
:name
)
{
'!!!!!!'
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when name is present'
do
let
(
:name
)
{
'cluster-name-1'
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when record is persisted'
do
let
(
:name
)
{
'cluster-name-1'
}
before
do
cluster
.
save!
end
context
'when name is changed'
do
before
do
cluster
.
name
=
'new-cluster-name'
end
it
{
is_expected
.
to
be_falsey
}
end
context
'when name is same'
do
before
do
cluster
.
name
=
name
end
it
{
is_expected
.
to
be_truthy
}
end
end
end
end
context
'when validates restrict_modification'
do
context
'when creation is on going'
do
let!
(
:cluster
)
{
create
(
:cluster
,
:providing_by_gcp
)
}
it
{
expect
(
cluster
.
update
(
enabled:
false
)).
to
be_falsey
}
end
context
'when creation is done'
do
let!
(
:cluster
)
{
create
(
:cluster
,
:provided_by_gcp
)
}
it
{
expect
(
cluster
.
update
(
enabled:
false
)).
to
be_truthy
}
end
end
end
describe
'#provider'
do
subject
{
cluster
.
provider
}
context
'when provider is gcp'
do
let
(
:cluster
)
{
create
(
:cluster
,
:provided_by_gcp
)
}
it
'returns a provider'
do
is_expected
.
to
eq
(
cluster
.
provider_gcp
)
expect
(
subject
.
class
.
name
.
deconstantize
).
to
eq
(
Clusters
::
Providers
.
to_s
)
end
end
context
'when provider is user'
do
let
(
:cluster
)
{
create
(
:cluster
,
:provided_by_user
)
}
it
{
is_expected
.
to
be_nil
}
end
end
describe
'#platform'
do
subject
{
cluster
.
platform
}
context
'when platform is kubernetes'
do
let
(
:cluster
)
{
create
(
:cluster
,
:provided_by_user
)
}
it
'returns a platform'
do
is_expected
.
to
eq
(
cluster
.
platform_kubernetes
)
expect
(
subject
.
class
.
name
.
deconstantize
).
to
eq
(
Clusters
::
Platforms
.
to_s
)
end
end
end
describe
'#first_project'
do
subject
{
cluster
.
first_project
}
context
'when cluster belongs to a project'
do
let
(
:cluster
)
{
create
(
:cluster
,
:project
)
}
let
(
:project
)
{
Clusters
::
Project
.
find_by_cluster_id
(
cluster
.
id
).
project
}
it
{
is_expected
.
to
eq
(
project
)
}
end
context
'when cluster does not belong to projects'
do
let
(
:cluster
)
{
create
(
:cluster
)
}
it
{
is_expected
.
to
be_nil
}
end
end
end
spec/models/clusters/platforms/kubernetes_spec.rb
0 → 100644
View file @
478e59fe
require
'spec_helper'
describe
Clusters
::
Platforms
::
Kubernetes
,
:use_clean_rails_memory_store_caching
do
include
KubernetesHelpers
include
ReactiveCachingHelpers
it
{
is_expected
.
to
belong_to
(
:cluster
)
}
it
{
is_expected
.
to
be_kind_of
(
Gitlab
::
Kubernetes
)
}
it
{
is_expected
.
to
be_kind_of
(
ReactiveCaching
)
}
it
{
is_expected
.
to
respond_to
:ca_pem
}
describe
'before_validation'
do
context
'when namespace includes upper case'
do
let
(
:kubernetes
)
{
create
(
:platform_kubernetes
,
namespace:
namespace
)
}
let
(
:namespace
)
{
'ABC'
}
it
'converts to lower case'
do
expect
(
kubernetes
.
namespace
).
to
eq
(
'abc'
)
end
end
end
describe
'validation'
do
subject
{
kubernetes
.
valid?
}
context
'when validates namespace'
do
let
(
:kubernetes
)
{
build
(
:platform_kubernetes
,
namespace:
namespace
)
}
context
'when namespace is blank'
do
let
(
:namespace
)
{
''
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when namespace is longer than 63'
do
let
(
:namespace
)
{
'a'
*
64
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when namespace includes invalid character'
do
let
(
:namespace
)
{
'!!!!!!'
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when namespace is vaild'
do
let
(
:namespace
)
{
'namespace-123'
}
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when validates api_url'
do
context
'when updates a record'
do
let
(
:kubernetes
)
{
create
(
:platform_kubernetes
)
}
before
do
kubernetes
.
api_url
=
api_url
end
context
'when api_url is invalid url'
do
let
(
:api_url
)
{
'!!!!!!'
}
it
{
expect
(
kubernetes
.
save
).
to
be_falsey
}
end
context
'when api_url is nil'
do
let
(
:api_url
)
{
nil
}
it
{
expect
(
kubernetes
.
save
).
to
be_falsey
}
end
context
'when api_url is valid url'
do
let
(
:api_url
)
{
'https://111.111.111.111'
}
it
{
expect
(
kubernetes
.
save
).
to
be_truthy
}
end
end
context
'when creates a record'
do
let
(
:kubernetes
)
{
build
(
:platform_kubernetes
)
}
before
do
kubernetes
.
api_url
=
api_url
end
context
'when api_url is nil'
do
let
(
:api_url
)
{
nil
}
it
{
expect
(
kubernetes
.
save
).
to
be_truthy
}
end
end
end
context
'when validates token'
do
context
'when updates a record'
do
let
(
:kubernetes
)
{
create
(
:platform_kubernetes
)
}
before
do
kubernetes
.
token
=
token
end
context
'when token is nil'
do
let
(
:token
)
{
nil
}
it
{
expect
(
kubernetes
.
save
).
to
be_falsey
}
end
end
context
'when creates a record'
do
let
(
:kubernetes
)
{
build
(
:platform_kubernetes
)
}
before
do
kubernetes
.
token
=
token
end
context
'when token is nil'
do
let
(
:token
)
{
nil
}
it
{
expect
(
kubernetes
.
save
).
to
be_truthy
}
end
end
end
end
describe
'#actual_namespace'
do
subject
{
kubernetes
.
actual_namespace
}
let!
(
:cluster
)
{
create
(
:cluster
,
:project
,
platform_kubernetes:
kubernetes
)
}
let
(
:kubernetes
)
{
create
(
:platform_kubernetes
,
namespace:
namespace
)
}
context
'when namespace is present'
do
let
(
:namespace
)
{
'namespace-123'
}
it
{
is_expected
.
to
eq
(
namespace
)
}
end
context
'when namespace is not present'
do
let
(
:namespace
)
{
nil
}
it
{
is_expected
.
to
eq
(
"
#{
cluster
.
project
.
path
}
-
#{
cluster
.
project
.
id
}
"
)
}
end
end
describe
'.namespace_for_project'
do
subject
{
described_class
.
namespace_for_project
(
project
)
}
let
(
:project
)
{
create
(
:project
)
}
it
{
is_expected
.
to
eq
(
"
#{
project
.
path
}
-
#{
project
.
id
}
"
)
}
end
describe
'#default_namespace'
do
subject
{
kubernetes
.
default_namespace
}
let
(
:kubernetes
)
{
create
(
:platform_kubernetes
)
}
context
'when cluster belongs to a project'
do
let!
(
:cluster
)
{
create
(
:cluster
,
:project
,
platform_kubernetes:
kubernetes
)
}
it
{
is_expected
.
to
eq
(
"
#{
cluster
.
project
.
path
}
-
#{
cluster
.
project
.
id
}
"
)
}
end
context
'when cluster belongs to nothing'
do
let!
(
:cluster
)
{
create
(
:cluster
,
platform_kubernetes:
kubernetes
)
}
it
{
is_expected
.
to
be_nil
}
end
end
describe
'#predefined_variables'
do
let!
(
:cluster
)
{
create
(
:cluster
,
:project
,
platform_kubernetes:
kubernetes
)
}
let
(
:kubernetes
)
{
create
(
:platform_kubernetes
,
api_url:
api_url
,
ca_cert:
ca_pem
,
token:
token
)
}
let
(
:api_url
)
{
'https://kube.domain.com'
}
let
(
:ca_pem
)
{
'CA PEM DATA'
}
let
(
:token
)
{
'token'
}
let
(
:kubeconfig
)
do
config_file
=
expand_fixture_path
(
'config/kubeconfig.yml'
)
config
=
YAML
.
load
(
File
.
read
(
config_file
))
config
.
dig
(
'users'
,
0
,
'user'
)[
'token'
]
=
token
config
.
dig
(
'contexts'
,
0
,
'context'
)[
'namespace'
]
=
namespace
config
.
dig
(
'clusters'
,
0
,
'cluster'
)[
'certificate-authority-data'
]
=
Base64
.
strict_encode64
(
ca_pem
)
YAML
.
dump
(
config
)
end
shared_examples
'setting variables'
do
it
'sets the variables'
do
expect
(
kubernetes
.
predefined_variables
).
to
include
(
{
key:
'KUBE_URL'
,
value:
api_url
,
public:
true
},
{
key:
'KUBE_TOKEN'
,
value:
token
,
public:
false
},
{
key:
'KUBE_NAMESPACE'
,
value:
namespace
,
public:
true
},
{
key:
'KUBECONFIG'
,
value:
kubeconfig
,
public:
false
,
file:
true
},
{
key:
'KUBE_CA_PEM'
,
value:
ca_pem
,
public:
true
},
{
key:
'KUBE_CA_PEM_FILE'
,
value:
ca_pem
,
public:
true
,
file:
true
}
)
end
end
context
'namespace is provided'
do
let
(
:namespace
)
{
'my-project'
}
before
do
kubernetes
.
namespace
=
namespace
end
it_behaves_like
'setting variables'
end
context
'no namespace provided'
do
let
(
:namespace
)
{
kubernetes
.
actual_namespace
}
it_behaves_like
'setting variables'
it
'sets the KUBE_NAMESPACE'
do
kube_namespace
=
kubernetes
.
predefined_variables
.
find
{
|
h
|
h
[
:key
]
==
'KUBE_NAMESPACE'
}
expect
(
kube_namespace
).
not_to
be_nil
expect
(
kube_namespace
[
:value
]).
to
match
(
/\A
#{
Gitlab
::
PathRegex
::
PATH_REGEX_STR
}
-\d+\z/
)
end
end
end
describe
'#terminals'
do
subject
{
service
.
terminals
(
environment
)
}
let!
(
:cluster
)
{
create
(
:cluster
,
:project
,
platform_kubernetes:
service
)
}
let
(
:project
)
{
cluster
.
project
}
let
(
:service
)
{
create
(
:platform_kubernetes
)
}
let
(
:environment
)
{
build
(
:environment
,
project:
project
,
name:
"env"
,
slug:
"env-000000"
)
}
context
'with invalid pods'
do
it
'returns no terminals'
do
stub_reactive_cache
(
service
,
pods:
[{
"bad"
=>
"pod"
}])
is_expected
.
to
be_empty
end
end
context
'with valid pods'
do
let
(
:pod
)
{
kube_pod
(
app:
environment
.
slug
)
}
let
(
:terminals
)
{
kube_terminals
(
service
,
pod
)
}
before
do
stub_reactive_cache
(
service
,
pods:
[
pod
,
pod
,
kube_pod
(
app:
"should-be-filtered-out"
)]
)
end
it
'returns terminals'
do
is_expected
.
to
eq
(
terminals
+
terminals
)
end
it
'uses max session time from settings'
do
stub_application_setting
(
terminal_max_session_time:
600
)
times
=
subject
.
map
{
|
terminal
|
terminal
[
:max_session_time
]
}
expect
(
times
).
to
eq
[
600
,
600
,
600
,
600
]
end
end
end
describe
'#calculate_reactive_cache'
do
subject
{
service
.
calculate_reactive_cache
}
let!
(
:cluster
)
{
create
(
:cluster
,
:project
,
enabled:
enabled
,
platform_kubernetes:
service
)
}
let
(
:service
)
{
create
(
:platform_kubernetes
,
:ca_cert
)
}
let
(
:enabled
)
{
true
}
context
'when cluster is disabled'
do
let
(
:enabled
)
{
false
}
it
{
is_expected
.
to
be_nil
}
end
context
'when kubernetes responds with valid pods'
do
before
do
stub_kubeclient_pods
end
it
{
is_expected
.
to
eq
(
pods:
[
kube_pod
])
}
end
context
'when kubernetes responds with 500s'
do
before
do
stub_kubeclient_pods
(
status:
500
)
end
it
{
expect
{
subject
}.
to
raise_error
(
KubeException
)
}
end
context
'when kubernetes responds with 404s'
do
before
do
stub_kubeclient_pods
(
status:
404
)
end
it
{
is_expected
.
to
eq
(
pods:
[])
}
end
end
end
spec/models/clusters/project_spec.rb
0 → 100644
View file @
478e59fe
require
'spec_helper'
describe
Clusters
::
Project
do
it
{
is_expected
.
to
belong_to
(
:cluster
)
}
it
{
is_expected
.
to
belong_to
(
:project
)
}
end
spec/models/clusters/providers/gcp_spec.rb
0 → 100644
View file @
478e59fe
require
'spec_helper'
describe
Clusters
::
Providers
::
Gcp
do
it
{
is_expected
.
to
belong_to
(
:cluster
)
}
it
{
is_expected
.
to
validate_presence_of
(
:zone
)
}
describe
'default_value_for'
do
let
(
:gcp
)
{
build
(
:provider_gcp
)
}
it
"has default value"
do
expect
(
gcp
.
zone
).
to
eq
(
'us-central1-a'
)
expect
(
gcp
.
num_nodes
).
to
eq
(
3
)
expect
(
gcp
.
machine_type
).
to
eq
(
'n1-standard-4'
)
end
end
describe
'validation'
do
subject
{
gcp
.
valid?
}
context
'when validates gcp_project_id'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
gcp_project_id:
gcp_project_id
)
}
context
'when gcp_project_id is shorter than 1'
do
let
(
:gcp_project_id
)
{
''
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when gcp_project_id is longer than 63'
do
let
(
:gcp_project_id
)
{
'a'
*
64
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when gcp_project_id includes invalid character'
do
let
(
:gcp_project_id
)
{
'!!!!!!'
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when gcp_project_id is valid'
do
let
(
:gcp_project_id
)
{
'gcp-project-1'
}
it
{
is_expected
.
to
be_truthy
}
end
end
context
'when validates num_nodes'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
num_nodes:
num_nodes
)
}
context
'when num_nodes is string'
do
let
(
:num_nodes
)
{
'A3'
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when num_nodes is nil'
do
let
(
:num_nodes
)
{
nil
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when num_nodes is smaller than 1'
do
let
(
:num_nodes
)
{
0
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when num_nodes is valid'
do
let
(
:num_nodes
)
{
3
}
it
{
is_expected
.
to
be_truthy
}
end
end
end
describe
'#state_machine'
do
context
'when any => [:created]'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
:creating
)
}
before
do
gcp
.
make_created
end
it
'nullify access_token and operation_id'
do
expect
(
gcp
.
access_token
).
to
be_nil
expect
(
gcp
.
operation_id
).
to
be_nil
expect
(
gcp
).
to
be_created
end
end
context
'when any => [:creating]'
do
let
(
:gcp
)
{
build
(
:provider_gcp
)
}
context
'when operation_id is present'
do
let
(
:operation_id
)
{
'operation-xxx'
}
before
do
gcp
.
make_creating
(
operation_id
)
end
it
'sets operation_id'
do
expect
(
gcp
.
operation_id
).
to
eq
(
operation_id
)
expect
(
gcp
).
to
be_creating
end
end
context
'when operation_id is nil'
do
let
(
:operation_id
)
{
nil
}
it
'raises an error'
do
expect
{
gcp
.
make_creating
(
operation_id
)
}
.
to
raise_error
(
'operation_id is required'
)
end
end
end
context
'when any => [:errored]'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
:creating
)
}
let
(
:status_reason
)
{
'err msg'
}
it
'nullify access_token and operation_id'
do
gcp
.
make_errored
(
status_reason
)
expect
(
gcp
.
access_token
).
to
be_nil
expect
(
gcp
.
operation_id
).
to
be_nil
expect
(
gcp
.
status_reason
).
to
eq
(
status_reason
)
expect
(
gcp
).
to
be_errored
end
context
'when status_reason is nil'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
:errored
)
}
it
'does not set status_reason'
do
gcp
.
make_errored
(
nil
)
expect
(
gcp
.
status_reason
).
not_to
be_nil
end
end
end
end
describe
'#on_creation?'
do
subject
{
gcp
.
on_creation?
}
context
'when status is creating'
do
let
(
:gcp
)
{
create
(
:provider_gcp
,
:creating
)
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when status is created'
do
let
(
:gcp
)
{
create
(
:provider_gcp
,
:created
)
}
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#api_client'
do
subject
{
gcp
.
api_client
}
context
'when status is creating'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
:creating
)
}
it
'returns Cloud Platform API clinet'
do
expect
(
subject
).
to
be_an_instance_of
(
GoogleApi
::
CloudPlatform
::
Client
)
expect
(
subject
.
access_token
).
to
eq
(
gcp
.
access_token
)
end
end
context
'when status is created'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
:created
)
}
it
{
is_expected
.
to
be_nil
}
end
context
'when status is errored'
do
let
(
:gcp
)
{
build
(
:provider_gcp
,
:errored
)
}
it
{
is_expected
.
to
be_nil
}
end
end
end
spec/models/gcp/cluster_spec.rb
deleted
100644 → 0
View file @
d0cff7f5
require
'spec_helper'
describe
Gcp
::
Cluster
do
it
{
is_expected
.
to
belong_to
(
:project
)
}
it
{
is_expected
.
to
belong_to
(
:user
)
}
it
{
is_expected
.
to
belong_to
(
:service
)
}
it
{
is_expected
.
to
validate_presence_of
(
:gcp_cluster_zone
)
}
describe
'.enabled'
do
subject
{
described_class
.
enabled
}
let!
(
:cluster
)
{
create
(
:gcp_cluster
,
enabled:
true
)
}
before
do
create
(
:gcp_cluster
,
enabled:
false
)
end
it
{
is_expected
.
to
contain_exactly
(
cluster
)
}
end
describe
'.disabled'
do
subject
{
described_class
.
disabled
}
let!
(
:cluster
)
{
create
(
:gcp_cluster
,
enabled:
false
)
}
before
do
create
(
:gcp_cluster
,
enabled:
true
)
end
it
{
is_expected
.
to
contain_exactly
(
cluster
)
}
end
describe
'#default_value_for'
do
let
(
:cluster
)
{
described_class
.
new
}
it
{
expect
(
cluster
.
gcp_cluster_zone
).
to
eq
(
'us-central1-a'
)
}
it
{
expect
(
cluster
.
gcp_cluster_size
).
to
eq
(
3
)
}
it
{
expect
(
cluster
.
gcp_machine_type
).
to
eq
(
'n1-standard-4'
)
}
end
describe
'#validates'
do
subject
{
cluster
.
valid?
}
context
'when validates gcp_project_id'
do
let
(
:cluster
)
{
build
(
:gcp_cluster
,
gcp_project_id:
gcp_project_id
)
}
context
'when valid'
do
let
(
:gcp_project_id
)
{
'gcp-project-12345'
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when empty'
do
let
(
:gcp_project_id
)
{
''
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when too long'
do
let
(
:gcp_project_id
)
{
'A'
*
64
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when includes abnormal character'
do
let
(
:gcp_project_id
)
{
'!!!!!!'
}
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when validates gcp_cluster_name'
do
let
(
:cluster
)
{
build
(
:gcp_cluster
,
gcp_cluster_name:
gcp_cluster_name
)
}
context
'when valid'
do
let
(
:gcp_cluster_name
)
{
'test-cluster'
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when empty'
do
let
(
:gcp_cluster_name
)
{
''
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when too long'
do
let
(
:gcp_cluster_name
)
{
'A'
*
64
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when includes abnormal character'
do
let
(
:gcp_cluster_name
)
{
'!!!!!!'
}
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when validates gcp_cluster_size'
do
let
(
:cluster
)
{
build
(
:gcp_cluster
,
gcp_cluster_size:
gcp_cluster_size
)
}
context
'when valid'
do
let
(
:gcp_cluster_size
)
{
1
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when zero'
do
let
(
:gcp_cluster_size
)
{
0
}
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when validates project_namespace'
do
let
(
:cluster
)
{
build
(
:gcp_cluster
,
project_namespace:
project_namespace
)
}
context
'when valid'
do
let
(
:project_namespace
)
{
'default-namespace'
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when empty'
do
let
(
:project_namespace
)
{
''
}
it
{
is_expected
.
to
be_truthy
}
end
context
'when too long'
do
let
(
:project_namespace
)
{
'A'
*
64
}
it
{
is_expected
.
to
be_falsey
}
end
context
'when includes abnormal character'
do
let
(
:project_namespace
)
{
'!!!!!!'
}
it
{
is_expected
.
to
be_falsey
}
end
end
context
'when validates restrict_modification'
do
let
(
:cluster
)
{
create
(
:gcp_cluster
)
}
before
do
cluster
.
make_creating!
end
context
'when created'
do
before
do
cluster
.
make_created!
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when creating'
do
it
{
is_expected
.
to
be_falsey
}
end
end
end
describe
'#state_machine'
do
let
(
:cluster
)
{
build
(
:gcp_cluster
)
}
context
'when transits to created state'
do
before
do
cluster
.
gcp_token
=
'tmp'
cluster
.
gcp_operation_id
=
'tmp'
cluster
.
make_created!
end
it
'nullify gcp_token and gcp_operation_id'
do
expect
(
cluster
.
gcp_token
).
to
be_nil
expect
(
cluster
.
gcp_operation_id
).
to
be_nil
expect
(
cluster
).
to
be_created
end
end
context
'when transits to errored state'
do
let
(
:reason
)
{
'something wrong'
}
before
do
cluster
.
make_errored!
(
reason
)
end
it
'sets status_reason'
do
expect
(
cluster
.
status_reason
).
to
eq
(
reason
)
expect
(
cluster
).
to
be_errored
end
end
end
describe
'#project_namespace_placeholder'
do
subject
{
cluster
.
project_namespace_placeholder
}
let
(
:cluster
)
{
create
(
:gcp_cluster
)
}
it
'returns a placeholder'
do
is_expected
.
to
eq
(
"
#{
cluster
.
project
.
path
}
-
#{
cluster
.
project
.
id
}
"
)
end
end
describe
'#on_creation?'
do
subject
{
cluster
.
on_creation?
}
let
(
:cluster
)
{
create
(
:gcp_cluster
)
}
context
'when status is creating'
do
before
do
cluster
.
make_creating!
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when status is created'
do
before
do
cluster
.
make_created!
end
it
{
is_expected
.
to
be_falsey
}
end
end
describe
'#api_url'
do
subject
{
cluster
.
api_url
}
let
(
:cluster
)
{
create
(
:gcp_cluster
,
:created_on_gke
)
}
let
(
:api_url
)
{
'https://'
+
cluster
.
endpoint
}
it
{
is_expected
.
to
eq
(
api_url
)
}
end
describe
'#restrict_modification'
do
subject
{
cluster
.
restrict_modification
}
let
(
:cluster
)
{
create
(
:gcp_cluster
)
}
context
'when status is created'
do
before
do
cluster
.
make_created!
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when status is creating'
do
before
do
cluster
.
make_creating!
end
it
{
is_expected
.
to
be_falsey
}
it
'sets error'
do
is_expected
.
to
be_falsey
expect
(
cluster
.
errors
).
not_to
be_empty
end
end
end
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