github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/sysconfig/gadget_defaults_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2020 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 sysconfig_test
    21  
    22  import (
    23  	"path/filepath"
    24  
    25  	. "gopkg.in/check.v1"
    26  
    27  	"github.com/snapcore/snapd/asserts"
    28  	"github.com/snapcore/snapd/asserts/assertstest"
    29  	"github.com/snapcore/snapd/boot"
    30  	"github.com/snapcore/snapd/osutil"
    31  
    32  	// to set ApplyFilesystemOnlyDefaults hook
    33  	_ "github.com/snapcore/snapd/overlord/configstate/configcore"
    34  	"github.com/snapcore/snapd/snap"
    35  	"github.com/snapcore/snapd/snap/snaptest"
    36  	"github.com/snapcore/snapd/snap/squashfs"
    37  	"github.com/snapcore/snapd/sysconfig"
    38  	"github.com/snapcore/snapd/systemd"
    39  )
    40  
    41  var gadgetYaml = `
    42  volumes:
    43    pc:
    44      bootloader: grub
    45  `
    46  
    47  var fakeModel = assertstest.FakeAssertion(map[string]interface{}{
    48  	"type":         "model",
    49  	"authority-id": "my-brand",
    50  	"series":       "16",
    51  	"brand-id":     "my-brand",
    52  	"model":        "my-model",
    53  	"architecture": "amd64",
    54  	"base":         "core18",
    55  	"gadget":       "pc",
    56  	"kernel":       "pc-kernel",
    57  }).(*asserts.Model)
    58  
    59  func fake20Model(grade string) *asserts.Model {
    60  	return assertstest.FakeAssertion(map[string]interface{}{
    61  		"type":         "model",
    62  		"authority-id": "my-brand",
    63  		"series":       "16",
    64  		"brand-id":     "my-brand",
    65  		"model":        "my-model",
    66  		"architecture": "amd64",
    67  		"base":         "core20",
    68  		"grade":        grade,
    69  		"snaps": []interface{}{
    70  			map[string]interface{}{
    71  				"name":            "kernel",
    72  				"id":              "kerneldididididididididididididi",
    73  				"type":            "kernel",
    74  				"default-channel": "20",
    75  			},
    76  			map[string]interface{}{
    77  				"name":            "pc",
    78  				"id":              "gadgetididididididididididididid",
    79  				"type":            "gadget",
    80  				"default-channel": "20",
    81  			},
    82  		},
    83  	}).(*asserts.Model)
    84  }
    85  
    86  func (s *sysconfigSuite) TestConfigureTargetSystemNonUC20(c *C) {
    87  	err := sysconfig.ConfigureTargetSystem(fakeModel, nil)
    88  	c.Assert(err, ErrorMatches, "internal error: ConfigureTargetSystem can only be used with a model with a grade")
    89  }
    90  
    91  func (s *sysconfigSuite) TestGadgetDefaults(c *C) {
    92  	const gadgetDefaultsYaml = `
    93  defaults:
    94    system:
    95      service:
    96        rsyslog.disable: true
    97        ssh.disable: true
    98      journal.persistent: true
    99  `
   100  	si := &snap.SideInfo{
   101  		RealName: "pc",
   102  		Revision: snap.R(1),
   103  		SnapID:   "idid",
   104  	}
   105  	snapInfo := snaptest.MockSnapWithFiles(c, "name: pc\ntype: gadget", si, [][]string{
   106  		{"meta/gadget.yaml", gadgetYaml + gadgetDefaultsYaml},
   107  	})
   108  
   109  	var sysctlArgs [][]string
   110  	systemctlRestorer := systemd.MockSystemctl(func(args ...string) (buf []byte, err error) {
   111  		sysctlArgs = append(sysctlArgs, args)
   112  		return nil, nil
   113  	})
   114  	defer systemctlRestorer()
   115  
   116  	journalPath := filepath.Join(boot.InstallHostWritableDir, "_writable_defaults/var/log/journal")
   117  	sshDontRunFile := filepath.Join(boot.InstallHostWritableDir, "_writable_defaults/etc/ssh/sshd_not_to_be_run")
   118  
   119  	// sanity
   120  	c.Check(osutil.FileExists(sshDontRunFile), Equals, false)
   121  	exists, _, _ := osutil.DirExists(journalPath)
   122  	c.Check(exists, Equals, false)
   123  
   124  	err := sysconfig.ConfigureTargetSystem(fake20Model("signed"), &sysconfig.Options{
   125  		TargetRootDir: boot.InstallHostWritableDir,
   126  		GadgetDir:     snapInfo.MountDir(),
   127  	})
   128  	c.Assert(err, IsNil)
   129  
   130  	c.Check(osutil.FileExists(sshDontRunFile), Equals, true)
   131  	exists, _, _ = osutil.DirExists(journalPath)
   132  	c.Check(exists, Equals, true)
   133  
   134  	c.Check(sysctlArgs, DeepEquals, [][]string{{"--root", filepath.Join(boot.InstallHostWritableDir, "_writable_defaults"), "mask", "rsyslog.service"}})
   135  }
   136  
   137  func (s *sysconfigSuite) TestInstallModeEarlyDefaultsFromGadgetInvalid(c *C) {
   138  	const gadgetDefaultsYaml = `
   139  defaults:
   140    system:
   141      service:
   142        rsyslog:
   143          disable: foo
   144  `
   145  	si := &snap.SideInfo{
   146  		RealName: "pc",
   147  		Revision: snap.R(1),
   148  		SnapID:   "idid",
   149  	}
   150  	snapInfo := snaptest.MockSnapWithFiles(c, "name: pc\ntype: gadget", si, [][]string{
   151  		{"meta/gadget.yaml", gadgetYaml + gadgetDefaultsYaml},
   152  	})
   153  
   154  	err := sysconfig.ConfigureTargetSystem(fake20Model("signed"), &sysconfig.Options{
   155  		TargetRootDir: boot.InstallHostWritableDir,
   156  		GadgetDir:     snapInfo.MountDir(),
   157  	})
   158  	c.Check(err, ErrorMatches, `option "service.rsyslog.disable" has invalid value "foo"`)
   159  }
   160  
   161  func (s *sysconfigSuite) TestInstallModeEarlyDefaultsFromGadgetSeedSnap(c *C) {
   162  	const gadgetDefaultsYaml = `
   163  defaults:
   164    system:
   165      service:
   166        rsyslog.disable: true
   167        ssh.disable: true
   168      journal.persistent: true
   169  `
   170  	snapFile := snaptest.MakeTestSnapWithFiles(c, "name: pc\ntype: gadget\nversion: 1", [][]string{
   171  		{"meta/gadget.yaml", gadgetYaml + gadgetDefaultsYaml},
   172  	})
   173  
   174  	snapContainer := squashfs.New(snapFile)
   175  
   176  	var sysctlArgs [][]string
   177  	systemctlRestorer := systemd.MockSystemctl(func(args ...string) (buf []byte, err error) {
   178  		sysctlArgs = append(sysctlArgs, args)
   179  		return nil, nil
   180  	})
   181  	defer systemctlRestorer()
   182  
   183  	journalPath := filepath.Join(boot.InstallHostWritableDir, "_writable_defaults/var/log/journal")
   184  	sshDontRunFile := filepath.Join(boot.InstallHostWritableDir, "_writable_defaults/etc/ssh/sshd_not_to_be_run")
   185  
   186  	// sanity
   187  	c.Check(osutil.FileExists(sshDontRunFile), Equals, false)
   188  	exists, _, _ := osutil.DirExists(journalPath)
   189  	c.Check(exists, Equals, false)
   190  
   191  	err := sysconfig.ConfigureTargetSystem(fake20Model("signed"), &sysconfig.Options{
   192  		TargetRootDir: boot.InstallHostWritableDir,
   193  		GadgetSnap:    snapContainer,
   194  	})
   195  	c.Assert(err, IsNil)
   196  
   197  	c.Check(osutil.FileExists(sshDontRunFile), Equals, true)
   198  	exists, _, _ = osutil.DirExists(journalPath)
   199  	c.Check(exists, Equals, true)
   200  
   201  	c.Check(sysctlArgs, DeepEquals, [][]string{{"--root", filepath.Join(boot.InstallHostWritableDir, "_writable_defaults"), "mask", "rsyslog.service"}})
   202  }