overlord/ifacestate: reload snap connections when setting up security for a given snap #950

Merged
merged 9 commits into from Apr 14, 2016
@@ -78,7 +78,7 @@ func (m *InterfaceManager) initialize(extra []interfaces.Interface) error {
if err := m.addSnaps(); err != nil {
return err
}
- if err := m.reloadConnections(); err != nil {
+ if err := m.reloadConnections(""); err != nil {
return err
}
return nil
@@ -112,7 +112,10 @@ func (m *InterfaceManager) addSnaps() error {
return nil
}
-func (m *InterfaceManager) reloadConnections() error {
+// reloadConnections reloads connections stored in the state in the repository.
+// Using non-empty snapName the operation can be scoped to connections
+// affecting a given snap.
+func (m *InterfaceManager) reloadConnections(snapName string) error {
conns, err := getConns(m.state)
if err != nil {
return err
@@ -122,6 +125,9 @@ func (m *InterfaceManager) reloadConnections() error {
if err != nil {
return err
}
+ if snapName != "" && plugRef.Snap != snapName && slotRef.Snap != snapName {
+ continue
+ }
err = m.repo.Connect(plugRef.Snap, plugRef.Name, slotRef.Snap, slotRef.Name)
if err != nil {
return err
@@ -187,20 +193,18 @@ func (m *InterfaceManager) doSetupSnapSecurity(task *state.Task, _ *tomb.Tomb) e
return err
}
}
+ if err := m.reloadConnections(snapName); err != nil {
+ return err
+ }
if err := m.autoConnect(task, snapName); err != nil {
return err
}
- // TODO: re-connect all connection affecting given snap
- // TODO: - removing failed connections from the state
if len(affectedSnaps) == 0 {
affectedSnaps = append(affectedSnaps, snapInfo)
}
for _, snapInfo := range affectedSnaps {
- for _, backend := range securityBackends {
- developerMode := false // TODO: move this to snap.Info
- if err := backend.Setup(snapInfo, developerMode, m.repo); err != nil {
- return state.Retry
- }
+ if err := setupSnapSecurity(task, snapInfo, m.repo); err != nil {
+ return state.Retry
}
}
return nil
@@ -229,7 +229,7 @@ func (s *interfaceManagerSuite) addSetupSnapSecurityChange(c *C, snapName string
defer s.state.Unlock()
task := s.state.NewTask("setup-snap-security", "")
- ss := snapstate.SnapSetup{Name: "snap"}
+ ss := snapstate.SnapSetup{Name: snapName}
task.Set("snap-setup", ss)
taskset := state.NewTaskSet(task)
change := s.state.NewChange("test", "")
@@ -336,6 +336,46 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyKeepsExistingConnectionSt
})
}
+func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOnPlugSide(c *C) {
@niemeyer

niemeyer Apr 14, 2016

Contributor

LGTM, but let's please rename these function names to be at most half that len. Let's use comments to document them instead.

+ s.testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c, "consumer")
+}
+
+func (s *interfaceManagerSuite) TestDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOnSlotSide(c *C) {
+ s.testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c, "producer")
+}
+
+func (s *interfaceManagerSuite) testDoSetupSnapSecuirtyReloadsConnectionsWhenInvokedOn(c *C, snapName string) {
+ s.mockIface(c, &interfaces.TestInterface{InterfaceName: "test"})
+ s.mockSnap(c, consumerYaml)
+ s.mockSnap(c, producerYaml)
+
+ s.state.Lock()
+ s.state.Set("conns", map[string]interface{}{
+ "consumer:plug producer:slot": map[string]interface{}{"interface": "test"},
+ })
+ s.state.Unlock()
+
+ mgr := s.manager(c)
+
+ // Run the setup-snap-security task
+ change := s.addSetupSnapSecurityChange(c, snapName)
+ mgr.Ensure()
+ mgr.Wait()
+ mgr.Stop()
+
+ s.state.Lock()
+ defer s.state.Unlock()
+ c.Check(change.Status(), Equals, state.DoneStatus)
+
+ repo := mgr.Repository()
+ plug := repo.Plug("consumer", "plug")
+ slot := repo.Slot("producer", "slot")
+ c.Assert(plug.Connections, HasLen, 1)
+ c.Assert(slot.Connections, HasLen, 1)
+ c.Check(plug.Connections[0], DeepEquals, interfaces.SlotRef{Snap: "producer", Name: "slot"})
+ c.Check(slot.Connections[0], DeepEquals, interfaces.PlugRef{Snap: "consumer", Name: "plug"})
+}
+
func (s *interfaceManagerSuite) TestConnectTracksConnectionsInState(c *C) {
s.mockIface(c, &interfaces.TestInterface{InterfaceName: "test"})
s.mockSnap(c, consumerYaml)