podman 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/lib/podman.rb +1 -0
  3. data/lib/vagrant/podman/action/build.rb +99 -0
  4. data/lib/vagrant/podman/action/compare_synced_folders.rb +65 -0
  5. data/lib/vagrant/podman/action/connect_networks.rb +80 -0
  6. data/lib/vagrant/podman/action/create.rb +165 -0
  7. data/lib/vagrant/podman/action/destroy.rb +34 -0
  8. data/lib/vagrant/podman/action/destroy_build_image.rb +51 -0
  9. data/lib/vagrant/podman/action/destroy_network.rb +53 -0
  10. data/lib/vagrant/podman/action/forwarded_ports.rb +36 -0
  11. data/lib/vagrant/podman/action/has_ssh.rb +21 -0
  12. data/lib/vagrant/podman/action/host_machine.rb +75 -0
  13. data/lib/vagrant/podman/action/host_machine_build_dir.rb +49 -0
  14. data/lib/vagrant/podman/action/host_machine_port_checker.rb +34 -0
  15. data/lib/vagrant/podman/action/host_machine_port_warning.rb +40 -0
  16. data/lib/vagrant/podman/action/host_machine_required.rb +20 -0
  17. data/lib/vagrant/podman/action/host_machine_sync_folders.rb +176 -0
  18. data/lib/vagrant/podman/action/host_machine_sync_folders_disable.rb +91 -0
  19. data/lib/vagrant/podman/action/init_state.rb +23 -0
  20. data/lib/vagrant/podman/action/is_build.rb +19 -0
  21. data/lib/vagrant/podman/action/is_host_machine_created.rb +32 -0
  22. data/lib/vagrant/podman/action/login.rb +51 -0
  23. data/lib/vagrant/podman/action/prepare_forwarded_port_collision_params.rb +64 -0
  24. data/lib/vagrant/podman/action/prepare_networks.rb +397 -0
  25. data/lib/vagrant/podman/action/prepare_nfs_settings.rb +60 -0
  26. data/lib/vagrant/podman/action/prepare_nfs_valid_ids.rb +22 -0
  27. data/lib/vagrant/podman/action/prepare_ssh.rb +48 -0
  28. data/lib/vagrant/podman/action/pull.rb +30 -0
  29. data/lib/vagrant/podman/action/start.rb +24 -0
  30. data/lib/vagrant/podman/action/stop.rb +24 -0
  31. data/lib/vagrant/podman/action/wait_for_running.rb +71 -0
  32. data/lib/vagrant/podman/action.rb +319 -0
  33. data/lib/vagrant/podman/cap/has_communicator.rb +14 -0
  34. data/lib/vagrant/podman/cap/proxy_machine.rb +15 -0
  35. data/lib/vagrant/podman/cap/public_address.rb +26 -0
  36. data/lib/vagrant/podman/command/exec.rb +112 -0
  37. data/lib/vagrant/podman/command/logs.rb +111 -0
  38. data/lib/vagrant/podman/command/run.rb +76 -0
  39. data/lib/vagrant/podman/communicator.rb +199 -0
  40. data/lib/vagrant/podman/config.rb +368 -0
  41. data/lib/vagrant/podman/driver/compose.rb +315 -0
  42. data/lib/vagrant/podman/driver.rb +417 -0
  43. data/lib/vagrant/podman/errors.rb +108 -0
  44. data/lib/vagrant/podman/executor/local.rb +48 -0
  45. data/lib/vagrant/podman/executor/vagrant.rb +88 -0
  46. data/lib/vagrant/podman/hostmachine/Vagrantfile +3 -0
  47. data/lib/vagrant/podman/plugin.rb +89 -0
  48. data/lib/vagrant/podman/provider.rb +216 -0
  49. data/lib/vagrant/podman/synced_folder.rb +35 -0
  50. data/templates/locales/providers_podman.yml +321 -0
  51. metadata +103 -0
