func setSnapConf(c *Command, r *http.Request, user *auth.UserState) Response { vars := muxVars(r) snapName := vars["name"] var patchValues map[string]interface{} decoder := json.NewDecoder(r.Body) if err := decoder.Decode(&patchValues); err != nil { return BadRequest("cannot decode request body into patch values: %v", err) } // TODO: Add patch values to configmanager s := c.d.overlord.State() s.Lock() defer s.Unlock() hookTaskSummary := fmt.Sprintf(i18n.G("Run apply-config hook for %s"), snapName) task := hookstate.HookTask(s, hookTaskSummary, snapName, snap.Revision{}, "apply-config") taskset := state.NewTaskSet(task) change := s.NewChange("configure-snap", fmt.Sprintf("Setting config for %s", snapName)) change.AddAll(taskset) s.EnsureBefore(0) return AsyncResponse(nil, &Meta{Change: change.ID()}) }
func (s *hookManagerSuite) SetUpTest(c *C) { dirs.SetRootDir(c.MkDir()) s.state = state.New(nil) manager, err := hookstate.Manager(s.state) c.Assert(err, IsNil) s.manager = manager s.state.Lock() s.task = hookstate.HookTask(s.state, "test summary", "test-snap", snap.R(1), "test-hook") c.Assert(s.task, NotNil, Commentf("Expected HookTask to return a task")) s.change = s.state.NewChange("kind", "summary") s.change.AddTask(s.task) s.state.Unlock() s.command = testutil.MockCommand(c, "snap", "") }
// Configure returns a taskset to apply the given configuration patch. func Configure(s *state.State, snapName string, patch map[string]interface{}) *state.TaskSet { hooksup := &hookstate.HookSetup{ Snap: snapName, Hook: "configure", Optional: len(patch) == 0, } var contextData map[string]interface{} if len(patch) > 0 { contextData = map[string]interface{}{"patch": patch} } var summary string if hooksup.Optional { summary = fmt.Sprintf(i18n.G("Run configure hook of %q snap if present"), snapName) } else { summary = fmt.Sprintf(i18n.G("Run configure hook of %q snap"), snapName) } task := hookstate.HookTask(s, summary, hooksup, contextData) return state.NewTaskSet(task) }
func (s *hookManagerSuite) SetUpTest(c *C) { dirs.SetRootDir(c.MkDir()) s.state = state.New(nil) manager, err := hookstate.Manager(s.state) c.Assert(err, IsNil) s.manager = manager hooksup := &hookstate.HookSetup{ Snap: "test-snap", Hook: "configure", Revision: snap.R(1), } initialContext := map[string]interface{}{ "test-key": "test-value", } s.state.Lock() s.task = hookstate.HookTask(s.state, "test summary", hooksup, initialContext) c.Assert(s.task, NotNil, Commentf("Expected HookTask to return a task")) s.change = s.state.NewChange("kind", "summary") s.change.AddTask(s.task) sideInfo := &snap.SideInfo{RealName: "test-snap", SnapID: "some-snap-id", Revision: snap.R(1)} snaptest.MockSnap(c, snapYaml, snapContents, sideInfo) snapstate.Set(s.state, "test-snap", &snapstate.SnapState{ Active: true, Sequence: []*snap.SideInfo{sideInfo}, Current: snap.R(1), }) s.state.Unlock() s.command = testutil.MockCommand(c, "snap", "") s.context = nil s.mockHandler = hooktest.NewMockHandler() s.manager.Register(regexp.MustCompile("configure"), func(context *hookstate.Context) hookstate.Handler { s.context = context return s.mockHandler }) }
func (s *hookManagerSuite) TestHookTask(c *C) { s.state.Lock() defer s.state.Unlock() hooksup := &hookstate.HookSetup{ Snap: "test-snap", Hook: "configure", Revision: snap.R(1), } task := hookstate.HookTask(s.state, "test summary", hooksup, nil) c.Check(task.Kind(), Equals, "run-hook") var setup hookstate.HookSetup err := task.Get("hook-setup", &setup) c.Check(err, IsNil) c.Check(setup.Snap, Equals, "test-snap") c.Check(setup.Revision, Equals, snap.R(1)) c.Check(setup.Hook, Equals, "configure") }
func (m *DeviceManager) ensureOperational() error { m.state.Lock() defer m.state.Unlock() device, err := auth.Device(m.state) if err != nil { return err } if device.Serial != "" { // serial is set, we are all set return nil } if device.Brand == "" || device.Model == "" { // need first-boot, loading of model assertion info if release.OnClassic { // TODO: are we going to have model assertions on classic or need will need to cheat here? return nil } // cannot proceed yet, once first boot is done these will be set // and we can pick up from there return nil } if m.changeInFlight("become-operational") { return nil } if serialRequestURL == "" { // cannot do anything actually return nil } gadgetInfo, err := snapstate.GadgetInfo(m.state) if err == state.ErrNoState { // no gadget installed yet, cannot proceed return nil } if err != nil { return err } // XXX: some of these will need to be split and use hooks // retries might need to embrace more than one "task" then, // need to be careful tasks := []*state.Task{} var prepareDevice *state.Task if gadgetInfo.Hooks["prepare-device"] != nil { summary := i18n.G("Run prepare-device hook") hooksup := &hookstate.HookSetup{ Snap: gadgetInfo.Name(), Hook: "prepare-device", } prepareDevice = hookstate.HookTask(m.state, summary, hooksup, nil) tasks = append(tasks, prepareDevice) } genKey := m.state.NewTask("generate-device-key", i18n.G("Generate device key")) if prepareDevice != nil { genKey.WaitFor(prepareDevice) } tasks = append(tasks, genKey) requestSerial := m.state.NewTask("request-serial", i18n.G("Request device serial")) requestSerial.WaitFor(genKey) tasks = append(tasks, requestSerial) chg := m.state.NewChange("become-operational", i18n.G("Initialize device")) chg.AddAll(state.NewTaskSet(tasks...)) return nil }