gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/overlord/patch/patch6_1.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2018 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 patch
    21  
    22  import (
    23  	"github.com/snapcore/snapd/interfaces"
    24  	"github.com/snapcore/snapd/overlord/state"
    25  	"github.com/snapcore/snapd/snap"
    26  )
    27  
    28  type connStatePatch6_1 struct {
    29  	Auto             bool                   `json:"auto,omitempty"`
    30  	ByGadget         bool                   `json:"by-gadget,omitempty"`
    31  	Interface        string                 `json:"interface,omitempty"`
    32  	Undesired        bool                   `json:"undesired,omitempty"`
    33  	StaticPlugAttrs  map[string]interface{} `json:"plug-static,omitempty"`
    34  	DynamicPlugAttrs map[string]interface{} `json:"plug-dynamic,omitempty"`
    35  	StaticSlotAttrs  map[string]interface{} `json:"slot-static,omitempty"`
    36  	DynamicSlotAttrs map[string]interface{} `json:"slot-dynamic,omitempty"`
    37  }
    38  
    39  // processConns updates conns map and augments it with plug-static and slot-static attributes from current snap info.
    40  // NOTE: missing snap or missing plugs/slots are ignored and not reported as errors as we might have stale connections
    41  // and ifacemgr deals with them (i.e. discards) on startup; we want to process all good slots and plugs here.
    42  func processConns(conns map[string]connStatePatch6_1, infos map[string]*snap.Info) (bool, error) {
    43  	var updated bool
    44  	for id, conn := range conns {
    45  		// static attributes already present
    46  		if len(conn.StaticPlugAttrs) > 0 || len(conn.StaticSlotAttrs) > 0 {
    47  			continue
    48  		}
    49  
    50  		// undesired connections have all their attributes dropped, so don't set them
    51  		if conn.Undesired {
    52  			continue
    53  		}
    54  
    55  		connRef, err := interfaces.ParseConnRef(id)
    56  		if err != nil {
    57  			return false, err
    58  		}
    59  
    60  		var ok bool
    61  		var plugSnapInfo, slotSnapInfo *snap.Info
    62  
    63  		// read current snap info from disk and keep it around in infos map
    64  		if plugSnapInfo, ok = infos[connRef.PlugRef.Snap]; !ok {
    65  			plugSnapInfo, err = snap.ReadCurrentInfo(connRef.PlugRef.Snap)
    66  			if err == nil {
    67  				infos[connRef.PlugRef.Snap] = plugSnapInfo
    68  			}
    69  		}
    70  		if slotSnapInfo, ok = infos[connRef.SlotRef.Snap]; !ok {
    71  			slotSnapInfo, err = snap.ReadCurrentInfo(connRef.SlotRef.Snap)
    72  			if err == nil {
    73  				infos[connRef.SlotRef.Snap] = slotSnapInfo
    74  			}
    75  		}
    76  
    77  		if slotSnapInfo != nil {
    78  			if slot, ok := slotSnapInfo.Slots[connRef.SlotRef.Name]; ok && slot.Attrs != nil {
    79  				conn.StaticSlotAttrs = slot.Attrs
    80  				updated = true
    81  			}
    82  		}
    83  
    84  		if plugSnapInfo != nil {
    85  			if plug, ok := plugSnapInfo.Plugs[connRef.PlugRef.Name]; ok && plug.Attrs != nil {
    86  				conn.StaticPlugAttrs = plug.Attrs
    87  				updated = true
    88  			}
    89  		}
    90  
    91  		conns[id] = conn
    92  	}
    93  
    94  	return updated, nil
    95  }
    96  
    97  // patch6_1:
    98  //  - add static plug and slot attributes to connections that miss them. Attributes are read from current snap info.
    99  func patch6_1(st *state.State) error {
   100  	infos := make(map[string]*snap.Info)
   101  
   102  	// update all pending "discard-conns" tasks as they may keep connection data in "removed".
   103  	for _, task := range st.Tasks() {
   104  		if task.Change().Status().Ready() {
   105  			continue
   106  		}
   107  
   108  		var removed map[string]connStatePatch6_1
   109  		if task.Kind() == "discard-conns" {
   110  			err := task.Get("removed", &removed)
   111  			if err == state.ErrNoState {
   112  				continue
   113  			}
   114  			if err != nil {
   115  				return err
   116  			}
   117  		}
   118  
   119  		updated, err := processConns(removed, infos)
   120  		if err != nil {
   121  			return err
   122  		}
   123  
   124  		if updated {
   125  			task.Set("removed", removed)
   126  		}
   127  	}
   128  
   129  	// update conns
   130  	var conns map[string]connStatePatch6_1
   131  	err := st.Get("conns", &conns)
   132  	if err == state.ErrNoState {
   133  		// no connections to process
   134  		return nil
   135  	}
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	updated, err := processConns(conns, infos)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	if updated {
   145  		st.Set("conns", conns)
   146  	}
   147  
   148  	return nil
   149  }