Пример #1
0
// patch1 adds the snap type and the current revision to the snap state.
func patch1(s *state.State) error {
	var stateMap map[string]*snapstate.SnapState

	err := s.Get("snaps", &stateMap)
	if err == state.ErrNoState {
		return nil
	}
	if err != nil {
		return err
	}

	for snapName, snapState := range stateMap {
		seq := snapState.Sequence
		if len(seq) == 0 {
			continue
		}
		typ := snap.TypeApp
		snapInfo, err := readInfo(snapName, seq[len(seq)-1])
		if err != nil {
			logger.Noticef("Recording type for snap %q: cannot retrieve info, assuming it's a app: %v", snapName, err)
		} else {
			logger.Noticef("Recording type for snap %q: setting to %q", snapName, snapInfo.Type)
			typ = snapInfo.Type
		}
		snapState.SetType(typ)
		snapState.Current = seq[len(seq)-1].Revision
	}

	s.Set("snaps", stateMap)
	return nil
}
Пример #2
0
// NewUser tracks a new authenticated user and saves its details in the state
func NewUser(st *state.State, username, macaroon string, discharges []string) (*UserState, error) {
	var authStateData AuthState

	err := st.Get("auth", &authStateData)
	if err == state.ErrNoState {
		authStateData = AuthState{}
	} else if err != nil {
		return nil, err
	}

	sort.Strings(discharges)
	authStateData.LastID++
	authenticatedUser := UserState{
		ID:              authStateData.LastID,
		Username:        username,
		Macaroon:        macaroon,
		Discharges:      discharges,
		StoreMacaroon:   macaroon,
		StoreDischarges: discharges,
	}
	authStateData.Users = append(authStateData.Users, authenticatedUser)

	st.Set("auth", authStateData)

	return &authenticatedUser, nil
}
Пример #3
0
func newRunnerManager(s *state.State) *runnerManager {
	rm := &runnerManager{
		runner: state.NewTaskRunner(s),
	}

	rm.runner.AddHandler("runMgr1", func(t *state.Task, _ *tomb.Tomb) error {
		s := t.State()
		s.Lock()
		defer s.Unlock()
		s.Set("runMgr1Mark", 1)
		return nil
	}, nil)
	rm.runner.AddHandler("runMgr2", func(t *state.Task, _ *tomb.Tomb) error {
		s := t.State()
		s.Lock()
		defer s.Unlock()
		s.Set("runMgr2Mark", 1)
		return nil
	}, nil)
	rm.runner.AddHandler("runMgrEnsureBefore", func(t *state.Task, _ *tomb.Tomb) error {
		s := t.State()
		s.Lock()
		defer s.Unlock()
		s.EnsureBefore(20 * time.Millisecond)
		return nil
	}, nil)

	return rm
}
Пример #4
0
// Init initializes an empty state to the current implemented patch level.
func Init(s *state.State) {
	s.Lock()
	defer s.Unlock()
	if s.Get("patch-level", new(int)) != state.ErrNoState {
		panic("internal error: expected empty state, attempting to override patch-level without actual patching")
	}
	s.Set("patch-level", Level)
}
Пример #5
0
// patch2:
// - migrates SnapSetup.Name to SnapSetup.SideInfo.RealName
// - backfills SnapState.{Sequence,Candidate}.RealName if its missing
func patch2(s *state.State) error {

	var stateMap map[string]*OldSnapState
	err := s.Get("snaps", &stateMap)
	if err == state.ErrNoState {
		return nil
	}
	if err != nil {
		return err
	}

	// migrate SnapSetup in all tasks:
	//  - the new SnapSetup uses SideInfo, backfil from Candidate
	//  - also move SnapSetup.{Name,Revision} into SnapSetup.SideInfo.{RealName,Revision}
	var oldSS OldSnapSetup
	var newSS snapstate.SnapSetup
	for _, t := range s.Tasks() {
		err := t.Get("snap-setup", &oldSS)
		if err == state.ErrNoState {
			continue
		}
		if err != nil && err != state.ErrNoState {
			return err
		}
		// some things stay the same
		newSS.Channel = oldSS.Channel
		newSS.Flags = oldSS.Flags
		newSS.SnapPath = oldSS.SnapPath
		newSS.DownloadInfo = oldSS.DownloadInfo
		newSS.SideInfo = oldSS.SideInfo
		// ... and some change
		if newSS.SideInfo == nil {
			newSS.SideInfo = &snap.SideInfo{}
			if snapst, ok := stateMap[oldSS.Name]; ok && snapst.Candidate != nil {
				newSS.SideInfo = snapst.Candidate
			}
		}
		if newSS.SideInfo.RealName == "" {
			newSS.SideInfo.RealName = oldSS.Name
		}
		if newSS.SideInfo.Revision.Unset() {
			newSS.SideInfo.Revision = oldSS.Revision
		}
		t.Set("snap-setup", &newSS)
	}

	// backfill snapstate.SnapState.{Sequence,Candidate} with RealName
	// (if that is missing, was missing for e.g. sideloaded snaps)
	for snapName, snapState := range stateMap {
		for _, si := range snapState.Sequence {
			setRealName(si, snapName)
		}
	}
	s.Set("snaps", stateMap)

	return nil
}
Пример #6
0
func applyOne(patch func(s *state.State) error, s *state.State, level int) error {
	s.Lock()
	defer s.Unlock()

	err := patch(s)
	if err != nil {
		return err
	}

	s.Set("patch-level", level+1)
	return nil
}
Пример #7
0
// patch2:
// - migrates SnapSetup.Name to SnapSetup.SideInfo.RealName
// - backfills SnapState.{Sequence,Candidate}.RealName if its missing
func patch2(s *state.State) error {

	var oldStateMap map[string]*patch1SnapState
	err := s.Get("snaps", &oldStateMap)
	if err == state.ErrNoState {
		return nil
	}
	if err != nil {
		return err
	}
	newStateMap := make(map[string]*patch2SnapState, len(oldStateMap))

	for key, oldSnapState := range oldStateMap {
		newStateMap[key] = patch2SnapStateFromPatch1(oldSnapState, key)
	}

	// migrate SnapSetup in all tasks:
	//  - the new SnapSetup uses SideInfo, backfil from Candidate
	//  - also move SnapSetup.{Name,Revision} into SnapSetup.SideInfo.{RealName,Revision}
	var oldSS patch1SnapSetup
	for _, t := range s.Tasks() {
		var newSS patch2SnapSetup
		err := t.Get("snap-setup", &oldSS)
		if err == state.ErrNoState {
			continue
		}
		if err != nil && err != state.ErrNoState {
			return err
		}
		// some things stay the same
		newSS.Channel = oldSS.Channel
		newSS.Flags = patch2Flags(oldSS.Flags)
		newSS.SnapPath = oldSS.SnapPath
		// ... and some change
		newSS.SideInfo = &patch2SideInfo{}
		if snapst, ok := oldStateMap[oldSS.Name]; ok && snapst.Candidate != nil {
			newSS.SideInfo = patch2SideInfoFromPatch1(snapst.Candidate, oldSS.Name)
		}
		if newSS.SideInfo.RealName == "" {
			newSS.SideInfo.RealName = oldSS.Name
		}
		if newSS.SideInfo.Revision.Unset() {
			newSS.SideInfo.Revision = oldSS.Revision
		}
		t.Set("snap-setup", &newSS)
	}

	s.Set("snaps", newStateMap)

	return nil
}
Пример #8
0
// SetDevice updates the device details in the state.
func SetDevice(st *state.State, device *DeviceState) error {
	var authStateData AuthState

	err := st.Get("auth", &authStateData)
	if err == state.ErrNoState {
		authStateData = AuthState{}
	} else if err != nil {
		return err
	}

	authStateData.Device = device
	st.Set("auth", authStateData)

	return nil
}
Пример #9
0
// patch6:
//  - move from a flags-are-ints world to a flags-are-struct-of-bools world
func patch6(st *state.State) error {
	var oldStateMap map[string]*patch4SnapState
	err := st.Get("snaps", &oldStateMap)
	if err == state.ErrNoState {
		return nil
	}
	if err != nil {
		return err
	}
	newStateMap := make(map[string]*patch6SnapState, len(oldStateMap))

	for key, old := range oldStateMap {
		newStateMap[key] = &patch6SnapState{
			SnapType:    old.SnapType,
			Sequence:    old.Sequence,
			Active:      old.Active,
			Current:     old.Current,
			Channel:     old.Channel,
			patch6Flags: patch6FlagsFromPatch4(old.Flags),
		}
	}

	for _, task := range st.Tasks() {
		var old patch4SnapSetup
		err := task.Get("snap-setup", &old)
		if err == state.ErrNoState {
			continue
		}
		if err != nil && err != state.ErrNoState {
			return err
		}

		task.Set("snap-setup", &patch6SnapSetup{
			Channel:      old.Channel,
			UserID:       old.UserID,
			SnapPath:     old.SnapPath,
			DownloadInfo: old.DownloadInfo,
			SideInfo:     old.SideInfo,
			patch6Flags:  patch6FlagsFromPatch4(old.Flags),
		})
	}

	st.Set("snaps", newStateMap)

	return nil
}
Пример #10
0
// UpdateUser updates user in state
func UpdateUser(st *state.State, user *UserState) error {
	var authStateData AuthState

	err := st.Get("auth", &authStateData)
	if err != nil {
		return err
	}

	for i := range authStateData.Users {
		if authStateData.Users[i].ID == user.ID {
			authStateData.Users[i] = *user
			st.Set("auth", authStateData)
			return nil
		}
	}

	return fmt.Errorf("invalid user")
}
Пример #11
0
// Set sets the SnapState of the given snap, overwriting any earlier state.
func Set(s *state.State, name string, snapst *SnapState) {
	var snaps map[string]*json.RawMessage
	err := s.Get("snaps", &snaps)
	if err != nil && err != state.ErrNoState {
		panic("internal error: cannot unmarshal snaps state: " + err.Error())
	}
	if snaps == nil {
		snaps = make(map[string]*json.RawMessage)
	}
	if snapst == nil || (len(snapst.Sequence) == 0) {
		delete(snaps, name)
	} else {
		data, err := json.Marshal(snapst)
		if err != nil {
			panic("internal error: cannot marshal snap state: " + err.Error())
		}
		raw := json.RawMessage(data)
		snaps[name] = &raw
	}
	s.Set("snaps", snaps)
}
Пример #12
0
func setAliases(st *state.State, snapName string, aliases map[string]string) {
	var allAliases map[string]*json.RawMessage
	err := st.Get("aliases", &allAliases)
	if err != nil && err != state.ErrNoState {
		panic("internal error: cannot unmarshal snap aliases state: " + err.Error())
	}
	if allAliases == nil {
		allAliases = make(map[string]*json.RawMessage)
	}
	if len(aliases) == 0 {
		delete(allAliases, snapName)
	} else {
		data, err := json.Marshal(aliases)
		if err != nil {
			panic("internal error: cannot marshal snap aliases state: " + err.Error())
		}
		raw := json.RawMessage(data)
		allAliases[snapName] = &raw
	}
	st.Set("aliases", allAliases)
}
Пример #13
0
// NewUser tracks a new authenticated user and saves its details in the state
func NewUser(st *state.State, username, email, macaroon string, discharges []string) (*UserState, error) {
	var authStateData AuthState

	err := st.Get("auth", &authStateData)
	if err == state.ErrNoState {
		authStateData = AuthState{}
	} else if err != nil {
		return nil, err
	}

	if authStateData.MacaroonKey == nil {
		authStateData.MacaroonKey, err = generateMacaroonKey()
		if err != nil {
			return nil, err
		}
	}

	authStateData.LastID++

	localMacaroon, err := newUserMacaroon(authStateData.MacaroonKey, authStateData.LastID)
	if err != nil {
		return nil, err
	}

	sort.Strings(discharges)
	authenticatedUser := UserState{
		ID:              authStateData.LastID,
		Username:        username,
		Email:           email,
		Macaroon:        localMacaroon,
		Discharges:      nil,
		StoreMacaroon:   macaroon,
		StoreDischarges: discharges,
	}
	authStateData.Users = append(authStateData.Users, authenticatedUser)

	st.Set("auth", authStateData)

	return &authenticatedUser, nil
}
Пример #14
0
// RemoveUser removes a user from the state given its ID
func RemoveUser(st *state.State, userID int) error {
	var authStateData AuthState

	err := st.Get("auth", &authStateData)
	if err != nil {
		return err
	}

	for i := range authStateData.Users {
		if authStateData.Users[i].ID == userID {
			// delete without preserving order
			n := len(authStateData.Users) - 1
			authStateData.Users[i] = authStateData.Users[n]
			authStateData.Users[n] = UserState{}
			authStateData.Users = authStateData.Users[:n]
			st.Set("auth", authStateData)
			return nil
		}
	}

	return fmt.Errorf("invalid user")
}
Пример #15
0
func setConns(st *state.State, conns map[string]connState) {
	st.Set("conns", conns)
}