Module: Kdeploy::DSL

Included in:
CLI
Defined in:
lib/kdeploy/dsl.rb

Overview

Domain-specific language for defining hosts, roles, and tasks

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



15
16
17
18
19
# File 'lib/kdeploy/dsl.rb', line 15

def self.extended(base)
  base.instance_variable_set(:@kdeploy_hosts, {})
  base.instance_variable_set(:@kdeploy_tasks, {})
  base.instance_variable_set(:@kdeploy_roles, {})
end

.included(base) ⇒ Object



8
9
10
11
12
13
# File 'lib/kdeploy/dsl.rb', line 8

def self.included(base)
  # Support `include Kdeploy::DSL` by promoting the DSL methods to class methods.
  # This keeps tests and external integrations simpler while preserving the
  # primary usage pattern (CLI uses `extend DSL`).
  base.extend(self)
end

Instance Method Details

#add_explicit_hosts(task, hosts) ⇒ Object



175
176
177
178
179
# File 'lib/kdeploy/dsl.rb', line 175

def add_explicit_hosts(task, hosts)
  task[:hosts]&.each do |host|
    hosts.add(host) if kdeploy_hosts.key?(host)
  end
end

#add_role_hosts(task, hosts) ⇒ Object



181
182
183
184
185
186
187
188
189
190
# File 'lib/kdeploy/dsl.rb', line 181

def add_role_hosts(task, hosts)
  task[:roles]&.each do |role|
    role_hosts = kdeploy_roles[role]
    next unless role_hosts

    role_hosts.each do |host|
      hosts.add(host) if kdeploy_hosts.key?(host)
    end
  end
end

#assign_task(task_name, on: nil, roles: nil) ⇒ Object

Assign task to roles or hosts after task definition

Raises:

  • (ArgumentError)


64
65
66
67
68
69
70
# File 'lib/kdeploy/dsl.rb', line 64

def assign_task(task_name, on: nil, roles: nil)
  task = kdeploy_tasks[task_name.to_sym]
  raise ArgumentError, "Task #{task_name} not found" unless task

  task[:hosts] = normalize_hosts_option(on) if on
  task[:roles] = normalize_roles_option(roles) if roles
end

#create_task_block(block) ⇒ Object



117
118
119
120
121
122
123
# File 'lib/kdeploy/dsl.rb', line 117

def create_task_block(block)
  lambda {
    @kdeploy_commands = []
    instance_eval(&block)
    @kdeploy_commands
  }
end

#get_task_hosts(task_name) ⇒ Object



161
162
163
164
165
166
167
168
169
# File 'lib/kdeploy/dsl.rb', line 161

def get_task_hosts(task_name)
  task = kdeploy_tasks[task_name]
  return kdeploy_hosts.keys if task_empty?(task)

  hosts = Set.new
  add_explicit_hosts(task, hosts)
  add_role_hosts(task, hosts)
  hosts.to_a
end

#host(name, **options) ⇒ Object



47
48
49
# File 'lib/kdeploy/dsl.rb', line 47

def host(name, **options)
  kdeploy_hosts[name] = options.merge(name: name)
end

#hostsObject

Stable read accessors for tests/integrations. Keep these as aliases so internal storage can evolve without breaking callers.



23
24
25
# File 'lib/kdeploy/dsl.rb', line 23

def hosts
  kdeploy_hosts
end

#include_tasks(file_path, roles: nil, on: nil) ⇒ Object

Include task file and automatically assign all tasks to specified roles or hosts



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
# File 'lib/kdeploy/dsl.rb', line 73

