diff options
author | Nick Thomas <nick@gitlab.com> | 2016-12-08 16:36:26 +0000 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2016-12-14 21:06:26 +0000 |
commit | b7b83fe0c9368fa6f04dcb6eb8cd247978bba76b (patch) | |
tree | 9e2a6a71c20b8c379cfc7031903df93456c3cb10 /app | |
parent | 3e90aa1119fc4c77e92e6492f1906f252d90b64e (diff) | |
download | gitlab-ce-b7b83fe0c9368fa6f04dcb6eb8cd247978bba76b.tar.gz |
Introduce deployment services, starting with a KubernetesService
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/concerns/service_params.rb | 2 | ||||
-rw-r--r-- | app/models/project.rb | 9 | ||||
-rw-r--r-- | app/models/project_services/deployment_service.rb | 11 | ||||
-rw-r--r-- | app/models/project_services/kubernetes_service.rb | 118 | ||||
-rw-r--r-- | app/models/service.rb | 1 |
5 files changed, 140 insertions, 1 deletions
diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index c33d7eecb9f..549a8526715 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -18,7 +18,7 @@ module ServiceParams :add_pusher, :send_from_committer_email, :disable_diffs, :external_wiki_url, :notify, :color, :server_host, :server_port, :default_irc_uri, :enable_ssl_verification, - :jira_issue_transition_id, :url, :project_key] + :jira_issue_transition_id, :url, :project_key, :ca_pem, :namespace] # Parameters to ignore if no value is specified FILTER_BLANK_PARAMS = [:password] diff --git a/app/models/project.rb b/app/models/project.rb index 77d740081c6..2c726cfc5df 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -106,6 +106,7 @@ class Project < ActiveRecord::Base has_one :bugzilla_service, dependent: :destroy has_one :gitlab_issue_tracker_service, dependent: :destroy, inverse_of: :project has_one :external_wiki_service, dependent: :destroy + has_one :kubernetes_service, dependent: :destroy, inverse_of: :project has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" has_one :forked_from_project, through: :forked_project_link @@ -742,6 +743,14 @@ class Project < ActiveRecord::Base @ci_service ||= ci_services.reorder(nil).find_by(active: true) end + def deployment_services + services.where(category: :deployment) + end + + def deployment_service + @deployment_service ||= deployment_services.reorder(nil).find_by(active: true) + end + def jira_tracker? issues_tracker.to_param == 'jira' end diff --git a/app/models/project_services/deployment_service.rb b/app/models/project_services/deployment_service.rb new file mode 100644 index 00000000000..55e98c31251 --- /dev/null +++ b/app/models/project_services/deployment_service.rb @@ -0,0 +1,11 @@ +# Base class for deployment services +# +# These services integrate with a deployment solution like Kubernetes/OpenShift, +# Mesosphere, etc, to provide additional features to environments. +class DeploymentService < Service + default_value_for :category, 'deployment' + + def supported_events + [] + end +end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb new file mode 100644 index 00000000000..80ae1191108 --- /dev/null +++ b/app/models/project_services/kubernetes_service.rb @@ -0,0 +1,118 @@ +class KubernetesService < DeploymentService + # Namespace defaults to the project path, but can be overridden in case that + # is an invalid or inappropriate name + prop_accessor :namespace + + # Access to kubernetes is directly through the API + prop_accessor :api_url + + # Bearer authentication + # TODO: user/password auth, client certificates + prop_accessor :token + + # Provide a custom CA bundle for self-signed deployments + prop_accessor :ca_pem + + with_options presence: true, if: :activated? do + validates :api_url, url: true + validates :token + + validates :namespace, + format: { + with: Gitlab::Regex.kubernetes_namespace_regex, + message: Gitlab::Regex.kubernetes_namespace_regex_message, + }, + length: 1..63 + end + + def initialize_properties + if properties.nil? + self.properties = {} + self.namespace = project.path if project.present? + end + end + + def title + 'Kubernetes' + end + + def description + 'Kubernetes / Openshift integration' + end + + def help + '' + end + + def to_param + 'kubernetes' + end + + def fields + [ + { type: 'text', + name: 'namespace', + title: 'Kubernetes namespace', + placeholder: 'Kubernetes namespace', + }, + { type: 'text', + name: 'api_url', + title: 'API URL', + placeholder: 'Kubernetes API URL, like https://kube.example.com/', + }, + { type: 'text', + name: 'token', + title: 'Service token', + placeholder: 'Service token', + }, + { type: 'textarea', + name: 'ca_pem', + title: 'Custom CA bundle', + placeholder: 'Certificate Authority bundle (PEM format)', + }, + ] + end + + # Check we can connect to the Kubernetes API + def test(*args) + kubeclient = build_kubeclient + kubeclient.discover + + { success: kubeclient.discovered, result: "Checked API discovery endpoint" } + rescue => err + { success: false, result: err } + end + + private + + def build_kubeclient(api_path = '/api', api_version = 'v1') + return nil unless api_url && namespace && token + + url = URI.parse(api_url) + url.path = url.path[0..-2] if url.path[-1] == "/" + url.path += api_path + + ::Kubeclient::Client.new( + url, + api_version, + ssl_options: kubeclient_ssl_options, + auth_options: kubeclient_auth_options, + http_proxy_uri: ENV['http_proxy'] + ) + 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 + + def kubeclient_auth_options + { bearer_token: token } + end +end diff --git a/app/models/service.rb b/app/models/service.rb index 0c36acfc1b7..e49a8fa2904 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -214,6 +214,7 @@ class Service < ActiveRecord::Base hipchat irker jira + kubernetes mattermost_slash_commands pipelines_email pivotaltracker |