github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/cmd/snap-preseed/main.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package main 21 22 import ( 23 "fmt" 24 "io" 25 "os" 26 "path/filepath" 27 28 "github.com/jessevdk/go-flags" 29 ) 30 31 const ( 32 shortHelp = "Prerun the first boot seeding of snaps in an image filesystem chroot with a snapd seed." 33 longHelp = ` 34 The snap-preseed command takes a directory containing an image, including seed 35 snaps (at /var/lib/snapd/seed), and runs through the snapd first-boot process 36 up to hook execution. No boot actions unrelated to snapd are performed. 37 It creates systemd units for seeded snaps, makes any connections, and generates 38 security profiles. The image is updated and consequently optimised to reduce 39 first-boot startup time` 40 ) 41 42 type options struct { 43 Reset bool `long:"reset"` 44 } 45 46 var ( 47 osGetuid = os.Getuid 48 Stdout io.Writer = os.Stdout 49 Stderr io.Writer = os.Stderr 50 51 opts options 52 ) 53 54 func Parser() *flags.Parser { 55 opts = options{} 56 parser := flags.NewParser(&opts, flags.HelpFlag|flags.PassDoubleDash|flags.PassAfterNonOption) 57 parser.ShortDescription = shortHelp 58 parser.LongDescription = longHelp 59 return parser 60 } 61 62 func main() { 63 parser := Parser() 64 if err := run(parser, os.Args[1:]); err != nil { 65 fmt.Fprintf(Stderr, "error: %v\n", err) 66 os.Exit(1) 67 } 68 } 69 70 func run(parser *flags.Parser, args []string) error { 71 if osGetuid() != 0 { 72 return fmt.Errorf("must be run as root") 73 } 74 75 rest, err := parser.ParseArgs(args) 76 if err != nil { 77 return err 78 } 79 80 if len(rest) == 0 { 81 return fmt.Errorf("need chroot path as argument") 82 } 83 84 chrootDir, err := filepath.Abs(rest[0]) 85 if err != nil { 86 return err 87 } 88 89 // safety check 90 if chrootDir == "/" { 91 return fmt.Errorf("cannot run snap-preseed against /") 92 } 93 94 if opts.Reset { 95 return resetPreseededChroot(chrootDir) 96 } 97 98 if err := checkChroot(chrootDir); err != nil { 99 return err 100 } 101 102 targetSnapd, cleanup, err := prepareChroot(chrootDir) 103 if err != nil { 104 return err 105 } 106 107 // executing inside the chroot 108 err = runPreseedMode(chrootDir, targetSnapd) 109 cleanup() 110 return err 111 }