Merge lp:~mvo/snappy/15.04-systemd-sockets into lp:~snappy-dev/snappy/15.04-deprecated
- 15.04-systemd-sockets
- Merge into 15.04-deprecated
Proposed by
Michael Vogt
Status: | Merged |
---|---|
Approved by: | John Lenton |
Approved revision: | 469 |
Merged at revision: | 470 |
Proposed branch: | lp:~mvo/snappy/15.04-systemd-sockets |
Merge into: | lp:~snappy-dev/snappy/15.04-deprecated |
Diff against target: |
386 lines (+218/-35) 5 files modified
docs/meta.md (+4/-0) snappy/click.go (+73/-15) snappy/click_test.go (+58/-3) snappy/snapp.go (+7/-0) systemd/systemd.go (+76/-17) |
To merge this branch: | bzr merge lp:~mvo/snappy/15.04-systemd-sockets |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John Lenton (community) | Approve | ||
Review via email: mp+270360@code.launchpad.net |
Commit message
Add support for systemd socket files.
Description of the change
Backport of the branch that adds systemd socket file generation which is important for docker.
To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'docs/meta.md' | |||
2 | --- docs/meta.md 2015-05-29 13:43:15 +0000 | |||
3 | +++ docs/meta.md 2015-09-08 06:48:07 +0000 | |||
4 | @@ -70,6 +70,10 @@ | |||
5 | 70 | * `bus-name`: (optional) message bus connection name for the service. | 70 | * `bus-name`: (optional) message bus connection name for the service. |
6 | 71 | May only be specified for snaps of 'type: framework' (see above). See | 71 | May only be specified for snaps of 'type: framework' (see above). See |
7 | 72 | frameworks.md for details. | 72 | frameworks.md for details. |
8 | 73 | * `socket`: (optional) Set to "true" is the service is socket activated | ||
9 | 74 | * `listen-stream`: (optional) The full path of the stream socket | ||
10 | 75 | * `socket-user`: (optional) The user that owns the stream socket | ||
11 | 76 | * `socket-group`: (optional) The group that own the stream socket | ||
12 | 73 | 77 | ||
13 | 74 | * `binaries`: the binaries (executables) that the snap provides | 78 | * `binaries`: the binaries (executables) that the snap provides |
14 | 75 | * `name`: (required) the name of the binary, the user will be able to | 79 | * `name`: (required) the name of the binary, the user will be able to |
15 | 76 | 80 | ||
16 | === modified file 'snappy/click.go' | |||
17 | --- snappy/click.go 2015-09-01 17:46:30 +0000 | |||
18 | +++ snappy/click.go 2015-09-08 06:48:07 +0000 | |||
19 | @@ -510,22 +510,46 @@ | |||
20 | 510 | return "", err | 510 | return "", err |
21 | 511 | } | 511 | } |
22 | 512 | 512 | ||
23 | 513 | socketFileName := "" | ||
24 | 514 | if service.Socket { | ||
25 | 515 | socketFileName = filepath.Base(generateSocketFileName(m, service)) | ||
26 | 516 | } | ||
27 | 517 | |||
28 | 513 | return systemd.New(globalRootDir, nil).GenServiceFile( | 518 | return systemd.New(globalRootDir, nil).GenServiceFile( |
29 | 514 | &systemd.ServiceDescription{ | 519 | &systemd.ServiceDescription{ |
44 | 515 | AppName: m.Name, | 520 | AppName: m.Name, |
45 | 516 | ServiceName: service.Name, | 521 | ServiceName: service.Name, |
46 | 517 | Version: m.Version, | 522 | Version: m.Version, |
47 | 518 | Description: service.Description, | 523 | Description: service.Description, |
48 | 519 | AppPath: baseDir, | 524 | AppPath: baseDir, |
49 | 520 | Start: service.Start, | 525 | Start: service.Start, |
50 | 521 | Stop: service.Stop, | 526 | Stop: service.Stop, |
51 | 522 | PostStop: service.PostStop, | 527 | PostStop: service.PostStop, |
52 | 523 | StopTimeout: time.Duration(service.StopTimeout), | 528 | StopTimeout: time.Duration(service.StopTimeout), |
53 | 524 | AaProfile: aaProfile, | 529 | AaProfile: aaProfile, |
54 | 525 | IsFramework: m.Type == SnapTypeFramework, | 530 | IsFramework: m.Type == SnapTypeFramework, |
55 | 526 | IsNetworked: service.Ports != nil && len(service.Ports.External) > 0, | 531 | IsNetworked: service.Ports != nil && len(service.Ports.External) > 0, |
56 | 527 | BusName: service.BusName, | 532 | BusName: service.BusName, |
57 | 528 | UdevAppName: udevPartName, | 533 | UdevAppName: udevPartName, |
58 | 534 | Socket: service.Socket, | ||
59 | 535 | SocketFileName: socketFileName, | ||
60 | 536 | }), nil | ||
61 | 537 | } | ||
62 | 538 | |||
63 | 539 | func generateSnapSocketFile(service Service, baseDir string, aaProfile string, m *packageYaml) (string, error) { | ||
64 | 540 | if err := verifyServiceYaml(service); err != nil { | ||
65 | 541 | return "", err | ||
66 | 542 | } | ||
67 | 543 | |||
68 | 544 | serviceFileName := filepath.Base(generateServiceFileName(m, service)) | ||
69 | 545 | |||
70 | 546 | return systemd.New(globalRootDir, nil).GenSocketFile( | ||
71 | 547 | &systemd.ServiceDescription{ | ||
72 | 548 | ServiceFileName: serviceFileName, | ||
73 | 549 | ListenStream: service.ListenStream, | ||
74 | 550 | SocketMode: service.SocketMode, | ||
75 | 551 | SocketUser: service.SocketUser, | ||
76 | 552 | SocketGroup: service.SocketGroup, | ||
77 | 529 | }), nil | 553 | }), nil |
78 | 530 | } | 554 | } |
79 | 531 | 555 | ||
80 | @@ -537,6 +561,10 @@ | |||
81 | 537 | return filepath.Join(snapBusPolicyDir, fmt.Sprintf("%s_%s_%s.conf", m.Name, service.Name, m.Version)) | 561 | return filepath.Join(snapBusPolicyDir, fmt.Sprintf("%s_%s_%s.conf", m.Name, service.Name, m.Version)) |
82 | 538 | } | 562 | } |
83 | 539 | 563 | ||
84 | 564 | func generateSocketFileName(m *packageYaml, service Service) string { | ||
85 | 565 | return filepath.Join(snapServicesDir, fmt.Sprintf("%s_%s_%s.socket", m.Name, service.Name, m.Version)) | ||
86 | 566 | } | ||
87 | 567 | |||
88 | 540 | // takes a directory and removes the global root, this is needed | 568 | // takes a directory and removes the global root, this is needed |
89 | 541 | // when the SetRoot option is used and we need to generate | 569 | // when the SetRoot option is used and we need to generate |
90 | 542 | // content for the "Services" and "Binaries" section | 570 | // content for the "Services" and "Binaries" section |
91 | @@ -575,6 +603,7 @@ | |||
92 | 575 | // is in the service file when the SetRoot() option | 603 | // is in the service file when the SetRoot() option |
93 | 576 | // is used | 604 | // is used |
94 | 577 | realBaseDir := stripGlobalRootDir(baseDir) | 605 | realBaseDir := stripGlobalRootDir(baseDir) |
95 | 606 | // Generate service file | ||
96 | 578 | content, err := generateSnapServicesFile(service, realBaseDir, aaProfile, m) | 607 | content, err := generateSnapServicesFile(service, realBaseDir, aaProfile, m) |
97 | 579 | if err != nil { | 608 | if err != nil { |
98 | 580 | return err | 609 | return err |
99 | @@ -584,7 +613,18 @@ | |||
100 | 584 | if err := ioutil.WriteFile(serviceFilename, []byte(content), 0644); err != nil { | 613 | if err := ioutil.WriteFile(serviceFilename, []byte(content), 0644); err != nil { |
101 | 585 | return err | 614 | return err |
102 | 586 | } | 615 | } |
104 | 587 | 616 | // Generate systemd socket file if needed | |
105 | 617 | if service.Socket { | ||
106 | 618 | content, err := generateSnapSocketFile(service, realBaseDir, aaProfile, m) | ||
107 | 619 | if err != nil { | ||
108 | 620 | return err | ||
109 | 621 | } | ||
110 | 622 | socketFilename := generateSocketFileName(m, service) | ||
111 | 623 | os.MkdirAll(filepath.Dir(socketFilename), 0755) | ||
112 | 624 | if err := ioutil.WriteFile(socketFilename, []byte(content), 0644); err != nil { | ||
113 | 625 | return err | ||
114 | 626 | } | ||
115 | 627 | } | ||
116 | 588 | // If necessary, generate the DBus policy file so the framework | 628 | // If necessary, generate the DBus policy file so the framework |
117 | 589 | // service is allowed to start | 629 | // service is allowed to start |
118 | 590 | if m.Type == SnapTypeFramework && service.BusName != "" { | 630 | if m.Type == SnapTypeFramework && service.BusName != "" { |
119 | @@ -621,6 +661,20 @@ | |||
120 | 621 | return err | 661 | return err |
121 | 622 | } | 662 | } |
122 | 623 | } | 663 | } |
123 | 664 | |||
124 | 665 | if service.Socket { | ||
125 | 666 | socketName := filepath.Base(generateSocketFileName(m, service)) | ||
126 | 667 | // we always enable the socket even in inhibit hooks | ||
127 | 668 | if err := sysd.Enable(socketName); err != nil { | ||
128 | 669 | return err | ||
129 | 670 | } | ||
130 | 671 | |||
131 | 672 | if !inhibitHooks { | ||
132 | 673 | if err := sysd.Start(socketName); err != nil { | ||
133 | 674 | return err | ||
134 | 675 | } | ||
135 | 676 | } | ||
136 | 677 | } | ||
137 | 624 | } | 678 | } |
138 | 625 | 679 | ||
139 | 626 | return nil | 680 | return nil |
140 | @@ -652,6 +706,10 @@ | |||
141 | 652 | log.Printf("Warning: failed to remove service file for %s: %v", serviceName, err) | 706 | log.Printf("Warning: failed to remove service file for %s: %v", serviceName, err) |
142 | 653 | } | 707 | } |
143 | 654 | 708 | ||
144 | 709 | if err := os.Remove(generateSocketFileName(m, service)); err != nil && !os.IsNotExist(err) { | ||
145 | 710 | log.Printf("Failed to remove socket file for %q: %v", serviceName, err) | ||
146 | 711 | } | ||
147 | 712 | |||
148 | 655 | // Also remove DBus system policy file | 713 | // Also remove DBus system policy file |
149 | 656 | if err := os.Remove(generateBusPolicyFileName(m, service)); err != nil && !os.IsNotExist(err) { | 714 | if err := os.Remove(generateBusPolicyFileName(m, service)); err != nil && !os.IsNotExist(err) { |
150 | 657 | log.Printf("Warning: failed to remove bus policy file for service %s: %v", serviceName, err) | 715 | log.Printf("Warning: failed to remove bus policy file for service %s: %v", serviceName, err) |
151 | 658 | 716 | ||
152 | === modified file 'snappy/click_test.go' | |||
153 | --- snappy/click_test.go 2015-09-01 17:46:30 +0000 | |||
154 | +++ snappy/click_test.go 2015-09-08 06:48:07 +0000 | |||
155 | @@ -1200,9 +1200,10 @@ | |||
156 | 1200 | [Install] | 1200 | [Install] |
157 | 1201 | WantedBy=multi-user.target | 1201 | WantedBy=multi-user.target |
158 | 1202 | ` | 1202 | ` |
162 | 1203 | expectedServiceAppWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target", ".canonical", "canonical", "\n", helpers.UbuntuArchitecture()) | 1203 | expectedServiceAppWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target", ".canonical", "canonical", "\n", helpers.UbuntuArchitecture()) |
163 | 1204 | expectedNetAppWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target\nAfter=snappy-wait4network.service\nRequires=snappy-wait4network.service", ".canonical", "canonical", "\n", helpers.UbuntuArchitecture()) | 1204 | expectedNetAppWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target\nAfter=snappy-wait4network.service\nRequires=snappy-wait4network.service", ".canonical", "canonical", "\n", helpers.UbuntuArchitecture()) |
164 | 1205 | expectedServiceFmkWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "Before=ubuntu-snappy.frameworks.target\nAfter=ubuntu-snappy.frameworks-pre.target\nRequires=ubuntu-snappy.frameworks-pre.target", "", "", "BusName=foo.bar.baz\nType=dbus", helpers.UbuntuArchitecture()) | 1205 | expectedServiceFmkWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "Before=ubuntu-snappy.frameworks.target\nAfter=ubuntu-snappy.frameworks-pre.target\nRequires=ubuntu-snappy.frameworks-pre.target", "", "", "BusName=foo.bar.baz\nType=dbus", helpers.UbuntuArchitecture()) |
165 | 1206 | expectedSocketUsingWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "After=ubuntu-snappy.frameworks.target xkcd-webserver_xkcd-webserver_0.3.4.socket\nRequires=ubuntu-snappy.frameworks.target xkcd-webserver_xkcd-webserver_0.3.4.socket", ".canonical", "canonical", "\n", helpers.UbuntuArchitecture()) | ||
166 | 1206 | ) | 1207 | ) |
167 | 1207 | 1208 | ||
168 | 1208 | func (s *SnapTestSuite) TestSnappyGenerateSnapServiceAppWrapper(c *C) { | 1209 | func (s *SnapTestSuite) TestSnappyGenerateSnapServiceAppWrapper(c *C) { |
169 | @@ -1521,3 +1522,57 @@ | |||
170 | 1521 | exitCode: 1, | 1522 | exitCode: 1, |
171 | 1522 | }) | 1523 | }) |
172 | 1523 | } | 1524 | } |
173 | 1525 | |||
174 | 1526 | func (s *SnapTestSuite) TestSnappyGenerateSnapSocket(c *C) { | ||
175 | 1527 | service := Service{Name: "xkcd-webserver", | ||
176 | 1528 | Start: "bin/foo start", | ||
177 | 1529 | Description: "meep", | ||
178 | 1530 | Socket: true, | ||
179 | 1531 | ListenStream: "/var/run/docker.sock", | ||
180 | 1532 | SocketMode: "0660", | ||
181 | 1533 | SocketUser: "root", | ||
182 | 1534 | SocketGroup: "adm", | ||
183 | 1535 | } | ||
184 | 1536 | pkgPath := "/apps/xkcd-webserver.canonical/0.3.4/" | ||
185 | 1537 | aaProfile := "xkcd-webserver.canonical_xkcd-webserver_0.3.4" | ||
186 | 1538 | m := packageYaml{ | ||
187 | 1539 | Name: "xkcd-webserver", | ||
188 | 1540 | Version: "0.3.4"} | ||
189 | 1541 | |||
190 | 1542 | content, err := generateSnapSocketFile(service, pkgPath, aaProfile, &m) | ||
191 | 1543 | c.Assert(err, IsNil) | ||
192 | 1544 | c.Assert(content, Equals, `[Unit] | ||
193 | 1545 | Description= Socket Unit File | ||
194 | 1546 | PartOf=xkcd-webserver_xkcd-webserver_0.3.4.service | ||
195 | 1547 | X-Snappy=yes | ||
196 | 1548 | |||
197 | 1549 | [Socket] | ||
198 | 1550 | ListenStream=/var/run/docker.sock | ||
199 | 1551 | SocketMode=0660 | ||
200 | 1552 | SocketUSer=root | ||
201 | 1553 | SocketGroup=adm | ||
202 | 1554 | |||
203 | 1555 | [Install] | ||
204 | 1556 | WantedBy=sockets.target | ||
205 | 1557 | `) | ||
206 | 1558 | } | ||
207 | 1559 | |||
208 | 1560 | func (s *SnapTestSuite) TestSnappyGenerateSnapServiceWithSockte(c *C) { | ||
209 | 1561 | service := Service{ | ||
210 | 1562 | Name: "xkcd-webserver", | ||
211 | 1563 | Start: "bin/foo start", | ||
212 | 1564 | Stop: "bin/foo stop", | ||
213 | 1565 | PostStop: "bin/foo post-stop", | ||
214 | 1566 | StopTimeout: DefaultTimeout, | ||
215 | 1567 | Description: "A fun webserver", | ||
216 | 1568 | Socket: true, | ||
217 | 1569 | } | ||
218 | 1570 | pkgPath := "/apps/xkcd-webserver.canonical/0.3.4/" | ||
219 | 1571 | aaProfile := "xkcd-webserver.canonical_xkcd-webserver_0.3.4" | ||
220 | 1572 | m := packageYaml{Name: "xkcd-webserver", | ||
221 | 1573 | Version: "0.3.4"} | ||
222 | 1574 | |||
223 | 1575 | generatedWrapper, err := generateSnapServicesFile(service, pkgPath, aaProfile, &m) | ||
224 | 1576 | c.Assert(err, IsNil) | ||
225 | 1577 | c.Assert(generatedWrapper, Equals, expectedSocketUsingWrapper) | ||
226 | 1578 | } | ||
227 | 1524 | 1579 | ||
228 | === modified file 'snappy/snapp.go' | |||
229 | --- snappy/snapp.go 2015-07-07 02:35:22 +0000 | |||
230 | +++ snappy/snapp.go 2015-09-08 06:48:07 +0000 | |||
231 | @@ -146,6 +146,13 @@ | |||
232 | 146 | StopTimeout Timeout `yaml:"stop-timeout,omitempty" json:"stop-timeout,omitempty"` | 146 | StopTimeout Timeout `yaml:"stop-timeout,omitempty" json:"stop-timeout,omitempty"` |
233 | 147 | BusName string `yaml:"bus-name,omitempty" json:"bus-name,omitempty"` | 147 | BusName string `yaml:"bus-name,omitempty" json:"bus-name,omitempty"` |
234 | 148 | 148 | ||
235 | 149 | // set to yes if we need to create a systemd socket for this service | ||
236 | 150 | Socket bool `yaml:"socket,omitempty" json:"socket,omitempty"` | ||
237 | 151 | ListenStream string `yaml:"listen-stream,omitempty" json:"listen-stream,omitempty"` | ||
238 | 152 | SocketMode string `yaml:"socket-mode,omitempty" json:"socket-mode,omitempty"` | ||
239 | 153 | SocketUser string `yaml:"socket-user,omitempty" json:"socket-user,omitempty"` | ||
240 | 154 | SocketGroup string `yaml:"socket-group,omitempty" json:"socket-group,omitempty"` | ||
241 | 155 | |||
242 | 149 | // must be a pointer so that it can be "nil" and omitempty works | 156 | // must be a pointer so that it can be "nil" and omitempty works |
243 | 150 | Ports *Ports `yaml:"ports,omitempty" json:"ports,omitempty"` | 157 | Ports *Ports `yaml:"ports,omitempty" json:"ports,omitempty"` |
244 | 151 | 158 | ||
245 | 152 | 159 | ||
246 | === modified file 'systemd/systemd.go' | |||
247 | --- systemd/systemd.go 2015-09-01 17:46:30 +0000 | |||
248 | +++ systemd/systemd.go 2015-09-08 06:48:07 +0000 | |||
249 | @@ -66,30 +66,41 @@ | |||
250 | 66 | Kill(service, signal string) error | 66 | Kill(service, signal string) error |
251 | 67 | Restart(service string, timeout time.Duration) error | 67 | Restart(service string, timeout time.Duration) error |
252 | 68 | GenServiceFile(desc *ServiceDescription) string | 68 | GenServiceFile(desc *ServiceDescription) string |
253 | 69 | GenSocketFile(desc *ServiceDescription) string | ||
254 | 69 | } | 70 | } |
255 | 70 | 71 | ||
256 | 71 | // ServiceDescription describes a snappy systemd service | 72 | // ServiceDescription describes a snappy systemd service |
257 | 72 | type ServiceDescription struct { | 73 | type ServiceDescription struct { |
272 | 73 | AppName string | 74 | AppName string |
273 | 74 | ServiceName string | 75 | ServiceName string |
274 | 75 | Version string | 76 | Version string |
275 | 76 | Description string | 77 | Description string |
276 | 77 | AppPath string | 78 | AppPath string |
277 | 78 | Start string | 79 | Start string |
278 | 79 | Stop string | 80 | Stop string |
279 | 80 | PostStop string | 81 | PostStop string |
280 | 81 | StopTimeout time.Duration | 82 | StopTimeout time.Duration |
281 | 82 | AaProfile string | 83 | AaProfile string |
282 | 83 | IsFramework bool | 84 | IsFramework bool |
283 | 84 | IsNetworked bool | 85 | IsNetworked bool |
284 | 85 | BusName string | 86 | BusName string |
285 | 86 | UdevAppName string | 87 | UdevAppName string |
286 | 88 | Socket bool | ||
287 | 89 | SocketFileName string | ||
288 | 90 | ListenStream string | ||
289 | 91 | SocketMode string | ||
290 | 92 | SocketUser string | ||
291 | 93 | SocketGroup string | ||
292 | 94 | ServiceFileName string | ||
293 | 87 | } | 95 | } |
294 | 88 | 96 | ||
295 | 89 | const ( | 97 | const ( |
296 | 90 | // the default target for systemd units that we generate | 98 | // the default target for systemd units that we generate |
297 | 91 | servicesSystemdTarget = "multi-user.target" | 99 | servicesSystemdTarget = "multi-user.target" |
298 | 92 | 100 | ||
299 | 101 | // the default target for systemd units that we generate | ||
300 | 102 | socketsSystemdTarget = "sockets.target" | ||
301 | 103 | |||
302 | 93 | // the location to put system services | 104 | // the location to put system services |
303 | 94 | snapServicesDir = "/etc/systemd/system" | 105 | snapServicesDir = "/etc/systemd/system" |
304 | 95 | ) | 106 | ) |
305 | @@ -173,9 +184,9 @@ | |||
306 | 173 | serviceTemplate := `[Unit] | 184 | serviceTemplate := `[Unit] |
307 | 174 | Description={{.Description}} | 185 | Description={{.Description}} |
308 | 175 | {{if .IsFramework}}Before=ubuntu-snappy.frameworks.target | 186 | {{if .IsFramework}}Before=ubuntu-snappy.frameworks.target |
312 | 176 | After=ubuntu-snappy.frameworks-pre.target | 187 | After=ubuntu-snappy.frameworks-pre.target{{ if .Socket }} {{.SocketFileName}}{{end}} |
313 | 177 | Requires=ubuntu-snappy.frameworks-pre.target{{else}}After=ubuntu-snappy.frameworks.target | 188 | Requires=ubuntu-snappy.frameworks-pre.target{{ if .Socket }} {{.SocketFileName}}{{end}}{{else}}After=ubuntu-snappy.frameworks.target{{ if .Socket }} {{.SocketFileName}}{{end}} |
314 | 178 | Requires=ubuntu-snappy.frameworks.target{{end}}{{if .IsNetworked}} | 189 | Requires=ubuntu-snappy.frameworks.target{{ if .Socket }} {{.SocketFileName}}{{end}}{{end}}{{if .IsNetworked}} |
315 | 179 | After=snappy-wait4network.service | 190 | After=snappy-wait4network.service |
316 | 180 | Requires=snappy-wait4network.service{{end}} | 191 | Requires=snappy-wait4network.service{{end}} |
317 | 181 | X-Snappy=yes | 192 | X-Snappy=yes |
318 | @@ -213,6 +224,7 @@ | |||
319 | 213 | AppArch string | 224 | AppArch string |
320 | 214 | Home string | 225 | Home string |
321 | 215 | EnvVars string | 226 | EnvVars string |
322 | 227 | SocketFileName string | ||
323 | 216 | }{ | 228 | }{ |
324 | 217 | *desc, | 229 | *desc, |
325 | 218 | filepath.Join(desc.AppPath, desc.Start), | 230 | filepath.Join(desc.AppPath, desc.Start), |
326 | @@ -224,6 +236,7 @@ | |||
327 | 224 | helpers.UbuntuArchitecture(), | 236 | helpers.UbuntuArchitecture(), |
328 | 225 | "%h", | 237 | "%h", |
329 | 226 | "", | 238 | "", |
330 | 239 | desc.SocketFileName, | ||
331 | 227 | } | 240 | } |
332 | 228 | allVars := helpers.GetBasicSnapEnvVars(wrapperData) | 241 | allVars := helpers.GetBasicSnapEnvVars(wrapperData) |
333 | 229 | allVars = append(allVars, helpers.GetUserSnapEnvVars(wrapperData)...) | 242 | allVars = append(allVars, helpers.GetUserSnapEnvVars(wrapperData)...) |
334 | @@ -239,6 +252,52 @@ | |||
335 | 239 | return templateOut.String() | 252 | return templateOut.String() |
336 | 240 | } | 253 | } |
337 | 241 | 254 | ||
338 | 255 | func (s *systemd) GenSocketFile(desc *ServiceDescription) string { | ||
339 | 256 | serviceTemplate := `[Unit] | ||
340 | 257 | Description={{.Description}} Socket Unit File | ||
341 | 258 | PartOf={{.ServiceFileName}} | ||
342 | 259 | X-Snappy=yes | ||
343 | 260 | |||
344 | 261 | [Socket] | ||
345 | 262 | ListenStream={{.ListenStream}} | ||
346 | 263 | {{if .SocketMode}}SocketMode={{.SocketMode}}{{end}} | ||
347 | 264 | {{if .SocketUser}}SocketUSer={{.SocketUser}}{{end}} | ||
348 | 265 | {{if .SocketGroup}}SocketGroup={{.SocketGroup}}{{end}} | ||
349 | 266 | |||
350 | 267 | [Install] | ||
351 | 268 | WantedBy={{.SocketSystemdTarget}} | ||
352 | 269 | ` | ||
353 | 270 | var templateOut bytes.Buffer | ||
354 | 271 | t := template.Must(template.New("wrapper").Parse(serviceTemplate)) | ||
355 | 272 | |||
356 | 273 | wrapperData := struct { | ||
357 | 274 | // the service description | ||
358 | 275 | ServiceDescription | ||
359 | 276 | // and some composed values | ||
360 | 277 | ServiceFileName, | ||
361 | 278 | ListenStream string | ||
362 | 279 | SocketMode string | ||
363 | 280 | SocketUser string | ||
364 | 281 | SocketGroup string | ||
365 | 282 | SocketSystemdTarget string | ||
366 | 283 | }{ | ||
367 | 284 | *desc, | ||
368 | 285 | desc.ServiceFileName, | ||
369 | 286 | desc.ListenStream, | ||
370 | 287 | desc.SocketMode, | ||
371 | 288 | desc.SocketUser, | ||
372 | 289 | desc.SocketGroup, | ||
373 | 290 | socketsSystemdTarget, | ||
374 | 291 | } | ||
375 | 292 | |||
376 | 293 | if err := t.Execute(&templateOut, wrapperData); err != nil { | ||
377 | 294 | // this can never happen, except we forget a variable | ||
378 | 295 | logger.LogAndPanic(err) | ||
379 | 296 | } | ||
380 | 297 | |||
381 | 298 | return templateOut.String() | ||
382 | 299 | } | ||
383 | 300 | |||
384 | 242 | // Kill all processes of the unit with the given signal | 301 | // Kill all processes of the unit with the given signal |
385 | 243 | func (s *systemd) Kill(serviceName, signal string) error { | 302 | func (s *systemd) Kill(serviceName, signal string) error { |
386 | 244 | _, err := SystemctlCmd("kill", serviceName, "-s", signal) | 303 | _, err := SystemctlCmd("kill", serviceName, "-s", signal) |