summaryrefslogtreecommitdiff
path: root/app/models/clusters/concerns/application_status.rb
blob: 0b915126f8a346a01f986a99239c1c066048c2cd (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# frozen_string_literal: true

module Clusters
  module Concerns
    module ApplicationStatus
      extend ActiveSupport::Concern

      included do
        scope :available, -> do
          where(
            status: [
              self.state_machines[:status].states[:installed].value,
              self.state_machines[:status].states[:updated].value
            ]
          )
        end

        state_machine :status, initial: :not_installable do
          state :not_installable, value: -2
          state :errored, value: -1
          state :installable, value: 0
          state :scheduled, value: 1
          state :installing, value: 2
          state :installed, value: 3
          state :updating, value: 4
          state :updated, value: 5
          state :update_errored, value: 6
          state :uninstalling, value: 7
          state :uninstall_errored, value: 8
          state :uninstalled, value: 10

          # Used for applications that are pre-installed by the cluster,
          # e.g. Knative in GCP Cloud Run enabled clusters
          # Because we cannot upgrade or uninstall Knative in these clusters,
          # we define only one simple state transition to enter the `pre_installed` state,
          # and no exit transitions.
          state :pre_installed, value: 9

          event :make_externally_installed do
            transition any => :installed
          end

          event :make_externally_uninstalled do
            transition any => :uninstalled
          end

          event :make_scheduled do
            transition [:installable, :errored, :installed, :updated, :update_errored, :uninstall_errored] => :scheduled
          end

          event :make_installing do
            transition [:scheduled] => :installing
          end

          event :make_installed do
            transition [:installing] => :installed
            transition [:updating] => :updated
          end

          event :make_pre_installed do
            transition any => :pre_installed
          end

          event :make_errored do
            transition any - [:updating, :uninstalling] => :errored
            transition [:updating] => :update_errored
            transition [:uninstalling] => :uninstall_errored
          end

          event :make_updating do
            transition [:installed, :updated, :update_errored, :scheduled] => :updating
          end

          event :make_update_errored do
            transition any => :update_errored
          end

          event :make_uninstalling do
            transition [:scheduled] => :uninstalling
          end

          before_transition any => [:scheduled] do |application, _|
            application.status_reason = nil
          end

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

          before_transition any => [:updating] do |application, _|
            application.status_reason = nil
          end

          before_transition any => [:update_errored, :uninstall_errored] do |application, transition|
            status_reason = transition.args.first
            application.status_reason = status_reason if status_reason
          end

          before_transition any => [:installed, :updated] do |application, _|
            # When installing any application we are also performing an update
            # of tiller (see Gitlab::Kubernetes::Helm::ClientCommand) so
            # therefore we need to reflect that in the database.

            unless ::Gitlab::Kubernetes::Helm.local_tiller_enabled?
              application.cluster.application_helm.update!(version: Gitlab::Kubernetes::Helm::HELM_VERSION)
            end
          end

          after_transition any => [:uninstalling], :use_transactions => false do |application, _|
            application.prepare_uninstall
          end
        end
      end

      def status_states
        self.class.state_machines[:status].states.each_with_object({}) do |state, states|
          states[state.name] = state.value
        end
      end

      def updateable?
        installed? || updated? || update_errored?
      end

      def available?
        pre_installed? || installed? || updated?
      end

      def update_in_progress?
        updating?
      end
    end
  end
end