def include_tasks(file_path, roles: nil, on: nil)
  # Resolve relative paths based on the caller's file location
  unless File.absolute_path?(file_path)
    caller_file = caller_locations(1, 1).first.path
    base_dir = File.dirname(File.expand_path(caller_file))
    file_path = File.expand_path(file_path, base_dir)
  end

  # Store tasks before loading
  tasks_before = kdeploy_tasks.keys

  # Load the task file
  module_eval(File.read(file_path), file_path)

  # Get newly added tasks
  tasks_after = kdeploy_tasks.keys
  new_tasks = tasks_after - tasks_before

  # Assign roles/hosts to all new tasks (only if task doesn't already have hosts/roles)
  new_tasks.each do |task_name|
    task = kdeploy_tasks[task_name]
    # Only assign if task doesn't already have hosts or roles defined
    next if task[:hosts] || task[:roles]

    assign_task(task_name, roles: roles, on: on) if roles || on
  end
end

#inventory(&block) ⇒ Object



157
158
159
# File 'lib/kdeploy/dsl.rb', line 157

def inventory(&block)
  instance_eval(&block) if block_given?
end

#kdeploy_hostsObject



35
36
37
# File 'lib/kdeploy/dsl.rb', line 35

def kdeploy_hosts
  @kdeploy_hosts ||= {}
end

#kdeploy_rolesObject



43
44
45
# File 'lib/kdeploy/dsl.rb', line 43

def kdeploy_roles
  @kdeploy_roles ||= {}
end

#kdeploy_tasksObject



39
40
41
# File 'lib/kdeploy/dsl.rb', line 39

def kdeploy_tasks
  @kdeploy_tasks ||= {}
end

#normalize_hosts_option(on) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/kdeploy/dsl.rb', line 101

def normalize_hosts_option(on)
  return on if on.is_a?(Array)

  return [on] if on

  nil
end

#normalize_roles_option(roles) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/kdeploy/dsl.rb', line 109

def normalize_roles_option(roles)
  return roles if roles.is_a?(Array)

  return [roles] if roles

  nil
end

#role(name, hosts) ⇒ Object



51
52
53
# File 'lib/kdeploy/dsl.rb', line 51

def role(name, hosts)
  kdeploy_roles[name] = hosts
end

#rolesObject



31
32
33
# File 'lib/kdeploy/dsl.rb', line 31

def roles
  kdeploy_roles
end

#run(command, sudo: nil) ⇒ Object



125
126
127
128
# File 'lib/kdeploy/dsl.rb', line 125

def run(command, sudo: nil)
  @kdeploy_commands ||= []
  @kdeploy_commands << { type: :run, command: command, sudo: sudo }
end

#sync(source, destination, ignore: [], delete: false, exclude: []) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
# File 'lib/kdeploy/dsl.rb', line 145

def sync(source, destination, ignore: [], delete: false, exclude: [])
  @kdeploy_commands ||= []
  @kdeploy_commands << {
    type: :sync,
    source: source,
    destination: destination,
    ignore: Array(ignore),
    exclude: Array(exclude),
    delete: delete
  }
end

#task(name, on: nil, roles: nil, &block) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/kdeploy/dsl.rb', line 55

def task(name, on: nil, roles: nil, &block)
  kdeploy_tasks[name] = {
    hosts: normalize_hosts_option(on),
    roles: normalize_roles_option(roles),
    block: create_task_block(block)
  }
end

#task_empty?(task) ⇒ Boolean

Returns:

  • (Boolean)


171
172
173
# File 'lib/kdeploy/dsl.rb', line 171

def task_empty?(task)
  !task || (!task[:hosts] && !task[:roles])
end

#tasksObject



27
28
29
# File 'lib/kdeploy/dsl.rb', line 27

def tasks
  kdeploy_tasks
end

#upload(source, destination) ⇒ Object



130
131
132
133
# File 'lib/kdeploy/dsl.rb', line 130

def upload(source, destination)
  @kdeploy_commands ||= []
  @kdeploy_commands << { type: :upload, source: source, destination: destination }
end

#upload_template(source, destination, variables = {}) ⇒ Object



135
136
137
138
139
140
141
142
143
# File 'lib/kdeploy/dsl.rb', line 135

def upload_template(source, destination, variables = {})
  @kdeploy_commands ||= []
  @kdeploy_commands << {
    type: :upload_template,
    source: source,
    destination: destination,
    variables: variables
  }
end