summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorShinya Maeda <shinya@gitlab.com>2017-11-21 21:09:55 +0900
committerShinya Maeda <shinya@gitlab.com>2017-11-28 20:47:59 +0900
commit8a55d2c5526ee5cb93bb40075dbbeaa6fcb01f91 (patch)
treeb67163385d4e66e3a35fc4cf5da079dfca22ea55 /app
parent25a3a1838ab3224be0b6c658ea16fd1b37135372 (diff)
downloadgitlab-ce-8a55d2c5526ee5cb93bb40075dbbeaa6fcb01f91.tar.gz
Revert KubernetesService logic in Platforms::Kubernetes
Diffstat (limited to 'app')
-rw-r--r--app/models/clusters/platforms/kubernetes.rb123
1 files changed, 123 insertions, 0 deletions
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 6dc1ee810d3..a1e686d0d12 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -1,7 +1,12 @@
module Clusters
module Platforms
class Kubernetes < ActiveRecord::Base
+ include Gitlab::CurrentSettings
+ include Gitlab::Kubernetes
+ include ReactiveCaching
+
self.table_name = 'cluster_platforms_kubernetes'
+ self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.cluster_id] }
belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster'
@@ -29,6 +34,8 @@ module Clusters
validates :api_url, url: true, presence: true
validates :token, presence: true
+ after_save :clear_reactive_cache!
+
# TODO: Glue code till we migrate Kubernetes Integration into Platforms::Kubernetes
after_destroy :destroy_kubernetes_integration!
@@ -55,6 +62,80 @@ module Clusters
self.class.namespace_for_project(project) if project
end
+ def predefined_variables
+ config = YAML.dump(kubeconfig)
+
+ variables = [
+ { key: 'KUBE_URL', value: api_url, public: true },
+ { key: 'KUBE_TOKEN', value: token, public: false },
+ { key: 'KUBE_NAMESPACE', value: actual_namespace, public: true },
+ { key: 'KUBECONFIG', value: config, public: false, 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
+ end
+
+ # Constructs a list of terminals from the reactive cache
+ #
+ # Returns nil if the cache is empty, in which case you should try again a
+ # short time later
+ def terminals(environment)
+ with_reactive_cache do |data|
+ pods = filter_by_label(data[:pods], app: environment.slug)
+ terminals = pods.flat_map { |pod| terminals_for_pod(api_url, actual_namespace, pod) }
+ terminals.each { |terminal| add_terminal_auth(terminal, terminal_auth) }
+ end
+ end
+
+ # Caches resources in the namespace so other calls don't need to block on
+ # network access
+ def calculate_reactive_cache
+ return unless active? && project && !project.pending_delete?
+
+ # We may want to cache extra things in the future
+ { pods: read_pods }
+ end
+
+ def kubeconfig
+ to_kubeconfig(
+ url: api_url,
+ namespace: actual_namespace,
+ token: token,
+ ca_pem: ca_pem)
+ end
+
+ def read_secrets
+ kubeclient = build_kubeclient!
+
+ kubeclient.get_secrets.as_json
+ end
+
+ # Returns a hash of all pods in the namespace
+ def read_pods
+ kubeclient = build_kubeclient!
+
+ kubeclient.get_pods(namespace: actual_namespace).as_json
+ rescue KubeException => err
+ raise err unless err.error_code == 404
+ []
+ 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
@kubeclient ||= kubernetes_service.kubeclient if manages_kubernetes_service?
end
@@ -104,6 +185,48 @@ module Clusters
def ensure_kubernetes_service
@kubernetes_service ||= kubernetes_service || project&.build_kubernetes_service
end
+
+ def build_kubeclient!(api_path: 'api', api_version: 'v1')
+ raise "Incomplete settings" unless api_url && actual_namespace
+
+ unless (username && password) || token
+ raise "Either username/password or token is required to access API"
+ end
+
+ ::Kubeclient::Client.new(
+ join_api_url(api_path),
+ api_version,
+ auth_options: kubeclient_auth_options,
+ ssl_options: kubeclient_ssl_options,
+ http_proxy_uri: ENV['http_proxy']
+ )
+ end
+
+ def kubeclient_auth_options
+ return { username: username, password: password } if username && password
+ return { bearer_token: token } if token
+ end
+
+ def join_api_url(api_path)
+ url = URI.parse(api_url)
+ prefix = url.path.sub(%r{/+\z}, '')
+
+ url.path = [prefix, api_path].join("/")
+
+ url.to_s
+ end
+
+ def terminal_auth
+ {
+ token: token,
+ ca_pem: ca_pem,
+ max_session_time: current_application_settings.terminal_max_session_time
+ }
+ end
+
+ def enforce_namespace_to_lower_case
+ self.namespace = self.namespace&.downcase
+ end
end
end
end