capistrano-systemd-ng 0.1.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7e98a1566194f4df7c6c9db43a9ad46b94dd306e04f951b9bb238e497f61066f
4
+ data.tar.gz: b8316d110262ce8e20c7ab222a28df7a35786e2724091c111ada97de3d4b3e31
5
+ SHA512:
6
+ metadata.gz: 7c18bf423a59970a616448be2d7d955cddb65dcce6754b0e3ab02c90129431628e58a6da3173c067e7f99c52ad888430ea54ed25f0636b8308d61462a7d168f6
7
+ data.tar.gz: 37b19e87c582fb4b28b5187a72bf1b8ca2c5b8ab132b65dd992a8b2ed806808fb4705cf80982d4b0b9286e36f272fa60f5de216ac1ed2452e393ea9369e52c5f
@@ -0,0 +1,13 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: '10:00'
8
+ timezone: Asia/Tokyo
9
+ open-pull-requests-limit: 10
10
+ reviewers:
11
+ - minimum2scp
12
+ - nagachika
13
+ - akm
@@ -0,0 +1,33 @@
1
+ #
2
+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions
3
+ #
4
+
5
+ name: CI
6
+
7
+ on:
8
+ push:
9
+ branches:
10
+ - '**'
11
+
12
+ jobs:
13
+ test:
14
+ name: Test
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ ruby-version: [2.7, '3.0', 3.1]
19
+ fail-fast: false
20
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
21
+ steps:
22
+ # https://github.com/actions/checkout
23
+ - uses: actions/checkout@v2
24
+
25
+ # https://github.com/ruby/setup-ruby
26
+ - uses: ruby/setup-ruby@v1
27
+ with:
28
+ ruby-version: ${{ matrix.ruby-version }}
29
+ bundler-cache: true
30
+
31
+ - name: Test
32
+ run: bundle exec rake spec
33
+
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in capistrano-systemd-ng.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 YAMADA Tsuyoshi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,304 @@
1
+ # capistrano-systemd-ng
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/capistrano-systemd-ng.png)](https://rubygems.org/gems/capistrano-systemd-ng) [![CI](https://github.com/HLFH/capistrano-systemd-ng/actions/workflows/ci.yml/badge.svg)](https://github.com/HLFH/capistrano-systemd-ng/actions/workflows/ci.yml)
4
+
5
+ This gem adds capistrano tasks to control multiple services with systemd.
6
+ This gem supports capistrano > 3.17.0.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'capistrano-systemd-ng', require: false
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install capistrano-systemd-ng
23
+
24
+ ## Usage
25
+
26
+ Add these lines to your Capfile:
27
+
28
+ ```ruby
29
+ require "capistrano/systemd/multiservice"
30
+ install_plugin Capistrano::Systemd::MultiService.new_service("example1")
31
+ install_plugin Capistrano::Systemd::MultiService.new_service("example2")
32
+ ```
33
+
34
+ And put `config/systemd/example1.service.erb` (and `config/systemd/example2.service.erb`, ...) like this:
35
+
36
+ ```
37
+ [Unit]
38
+ Description = <%= fetch(:application) %> application server example1
39
+
40
+ [Service]
41
+ Environment = RAILS_ENV=<%= fetch(:rails_env) %>
42
+ Environment = PWD=<%= current_path %>
43
+ WorkingDirectory = <%= current_path %>
44
+ ExecStart = bundle exec some-application-server start
45
+ User = exampleuser
46
+ Group = examplegroup
47
+
48
+ [Install]
49
+ WantedBy = multi-user.target
50
+ ```
51
+
52
+ * see [systemd.service(5)](https://www.freedesktop.org/software/systemd/man/systemd.service.html) for details
53
+ * when `:application` is set to `foo`, this file will be installed as `foo_example1.service` (and `foo_example2.service`, ...)
54
+
55
+ And add these lines to config/deploy.rb if you want to reload/restart services on deploy:
56
+
57
+ ```ruby
58
+ after 'deploy:publishing', 'systemd:example1:restart'
59
+ after 'deploy:publishing', 'systemd:example2:reload-or-restart'
60
+ ```
61
+
62
+ And then deploy.
63
+
64
+ ```shell
65
+ # Upload and install systemd service unit files before deploy
66
+ cap STAGE systemd:example1:setup systemd:example2:setup
67
+
68
+ # Deploy as usual
69
+ cap STAGE deploy
70
+ ```
71
+
72
+ ### User services
73
+
74
+ To have the service installed under your own user rather than root
75
+
76
+ ```ruby
77
+ require "capistrano/systemd/multiservice"
78
+ install_plugin Capistrano::Systemd::MultiService.new_service("example1", service_type: 'user')
79
+ install_plugin Capistrano::Systemd::MultiService.new_service("example2", service_type: 'user')
80
+ ```
81
+
82
+ If using the user service type services will be installed in your users home directory under ``` /.config/systemd/user ```.
83
+ Systemd commands on those services can be run by passing a `--user` flag, e.g. ```systemctl --user list-unit-files```
84
+ Nothing else in setup should require change and Capistrano tasks should remain the same as when installing system services.
85
+
86
+ ## Capistrano Tasks
87
+
88
+ With `install_plugin Capistrano::Systemd::MultiService.new_service("example1")`,
89
+ following tasks are defined.
90
+
91
+ - `systemd:example1:setup`
92
+ - `systemd:example1:remove`
93
+ - `systemd:example1:validate`
94
+ - `systemd:example1:daemon-reload`
95
+ - `systemd:example1:start`
96
+ - `systemd:example1:stop`
97
+ - `systemd:example1:reload`
98
+ - `systemd:example1:restart`
99
+ - `systemd:example1:reload-or-restart`
100
+ - `systemd:example1:enable`
101
+ - `systemd:example1:disable`
102
+
103
+ See lib/capistrano/tasks/systemd/multiservice/system\_service.rake, lib/capistrano/systemd/multiservice/system\_service.rb for details.
104
+
105
+ ## Configuration Variables
106
+
107
+ With `install_plugin Capistrano::Systemd::MultiService.new_service("example1")`,
108
+ following Configuration variables are defined.
109
+
110
+ - `:systemd_example1_role`
111
+ - `:systemd_example1_units_src`
112
+ - `:systemd_example1_units_dir`
113
+ - `:systemd_example1_units_dest`
114
+ - `:systemd_example1_instances`
115
+ - `:systemd_example1_service`
116
+ - `:systemd_example1_instance_services`
117
+
118
+ See lib/capistrano/systemd/multiservice/system\_service.rb for details.
119
+
120
+ ## Examples
121
+
122
+ ### Rails application with unicorn and delayed\_job
123
+
124
+ #### `Capfile`
125
+
126
+ ```ruby
127
+ ## ...snip...
128
+
129
+ require 'capistrano/systemd/multiservice'
130
+ install_plugin Capistrano::Systemd::MultiService.new_service('unicorn')
131
+ install_plugin Capistrano::Systemd::MultiService.new_service('delayed_job')
132
+
133
+ ## ...snip...
134
+ ```
135
+
136
+ #### `config/deploy.rb`
137
+
138
+ ```ruby
139
+ ## ...snip...
140
+
141
+ set :application, 'foo'
142
+
143
+ ## ...snip...
144
+
145
+ set :systemd_delayed_job_instances, ->{ 3.times.to_a }
146
+
147
+ after 'deploy:restart', 'systemd:unicorn:reload-or-restart'
148
+ after 'deploy:restart', 'systemd:delayed_job:restart'
149
+
150
+ after 'deploy:publishing', 'deploy:restart'
151
+
152
+ ## ...snip...
153
+ ```
154
+
155
+ #### `config/systemd/unicorn.service.erb`
156
+
157
+ This file will be installed as `foo_unicorn.service`.
158
+
159
+ ```
160
+ [Unit]
161
+ Description = <%= fetch(:application) %> unicorn rack server
162
+
163
+ [Service]
164
+ Environment = PATH=<%= fetch(:rbenv_path) %>/shims:/usr/local/bin:/usr/bin:/bin
165
+ Environment = RBENV_VERSION=<%= fetch(:rbenv_ruby) %>
166
+ Environment = RBENV_ROOT=<%= fetch(:rbenv_path) %>
167
+ Environment = RAILS_ENV=<%= fetch(:rails_env) %>
168
+ Environment = PWD=<%= current_path %>
169
+
170
+ WorkingDirectory = <%= current_path %>
171
+
172
+ ExecStart = <%= fetch(:rbenv_path) %>/bin/rbenv exec bundle exec unicorn -c <%= current_path %>/config/unicorn.rb
173
+ ExecReload = /bin/kill -USR2 $MAINPID
174
+
175
+ PIDFile = <%= shared_path %>/tmp/pids/unicorn.pid
176
+ KillSignal = SIGQUIT
177
+ KillMode = process
178
+ TimeoutStopSec = 62
179
+ Restart = always
180
+
181
+ User = app-user
182
+ Group = app-group
183
+
184
+ [Install]
185
+ WantedBy = multi-user.target
186
+ ```
187
+
188
+ #### `config/systemd/delayed_job.service.erb`
189
+
190
+ This file will be installed as `foo_delayed_job.service`.
191
+
192
+ ```
193
+ [Unit]
194
+ Description = <%= fetch(:application) %> delayed_job
195
+ Requires = <%= fetch(:"#{prefix}_instance_services").join(" ") %>
196
+
197
+ [Service]
198
+ Type = oneshot
199
+ RemainAfterExit = yes
200
+ ExecStart = /bin/true
201
+ ExecReload = /bin/true
202
+
203
+ [Install]
204
+ WantedBy = multi-user.target
205
+ ```
206
+
207
+ #### `config/systemd/delayed_job@.service.erb`
208
+
209
+ This file will be installed as `foo_delayed_job@.service`, and creates 3 instanced service units
210
+ `foo_delayed_job@0.service`, `foo_delayed_job@1.service`, `foo_delayed_job@2.service`
211
+ because `:systemd_delayed_job_instances` is set to `->{ 3.times.to_a }` in `config/deploy.rb`.
212
+
213
+ ```
214
+ [Unit]
215
+ Description = <%= fetch(:application) %> delayed_job (instance %i)
216
+ PartOf = <%= fetch(:"#{prefix}_service") %>
217
+ ReloadPropagatedFrom = <%= fetch(:"#{prefix}_service") %>
218
+
219
+ [Service]
220
+ Type = forking
221
+
222
+ Environment = PATH=<%= fetch(:rbenv_path) %>/shims:/usr/local/bin:/usr/bin:/bin
223
+ Environment = RBENV_VERSION=<%= fetch(:rbenv_ruby) %>
224
+ Environment = RBENV_ROOT=<%= fetch(:rbenv_path) %>
225
+ Environment = RAILS_ENV=<%= fetch(:rails_env) %>
226
+ Environment = PWD=<%= current_path %>
227
+
228
+ WorkingDirectory = <%= current_path %>
229
+
230
+ ExecStart = <%= fetch(:rbenv_path) %>/bin/rbenv exec bundle exec bin/delayed_job -p <%= fetch(:application) %> -i %i start
231
+ ExecStop = <%= fetch(:rbenv_path) %>/bin/rbenv exec bundle exec bin/delayed_job -p <%= fetch(:application) %> -i %i stop
232
+ ExecReload = /bin/kill -HUP $MAINPID
233
+
234
+ PIDFile = <%= shared_path %>/tmp/pids/delayed_job.%i.pid
235
+ TimeoutStopSec = 22
236
+ Restart = always
237
+
238
+ User = app-user
239
+ Group = app-group
240
+
241
+ [Install]
242
+ WantedBy = multi-user.target
243
+ ```
244
+
245
+ #### `config/unicorn.rb`
246
+
247
+ ```ruby
248
+ shared_path = "/path/to/shared"
249
+
250
+ worker_processes 5
251
+ listen "#{shared_path}/tmp/sockets/unicorn.sock"
252
+ pid "#{shared_path}/tmp/pids/unicorn.pid"
253
+ stderr_path "#{shared_path}/log/unicorn_stderr.log"
254
+ stdout_path "#{shared_path}/log/unicorn_stdout.log"
255
+ preload_app true
256
+
257
+ before_exec do |server|
258
+ ENV["BUNDLE_GEMFILE"] = "/path/to/current/Gemfile"
259
+ end
260
+
261
+ before_fork do |server, worker|
262
+ if defined? ActiveRecord::Base
263
+ ActiveRecord::Base.connection.disconnect!
264
+ end
265
+
266
+ old_pid = "#{server.config[:pid]}.oldbin"
267
+ if old_pid != server.pid
268
+ begin
269
+ sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
270
+ Process.kill(sig, File.read(old_pid).to_i)
271
+ rescue Errno::ENOENT, Errno::ESRCH
272
+ end
273
+ end
274
+
275
+ sleep 1
276
+ end
277
+
278
+ after_fork do |server, worker|
279
+ if defined?(ActiveRecord::Base)
280
+ ActiveRecord::Base.establish_connection
281
+ end
282
+ end
283
+ ```
284
+
285
+ #### Commands to setup systemd services and deploy
286
+
287
+ ```shell
288
+ # Upload and install systemd service unit files before deploy
289
+ cap STAGE systemd:unicorn:setup systemd:delayed_job:setup
290
+
291
+ # Deploy as usual
292
+ cap STAGE deploy
293
+ ```
294
+
295
+ ## Development
296
+
297
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
298
+
299
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
300
+
301
+ ## Contributing
302
+
303
+ Bug reports and pull requests are welcome on GitHub at https://github.com/HLFH/capistrano-systemd-ng.
304
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "capistrano/systemd/multiservice"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'capistrano/systemd/multiservice/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "capistrano-systemd-ng"
8
+ spec.version = Capistrano::Systemd::MultiService::VERSION
9
+ spec.authors = ["Gaspard d'Hautefeuille", "YAMADA Tsuyoshi"]
10
+ spec.email = ["github@dhautefeuille.eu"]
11
+
12
+ spec.summary = %q{Capistrano Plugin to control services by systemd}
13
+ spec.description = %q{Capistrano Plugin to control services by systemd (supports capistrano > 3.17.0)}
14
+ spec.homepage = "https://github.com/HLFH/capistrano-systemd-ng"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "capistrano", ">= 3.7.0", "< 3.18.0"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "mocha", "~> 1.2"
29
+ end
@@ -0,0 +1,124 @@
1
+ require "erb"
2
+ require "stringio"
3
+ require "capistrano/plugin"
4
+
5
+ module Capistrano
6
+ module Systemd
7
+ module MultiService
8
+ class SystemService < ::Capistrano::Plugin
9
+ attr_reader :app
10
+
11
+ def initialize(app)
12
+ @app = app
13
+ super()
14
+ end
15
+
16
+ def nsp
17
+ @app.to_sym
18
+ end
19
+
20
+ def prefix
21
+ "systemd_#{@app}"
22
+ end
23
+
24
+ def define_tasks
25
+ eval_rakefile File.expand_path("../../../tasks/systemd/multiservice/system_service.rake", __FILE__)
26
+ end
27
+
28
+ def register_hooks
29
+ after "deploy:check", "systemd:#{nsp}:validate"
30
+ after "systemd:#{nsp}:setup", "systemd:#{nsp}:daemon-reload"
31
+ after "systemd:#{nsp}:setup", "systemd:#{nsp}:enable"
32
+ before "systemd:#{nsp}:remove", "systemd:#{nsp}:disable"
33
+ after "systemd:#{nsp}:remove", "systemd:#{nsp}:daemon-reload"
34
+ end
35
+
36
+ def set_defaults
37
+ set_if_empty :"#{prefix}_role", ->{ :app }
38
+
39
+ set_if_empty :"#{prefix}_units_src", ->{ Dir["config/systemd/#{@app}{,@}.*.erb"].sort }
40
+
41
+ set_if_empty :"#{prefix}_units_dir", ->{ default_units_dir }
42
+
43
+ set_if_empty :"#{prefix}_units_dest", ->{
44
+ fetch(:"#{prefix}_units_src").map{|src|
45
+ "%s/%s_%s" % [ fetch(:"#{prefix}_units_dir"), fetch(:application), File.basename(src, ".erb") ]
46
+ }
47
+ }
48
+
49
+ set_if_empty :"#{prefix}_instances", ->{
50
+ if fetch(:"#{prefix}_units_dest").map{|dst| File.basename(dst) }.find{|f| f =~ /@\.service\z/ }
51
+ 1.times.to_a
52
+ else
53
+ nil
54
+ end
55
+ }
56
+
57
+ set_if_empty :"#{prefix}_service", ->{
58
+ service = fetch(:"#{prefix}_units_dest").map{|dst| File.basename(dst) }.find{|f| f =~ /\.service\z/ && f !~ /@\.service\z/ }
59
+ service || fetch(:"#{prefix}_instance_services")
60
+ }
61
+
62
+ set_if_empty :"#{prefix}_instance_services", ->{
63
+ if fetch(:"#{prefix}_instances")
64
+ fetch(:"#{prefix}_instances").map{|i|
65
+ service_template = fetch(:"#{prefix}_units_dest").map{|dst| File.basename(dst) }.find{|f| f =~ /@\.service\z/ }
66
+ service_template && service_template.sub(/@\.service\z/, "@#{i}.service")
67
+ }
68
+ else
69
+ []
70
+ end
71
+ }
72
+ end
73
+
74
+ def default_units_dir
75
+ "/etc/systemd/system"
76
+ end
77
+
78
+ def setup
79
+ fetch(:"#{prefix}_units_src").zip(fetch(:"#{prefix}_units_dest")).each do |src, dest|
80
+ buf = StringIO.new(ERB.new(File.read(src), nil, 2).result(binding))
81
+ setup_service buf, src, dest
82
+ end
83
+ end
84
+
85
+ def remove
86
+ backend.sudo :rm, '-f', '--', fetch(:"#{prefix}_units_dest")
87
+ end
88
+
89
+ def validate
90
+ fetch(:"#{prefix}_units_dest").each do |dest|
91
+ unless backend.test("[ -f #{dest} ]")
92
+ backend.error "#{dest} not found"
93
+ exit 1
94
+ end
95
+ end
96
+ end
97
+
98
+ def daemon_reload
99
+ systemctl :"daemon-reload"
100
+ end
101
+
102
+ %i[start stop reload restart reload-or-restart enable disable].each do |act|
103
+ define_method act.to_s.tr('-','_') do
104
+ systemctl act, fetch(:"#{prefix}_service")
105
+ end
106
+ end
107
+
108
+ def systemctl(*args)
109
+ args.unshift :sudo, :systemctl
110
+ backend.execute(*args)
111
+ end
112
+
113
+ private
114
+
115
+ def setup_service(buf, src, dest)
116
+ remote_tmp = "#{fetch(:tmp_dir)}/#{File.basename(src, ".erb")}"
117
+ backend.upload! buf, remote_tmp
118
+ backend.sudo :install, '-m 644 -o root -g root -D', remote_tmp, dest
119
+ backend.execute :rm, remote_tmp
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,28 @@
1
+ require_relative './system_service'
2
+
3
+ module Capistrano
4
+ module Systemd
5
+ module MultiService
6
+ class UserService < SystemService
7
+ def systemctl(*args)
8
+ args.unshift :systemctl, '--user'
9
+ backend.execute(*args)
10
+ end
11
+
12
+ def remove
13
+ backend.execute :rm, '-f', '--', fetch(:"#{prefix}_units_dest")
14
+ end
15
+
16
+ def default_units_dir
17
+ "/home/#{fetch(:user)}/.config/systemd/user"
18
+ end
19
+
20
+ protected
21
+
22
+ def setup_service(buf, src, dest)
23
+ backend.upload! buf, dest
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ module Capistrano
2
+ module Systemd
3
+ module MultiService
4
+ VERSION = "0.1.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ require "capistrano/systemd/multiservice/version"
2
+ require "capistrano/systemd/multiservice/system_service"
3
+ require "capistrano/systemd/multiservice/user_service"
4
+
5
+ module Capistrano
6
+ module Systemd
7
+ module MultiService
8
+ SERVICE_TYPES = %w[system user].freeze
9
+
10
+ class ServiceTypeError < RuntimeError; end
11
+
12
+ def self.new_service(app, service_type: 'system')
13
+ service_type = service_type.to_s
14
+ unless SERVICE_TYPES.include?(service_type)
15
+ raise ServiceTypeError,
16
+ "Service type has to be one of #{SERVICE_TYPES}"
17
+ end
18
+
19
+ const_get("#{service_type.capitalize}Service").new(app)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # This trick lets us access the Capistrano::Systemd::MultiService plugin within `on` blocks
2
+ svc = self
3
+
4
+ namespace :systemd do
5
+ namespace svc.nsp do
6
+ {
7
+ setup: "Setup %{app} systemd unit file",
8
+ remove: "Remove %{app} systemd unit file",
9
+ validate: "Validate %{app} systemd unit file",
10
+ "daemon-reload": "Run systemctl daemon-reload",
11
+ start: "Run systemctl %{task_name} for %{app}",
12
+ stop: "Run systemctl %{task_name} for %{app}",
13
+ reload: "Run systemctl %{task_name} for %{app}",
14
+ restart: "Run systemctl %{task_name} for %{app}",
15
+ "reload-or-restart": "Run systemctl %{task_name} for %{app}",
16
+ enable: "Run systemctl %{task_name} for %{app}",
17
+ disable: "Run systemctl %{task_name} for %{app}",
18
+ }.each do |task_name, desc_template|
19
+ desc(desc_template % { app: svc.app, task_name: task_name})
20
+ task task_name do
21
+ on roles(fetch(:"#{svc.prefix}_role")) do
22
+ svc.__send__ task_name.to_s.tr('-', '_')
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-systemd-ng
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Gaspard d'Hautefeuille
8
+ - YAMADA Tsuyoshi
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2023-06-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 3.7.0
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: 3.18.0
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 3.7.0
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.18.0
34
+ - !ruby/object:Gem::Dependency
35
+ name: bundler
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :development
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: mocha
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.2'
90
+ description: Capistrano Plugin to control services by systemd (supports capistrano
91
+ > 3.17.0)
92
+ email:
93
+ - github@dhautefeuille.eu
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files: []
97
+ files:
98
+ - ".github/dependabot.yml"
99
+ - ".github/workflows/ci.yml"
100
+ - ".gitignore"
101
+ - ".rspec"
102
+ - Gemfile
103
+ - LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - bin/console
107
+ - bin/setup
108
+ - capistrano-systemd-ng.gemspec
109
+ - lib/capistrano/systemd/multiservice.rb
110
+ - lib/capistrano/systemd/multiservice/system_service.rb
111
+ - lib/capistrano/systemd/multiservice/user_service.rb
112
+ - lib/capistrano/systemd/multiservice/version.rb
113
+ - lib/capistrano/tasks/systemd/multiservice/system_service.rake
114
+ homepage: https://github.com/HLFH/capistrano-systemd-ng
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.4.14
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Capistrano Plugin to control services by systemd
137
+ test_files: []