github.com/chipaca/snappy@v0.0.0-20210104084008-1f06296fe8ad/daemon/api_aliases_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2014-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 daemon_test
    21  
    22  import (
    23  	"bytes"
    24  	"context"
    25  	"encoding/json"
    26  	"net/http"
    27  	"net/http/httptest"
    28  	"os"
    29  	"path/filepath"
    30  
    31  	"gopkg.in/check.v1"
    32  
    33  	"github.com/snapcore/snapd/daemon"
    34  	"github.com/snapcore/snapd/dirs"
    35  	"github.com/snapcore/snapd/osutil"
    36  	"github.com/snapcore/snapd/overlord/snapstate"
    37  	"github.com/snapcore/snapd/overlord/state"
    38  	"github.com/snapcore/snapd/snap"
    39  )
    40  
    41  var _ = check.Suite(&aliasesSuite{})
    42  
    43  type aliasesSuite struct {
    44  	apiBaseSuite
    45  }
    46  
    47  const aliasYaml = `
    48  name: alias-snap
    49  version: 1
    50  apps:
    51   app:
    52   app2:
    53  `
    54  
    55  func (s *aliasesSuite) TestAliasSuccess(c *check.C) {
    56  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
    57  	c.Assert(err, check.IsNil)
    58  	d := s.daemon(c)
    59  
    60  	s.mockSnap(c, aliasYaml)
    61  
    62  	oldAutoAliases := snapstate.AutoAliases
    63  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
    64  		return nil, nil
    65  	}
    66  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
    67  
    68  	d.Overlord().Loop()
    69  	defer d.Overlord().Stop()
    70  
    71  	action := &daemon.AliasAction{
    72  		Action: "alias",
    73  		Snap:   "alias-snap",
    74  		App:    "app",
    75  		Alias:  "alias1",
    76  	}
    77  	text, err := json.Marshal(action)
    78  	c.Assert(err, check.IsNil)
    79  	buf := bytes.NewBuffer(text)
    80  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
    81  	c.Assert(err, check.IsNil)
    82  	rec := httptest.NewRecorder()
    83  	s.req(c, req, nil).ServeHTTP(rec, req)
    84  	c.Assert(rec.Code, check.Equals, 202)
    85  	var body map[string]interface{}
    86  	err = json.Unmarshal(rec.Body.Bytes(), &body)
    87  	c.Check(err, check.IsNil)
    88  	id := body["change"].(string)
    89  
    90  	st := d.Overlord().State()
    91  	st.Lock()
    92  	chg := st.Change(id)
    93  	st.Unlock()
    94  	c.Assert(chg, check.NotNil)
    95  
    96  	<-chg.Ready()
    97  
    98  	st.Lock()
    99  	err = chg.Err()
   100  	st.Unlock()
   101  	c.Assert(err, check.IsNil)
   102  
   103  	// sanity check
   104  	c.Check(osutil.IsSymlink(filepath.Join(dirs.SnapBinariesDir, "alias1")), check.Equals, true)
   105  }
   106  
   107  func (s *aliasesSuite) TestAliasChangeConflict(c *check.C) {
   108  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
   109  	c.Assert(err, check.IsNil)
   110  	s.daemon(c)
   111  
   112  	s.mockSnap(c, aliasYaml)
   113  
   114  	s.simulateConflict("alias-snap")
   115  
   116  	oldAutoAliases := snapstate.AutoAliases
   117  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
   118  		return nil, nil
   119  	}
   120  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
   121  
   122  	action := &daemon.AliasAction{
   123  		Action: "alias",
   124  		Snap:   "alias-snap",
   125  		App:    "app",
   126  		Alias:  "alias1",
   127  	}
   128  	text, err := json.Marshal(action)
   129  	c.Assert(err, check.IsNil)
   130  	buf := bytes.NewBuffer(text)
   131  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
   132  	c.Assert(err, check.IsNil)
   133  	rec := httptest.NewRecorder()
   134  	s.req(c, req, nil).ServeHTTP(rec, req)
   135  	c.Check(rec.Code, check.Equals, 409)
   136  
   137  	var body map[string]interface{}
   138  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   139  	c.Check(err, check.IsNil)
   140  	c.Check(body, check.DeepEquals, map[string]interface{}{
   141  		"status-code": 409.,
   142  		"status":      "Conflict",
   143  		"result": map[string]interface{}{
   144  			"message": `snap "alias-snap" has "manip" change in progress`,
   145  			"kind":    "snap-change-conflict",
   146  			"value": map[string]interface{}{
   147  				"change-kind": "manip",
   148  				"snap-name":   "alias-snap",
   149  			},
   150  		},
   151  		"type": "error"})
   152  }
   153  
   154  func (s *aliasesSuite) TestAliasErrors(c *check.C) {
   155  	s.daemon(c)
   156  
   157  	errScenarios := []struct {
   158  		mangle func(*daemon.AliasAction)
   159  		err    string
   160  	}{
   161  		{func(a *daemon.AliasAction) { a.Action = "" }, `unsupported alias action: ""`},
   162  		{func(a *daemon.AliasAction) { a.Action = "what" }, `unsupported alias action: "what"`},
   163  		{func(a *daemon.AliasAction) { a.Snap = "lalala" }, `snap "lalala" is not installed`},
   164  		{func(a *daemon.AliasAction) { a.Alias = ".foo" }, `invalid alias name: ".foo"`},
   165  		{func(a *daemon.AliasAction) { a.Aliases = []string{"baz"} }, `cannot interpret request, snaps can no longer be expected to declare their aliases`},
   166  	}
   167  
   168  	for _, scen := range errScenarios {
   169  		action := &daemon.AliasAction{
   170  			Action: "alias",
   171  			Snap:   "alias-snap",
   172  			App:    "app",
   173  			Alias:  "alias1",
   174  		}
   175  		scen.mangle(action)
   176  
   177  		text, err := json.Marshal(action)
   178  		c.Assert(err, check.IsNil)
   179  		buf := bytes.NewBuffer(text)
   180  		req, err := http.NewRequest("POST", "/v2/aliases", buf)
   181  		c.Assert(err, check.IsNil)
   182  
   183  		rsp := s.req(c, req, nil).(*daemon.Resp)
   184  		c.Check(rsp.Type, check.Equals, daemon.ResponseTypeError)
   185  		c.Check(rsp.Status, check.Equals, 400)
   186  		c.Check(rsp.Result.(*daemon.ErrorResult).Message, check.Matches, scen.err)
   187  	}
   188  }
   189  
   190  func (s *aliasesSuite) TestUnaliasSnapSuccess(c *check.C) {
   191  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
   192  	c.Assert(err, check.IsNil)
   193  	d := s.daemon(c)
   194  
   195  	s.mockSnap(c, aliasYaml)
   196  
   197  	oldAutoAliases := snapstate.AutoAliases
   198  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
   199  		return nil, nil
   200  	}
   201  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
   202  
   203  	d.Overlord().Loop()
   204  	defer d.Overlord().Stop()
   205  
   206  	action := &daemon.AliasAction{
   207  		Action: "unalias",
   208  		Snap:   "alias-snap",
   209  	}
   210  	text, err := json.Marshal(action)
   211  	c.Assert(err, check.IsNil)
   212  	buf := bytes.NewBuffer(text)
   213  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
   214  	c.Assert(err, check.IsNil)
   215  	rec := httptest.NewRecorder()
   216  	s.req(c, req, nil).ServeHTTP(rec, req)
   217  	c.Assert(rec.Code, check.Equals, 202)
   218  	var body map[string]interface{}
   219  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   220  	c.Check(err, check.IsNil)
   221  	id := body["change"].(string)
   222  
   223  	st := d.Overlord().State()
   224  	st.Lock()
   225  	chg := st.Change(id)
   226  	c.Check(chg.Summary(), check.Equals, `Disable all aliases for snap "alias-snap"`)
   227  	st.Unlock()
   228  	c.Assert(chg, check.NotNil)
   229  
   230  	<-chg.Ready()
   231  
   232  	st.Lock()
   233  	defer st.Unlock()
   234  	err = chg.Err()
   235  	c.Assert(err, check.IsNil)
   236  
   237  	// sanity check
   238  	var snapst snapstate.SnapState
   239  	err = snapstate.Get(st, "alias-snap", &snapst)
   240  	c.Assert(err, check.IsNil)
   241  	c.Check(snapst.AutoAliasesDisabled, check.Equals, true)
   242  }
   243  
   244  func (s *aliasesSuite) TestUnaliasDWIMSnapSuccess(c *check.C) {
   245  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
   246  	c.Assert(err, check.IsNil)
   247  	d := s.daemon(c)
   248  
   249  	s.mockSnap(c, aliasYaml)
   250  
   251  	oldAutoAliases := snapstate.AutoAliases
   252  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
   253  		return nil, nil
   254  	}
   255  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
   256  
   257  	d.Overlord().Loop()
   258  	defer d.Overlord().Stop()
   259  
   260  	action := &daemon.AliasAction{
   261  		Action: "unalias",
   262  		Snap:   "alias-snap",
   263  		Alias:  "alias-snap",
   264  	}
   265  	text, err := json.Marshal(action)
   266  	c.Assert(err, check.IsNil)
   267  	buf := bytes.NewBuffer(text)
   268  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
   269  	c.Assert(err, check.IsNil)
   270  	rec := httptest.NewRecorder()
   271  	s.req(c, req, nil).ServeHTTP(rec, req)
   272  	c.Assert(rec.Code, check.Equals, 202)
   273  	var body map[string]interface{}
   274  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   275  	c.Check(err, check.IsNil)
   276  	id := body["change"].(string)
   277  
   278  	st := d.Overlord().State()
   279  	st.Lock()
   280  	chg := st.Change(id)
   281  	c.Check(chg.Summary(), check.Equals, `Disable all aliases for snap "alias-snap"`)
   282  	st.Unlock()
   283  	c.Assert(chg, check.NotNil)
   284  
   285  	<-chg.Ready()
   286  
   287  	st.Lock()
   288  	defer st.Unlock()
   289  	err = chg.Err()
   290  	c.Assert(err, check.IsNil)
   291  
   292  	// sanity check
   293  	var snapst snapstate.SnapState
   294  	err = snapstate.Get(st, "alias-snap", &snapst)
   295  	c.Assert(err, check.IsNil)
   296  	c.Check(snapst.AutoAliasesDisabled, check.Equals, true)
   297  }
   298  
   299  func (s *aliasesSuite) TestUnaliasAliasSuccess(c *check.C) {
   300  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
   301  	c.Assert(err, check.IsNil)
   302  	d := s.daemon(c)
   303  
   304  	s.mockSnap(c, aliasYaml)
   305  
   306  	oldAutoAliases := snapstate.AutoAliases
   307  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
   308  		return nil, nil
   309  	}
   310  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
   311  
   312  	d.Overlord().Loop()
   313  	defer d.Overlord().Stop()
   314  
   315  	action := &daemon.AliasAction{
   316  		Action: "alias",
   317  		Snap:   "alias-snap",
   318  		App:    "app",
   319  		Alias:  "alias1",
   320  	}
   321  	text, err := json.Marshal(action)
   322  	c.Assert(err, check.IsNil)
   323  	buf := bytes.NewBuffer(text)
   324  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
   325  	c.Assert(err, check.IsNil)
   326  	rec := httptest.NewRecorder()
   327  	s.req(c, req, nil).ServeHTTP(rec, req)
   328  	c.Assert(rec.Code, check.Equals, 202)
   329  	var body map[string]interface{}
   330  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   331  	c.Check(err, check.IsNil)
   332  	id := body["change"].(string)
   333  
   334  	st := d.Overlord().State()
   335  	st.Lock()
   336  	chg := st.Change(id)
   337  	st.Unlock()
   338  	c.Assert(chg, check.NotNil)
   339  
   340  	<-chg.Ready()
   341  
   342  	st.Lock()
   343  	err = chg.Err()
   344  	st.Unlock()
   345  	c.Assert(err, check.IsNil)
   346  
   347  	// unalias
   348  	action = &daemon.AliasAction{
   349  		Action: "unalias",
   350  		Alias:  "alias1",
   351  	}
   352  	text, err = json.Marshal(action)
   353  	c.Assert(err, check.IsNil)
   354  	buf = bytes.NewBuffer(text)
   355  	req, err = http.NewRequest("POST", "/v2/aliases", buf)
   356  	c.Assert(err, check.IsNil)
   357  	rec = httptest.NewRecorder()
   358  	s.req(c, req, nil).ServeHTTP(rec, req)
   359  	c.Assert(rec.Code, check.Equals, 202)
   360  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   361  	c.Check(err, check.IsNil)
   362  	id = body["change"].(string)
   363  
   364  	st.Lock()
   365  	chg = st.Change(id)
   366  	c.Check(chg.Summary(), check.Equals, `Remove manual alias "alias1" for snap "alias-snap"`)
   367  	st.Unlock()
   368  	c.Assert(chg, check.NotNil)
   369  
   370  	<-chg.Ready()
   371  
   372  	st.Lock()
   373  	defer st.Unlock()
   374  	err = chg.Err()
   375  	c.Assert(err, check.IsNil)
   376  
   377  	// sanity check
   378  	c.Check(osutil.FileExists(filepath.Join(dirs.SnapBinariesDir, "alias1")), check.Equals, false)
   379  }
   380  
   381  func (s *aliasesSuite) TestUnaliasDWIMAliasSuccess(c *check.C) {
   382  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
   383  	c.Assert(err, check.IsNil)
   384  	d := s.daemon(c)
   385  
   386  	s.mockSnap(c, aliasYaml)
   387  
   388  	oldAutoAliases := snapstate.AutoAliases
   389  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
   390  		return nil, nil
   391  	}
   392  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
   393  
   394  	d.Overlord().Loop()
   395  	defer d.Overlord().Stop()
   396  
   397  	action := &daemon.AliasAction{
   398  		Action: "alias",
   399  		Snap:   "alias-snap",
   400  		App:    "app",
   401  		Alias:  "alias1",
   402  	}
   403  	text, err := json.Marshal(action)
   404  	c.Assert(err, check.IsNil)
   405  	buf := bytes.NewBuffer(text)
   406  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
   407  	c.Assert(err, check.IsNil)
   408  	rec := httptest.NewRecorder()
   409  	s.req(c, req, nil).ServeHTTP(rec, req)
   410  	c.Assert(rec.Code, check.Equals, 202)
   411  	var body map[string]interface{}
   412  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   413  	c.Check(err, check.IsNil)
   414  	id := body["change"].(string)
   415  
   416  	st := d.Overlord().State()
   417  	st.Lock()
   418  	chg := st.Change(id)
   419  	st.Unlock()
   420  	c.Assert(chg, check.NotNil)
   421  
   422  	<-chg.Ready()
   423  
   424  	st.Lock()
   425  	err = chg.Err()
   426  	st.Unlock()
   427  	c.Assert(err, check.IsNil)
   428  
   429  	// DWIM unalias an alias
   430  	action = &daemon.AliasAction{
   431  		Action: "unalias",
   432  		Snap:   "alias1",
   433  		Alias:  "alias1",
   434  	}
   435  	text, err = json.Marshal(action)
   436  	c.Assert(err, check.IsNil)
   437  	buf = bytes.NewBuffer(text)
   438  	req, err = http.NewRequest("POST", "/v2/aliases", buf)
   439  	c.Assert(err, check.IsNil)
   440  	rec = httptest.NewRecorder()
   441  	s.req(c, req, nil).ServeHTTP(rec, req)
   442  	c.Assert(rec.Code, check.Equals, 202)
   443  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   444  	c.Check(err, check.IsNil)
   445  	id = body["change"].(string)
   446  
   447  	st.Lock()
   448  	chg = st.Change(id)
   449  	c.Check(chg.Summary(), check.Equals, `Remove manual alias "alias1" for snap "alias-snap"`)
   450  	st.Unlock()
   451  	c.Assert(chg, check.NotNil)
   452  
   453  	<-chg.Ready()
   454  
   455  	st.Lock()
   456  	defer st.Unlock()
   457  	err = chg.Err()
   458  	c.Assert(err, check.IsNil)
   459  
   460  	// sanity check
   461  	c.Check(osutil.FileExists(filepath.Join(dirs.SnapBinariesDir, "alias1")), check.Equals, false)
   462  }
   463  
   464  func (s *aliasesSuite) TestPreferSuccess(c *check.C) {
   465  	err := os.MkdirAll(dirs.SnapBinariesDir, 0755)
   466  	c.Assert(err, check.IsNil)
   467  	d := s.daemon(c)
   468  
   469  	s.mockSnap(c, aliasYaml)
   470  
   471  	oldAutoAliases := snapstate.AutoAliases
   472  	snapstate.AutoAliases = func(*state.State, *snap.Info) (map[string]string, error) {
   473  		return nil, nil
   474  	}
   475  	defer func() { snapstate.AutoAliases = oldAutoAliases }()
   476  
   477  	d.Overlord().Loop()
   478  	defer d.Overlord().Stop()
   479  
   480  	action := &daemon.AliasAction{
   481  		Action: "prefer",
   482  		Snap:   "alias-snap",
   483  	}
   484  	text, err := json.Marshal(action)
   485  	c.Assert(err, check.IsNil)
   486  	buf := bytes.NewBuffer(text)
   487  	req, err := http.NewRequest("POST", "/v2/aliases", buf)
   488  	c.Assert(err, check.IsNil)
   489  	rec := httptest.NewRecorder()
   490  	s.req(c, req, nil).ServeHTTP(rec, req)
   491  	c.Assert(rec.Code, check.Equals, 202)
   492  	var body map[string]interface{}
   493  	err = json.Unmarshal(rec.Body.Bytes(), &body)
   494  	c.Check(err, check.IsNil)
   495  	id := body["change"].(string)
   496  
   497  	st := d.Overlord().State()
   498  	st.Lock()
   499  	chg := st.Change(id)
   500  	c.Check(chg.Summary(), check.Equals, `Prefer aliases of snap "alias-snap"`)
   501  	st.Unlock()
   502  	c.Assert(chg, check.NotNil)
   503  
   504  	<-chg.Ready()
   505  
   506  	st.Lock()
   507  	defer st.Unlock()
   508  	err = chg.Err()
   509  	c.Assert(err, check.IsNil)
   510  
   511  	// sanity check
   512  	var snapst snapstate.SnapState
   513  	err = snapstate.Get(st, "alias-snap", &snapst)
   514  	c.Assert(err, check.IsNil)
   515  	c.Check(snapst.AutoAliasesDisabled, check.Equals, false)
   516  }
   517  
   518  func (s *aliasesSuite) TestAliases(c *check.C) {
   519  	d := s.daemon(c)
   520  
   521  	st := d.Overlord().State()
   522  	st.Lock()
   523  	snapstate.Set(st, "alias-snap1", &snapstate.SnapState{
   524  		Sequence: []*snap.SideInfo{
   525  			{RealName: "alias-snap1", Revision: snap.R(11)},
   526  		},
   527  		Current: snap.R(11),
   528  		Active:  true,
   529  		Aliases: map[string]*snapstate.AliasTarget{
   530  			"alias1": {Manual: "cmd1x", Auto: "cmd1"},
   531  			"alias2": {Auto: "cmd2"},
   532  		},
   533  	})
   534  	snapstate.Set(st, "alias-snap2", &snapstate.SnapState{
   535  		Sequence: []*snap.SideInfo{
   536  			{RealName: "alias-snap2", Revision: snap.R(12)},
   537  		},
   538  		Current:             snap.R(12),
   539  		Active:              true,
   540  		AutoAliasesDisabled: true,
   541  		Aliases: map[string]*snapstate.AliasTarget{
   542  			"alias2": {Auto: "cmd2"},
   543  			"alias3": {Manual: "cmd3"},
   544  			"alias4": {Manual: "cmd4x", Auto: "cmd4"},
   545  		},
   546  	})
   547  	st.Unlock()
   548  
   549  	req, err := http.NewRequest("GET", "/v2/aliases", nil)
   550  	c.Assert(err, check.IsNil)
   551  
   552  	rsp := s.req(c, req, nil).(*daemon.Resp)
   553  	c.Check(rsp.Type, check.Equals, daemon.ResponseTypeSync)
   554  	c.Check(rsp.Status, check.Equals, 200)
   555  	c.Check(rsp.Result, check.DeepEquals, map[string]map[string]daemon.AliasStatus{
   556  		"alias-snap1": {
   557  			"alias1": {
   558  				Command: "alias-snap1.cmd1x",
   559  				Status:  "manual",
   560  				Manual:  "cmd1x",
   561  				Auto:    "cmd1",
   562  			},
   563  			"alias2": {
   564  				Command: "alias-snap1.cmd2",
   565  				Status:  "auto",
   566  				Auto:    "cmd2",
   567  			},
   568  		},
   569  		"alias-snap2": {
   570  			"alias2": {
   571  				Command: "alias-snap2.cmd2",
   572  				Status:  "disabled",
   573  				Auto:    "cmd2",
   574  			},
   575  			"alias3": {
   576  				Command: "alias-snap2.cmd3",
   577  				Status:  "manual",
   578  				Manual:  "cmd3",
   579  			},
   580  			"alias4": {
   581  				Command: "alias-snap2.cmd4x",
   582  				Status:  "manual",
   583  				Manual:  "cmd4x",
   584  				Auto:    "cmd4",
   585  			},
   586  		},
   587  	})
   588  
   589  }
   590  
   591  func (s *aliasesSuite) TestInstallUnaliased(c *check.C) {
   592  	var calledFlags snapstate.Flags
   593  
   594  	defer daemon.MockSnapstateInstall(func(ctx context.Context, s *state.State, name string, opts *snapstate.RevisionOptions, userID int, flags snapstate.Flags) (*state.TaskSet, error) {
   595  		calledFlags = flags
   596  
   597  		t := s.NewTask("fake-install-snap", "Doing a fake install")
   598  		return state.NewTaskSet(t), nil
   599  	})()
   600  
   601  	d := s.daemon(c)
   602  	inst := &daemon.SnapInstruction{
   603  		Action: "install",
   604  		// Install the snap without enabled automatic aliases
   605  		Unaliased: true,
   606  		Snaps:     []string{"fake"},
   607  	}
   608  
   609  	st := d.Overlord().State()
   610  	st.Lock()
   611  	defer st.Unlock()
   612  	_, _, err := inst.Dispatch()(inst, st)
   613  	c.Check(err, check.IsNil)
   614  
   615  	c.Check(calledFlags.Unaliased, check.Equals, true)
   616  }
   617  
   618  func (s *aliasesSuite) TestInstallIgnoreRunning(c *check.C) {
   619  	var calledFlags snapstate.Flags
   620  
   621  	defer daemon.MockSnapstateInstall(func(ctx context.Context, s *state.State, name string, opts *snapstate.RevisionOptions, userID int, flags snapstate.Flags) (*state.TaskSet, error) {
   622  		calledFlags = flags
   623  
   624  		t := s.NewTask("fake-install-snap", "Doing a fake install")
   625  		return state.NewTaskSet(t), nil
   626  	})()
   627  
   628  	d := s.daemon(c)
   629  	inst := &daemon.SnapInstruction{
   630  		Action: "install",
   631  		// Install the snap without enabled automatic aliases
   632  		IgnoreRunning: true,
   633  		Snaps:         []string{"fake"},
   634  	}
   635  
   636  	st := d.Overlord().State()
   637  	st.Lock()
   638  	defer st.Unlock()
   639  	_, _, err := inst.Dispatch()(inst, st)
   640  	c.Check(err, check.IsNil)
   641  
   642  	c.Check(calledFlags.IgnoreRunning, check.Equals, true)
   643  }