summaryrefslogtreecommitdiff
path: root/app/models/gcp/cluster.rb
blob: 18bd6a6dcb47e6d8f17f4c9b66a99715999d4728 (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
106
107
108
109
110
111
112
113
module Gcp
  class Cluster < ActiveRecord::Base
    extend Gitlab::Gcp::Model
    include Presentable

    belongs_to :project, inverse_of: :cluster
    belongs_to :user
    belongs_to :service

    default_value_for :gcp_cluster_zone, 'us-central1-a'
    default_value_for :gcp_cluster_size, 3
    default_value_for :gcp_machine_type, 'n1-standard-4'

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

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

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

    validates :gcp_project_id,
      length: 1..63,
      format: {
        with: Gitlab::Regex.kubernetes_namespace_regex,
        message: Gitlab::Regex.kubernetes_namespace_regex_message
      }

    validates :gcp_cluster_name,
      length: 1..63,
      format: {
        with: Gitlab::Regex.kubernetes_namespace_regex,
        message: Gitlab::Regex.kubernetes_namespace_regex_message
      }

    validates :gcp_cluster_zone, presence: true

    validates :gcp_cluster_size,
      presence: true,
      numericality: {
        only_integer: true,
        greater_than: 0
      }

    validates :project_namespace,
      allow_blank: true,
      length: 1..63,
      format: {
        with: Gitlab::Regex.kubernetes_namespace_regex,
        message: Gitlab::Regex.kubernetes_namespace_regex_message
      }

    # if we do not do status transition we prevent change
    validate :restrict_modification, on: :update, unless: :status_changed?

    state_machine :status, initial: :scheduled do
      state :scheduled, value: 1
      state :creating, value: 2
      state :created, value: 3
      state :errored, value: 4

      event :make_creating do
        transition any - [:creating] => :creating
      end

      event :make_created do
        transition any - [:created] => :created
      end

      event :make_errored do
        transition any - [:errored] => :errored
      end

      before_transition any => [:errored, :created] do |cluster|
        cluster.gcp_token = nil
        cluster.gcp_operation_id = nil
      end

      before_transition any => [:errored] do |cluster, transition|
        status_reason = transition.args.first
        cluster.status_reason = status_reason if status_reason
      end
    end

    def project_namespace_placeholder
      "#{project.path}-#{project.id}"
    end

    def on_creation?
      scheduled? || creating?
    end

    def api_url
      'https://' + endpoint if endpoint
    end

    def restrict_modification
      if on_creation?
        errors.add(:base, "cannot modify during creation")
        return false
      end

      true
    end
  end
end