Class: Kitsune::Kit::Operations::EnsureService

Inherits:
Object
  • Object
show all
Defined in:
lib/kitsune/kit/operations/ensure_service.rb

Constant Summary collapse

TYPES =
%w[postgres redis].freeze
MARKER_DIRECTORY =
"/var/lib/kitsune/state"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config:, type:, transport_factory:, state_store:, secret_store:, clock: -> { Time.now.utc }) ⇒ EnsureService

Returns a new instance of EnsureService.

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 21

def initialize(config:, type:, transport_factory:, state_store:, secret_store:, clock: -> { Time.now.utc })
  @config = config
  @type = type.to_s
  raise ArgumentError, "unknown service type: #{@type}" unless TYPES.include?(@type)

  @service = config.services.public_send(@type)
  @transport_factory = transport_factory
  @state_store = state_store
  @secret_store = secret_store
  @resource = "service.#{@type}"
  @managed_state = ServiceState.new(state_store: state_store, environment: config.environment,
                                    resource: resource)
  @compose = ServiceCompose.new(config: config, type: @type, service: @service)
  @clock = clock
end

Instance Attribute Details

#resourceObject (readonly)

Returns the value of attribute resource.



19
20
21
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 19

def resource
  @resource
end

Instance Method Details

#apply(change) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 54

def apply(change)
  return true unless change.changed?

  @firewall_changed = false
  previous_state = managed_state
  password = validated_secret
  files.ensure_managed_or_absent!(remote_fingerprint)
  prepare_backup
  transport.execute("mkdir", arguments: ["-p", service_directory], timeout: 10).then do |result|
    raise_remote!(result, "create service directory")
  end
  transport.upload(content: compose_content, remote_path: compose_path, mode: "0600")
  transport.upload(content: env_content(password), remote_path: env_path, mode: "0600")
  validate_compose
  start_service
  verify_service
  firewall.reconcile(managed_state)
  @firewall_changed = true
  write_marker
  record_state(change)
  true
rescue StandardError => e
  recover_failed_apply(previous_state, e)
end

#backupObject



89
90
91
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 89

def backup
  backup_operation.call(managed_state)
end

#destroy_dataObject



106
107
108
109
110
111
112
113
114
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 106

def destroy_data
  previous = managed_state
  return false unless previous

  compose("down", "--volumes", "--remove-orphans")
  files.destroy(previous, marker_path: marker_path)
  @managed_state.delete("destroy_data")
  true
end

#planObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 37

def plan
  return pending_change unless transport_factory.server&.public_ip

  actual = remote_fingerprint
  files.ensure_managed_or_absent!(actual)
  return unchanged_change if actual == fingerprint

  Change.new(
    resource: resource,
    action: actual.empty? ? "create" : "update",
    summary: "#{actual.empty? ? 'Install' : 'Update'} #{@type} service",
    details: safe_details(actual)
  )
rescue Errors::ConnectionError
  pending_change
end

#removeObject



79
80
81
82
83
84
85
86
87
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 79

def remove
  return false unless managed?

  compose("down", "--remove-orphans")
  firewall.remove
  remove_marker
  @managed_state.record_remove
  true
end

#rollbackObject



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/kitsune/kit/operations/ensure_service.rb', line 93

def rollback
  previous = managed_state
  return false unless previous

  remove
  if files.restore_previous(previous, marker_path: marker_path)
    firewall.restore(previous["previous_state"] || {})
    start_service if previous.dig("previous_state", "installed") != false
  end
  @managed_state.record_rollback(previous)
  true
end