Class: Bard::Target

Inherits:
Object
  • Object
show all
Defined in:
lib/bard/target.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, config) ⇒ Target

Returns a new instance of Target.



11
12
13
14
15
16
17
18
19
20
# File 'lib/bard/target.rb', line 11

def initialize(key, config)
  @key = key
  @config = config
  @capabilities = []
  @ping_urls = []
  @strategy_options_hash = {}
  @deploy_strategy = nil
  @path = nil
  @server = nil
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, **kwargs, &block) ⇒ Object

Dynamic strategy DSL via method_missing



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/bard/target.rb', line 151

def method_missing(method, *args, **kwargs, &block)
  strategy_class = DeployStrategy[method]

  if strategy_class
    # This is a deployment strategy
    @deploy_strategy = method

    # Store options
    @strategy_options_hash[method] = kwargs

    # Auto-configure ping if first arg is a URL
    if args.first && args.first.to_s =~ /^https?:\/\//
      ping(args.first)
    end

    # Call the strategy's initializer if it wants to configure the target
    # (This will be handled by the strategy class)
  else
    super
  end
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



8
9
10
# File 'lib/bard/target.rb', line 8

def config
  @config
end

#deploy_strategyObject (readonly)

Deploy strategy



122
123
124
# File 'lib/bard/target.rb', line 122

def deploy_strategy
  @deploy_strategy
end

#envObject

Returns the value of attribute env.



9
10
11
# File 'lib/bard/target.rb', line 9

def env
  @env
end

#gatewayObject

Returns the value of attribute gateway.



9
10
11
# File 'lib/bard/target.rb', line 9

def gateway
  @gateway
end

#keyObject (readonly)

Returns the value of attribute key.



8
9
10
# File 'lib/bard/target.rb', line 8

def key
  @key
end

#path(new_path = nil) ⇒ Object (readonly)

Path configuration



79
80
81
# File 'lib/bard/target.rb', line 79

def path
  @path
end

#serverObject

Returns the value of attribute server.



9
10
11
# File 'lib/bard/target.rb', line 9

def server
  @server
end

#ssh_keyObject

Returns the value of attribute ssh_key.



9
10
11
# File 'lib/bard/target.rb', line 9

def ssh_key
  @ssh_key
end

Instance Method Details

#copy_dir(path, to:, verbose: false) ⇒ Object



200
201
202
203
204
# File 'lib/bard/target.rb', line 200

def copy_dir(path, to:, verbose: false)
  require_capability!(:ssh)
  to.require_capability!(:ssh)
  Copy.dir(path, from: self, to: to, verbose: verbose)
end

#copy_file(path, to:, verbose: false) ⇒ Object

File transfer



194
195
196
197
198
# File 'lib/bard/target.rb', line 194

def copy_file(path, to:, verbose: false)
  require_capability!(:ssh)
  to.require_capability!(:ssh)
  Copy.file(path, from: self, to: to, verbose: verbose)
end

#deploy_strategy_instanceObject



141
142
143
144
145
146
147
148
# File 'lib/bard/target.rb', line 141

def deploy_strategy_instance
  raise "No deployment strategy configured for target #{key}" unless @deploy_strategy

  strategy_class = DeployStrategy[@deploy_strategy]
  raise "Unknown deployment strategy: #{@deploy_strategy}" unless strategy_class

  strategy_class.new(self)
end

#enable_capability(capability) ⇒ Object

Capability tracking



23
24
25
# File 'lib/bard/target.rb', line 23

def enable_capability(capability)
  @capabilities << capability unless @capabilities.include?(capability)
end

#exec!(command, home: false) ⇒ Object



188
189
190
191
# File 'lib/bard/target.rb', line 188

def exec!(command, home: false)
  require_capability!(:ssh)
  Command.exec!(command, on: server, home: home)
end

#github_pages(url = nil) ⇒ Object

GitHub Pages deployment configuration



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/bard/target.rb', line 125

def github_pages(url = nil)
  if url.nil?
    # Getter
    @github_pages_url
  else
    # Setter
    @deploy_strategy = :github_pages
    @github_pages_url = url
    enable_capability(:github_pages)
  end
end

#has_capability?(capability) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/bard/target.rb', line 27

def has_capability?(capability)
  @capabilities.include?(capability)
end

#openObject



116
117
118
119
# File 'lib/bard/target.rb', line 116

def open
  require_capability!(:ping)
  system "open #{ping_urls.first}"
end

#ping(*urls) ⇒ Object

