github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/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 // for SanitizePlugsSlots 31 "github.com/snapcore/snapd/interfaces/builtin" 32 "github.com/snapcore/snapd/snap" 33 ) 34 35 const ( 36 shortHelp = "Prerun the first boot seeding of snaps in an image filesystem chroot with a snapd seed." 37 longHelp = ` 38 The snap-preseed command takes a directory containing an image, including seed 39 snaps (at /var/lib/snapd/seed), and runs through the snapd first-boot process 40 up to hook execution. No boot actions unrelated to snapd are performed. 41 It creates systemd units for seeded snaps, makes any connections, and generates 42 security profiles. The image is updated and consequently optimised to reduce 43 first-boot startup time` 44 ) 45 46 type options struct { 47 Reset bool `long:"reset"` 48 } 49 50 var ( 51 osGetuid = os.Getuid 52 Stdout io.Writer = os.Stdout 53 Stderr io.Writer = os.Stderr 54 55 opts options 56 ) 57 58 func Parser() *flags.Parser { 59 opts = options{} 60 parser := flags.NewParser(&opts, flags.HelpFlag|flags.PassDoubleDash|flags.PassAfterNonOption) 61 parser.ShortDescription = shortHelp 62 parser.LongDescription = longHelp 63 return parser 64 } 65 66 func main() { 67 parser := Parser() 68 if err := run(parser, os.Args[1:]); err != nil { 69 fmt.Fprintf(Stderr, "error: %v\n", err) 70 os.Exit(1) 71 } 72 } 73 74 func run(parser *flags.Parser, args []string) error { 75 // real validation of plugs and slots; needs to be set 76 // for processing of seeds with gadget because of readInfo(). 77 snap.SanitizePlugsSlots = builtin.SanitizePlugsSlots 78 79 if osGetuid() != 0 { 80 return fmt.Errorf("must be run as root") 81 } 82 83 rest, err := parser.ParseArgs(args) 84 if err != nil { 85 return err 86 } 87 88 if len(rest) == 0 { 89 return fmt.Errorf("need chroot path as argument") 90 } 91 92 chrootDir, err := filepath.Abs(rest[0]) 93 if err != nil { 94 return err 95 } 96 97 // safety check 98 if chrootDir == "/" { 99 return fmt.Errorf("cannot run snap-preseed against /") 100 } 101 102 if opts.Reset { 103 return resetPreseededChroot(chrootDir) 104 } 105 106 if err := checkChroot(chrootDir); err != nil { 107 return err 108 } 109 110 targetSnapd, cleanup, err := prepareChroot(chrootDir) 111 if err != nil { 112 return err 113 } 114 115 // executing inside the chroot 116 err = runPreseedMode(chrootDir, targetSnapd) 117 cleanup() 118 return err 119 }