summaryrefslogtreecommitdiff
path: root/app/models/clusters/platforms/kubernetes.rb
blob: 74f7c9442db3a2d9734865f0d6c60d61758c011e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module Clusters
  module Platforms
    class Kubernetes < ActiveRecord::Base
      self.table_name = 'cluster_platforms_kubernetes'

      belongs_to :cluster, inverse_of: :platform_kubernetes, class_name: 'Clusters::Cluster'

      attr_encrypted :password,
        mode: :per_attribute_iv,
        key: Gitlab::Application.secrets.db_key_base,
        algorithm: 'aes-256-cbc'

      attr_encrypted :token,
        mode: :per_attribute_iv,
        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,
        format: {
          with: Gitlab::Regex.kubernetes_namespace_regex,
          message: Gitlab::Regex.kubernetes_namespace_regex_message
        }

      # We expect to be `active?` only when enabled and cluster is created (the api_url is assigned)
      validates :api_url, url: true, presence: true
      validates :token, presence: true

      # TODO: Glue code till we migrate Kubernetes Integration into Platforms::Kubernetes
      after_destroy :destroy_kubernetes_integration!

      alias_attribute :ca_pem, :ca_cert

      delegate :project, to: :cluster, allow_nil: true
      delegate :enabled?, to: :cluster, allow_nil: true

      class << self
        def namespace_for_project(project)
          "#{project.path}-#{project.id}"
        end
      end

      def actual_namespace
        if namespace.present?
          namespace
        else
          default_namespace
        end
      end

      def default_namespace
        self.class.namespace_for_project(project) if project
      end

      def kubeclient
        @kubeclient ||= kubernetes_service.kubeclient if manages_kubernetes_service?
      end

      def update_kubernetes_integration!
        raise 'Kubernetes service already configured' unless manages_kubernetes_service?

        # This is neccesary, otheriwse enabled? returns true even though cluster updated with enabled: false
        cluster.reload

        ensure_kubernetes_service&.update!(
          active: enabled?,
          api_url: api_url,
          namespace: namespace,
          token: token,
          ca_pem: ca_cert
        )
      end

      private

      def enforce_namespace_to_lower_case
        self.namespace = self.namespace&.downcase
      end

      # TODO: glue code till we migrate Kubernetes Service into Platforms::Kubernetes class
      def manages_kubernetes_service?
        return true unless kubernetes_service&.active?

        kubernetes_service.api_url == api_url
      end

      def destroy_kubernetes_integration!
        return unless manages_kubernetes_service?

        kubernetes_service&.destroy!
      end

      def kubernetes_service
        @kubernetes_service ||= project&.kubernetes_service
      end

      def ensure_kubernetes_service
        @kubernetes_service ||= kubernetes_service || project&.build_kubernetes_service
      end
    end
  end
end