Ping configuration



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/bard/target.rb', line 88

def ping(*urls)
  if urls.empty?
    # Getter
    @ping_urls
  elsif urls.first == false
    # Disable ping
    @ping_urls = []
    @capabilities.delete(:ping)
  else
    # Enable ping
    @ping_urls = urls.flatten
    enable_capability(:ping)
  end
end

#ping!Object



107
108
109
110
111
112
113
114
# File 'lib/bard/target.rb', line 107

def ping!
  require_capability!(:ping)
  require "bard/ping"
  failed_urls = Bard::Ping.call(self)
  if failed_urls.any?
    raise "Ping failed for: #{failed_urls.join(', ')}"
  end
end

#ping_urlsObject



103
104
105
# File 'lib/bard/target.rb', line 103

def ping_urls
  @ping_urls
end

#require_capability!(capability) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/bard/target.rb', line 31

def require_capability!(capability)
  unless has_capability?(capability)
    error_message = case capability
    when :ssh
      "SSH not configured for this target"
    when :ping
      "Ping URL not configured for this target"
    else
      "#{capability} capability not configured for this target"
    end
    raise error_message
  end
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
# File 'lib/bard/target.rb', line 173

def respond_to_missing?(method, include_private = false)
  DeployStrategy[method] || super
end

#rsync_uri(file_path = nil) ⇒ Object



214
215
216
217
218
219
220
# File 'lib/bard/target.rb', line 214

def rsync_uri(file_path = nil)
  uri = URI("ssh://#{ssh_uri}")
  str = "#{uri.user}@#{uri.host}"
  str += ":#{path}"
  str += "/#{file_path}" if file_path
  str
end

#run(command, home: false, verbose: false, quiet: false) ⇒ Object



183
184
185
186
# File 'lib/bard/target.rb', line 183

def run(command, home: false, verbose: false, quiet: false)
  require_capability!(:ssh)
  Command.run(command, on: server, home: home, verbose: verbose, quiet: quiet)
end

#run!(command, home: false, verbose: false, quiet: false) ⇒ Object

Remote command execution



178
179
180
181
# File 'lib/bard/target.rb', line 178

def run!(command, home: false, verbose: false, quiet: false)
  require_capability!(:ssh)
  Command.run!(command, on: server, home: home, verbose: verbose, quiet: quiet)
end

#scp_uri(file_path = nil) ⇒ Object

URI methods for compatibility



207
208
209
210
211
212
# File 'lib/bard/target.rb', line 207

def scp_uri(file_path = nil)
  uri = URI("scp://#{ssh_uri}")
  uri.path = "/#{path}"
  uri.path += "/#{file_path}" if file_path
  uri
end

#ssh(uri_or_false = nil, **options) ⇒ Object

SSH configuration



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
# File 'lib/bard/target.rb', line 46

def ssh(uri_or_false = nil, **options)
  if uri_or_false.nil?
    # Getter - return false if explicitly disabled, otherwise return server
    return @ssh_disabled ? false : @server
  elsif uri_or_false == false
    # Disable SSH
    @server = nil
    @ssh_disabled = true
    @capabilities.delete(:ssh)
  else
    # Enable SSH
    require "bard/ssh_server"
    @server = SSHServer.new(uri_or_false, **options)
    @path = options[:path] if options[:path]
    @gateway = options[:gateway] if options[:gateway]
    @ssh_key = options[:ssh_key] if options[:ssh_key]
    @env = options[:env] if options[:env]
    enable_capability(:ssh)

    # Set SSH as default deployment strategy if none set
    @deploy_strategy ||= :ssh

    # Auto-configure ping from hostname
    hostname = @server.hostname
    ping(hostname) if hostname
  end
end

#ssh_uriObject



74
75
76
# File 'lib/bard/target.rb', line 74

def ssh_uri
  server&.ssh_uri
end

#strategy_options(strategy_name) ⇒ Object



137
138
139
# File 'lib/bard/target.rb', line 137

def strategy_options(strategy_name)
  @strategy_options_hash[strategy_name] || {}
end

#to_sObject

Utility methods



223
224
225
# File 'lib/bard/target.rb', line 223

def to_s
  key.to_s
end

#to_symObject



227
228
229
# File 'lib/bard/target.rb', line 227

def to_sym
  key
end

#with(attrs) ⇒ Object



231
232
233
234
235
236
237
# File 'lib/bard/target.rb', line 231

def with(attrs)
  dup.tap do |t|
    attrs.each do |key, value|
      t.send(key, value)
    end
  end
end