Merge lp:~chipaca/snappy/dynamicExclusion into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by John Lenton on 2015-07-29
Status: Superseded
Proposed branch: lp:~chipaca/snappy/dynamicExclusion
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Diff against target: 490 lines (+278/-4)
13 files modified
debian/golang-snappy-dev.install (+1/-0)
debian/rules (+9/-0)
debian/snappy-wait4network.service (+9/-0)
debian/ubuntu-snappy-cli.install (+1/-0)
snappy/build.go (+53/-2)
snappy/build_test.go (+22/-0)
snappy/click.go (+1/-0)
snappy/click_test.go (+21/-0)
snappy/firstboot.go (+10/-1)
snappy/firstboot_test.go (+25/-0)
systemd/systemd.go (+4/-1)
systemd/systemd_test.go (+45/-0)
wait4network/wait4network.go (+77/-0)
To merge this branch: bzr merge lp:~chipaca/snappy/dynamicExclusion
Reviewer Review Type Date Requested Status
Snappy Developers 2015-07-29 Pending
Review via email: mp+266199@code.launchpad.net

This proposal has been superseded by a proposal from 2015-07-29.

Commit Message

Introducing .snapignore, which is made of lines of regexps and not globs.

To post a comment you must log in.
lp:~chipaca/snappy/dynamicExclusion updated on 2015-07-29
618. By John Lenton on 2015-07-29

