BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
2d1a77b8
Commit
2d1a77b8
authored
Oct 01, 2017
by
Shinya Maeda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert KubernetesService. Introduce FetchKubernetesTokenService.
parent
e499c1c3
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
123 additions
and
80 deletions
+123
-80
cluster.rb
app/models/ci/cluster.rb
+5
-3
kubernetes_service.rb
app/models/project_services/kubernetes_service.rb
+1
-15
create_cluster_service.rb
app/services/ci/create_cluster_service.rb
+4
-0
fetch_kubernetes_token_service.rb
app/services/ci/fetch_kubernetes_token_service.rb
+70
-0
integrate_cluster_service.rb
app/services/ci/integrate_cluster_service.rb
+11
-16
update_cluster_service.rb
app/services/ci/update_cluster_service.rb
+5
-9
_form.html.haml
app/views/projects/clusters/_form.html.haml
+2
-2
wait_for_cluster_creation_worker.rb
app/workers/wait_for_cluster_creation_worker.rb
+19
-32
client.rb
lib/google_api/cloud_platform/client.rb
+6
-3
No files found.
app/models/ci/cluster.rb
View file @
2d1a77b8
...
@@ -33,13 +33,15 @@ module Ci
...
@@ -33,13 +33,15 @@ module Ci
}
}
def
error!
(
reason
)
def
error!
(
reason
)
update!
(
status:
statuses
[
:errored
],
update!
(
status:
statuses
[
:errored
],
status_reason:
reason
,
gcp_token:
nil
)
status_reason:
reason
,
gcp_token:
nil
)
end
end
def
on_creation?
def
on_creation?
scheduled?
||
creating?
scheduled?
||
creating?
end
end
def
api_url
'https://'
+
endpoint
end
end
end
end
end
app/models/project_services/kubernetes_service.rb
View file @
2d1a77b8
...
@@ -15,7 +15,6 @@ class KubernetesService < DeploymentService
...
@@ -15,7 +15,6 @@ class KubernetesService < DeploymentService
# Bearer authentication
# Bearer authentication
# TODO: user/password auth, client certificates
# TODO: user/password auth, client certificates
prop_accessor
:token
prop_accessor
:token
attr_accessor
:username
,
:password
# Provide a custom CA bundle for self-signed deployments
# Provide a custom CA bundle for self-signed deployments
prop_accessor
:ca_pem
prop_accessor
:ca_pem
...
@@ -139,15 +138,6 @@ class KubernetesService < DeploymentService
...
@@ -139,15 +138,6 @@ class KubernetesService < DeploymentService
TEMPLATE_PLACEHOLDER
=
'Kubernetes namespace'
.
freeze
TEMPLATE_PLACEHOLDER
=
'Kubernetes namespace'
.
freeze
def
read_secrets
kubeclient
=
build_kubeclient!
kubeclient
.
get_secrets
.
as_json
rescue
KubeException
=>
err
raise
err
unless
err
.
error_code
==
404
[]
end
private
private
def
kubeconfig
def
kubeconfig
...
@@ -167,7 +157,7 @@ class KubernetesService < DeploymentService
...
@@ -167,7 +157,7 @@ class KubernetesService < DeploymentService
end
end
def
build_kubeclient!
(
api_path:
'api'
,
api_version:
'v1'
)
def
build_kubeclient!
(
api_path:
'api'
,
api_version:
'v1'
)
raise
"Incomplete settings"
unless
api_url
&&
(
token
||
(
username
&&
password
))
raise
"Incomplete settings"
unless
api_url
&&
actual_namespace
&&
token
::
Kubeclient
::
Client
.
new
(
::
Kubeclient
::
Client
.
new
(
join_api_url
(
api_path
),
join_api_url
(
api_path
),
...
@@ -200,11 +190,7 @@ class KubernetesService < DeploymentService
...
@@ -200,11 +190,7 @@ class KubernetesService < DeploymentService
end
end
def
kubeclient_auth_options
def
kubeclient_auth_options
if
token
{
bearer_token:
token
}
{
bearer_token:
token
}
else
{
username:
username
,
password:
password
}
end
end
end
def
join_api_url
(
api_path
)
def
join_api_url
(
api_path
)
...
...
app/services/ci/create_cluster_service.rb
View file @
2d1a77b8
module
Ci
module
Ci
class
CreateClusterService
<
BaseService
class
CreateClusterService
<
BaseService
def
execute
(
access_token
)
def
execute
(
access_token
)
if
params
[
'machine_type'
].
blank?
params
[
'machine_type'
]
=
GoogleApi
::
CloudPlatform
::
Client
::
DEFAULT_MACHINE_TYPE
end
project
.
clusters
.
create
(
project
.
clusters
.
create
(
params
.
merge
(
user:
current_user
,
params
.
merge
(
user:
current_user
,
status:
Ci
::
Cluster
.
statuses
[
:scheduled
],
status:
Ci
::
Cluster
.
statuses
[
:scheduled
],
...
...
app/services/ci/fetch_kubernetes_token_service.rb
0 → 100644
View file @
2d1a77b8
##
# TODO:
# Almost components in this class were copied from app/models/project_services/kubernetes_service.rb
# We should dry up those classes not to repeat the same code.
# Maybe we should have a special facility (e.g. lib/kubernetes_api) to maintain all Kubernetes API caller.
module
Ci
class
FetchKubernetesTokenService
attr_reader
:api_url
,
:ca_pem
,
:username
,
:password
def
initialize
(
api_url
,
ca_pem
,
username
,
password
)
@api_url
=
api_url
@ca_pem
=
ca_pem
@username
=
username
@password
=
password
end
def
execute
read_secrets
.
each
do
|
secret
|
name
=
secret
.
dig
(
'metadata'
,
'name'
)
if
/default-token/
=~
name
token_base64
=
secret
.
dig
(
'data'
,
'token'
)
return
Base64
.
decode64
(
token_base64
)
if
token_base64
end
end
end
private
def
read_secrets
kubeclient
=
build_kubeclient!
kubeclient
.
get_secrets
.
as_json
rescue
KubeException
=>
err
raise
err
unless
err
.
error_code
==
404
[]
end
def
build_kubeclient!
(
api_path:
'api'
,
api_version:
'v1'
)
raise
"Incomplete settings"
unless
api_url
&&
username
&&
password
::
Kubeclient
::
Client
.
new
(
join_api_url
(
api_path
),
api_version
,
auth_options:
{
username:
username
,
password:
password
},
ssl_options:
kubeclient_ssl_options
,
http_proxy_uri:
ENV
[
'http_proxy'
]
)
end
def
join_api_url
(
api_path
)
url
=
URI
.
parse
(
api_url
)
prefix
=
url
.
path
.
sub
(
%r{/+
\z
}
,
''
)
url
.
path
=
[
prefix
,
api_path
].
join
(
"/"
)
url
.
to_s
end
def
kubeclient_ssl_options
opts
=
{
verify_ssl:
OpenSSL
::
SSL
::
VERIFY_PEER
}
if
ca_pem
.
present?
opts
[
:cert_store
]
=
OpenSSL
::
X509
::
Store
.
new
opts
[
:cert_store
].
add_cert
(
OpenSSL
::
X509
::
Certificate
.
new
(
ca_pem
))
end
opts
end
end
end
app/services/ci/integrate_cluster_service.rb
View file @
2d1a77b8
module
Ci
module
Ci
class
IntegrateClusterService
class
IntegrateClusterService
def
execute
(
cluster
,
endpoint
,
ca_cert
,
token
,
username
,
password
)
def
execute
(
cluster
,
endpoint
,
ca_cert
,
token
,
username
,
password
)
kubernetes_service
||=
cluster
.
project
.
find_or_initialize_service
(
'kubernetes'
)
Ci
::
Cluster
.
transaction
do
Ci
::
Cluster
.
transaction
do
# Update service
kubernetes_service
||=
kubernetes_service
.
attributes
=
{
cluster
.
project
.
find_or_initialize_service
(
'kubernetes'
)
active:
true
,
api_url:
endpoint
,
ca_pem:
ca_cert
,
namespace:
cluster
.
project_namespace
,
token:
token
}
kubernetes_service
.
save!
# Save info in cluster record
cluster
.
update!
(
cluster
.
update!
(
enabled:
true
,
enabled:
true
,
service:
kubernetes_service
,
service:
kubernetes_service
,
...
@@ -25,10 +14,16 @@ module Ci
...
@@ -25,10 +14,16 @@ module Ci
ca_cert:
ca_cert
,
ca_cert:
ca_cert
,
endpoint:
endpoint
,
endpoint:
endpoint
,
gcp_token:
nil
,
gcp_token:
nil
,
status:
Ci
::
Cluster
.
statuses
[
:created
]
gcp_operation_id:
nil
,
)
status:
Ci
::
Cluster
.
statuses
[
:created
])
end
kubernetes_service
.
update!
(
active:
true
,
api_url:
cluster
.
api_url
,
ca_pem:
ca_cert
,
namespace:
cluster
.
project_namespace
,
token:
token
)
end
rescue
ActiveRecord
::
RecordInvalid
=>
e
rescue
ActiveRecord
::
RecordInvalid
=>
e
cluster
.
error!
(
"Failed to integrate cluster into kubernetes_service:
#{
e
.
message
}
"
)
cluster
.
error!
(
"Failed to integrate cluster into kubernetes_service:
#{
e
.
message
}
"
)
end
end
...
...
app/services/ci/update_cluster_service.rb
View file @
2d1a77b8
...
@@ -2,22 +2,18 @@ module Ci
...
@@ -2,22 +2,18 @@ module Ci
class
UpdateClusterService
<
BaseService
class
UpdateClusterService
<
BaseService
def
execute
(
cluster
)
def
execute
(
cluster
)
Ci
::
Cluster
.
transaction
do
Ci
::
Cluster
.
transaction
do
if
params
[
'enabled'
]
==
'true'
cluster
.
update!
(
enabled:
params
[
'enabled'
])
cluster
.
service
.
attributes
=
{
if
params
[
'enabled'
]
==
'true'
cluster
.
service
.
update!
(
active:
true
,
active:
true
,
api_url:
cluster
.
endpoint
,
api_url:
cluster
.
api_url
,
ca_pem:
cluster
.
ca_cert
,
ca_pem:
cluster
.
ca_cert
,
namespace:
cluster
.
project_namespace
,
namespace:
cluster
.
project_namespace
,
token:
cluster
.
kubernetes_token
token:
cluster
.
kubernetes_token
)
}
cluster
.
service
.
save!
else
else
cluster
.
service
.
update
(
active:
false
)
cluster
.
service
.
update
(
active:
false
)
end
end
cluster
.
update!
(
enabled:
params
[
'enabled'
])
end
end
rescue
ActiveRecord
::
RecordInvalid
=>
e
rescue
ActiveRecord
::
RecordInvalid
=>
e
cluster
.
errors
.
add
(
:base
,
e
.
message
)
cluster
.
errors
.
add
(
:base
,
e
.
message
)
...
...
app/views/projects/clusters/_form.html.haml
View file @
2d1a77b8
...
@@ -33,4 +33,4 @@
...
@@ -33,4 +33,4 @@
=
field
.
submit
s_
(
'ClusterIntegration|Create cluster'
),
class:
'btn btn-save'
=
field
.
submit
s_
(
'ClusterIntegration|Create cluster'
),
class:
'btn btn-save'
-# TODO: Remove before merge
-# TODO: Remove before merge
=
link_to
"Create on Google Container Engine"
,
namespace_project_clusters_path
(
@project
.
namespace
,
@project
,
cluster:
{
cluster_name:
"gke-test-creation
#{
Random
.
rand
(
100
)
}
"
,
gcp_project_id:
'gitlab-internal-153318'
,
cluster_zone:
'us-central1-a'
,
cluster_size:
'1'
,
project_namespace:
'aaa'
,
machine_type:
'???'
}),
method: :post
=
link_to
"Create on Google Container Engine"
,
namespace_project_clusters_path
(
@project
.
namespace
,
@project
,
cluster:
{
cluster_name:
"gke-test-creation
#{
Random
.
rand
(
100
)
}
"
,
gcp_project_id:
'gitlab-internal-153318'
,
cluster_zone:
'us-central1-a'
,
cluster_size:
'1'
,
project_namespace:
'aaa'
,
machine_type:
'n1-standard-1'
}),
method: :post
\ No newline at end of file
\ No newline at end of file
app/workers/wait_for_cluster_creation_worker.rb
View file @
2d1a77b8
...
@@ -19,67 +19,54 @@ class WaitForClusterCreationWorker
...
@@ -19,67 +19,54 @@ class WaitForClusterCreationWorker
operation
=
api_client
.
projects_zones_operations
(
operation
=
api_client
.
projects_zones_operations
(
cluster
.
gcp_project_id
,
cluster
.
gcp_project_id
,
cluster
.
cluster_zone
,
cluster
.
cluster_zone
,
cluster
.
gcp_operation_id
cluster
.
gcp_operation_id
)
)
if
operation
.
is_a?
(
StandardError
)
if
operation
.
is_a?
(
StandardError
)
return
cluster
.
error!
(
"Failed to request to CloudPlatform;
#{
operation
.
message
}
"
)
return
cluster
.
error!
(
"Failed to request to CloudPlatform;
#{
operation
.
message
}
"
)
end
end
case
operation
.
status
case
operation
.
status
when
'DONE'
integrate
(
api_client
,
cluster
)
when
'RUNNING'
when
'RUNNING'
if
Time
.
now
<
operation
.
start_time
.
to_time
+
TIMEOUT
if
Time
.
now
<
operation
.
start_time
.
to_time
+
TIMEOUT
WaitForClusterCreationWorker
.
perform_in
(
EAGER_INTERVAL
,
cluster
.
id
)
WaitForClusterCreationWorker
.
perform_in
(
EAGER_INTERVAL
,
cluster
.
id
)
else
else
return
cluster
.
error!
(
"Cluster creation time exceeds timeout;
#{
TIMEOUT
}
"
)
return
cluster
.
error!
(
"Cluster creation time exceeds timeout;
#{
TIMEOUT
}
"
)
end
end
when
'DONE'
integrate
(
cluster
,
api_client
)
else
else
return
cluster
.
error!
(
"Unexpected operation status;
#{
operation
.
status_message
}
"
)
return
cluster
.
error!
(
"Unexpected operation status;
#{
operation
.
status
}
#{
operation
.
status
_message
}
"
)
end
end
end
end
def
integrate
(
api_client
,
cluster
)
def
integrate
(
cluster
,
api_client
)
# Get cluster details (end point, etc)
gke_cluster
=
api_client
.
projects_zones_clusters_get
(
gke_cluster
=
api_client
.
projects_zones_clusters_get
(
cluster
.
gcp_project_id
,
cluster
.
gcp_project_id
,
cluster
.
cluster_zone
,
cluster
.
cluster_zone
,
cluster
.
cluster_name
cluster
.
cluster_name
)
)
if
gke_cluster
.
is_a?
(
StandardError
)
if
gke_cluster
.
is_a?
(
StandardError
)
return
cluster
.
error!
(
"Failed to request to CloudPlatform;
#{
gke_cluster
.
message
}
"
)
return
cluster
.
error!
(
"Failed to request to CloudPlatform;
#{
gke_cluster
.
message
}
"
)
end
end
# Get k8s token
begin
kubernetes_token
=
''
endpoint
=
gke_cluster
.
endpoint
KubernetesService
.
new
.
tap
do
|
ks
|
api_url
=
'https://'
+
endpoint
ks
.
api_url
=
'https://'
+
gke_cluster
.
endpoint
ca_cert
=
Base64
.
decode64
(
gke_cluster
.
master_auth
.
cluster_ca_certificate
)
ks
.
ca_pem
=
Base64
.
decode64
(
gke_cluster
.
master_auth
.
cluster_ca_certificate
)
username
=
gke_cluster
.
master_auth
.
username
ks
.
username
=
gke_cluster
.
master_auth
.
username
password
=
gke_cluster
.
master_auth
.
password
ks
.
password
=
gke_cluster
.
master_auth
.
password
rescue
Exception
=>
e
secrets
=
ks
.
read_secrets
return
cluster
.
error!
(
"Can not extract the extected data;
#{
e
}
"
)
secrets
.
each
do
|
secret
|
name
=
secret
.
dig
(
'metadata'
,
'name'
)
if
/default-token/
=~
name
token_base64
=
secret
.
dig
(
'data'
,
'token'
)
kubernetes_token
=
Base64
.
decode64
(
token_base64
)
break
end
end
end
end
kubernetes_token
=
Ci
::
FetchKubernetesTokenService
.
new
(
api_url
,
ca_cert
,
username
,
password
).
execute
unless
kubernetes_token
unless
kubernetes_token
return
cluster
.
error!
(
'Failed to get a default token of kubernetes'
)
return
cluster
.
error!
(
'Failed to get a default token of kubernetes'
)
end
end
# k8s endpoint, ca_cert
Ci
::
IntegrateClusterService
.
new
.
execute
(
endpoint
=
'https://'
+
gke_cluster
.
endpoint
cluster
,
endpoint
,
ca_cert
,
kubernetes_token
,
username
,
password
)
ca_cert
=
Base64
.
decode64
(
gke_cluster
.
master_auth
.
cluster_ca_certificate
)
username
=
gke_cluster
.
master_auth
.
username
password
=
gke_cluster
.
master_auth
.
password
Ci
::
IntegrateClusterService
.
new
.
execute
(
cluster
,
endpoint
,
ca_cert
,
kubernetes_token
,
username
,
password
)
end
end
end
end
lib/google_api/cloud_platform/client.rb
View file @
2d1a77b8
...
@@ -3,6 +3,8 @@ require 'google/apis/container_v1'
...
@@ -3,6 +3,8 @@ require 'google/apis/container_v1'
module
GoogleApi
module
GoogleApi
module
CloudPlatform
module
CloudPlatform
class
Client
<
GoogleApi
::
Auth
class
Client
<
GoogleApi
::
Auth
DEFAULT_MACHINE_TYPE
=
'n1-standard-1'
class
<<
self
class
<<
self
def
session_key_for_token
def
session_key_for_token
:cloud_platform_access_token
:cloud_platform_access_token
...
@@ -27,8 +29,6 @@ module GoogleApi
...
@@ -27,8 +29,6 @@ module GoogleApi
cluster
cluster
end
end
# Responce exmaple
# TODO: machine_type : Defailt 3.75 GB
def
projects_zones_clusters_create
(
project_id
,
zone
,
cluster_name
,
cluster_size
,
machine_type
:)
def
projects_zones_clusters_create
(
project_id
,
zone
,
cluster_name
,
cluster_size
,
machine_type
:)
service
=
Google
::
Apis
::
ContainerV1
::
ContainerService
.
new
service
=
Google
::
Apis
::
ContainerV1
::
ContainerService
.
new
service
.
authorization
=
access_token
service
.
authorization
=
access_token
...
@@ -37,7 +37,10 @@ module GoogleApi
...
@@ -37,7 +37,10 @@ module GoogleApi
{
{
"cluster"
:
{
"cluster"
:
{
"name"
:
cluster_name
,
"name"
:
cluster_name
,
"initial_node_count"
:
cluster_size
"initial_node_count"
:
cluster_size
,
"node_config"
:
{
"machine_type"
:
machine_type
# Default 3.75 GB, if ommit
}
}
}
}
}
)
)
...
...
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