@@ -0,0 +1,319 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ module VagrantPlugins
5
+ module PodmanProvider
6
+ module Action
7
+ # Include the built-in modules so we can use them as top-level things.
8
+ include Vagrant::Action::Builtin
9
+
10
+ # This action starts another container just like the real one running
11
+ # but only for the purpose of running a single command rather than
12
+ # to exist long-running.
13
+ def self.action_run_command
14
+ Vagrant::Action::Builder.new.tap do |b|
15
+ # We just call the "up" action. We create a separate action
16
+ # to hold this though in case we modify it in the future, and
17
+ # so that we can switch on the "machine_action" env var.
18
+ b.use action_up
19
+ end
20
+ end
21
+
22
+ # This action brings the "machine" up from nothing, including creating the
23
+ # container, configuring metadata, and booting.
24
+ def self.action_up
25
+ Vagrant::Action::Builder.new.tap do |b|
26
+ b.use Call, IsState, :not_created do |env, b2|
27
+ if env[:result]
28
+ b2.use HandleBox
29
+ end
30
+ end
31
+
32
+ b.use ConfigValidate
33
+ b.use HostMachine
34
+
35
+ # Yeah, this is supposed to be here twice (once more above). This
36
+ # catches the case when the container was supposed to be created,
37
+ # but the host state was unknown, and now we know its not actually
38
+ # created.
39
+ b.use Call, IsState, :not_created do |env, b2|
40
+ if env[:result]
41
+ b2.use HandleBox
42
+ b2.use DestroyBuildImage
43
+ end
44
+ end
45
+
46
+ b.use action_start
47
+ end
48
+ end
49
+
50
+ def self.action_package
51
+ lambda do |env|
52
+ raise Errors::PackageNotSupported
53
+ end
54
+ end
55
+
56
+ # This action just runs the provisioners on the machine.
57
+ def self.action_provision
58
+ Vagrant::Action::Builder.new.tap do |b|
59
+ b.use ConfigValidate
60
+ b.use Call, IsState, :not_created do |env, b2|
61
+ if env[:result]
62
+ b2.use Message, I18n.t("podman_provider.messages.not_created")
63
+ next
64
+ end
65
+
66
+ b2.use Call, IsState, :running do |env2, b3|
67
+ if !env2[:result]
68
+ b3.use Message, I18n.t("podman_provider.messages.not_running")
69
+ next
70
+ end
71
+
72
+ b3.use Call, HasProvisioner do |env3, b4|
73
+ b4.use Provision
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # This is the action that is primarily responsible for halting
81
+ # the virtual machine, gracefully or by force.
82
+ def self.action_halt
83
+ Vagrant::Action::Builder.new.tap do |b|
84
+ b.use Call, IsState, :host_state_unknown do |env, b2|
85
+ if env[:result]
86
+ b2.use HostMachine
87
+ end
88
+ end
89
+
90
+ b.use Call, IsState, :not_created do |env, b2|
91
+ if env[:result]
92
+ b2.use Message, I18n.t("podman_provider.messages.not_created")
93
+ next
94
+ end
95
+
96
+ b2.use Stop
97
+ end
98
+ end
99
+ end
100
+
101
+ # This action is responsible for reloading the machine, which
102
+ # brings it down, sucks in new configuration, and brings the
103
+ # machine back up with the new configuration.
104
+ def self.action_reload
105
+ Vagrant::Action::Builder.new.tap do |b|
106
+ b.use ConfigValidate
107
+ b.use Call, IsState, :not_created do |env, b2|
108
+ if env[:result]
109
+ b2.use Message, I18n.t("podman_provider.messages.not_created")
110
+ next
111
+ end
112
+
113
+ b2.use action_halt
114
+
115
+ b2.use Call, IsBuild do |env2, b3|
116
+ if env2[:result]
117
+ b3.use EnvSet, force_halt: true
118
+ b3.use action_halt
119
+ b3.use HostMachineSyncFoldersDisable
120
+ b3.use Destroy
121
+ b3.use ProvisionerCleanup
122
+ end
123
+ end
124
+
125
+ b2.use action_start
126
+ end
127
+ end
128
+ end
129
+
130
+ # This is the action that is primarily responsible for completely
131
+ # freeing the resources of the underlying virtual machine.
132
+ def self.action_destroy
133
+ Vagrant::Action::Builder.new.tap do |b|
134
+ b.use Call, IsHostMachineCreated do |env, b2|
135
+ if !env[:result]
136
+ b2.use Message, I18n.t("podman_provider.messages.not_created")
137
+ next
138
+ end
139
+
140
+ b2.use Call, IsState, :host_state_unknown do |env2, b3|
141
+ if env2[:result]
142
+ b3.use HostMachine
143
+ end
144
+ end
145
+
146
+ b2.use Call, IsState, :not_created do |env2, b3|
147
+ if env2[:result]
148
+ b3.use Message,
149
+ I18n.t("podman_provider.messages.not_created")
150
+ next
151
+ end
152
+
153
+ b3.use Call, DestroyConfirm do |env3, b4|
154
+ if env3[:result]
155
+ b4.use ConfigValidate
156
+ b4.use ProvisionerCleanup, :before
157
+ b4.use EnvSet, force_halt: true
158
+ b4.use action_halt
159
+ b4.use HostMachineSyncFoldersDisable
160
+ b4.use Destroy
161
+ b4.use DestroyNetwork
162
+ b4.use DestroyBuildImage
163
+ else
164
+ b4.use Message,
165
+ I18n.t("podman_provider.messages.will_not_destroy")
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ # This is the action that will exec into an SSH shell.
174
+ def self.action_ssh
175
+ Vagrant::Action::Builder.new.tap do |b|
176
+ b.use Call, IsState, :not_created do |env, b2|
177
+ if env[:result]
178
+ raise Errors::ContainerNotCreatedError
179
+ end
180
+
181
+ b2.use Call, IsState, :running do |env2, b3|
182
+ if !env2[:result]
183
+ raise Errors::ContainerNotRunningError
184
+ end
185
+
186
+ b3.use PrepareSSH
187
+ b3.use SSHExec
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ # This is the action that will run a single SSH command.
194
+ def self.action_ssh_run
195
+ Vagrant::Action::Builder.new.tap do |b|
196
+ b.use Call, IsState, :not_created do |env, b2|
197
+ if env[:result]
198
+ raise Errors::ContainerNotCreatedError
199
+ end
200
+
201
+ b2.use Call, IsState, :running do |env2, b3|
202
+ if !env2[:result]
203
+ raise Errors::ContainerNotRunningError
204
+ end
205
+
206
+ b3.use SSHRun
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ def self.action_start
213
+ Vagrant::Action::Builder.new.tap do |b|
214
+ b.use Call, IsState, :running do |env, b2|
215
+ if env[:machine_action] != :run_command
216
+ b2.use Call, HasProvisioner do |env2, b3|
217
+ b3.use Provision
218
+ end
219
+ end
220
+
221
+ # If the container is running and we're doing a run, we're done
222
+ next if env[:result] && env[:machine_action] != :run_command
223
+
224
+ b2.use Call, IsState, :not_created do |env2, b3|
225
+ if env2[:result]
226
+ # First time making this thing, set to the "preparing" state
227
+ b3.use InitState
228
+ else
229
+ b3.use EnvSet, host_machine_sync_folders: false
230
+ end
231
+ end
232
+
233
+ b2.use HostMachineBuildDir
234
+ b2.use HostMachineSyncFolders
235
+ b2.use PrepareNFSValidIds
236
+ b2.use SyncedFolderCleanup
237
+ b2.use SyncedFolders
238
+ b2.use PrepareNFSSettings
239
+ b2.use PrepareNetworks
240
+ b2.use Login
241
+ b2.use Build
242
+
243
+ if env[:machine_action] != :run_command
244
+ # If the container is NOT created yet, then do some setup steps
245
+ # necessary for creating it.
246
+
247
+ b2.use Call, IsState, :preparing do |env2, b3|
248
+ if env2[:result]
249
+ b3.use EnvSet, port_collision_repair: true
250
+ b3.use HostMachinePortWarning
251
+ b3.use HostMachinePortChecker
252
+ b3.use ForwardedPorts # This action converts the `ports` param into proper network configs
253
+ b3.use PrepareForwardedPortCollisionParams
254
+ b3.use HandleForwardedPortCollisions
255
+ b3.use Pull
256
+ b3.use Create
257
+ b3.use WaitForRunning
258
+ else
259
+ b3.use CompareSyncedFolders
260
+ end
261
+ end
262
+
263
+ b2.use ConnectNetworks
264
+ b2.use Start
265
+ b2.use WaitForRunning
266
+
267
+ b2.use Call, HasSSH do |env2, b3|
268
+ if env2[:result]
269
+ b3.use WaitForCommunicator
270
+ end
271
+ end
272
+ else
273
+ # We're in a run command, so we do things a bit differently.
274
+ b2.use Create
275
+ end
276
+ end
277
+ end
278
+ end
279
+
280
+ def self.action_suspend
281
+ lambda do |env|
282
+ raise Errors::SuspendNotSupported
283
+ end
284
+ end
285
+
286
+ # The autoload farm
287
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
288
+ autoload :Build, action_root.join("build")
289
+ autoload :CompareSyncedFolders, action_root.join("compare_synced_folders")
290
+ autoload :ConnectNetworks, action_root.join("connect_networks")
291
+ autoload :Create, action_root.join("create")
292
+ autoload :Destroy, action_root.join("destroy")
293
+ autoload :DestroyBuildImage, action_root.join("destroy_build_image")
294
+ autoload :DestroyNetwork, action_root.join("destroy_network")
295
+ autoload :ForwardedPorts, action_root.join("forwarded_ports")
296
+ autoload :HasSSH, action_root.join("has_ssh")
297
+ autoload :HostMachine, action_root.join("host_machine")
298
+ autoload :HostMachineBuildDir, action_root.join("host_machine_build_dir")
299
+ autoload :HostMachinePortChecker, action_root.join("host_machine_port_checker")
300
+ autoload :HostMachinePortWarning, action_root.join("host_machine_port_warning")
301
+ autoload :HostMachineRequired, action_root.join("host_machine_required")
302
+ autoload :HostMachineSyncFolders, action_root.join("host_machine_sync_folders")
303
+ autoload :HostMachineSyncFoldersDisable, action_root.join("host_machine_sync_folders_disable")
304
+ autoload :InitState, action_root.join("init_state")
305
+ autoload :IsBuild, action_root.join("is_build")
306
+ autoload :IsHostMachineCreated, action_root.join("is_host_machine_created")
307
+ autoload :Login, action_root.join("login")
308
+ autoload :PrepareForwardedPortCollisionParams, action_root.join("prepare_forwarded_port_collision_params")
309
+ autoload :PrepareNetworks, action_root.join("prepare_networks")
310
+ autoload :PrepareNFSValidIds, action_root.join("prepare_nfs_valid_ids")
311
+ autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings")
312
+ autoload :PrepareSSH, action_root.join("prepare_ssh")
313
+ autoload :Pull, action_root.join("pull")
314
+ autoload :Start, action_root.join("start")
315
+ autoload :Stop, action_root.join("stop")
316
+ autoload :WaitForRunning, action_root.join("wait_for_running")
317
+ end
318
+ end
319
+ end
@@ -0,0 +1,14 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ module VagrantPlugins
5
+ module PodmanProvider
6
+ module Cap
7
+ module HasCommunicator
8
+ def self.has_communicator(machine)
9
+ return machine.provider_config.has_ssh
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ module VagrantPlugins
5
+ module PodmanProvider
6
+ module Cap
7
+ module ProxyMachine
8
+ def self.proxy_machine(machine)
9
+ return nil if !machine.provider.host_vm?
10
+ machine.provider.host_vm
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ module VagrantPlugins
5
+ module PodmanProvider
6
+ module Cap
7
+ module PublicAddress
8
+ def self.public_address(machine)
9
+ return nil if machine.state.id != :running
10
+
11
+ # If we're using a host VM, then return the IP of that
12
+ # rather than of our own machine.
13
+ if machine.provider.host_vm?
14
+ host_machine = machine.provider.host_vm
15
+ return nil if !host_machine.provider.capability?(:public_address)
16
+ return host_machine.provider.capability(:public_address)
17
+ end
18
+
19
+ ssh_info = machine.ssh_info
20
+ return nil if !ssh_info
21
+ ssh_info[:host]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,112 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ require 'vagrant/util/safe_exec'
5
+
6
+ module VagrantPlugins
7
+ module PodmanProvider
8
+ module Command
9
+ class Exec < Vagrant.plugin("2", :command)
10
+ def self.synopsis
11
+ "attach to an already-running podman container"
12
+ end
13
+
14
+ def execute
15
+ options = {}
16
+ options[:detach] = false
17
+ options[:pty] = false
18
+ options[:interactive] = false
19
+ options[:prefix] = true
20
+
21
+ opts = OptionParser.new do |o|
22
+ o.banner = "Usage: vagrant podman-exec [options] [name] -- <command> [args]"
23
+ o.separator ""
24
+ o.separator "Options:"
25
+ o.separator ""
26
+
27
+ o.on("--[no-]detach", "Run in the background") do |d|
28
+ options[:detach] = d
29
+ end
30
+
31
+ o.on("-i", "--[no-]interactive", "Keep STDIN open even if not attached") do |i|
32
+ options[:interactive] = i
33
+ end
34
+
35
+ o.on("-t", "--[no-]tty", "Allocate a pty") do |t|
36
+ options[:pty] = t
37
+ end
38
+
39
+ o.on("-u", "--user USER", "User or UID") do |u|
40
+ options[:user] = u
41
+ end
42
+
43
+ o.on("--[no-]prefix", "Prefix output with machine names") do |p|
44
+ options[:prefix] = p
45
+ end
46
+ end
47
+
48
+ # Parse out the extra args to send to SSH, which is everything
49
+ # after the "--"
50
+ command = nil
51
+ split_index = @argv.index("--")
52
+ if split_index
53
+ command = @argv.drop(split_index + 1)
54
+ @argv = @argv.take(split_index)
55
+ end
56
+
57
+ # Parse the options
58
+ argv = parse_options(opts)
59
+ return if !argv
60
+
61
+ # Show the error if we don't have "--" _after_ parse_options
62
+ # so that "-h" and "--help" work properly.
63
+ if !split_index
64
+ raise Errors::ExecCommandRequired
65
+ end
66
+
67
+ target_opts = { provider: :podman }
68
+ target_opts[:single_target] = options[:pty]
69
+
70
+ with_target_vms(argv, target_opts) do |machine|
71
+ if machine.state.id != :running
72
+ @env.ui.info("#{machine.id} is not running.")
73
+ next
74
+ end
75
+ exec_command(machine, command, options)
76
+ end
77
+
78
+ return 0
79
+ end
80
+
81
+ def exec_command(machine, command, options)
82
+ exec_cmd = %w(podman exec)
83
+ exec_cmd << "-i" if options[:interactive]
84
+ exec_cmd << "-t" if options[:pty]
85
+ exec_cmd << "-u" << options[:user] if options[:user]
86
+ exec_cmd << machine.id
87
+ exec_cmd += options[:extra_args] if options[:extra_args]
88
+ exec_cmd += command
89
+
90
+ # Run this interactively if asked.
91
+ exec_options = options
92
+
93
+ if options[:pty]
94
+ Vagrant::Util::SafeExec.exec(exec_cmd[0], *exec_cmd[1..-1])
95
+ else
96
+ output = ""
97
+ machine.provider.driver.execute(*exec_cmd, exec_options) do |type, data|
98
+ output += data
99
+ end
100
+
101
+ output_options = {}
102
+ output_options[:prefix] = false if !options[:prefix]
103
+
104
+ if !output.empty?
105
+ machine.ui.output(output.chomp, **output_options)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,111 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ module VagrantPlugins
5
+ module PodmanProvider
6
+ module Command
7
+ class Logs < Vagrant.plugin("2", :command)
8
+ def self.synopsis
9
+ "outputs the logs from the Podman container"
10
+ end
11
+
12
+ def execute
13
+ options = {}
14
+ options[:follow] = false
15
+ options[:prefix] = true
16
+
17
+ opts = OptionParser.new do |o|
18
+ o.banner = "Usage: vagrant podman-logs [options]"
19
+ o.separator ""
20
+ o.separator "Options:"
21
+ o.separator ""
22
+
23
+ o.on("--[no-]follow", "Continue streaming in log output") do |f|
24
+ options[:follow] = f
25
+ end
26
+
27
+ o.on("--[no-]prefix", "Prefix output with machine names") do |p|
28
+ options[:prefix] = p
29
+ end
30
+ end
31
+
32
+ # Parse the options
33
+ argv = parse_options(opts)
34
+ return if !argv
35
+
36
+ # This keeps track of if we ran our action on any machines...
37
+ any_success = false
38
+
39
+ # Start a batch action that sends all the logs to stdout. This
40
+ # will parallelize, if enabled, across all containers that are
41
+ # chosen.
42
+ @env.batch do |batch|
43
+ with_target_vms(argv) do |machine|
44
+ if machine.provider_name != :podman
45
+ machine.ui.output(I18n.t("podman_provider.not_podman_provider"))
46
+ next
47
+ end
48
+
49
+ state = machine.state.id
50
+ if state == :host_state_unknown
51
+ machine.ui.output(I18n.t("podman_provider.logs_host_state_unknown"))
52
+ next
53
+ elsif state == :not_created
54
+ machine.ui.output(I18n.t("podman_provider.not_created_skip"))
55
+ next
56
+ end
57
+
58
+ # At least one was run!
59
+ any_success = true
60
+
61
+ batch.custom(machine) do |m|
62
+ execute_single(m, options)
63
+ end
64
+ end
65
+ end
66
+
67
+ # If we didn't run on any machines, then exit status 1
68
+ return any_success ? 0 : 1
69
+ end
70
+
71
+ protected
72
+
73
+ # Executes the "podman logs" command on a single machine and proxies
74
+ # the output to our UI.
75
+ def execute_single(machine, options)
76
+ command = ["podman", "logs"]
77
+ command << "--follow" if options[:follow]
78
+ command << machine.id
79
+
80
+ output_options = {}
81
+ output_options[:prefix] = false if !options[:prefix]
82
+
83
+ data_acc = ""
84
+ machine.provider.driver.execute(*command) do |type, data|
85
+ # Accumulate the data so we only output lines at a time
86
+ data_acc << data
87
+
88
+ # If we have a newline, then output all the lines we have so far
89
+ if data_acc.include?("\n")
90
+ lines = data_acc.split("\n")
91
+
92
+ if !data_acc.end_with?("\n")
93
+ data_acc = lines.pop.chomp
94
+ else
95
+ data_acc = ""
96
+ end
97
+
98
+ lines.each do |line|
99
+ line = " " if line == ""
100
+ machine.ui.output(line, **output_options)
101
+ end
102
+ end
103
+ end
104
+
105
+ # Output any remaining data
106
+ machine.ui.output(data_acc, **output_options) if !data_acc.empty?
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,76 @@
1
+ # Copyright (c) HashiCorp, Inc.
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ module VagrantPlugins
5
+ module PodmanProvider
6
+ module Command
7
+ class Run < Vagrant.plugin("2", :command)
8
+ def self.synopsis
9
+ "run a one-off command in the context of a container"
10
+ end
11
+
12
+ def execute
13
+ options = {}
14
+ options[:detach] = false
15
+ options[:pty] = false
16
+ options[:rm] = true
17
+
18
+ opts = OptionParser.new do |o|
19
+ o.banner = "Usage: vagrant podman-run [command...]"
20
+ o.separator ""
21
+ o.separator "Options:"
22
+ o.separator ""
23
+
24
+ o.on("--[no-]detach", "Run in the background") do |d|
25
+ options[:detach] = d
26
+ end
27
+
28
+ o.on("-t", "--[no-]tty", "Allocate a pty") do |t|
29
+ options[:pty] = t
30
+ end
31
+
32
+ o.on("-r,", "--[no-]rm", "Remove container after execution") do |r|
33
+ options[:rm] = r
34
+ end
35
+ end
36
+
37
+ # Parse out the extra args to send to SSH, which is everything
38
+ # after the "--"
39
+ command = nil
40
+ split_index = @argv.index("--")
41
+ if split_index
42
+ command = @argv.drop(split_index + 1)
43
+ @argv = @argv.take(split_index)
44
+ end
45
+
46
+ # Parse the options
47
+ argv = parse_options(opts)
48
+ return if !argv
49
+
50
+ # Show the error if we don't have "--" _after_ parse_options
51
+ # so that "-h" and "--help" work properly.
52
+ if !split_index
53
+ @env.ui.error(I18n.t("podman_provider.run_command_required"))
54
+ return 1
55
+ end
56
+
57
+ target_opts = { provider: :podman }
58
+ target_opts[:single_target] = options[:pty]
59
+
60
+ with_target_vms(argv, target_opts) do |machine|
61
+ # Run it!
62
+ machine.action(
63
+ :run_command,
64
+ run_command: command,
65
+ run_detach: options[:detach],
66
+ run_pty: options[:pty],
67
+ run_rm: options[:rm]
68
+ )
69
+ end
70
+
71
+ 0
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end