addressed issues found in review

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/golang-snappy-dev.install'
2--- debian/golang-snappy-dev.install 2015-03-18 19:26:18 +0000
3+++ debian/golang-snappy-dev.install 2015-07-29 09:50:51 +0000
4@@ -1,1 +1,2 @@
5+/usr/bin/xgettext-go
6 /usr/share/gocode
7
8=== modified file 'debian/rules'
9--- debian/rules 2015-07-01 07:48:19 +0000
10+++ debian/rules 2015-07-29 09:50:51 +0000
11@@ -4,6 +4,7 @@
12 #export DH_VERBOSE=1
13 export DH_OPTIONS
14 export DH_GOPKG := launchpad.net/snappy
15+#export DEB_BUILD_OPTIONS=nocheck
16
17 %:
18 dh $@ --buildsystem=golang --with=golang --fail-missing --with systemd
19@@ -30,6 +31,10 @@
20 --no-enable \
21 -pubuntu-snappy \
22 snappy-autopilot.service
23+ # enable wait4network
24+ dh_systemd_enable \
25+ -pubuntu-snappy \
26+ snappy-wait4network.service
27
28 override_dh_systemd_start:
29 # start boot-ok
30@@ -49,6 +54,10 @@
31 --no-start \
32 -pubuntu-snappy \
33 snappy-autopilot.service
34+ # start wait4network
35+ dh_systemd_start \
36+ -pubuntu-snappy \
37+ snappy-wait4network.service
38
39 override_dh_auto_build:
40 # this will update the i18n stuff
41
42=== added file 'debian/snappy-wait4network.service'
43--- debian/snappy-wait4network.service 1970-01-01 00:00:00 +0000
44+++ debian/snappy-wait4network.service 2015-07-29 09:50:51 +0000
45@@ -0,0 +1,9 @@
46+[Unit]
47+Description=Wait for network
48+After=network-online.target
49+
50+[Service]
51+Type=oneshot
52+RemainAfterExit=yes
53+TimeoutStartSec=0
54+ExecStart=/usr/bin/wait4network http://start.ubuntu.com/connectivity-check.html 4589f42e1546aa47ca181e5d949d310b 1s 5s
55
56=== modified file 'debian/ubuntu-snappy-cli.install'
57--- debian/ubuntu-snappy-cli.install 2015-07-01 07:47:55 +0000
58+++ debian/ubuntu-snappy-cli.install 2015-07-29 09:50:51 +0000
59@@ -1,4 +1,5 @@
60 /usr/bin/snappy
61+/usr/bin/wait4network
62 data/completion/snappy /usr/share/bash-completion/completions/
63 # i18n stuff
64 ../../share /usr
65
66=== modified file 'snappy/build.go'
67--- snappy/build.go 2015-07-23 11:05:37 +0000
68+++ snappy/build.go 2015-07-29 09:50:51 +0000
69@@ -51,7 +51,7 @@
70 //
71 // Please resist the temptation of optimizing the regexp by grouping
72 // things by hand. People will find it unreadable enough as it is.
73-var shouldExclude = regexp.MustCompile(strings.Join([]string{
74+var shouldExcludeDefault = regexp.MustCompile(strings.Join([]string{
75 `\.snap$`, // added
76 `\.click$`,
77 `^\..*\.sw.$`,
78@@ -82,8 +82,59 @@
79 `^_MTN$`,
80 `^_darcs$`,
81 `^{arch}$`,
82+ `^\.snapignore$`,
83 }, "|")).MatchString
84
85+// fake static function variables
86+type keep struct {
87+ basedir string
88+ exclude func(string) bool
89+}
90+
91+func (k *keep) shouldExclude(basedir string, file string) bool {
92+ if basedir == k.basedir {
93+ if k.exclude == nil {
94+ return false
95+ }
96+ return k.exclude(file)
97+ }
98+
99+ k.basedir = basedir
100+ k.exclude = nil
101+
102+ f, err := os.Open(filepath.Join(basedir, ".snapignore"))
103+ if err != nil {
104+ return false
105+ }
106+
107+ scanner := bufio.NewScanner(f)
108+ var lines []string
109+ for scanner.Scan() {
110+ line := scanner.Text()
111+ if _, err := regexp.Compile(line); err != nil {
112+ // not a regexp
113+ line = regexp.QuoteMeta(line)
114+ }
115+ lines = append(lines, line)
116+ }
117+
118+ fullRegex := strings.Join(lines, "|")
119+ exclude, err := regexp.Compile(fullRegex)
120+ if err == nil {
121+ k.exclude = exclude.MatchString
122+
123+ return k.exclude(file)
124+ }
125+
126+ panic(fmt.Sprintf("|-composition of valid regexps is invalid?!? Please report this bug: %#v", fullRegex))
127+}
128+
129+var shouldExcludeDynamic = new(keep).shouldExclude
130+
131+func shouldExclude(basedir string, file string) bool {
132+ return shouldExcludeDefault(file) || shouldExcludeDynamic(basedir, file)
133+}
134+
135 // small helper that return the architecture or "multi" if its multiple arches
136 func debArchitecture(m *packageYaml) string {
137 switch len(m.Architectures) {
138@@ -375,7 +426,7 @@
139 return errin
140 }
141
142- if shouldExclude(filepath.Base(path)) {
143+ if shouldExclude(sourceDir, filepath.Base(path)) {
144 if info.IsDir() {
145 return filepath.SkipDir
146 }
147
148=== modified file 'snappy/build_test.go'
149--- snappy/build_test.go 2015-06-08 16:26:25 +0000
150+++ snappy/build_test.go 2015-07-29 09:50:51 +0000
151@@ -356,6 +356,28 @@
152 c.Check(string(out), Matches, `(?m)Only in \S+: \.bzr`)
153 }
154
155+func (s *SnapTestSuite) TestExcludeDynamicFalseIfNoSnapignore(c *C) {
156+ basedir := c.MkDir()
157+ c.Check(shouldExcludeDynamic(basedir, "foo"), Equals, false)
158+}
159+
160+func (s *SnapTestSuite) TestExcludeDynamicWorksIfSnapignore(c *C) {
161+ basedir := c.MkDir()
162+ c.Assert(ioutil.WriteFile(filepath.Join(basedir, ".snapignore"), []byte("foo\nb.r\n"), 0644), IsNil)
163+ c.Check(shouldExcludeDynamic(basedir, "foo"), Equals, true)
164+ c.Check(shouldExcludeDynamic(basedir, "bar"), Equals, true)
165+ c.Check(shouldExcludeDynamic(basedir, "bzr"), Equals, true)
166+ c.Check(shouldExcludeDynamic(basedir, "baz"), Equals, false)
167+}
168+
169+func (s *SnapTestSuite) TestExcludeDynamicWeirdRegexps(c *C) {
170+ basedir := c.MkDir()
171+ c.Assert(ioutil.WriteFile(filepath.Join(basedir, ".snapignore"), []byte("*hello\n"), 0644), IsNil)
172+ // note “*hello” is not a valid regexp, so will be taken literally (not globbed!)
173+ c.Check(shouldExcludeDynamic(basedir, "ahello"), Equals, false)
174+ c.Check(shouldExcludeDynamic(basedir, "*hello"), Equals, true)
175+}
176+
177 func (s *SnapTestSuite) TestBuildSimpleOutputDir(c *C) {
178 sourceDir := makeExampleSnapSourceDir(c, `name: hello
179 version: 1.0.1
180
181=== modified file 'snappy/click.go'
182--- snappy/click.go 2015-07-23 11:05:37 +0000
183+++ snappy/click.go 2015-07-29 09:50:51 +0000
184@@ -444,6 +444,7 @@
185 StopTimeout: time.Duration(service.StopTimeout),
186 AaProfile: aaProfile,
187 IsFramework: m.Type == pkg.TypeFramework,
188+ IsNetworked: service.Ports != nil && len(service.Ports.External) > 0,
189 BusName: service.BusName,
190 UdevAppName: udevPartName,
191 }), nil
192
193=== modified file 'snappy/click_test.go'
194--- snappy/click_test.go 2015-07-23 11:05:37 +0000
195+++ snappy/click_test.go 2015-07-29 09:50:51 +0000
196@@ -1231,6 +1231,7 @@
197 WantedBy=multi-user.target
198 `
199 expectedServiceAppWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target", ".canonical", "canonical", "\n", helpers.UbuntuArchitecture())
200+ 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())
201 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())
202 )
203
204@@ -1253,6 +1254,26 @@
205 c.Assert(generatedWrapper, Equals, expectedServiceAppWrapper)
206 }
207
208+func (s *SnapTestSuite) TestSnappyGenerateSnapServiceAppWrapperWithExternalPort(c *C) {
209+ service := ServiceYaml{
210+ Name: "xkcd-webserver",
211+ Start: "bin/foo start",
212+ Stop: "bin/foo stop",
213+ PostStop: "bin/foo post-stop",
214+ StopTimeout: DefaultTimeout,
215+ Description: "A fun webserver",
216+ Ports: &Ports{External: map[string]Port{"foo": Port{}}},
217+ }
218+ pkgPath := "/apps/xkcd-webserver.canonical/0.3.4/"
219+ aaProfile := "xkcd-webserver.canonical_xkcd-webserver_0.3.4"
220+ m := packageYaml{Name: "xkcd-webserver",
221+ Version: "0.3.4"}
222+
223+ generatedWrapper, err := generateSnapServicesFile(service, pkgPath, aaProfile, &m)
224+ c.Assert(err, IsNil)
225+ c.Assert(generatedWrapper, Equals, expectedNetAppWrapper)
226+}
227+
228 func (s *SnapTestSuite) TestSnappyGenerateSnapServiceFmkWrapper(c *C) {
229 service := ServiceYaml{
230 Name: "xkcd-webserver",
231
232=== modified file 'snappy/firstboot.go'
233--- snappy/firstboot.go 2015-07-13 14:19:52 +0000
234+++ snappy/firstboot.go 2015-07-29 09:50:51 +0000
235@@ -28,6 +28,7 @@
236
237 "launchpad.net/snappy/helpers"
238 "launchpad.net/snappy/pkg"
239+ "launchpad.net/snappy/systemd"
240
241 "gopkg.in/yaml.v2"
242 )
243@@ -135,7 +136,15 @@
244 ethfile := filepath.Join(ethdir, eth)
245 data := fmt.Sprintf("auto %[1]s\n\nallow-hotplug %[1]s\niface %[1]s inet dhcp\n", eth)
246
247- return helpers.AtomicWriteFile(ethfile, []byte(data), 0644)
248+ if err := helpers.AtomicWriteFile(ethfile, []byte(data), 0644); err != nil {
249+ return err
250+ }
251+
252+ if _, err := systemd.SystemctlCmd("restart", "networking", "--no-block"); err != nil {
253+ return err
254+ }
255+
256+ return nil
257 }
258
259 func firstBootHasRun() bool {
260
261=== modified file 'snappy/firstboot_test.go'
262--- snappy/firstboot_test.go 2015-07-13 15:54:24 +0000
263+++ snappy/firstboot_test.go 2015-07-29 09:50:51 +0000
264@@ -28,6 +28,7 @@
265 . "gopkg.in/check.v1"
266
267 "launchpad.net/snappy/pkg"
268+ "launchpad.net/snappy/systemd"
269 )
270
271 type fakePart struct {
272@@ -54,11 +55,21 @@
273 oemConfig map[string]interface{}
274 globs []string
275 ethdir string
276+ sctlargs []string
277+ sctlerr error
278 }
279
280 var _ = Suite(&FirstBootTestSuite{})
281
282+func (s *FirstBootTestSuite) systemctl(args ...string) (out []byte, err error) {
283+ s.sctlargs = args
284+ return nil, s.sctlerr
285+}
286+
287 func (s *FirstBootTestSuite) SetUpTest(c *C) {
288+ s.sctlerr = nil
289+ s.sctlargs = nil
290+ systemd.SystemctlCmd = s.systemctl
291 stampFile = filepath.Join(c.MkDir(), "stamp")
292
293 configMyApp := make(SystemConfig)
294@@ -150,6 +161,20 @@
295 c.Assert(err, IsNil)
296 c.Check(string(bs), Equals, "auto eth42\n\nallow-hotplug eth42\niface eth42 inet dhcp\n")
297
298+ c.Check(s.sctlargs, DeepEquals, []string{"restart", "networking", "--no-block"})
299+}
300+
301+func (s *FirstBootTestSuite) TestEnableFirstEtherSomeEthFailsIfSystemctlFails(c *C) {
302+ dir := c.MkDir()
303+ _, err := os.Create(filepath.Join(dir, "eth42"))
304+ c.Assert(err, IsNil)
305+ s.sctlerr = fmt.Errorf("Error")
306+
307+ globs = []string{filepath.Join(dir, "eth*")}
308+ c.Check(enableFirstEther(), Equals, s.sctlerr)
309+ fs, _ := filepath.Glob(filepath.Join(ethdir, "*"))
310+ c.Check(fs, HasLen, 1)
311+ c.Check(s.sctlargs, DeepEquals, []string{"restart", "networking", "--no-block"})
312 }
313
314 func (s *FirstBootTestSuite) TestEnableFirstEtherBadEthDir(c *C) {
315
316=== modified file 'systemd/systemd.go'
317--- systemd/systemd.go 2015-07-23 13:15:56 +0000
318+++ systemd/systemd.go 2015-07-29 09:50:51 +0000
319@@ -84,6 +84,7 @@
320 StopTimeout time.Duration
321 AaProfile string
322 IsFramework bool
323+ IsNetworked bool
324 BusName string
325 UdevAppName string
326 }
327@@ -205,7 +206,9 @@
328 {{if .IsFramework}}Before=ubuntu-snappy.frameworks.target
329 After=ubuntu-snappy.frameworks-pre.target
330 Requires=ubuntu-snappy.frameworks-pre.target{{else}}After=ubuntu-snappy.frameworks.target
331-Requires=ubuntu-snappy.frameworks.target{{end}}
332+Requires=ubuntu-snappy.frameworks.target{{end}}{{if .IsNetworked}}
333+After=snappy-wait4network.service
334+Requires=snappy-wait4network.service{{end}}
335 X-Snappy=yes
336
337 [Service]
338
339=== modified file 'systemd/systemd_test.go'
340--- systemd/systemd_test.go 2015-07-23 13:15:56 +0000
341+++ systemd/systemd_test.go 2015-07-29 09:50:51 +0000
342@@ -181,6 +181,10 @@
343 expectedAppService = fmt.Sprintf(expectedServiceFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target", ".mvo", "mvo", "\n", helpers.UbuntuArchitecture())
344 expectedFmkService = fmt.Sprintf(expectedServiceFmt, "Before=ubuntu-snappy.frameworks.target\nAfter=ubuntu-snappy.frameworks-pre.target\nRequires=ubuntu-snappy.frameworks-pre.target", "", "", "\n", helpers.UbuntuArchitecture())
345 expectedDbusService = fmt.Sprintf(expectedServiceFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target", ".mvo", "mvo", "BusName=foo.bar.baz\nType=dbus", helpers.UbuntuArchitecture())
346+
347+ // things that need network
348+ expectedNetAppService = fmt.Sprintf(expectedServiceFmt, "After=ubuntu-snappy.frameworks.target\nRequires=ubuntu-snappy.frameworks.target\nAfter=snappy-wait4network.service\nRequires=snappy-wait4network.service", ".mvo", "mvo", "\n", helpers.UbuntuArchitecture())
349+ expectedNetFmkService = fmt.Sprintf(expectedServiceFmt, "Before=ubuntu-snappy.frameworks.target\nAfter=ubuntu-snappy.frameworks-pre.target\nRequires=ubuntu-snappy.frameworks-pre.target\nAfter=snappy-wait4network.service\nRequires=snappy-wait4network.service", "", "", "\n", helpers.UbuntuArchitecture())
350 )
351
352 func (s *SystemdTestSuite) TestGenAppServiceFile(c *C) {
353@@ -202,6 +206,26 @@
354 c.Check(New("", nil).GenServiceFile(desc), Equals, expectedAppService)
355 }
356
357+func (s *SystemdTestSuite) TestGenNetAppServiceFile(c *C) {
358+
359+ desc := &ServiceDescription{
360+ AppName: "app",
361+ ServiceName: "service",
362+ Version: "1.0",
363+ Description: "descr",
364+ AppPath: "/apps/app.mvo/1.0/",
365+ Start: "bin/start",
366+ Stop: "bin/stop",
367+ PostStop: "bin/stop --post",
368+ StopTimeout: time.Duration(10 * time.Second),
369+ AaProfile: "aa-profile",
370+ IsNetworked: true,
371+ UdevAppName: "app.mvo",
372+ }
373+
374+ c.Check(New("", nil).GenServiceFile(desc), Equals, expectedNetAppService)
375+}
376+
377 func (s *SystemdTestSuite) TestGenFmkServiceFile(c *C) {
378
379 desc := &ServiceDescription{
380@@ -222,6 +246,27 @@
381 c.Check(New("", nil).GenServiceFile(desc), Equals, expectedFmkService)
382 }
383
384+func (s *SystemdTestSuite) TestGenNetFmkServiceFile(c *C) {
385+
386+ desc := &ServiceDescription{
387+ AppName: "app",
388+ ServiceName: "service",
389+ Version: "1.0",
390+ Description: "descr",
391+ AppPath: "/apps/app/1.0/",
392+ Start: "bin/start",
393+ Stop: "bin/stop",
394+ PostStop: "bin/stop --post",
395+ StopTimeout: time.Duration(10 * time.Second),
396+ AaProfile: "aa-profile",
397+ IsNetworked: true,
398+ IsFramework: true,
399+ UdevAppName: "app",
400+ }
401+
402+ c.Check(New("", nil).GenServiceFile(desc), Equals, expectedNetFmkService)
403+}
404+
405 func (s *SystemdTestSuite) TestGenServiceFileWithBusName(c *C) {
406
407 desc := &ServiceDescription{
408
409=== added directory 'wait4network'
410=== added file 'wait4network/wait4network.go'
411--- wait4network/wait4network.go 1970-01-01 00:00:00 +0000
412+++ wait4network/wait4network.go 2015-07-29 09:50:51 +0000
413@@ -0,0 +1,77 @@
414+// -*- Mode: Go; indent-tabs-mode: t -*-
415+
416+/*
417+ * Copyright (C) 2014-2015 Canonical Ltd
418+ *
419+ * This program is free software: you can redistribute it and/or modify
420+ * it under the terms of the GNU General Public License version 3 as
421+ * published by the Free Software Foundation.
422+ *
423+ * This program is distributed in the hope that it will be useful,
424+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
425+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
426+ * GNU General Public License for more details.
427+ *
428+ * You should have received a copy of the GNU General Public License
429+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
430+ *
431+ */
432+
433+package main
434+
435+import (
436+ "crypto/md5"
437+ "fmt"
438+ "io"
439+ "net"
440+ "net/http"
441+ "os"
442+ "time"
443+)
444+
445+var (
446+ errUsage = fmt.Errorf("Usage: %s URL MD5 TIMEOUT INTERVAL; for example: http://start.ubuntu.com/connectivity-check.html 4589f42e1546aa47ca181e5d949d310b 1s 5s", os.Args[0])
447+)
448+
449+func die(err error) {
450+ fmt.Fprintln(os.Stderr, "error:", err)
451+ os.Exit(1)
452+}
453+
454+func main() {
455+ if len(os.Args) != 5 {
456+ die(errUsage)
457+ }
458+
459+ targetURL := os.Args[1]
460+ targetMD5 := os.Args[2]
461+ targetTimeout, err := time.ParseDuration(os.Args[3])
462+ if err != nil {
463+ die(err)
464+ }
465+ interval, err := time.ParseDuration(os.Args[4])
466+ if err != nil {
467+ die(err)
468+ }
469+
470+ client := &http.Client{
471+ Transport: &http.Transport{
472+ Dial: func(network, addr string) (net.Conn, error) {
473+ return net.DialTimeout(network, addr, targetTimeout)
474+ },
475+ },
476+ }
477+
478+ ticker := time.NewTicker(interval)
479+
480+ for {
481+ if resp, err := client.Get(targetURL); err == nil {
482+ h := md5.New()
483+ io.Copy(h, resp.Body)
484+ if fmt.Sprintf("%x", h.Sum(nil)) == targetMD5 {
485+ os.Exit(0)
486+ }
487+ }
488+ <-ticker.C
489+ }
490+}

Subscribers

People subscribed via source and target branches