Frameworks

Definition

Frameworks are a direct extension of the Ubuntu Core. As such frameworks have the following attributes:

Importantly, frameworks are not generally:

Note: snappy frameworks are somewhat different from the Ubuntu for Phones click frameworks and are more flexible. Most importantly, click frameworks for Ubuntu for Phones map to a particular release and are contracts between the platform (OS) and apps. Snappy splits out the platform (OS) and the framework such that the contract is split between the framework and the platform release (OS) (the release and installed frameworks can be seen via snappy info). As such, apps will specify the release they target (implementation covered elsewhere) and any frameworks they require.

Store process

Initially, frameworks and framework policy will be shipped in the same snap which will ensure that framework policy is always in sync with the framework for which it applies. To support this:

For the official Ubuntu Store, we may eventually allow separate ownership of frameworks from framework policies.

Usage

framework yaml

For frameworks, meta/package.yaml should contain something like:

name: foo
version: 1.1.234
type: framework
services:
  - name: bar
    description: "desc for bar service"
    start: bin/bar
binaries:
  - name: bin/baz
    description: "desc for baz binary"

Required fields for framework snaps:

Frameworks will typically need specialized security policy. See security.md for details.

In addition to the above yaml fields, the security policy used by apps is shipped in the meta/framework-policy directory according to the following hierarchy:

Because frameworks must be coinstallable, all shipped policy files will be prepended with the framework name followed by an underscore. Apps must reference the policy using the full name. For example, if the foo framework ships meta/framework-policy/apparmor/policygroups/bar-client, then apps must reference this as foo_bar-client.

While the above provides a lot of flexibility, it is important to remember a framework snap need only provide what apps will use. For example, if the foo framework is designed to have clients connect to the bar service over DBus, then the framework snap might provide meta/framework-policy/apparmor/policygroups/foo_bar-client and nothing else.

The contents of files in the apparmor directory use apparmor syntax as described in apparmor.d(5). When specifying DBus rules, set the peer label to refer to the AppArmor label (APP_ID) of the service to be accessed. Also, to ensure frameworks are coinstallable, the service should be implemented so its DBus path uses the format /pkgname/service.

For example, using the above example where the foo framework ships a bar DBus system service, a bin/exe utility, some data files and also a runtime state file, then meta/framework-policy/apparmor/policygroups/bar-client might contain something like:

/apps/foo/*/bin/exe  ixr,
/apps/foo/*/data/** r,
/var/lib/apps/foo/*/run/state r,
dbus (receive, send)
     bus=system
     peer=(label=foo_bar_*),

App yaml

For apps wanting to use a particular framework, meta/package.yaml simply references the security policy provided by the framework. Eg, if a service in the norf app wants to access the bar service provided by the foo framework in the above framework yaml example, it might use:

name: norf
version: 2.3
frameworks:
  - foo
services:
  - name: qux
    description: "desc for qux service"
    start: bin/qux
    caps:
      - networking
      - foo_bar-client

See security.md for more information on specifying caps and a security-template as provided by the framework snap.

User experience

The command line experience is:

$ snappy search foo
Name      Version      Description
foo       1.1.234      The foo framework

$ snappy install foo
Installing foo
Starting download of foo
4.03 MB / 4.03 MB [==============================] 100.00 % 124.66 KB/s
Done
Name                 Date       Version   Summary
foo                  2015-03-16 1.1.234   The foo framework

$ snappy list
Name                 Date       Version   Summary
ubuntu-core          2015-03-16 333       ubuntu-core description
foo                  2015-03-16 1.1.234   The foo framework
hello-world          2015-02-23 1.0.5

$ snappy list --updates
Name                  Date      Version
ubuntu-core          2015-03-16 333      ubuntu-core description
foo*                 2015-03-16 1.1.234  The foo framework
hello-world          2015-02-23 1.0.5

$ sudo snappy update
Installing foo (1.1.235)
4.03 MB / 4.03 MB [==============================] 100.00 % 124.66 KB/s
Done
Name                 Date       Version   Summary
foo                  2015-03-17 1.1.235   The foo framework

$ snappy list --updates
Name                  Date      Version
ubuntu-core          2015-03-16 333      ubuntu-core description
foo                  2015-03-17 1.1.235  The foo framework
hello-world          2015-02-23 1.0.5

$ snappy remove foo
Removing foo

$ snappy info
release: ubuntu-core/devel-proposed
architecture: amd64
frameworks: foo
apps: hello-world

A convenience afforded to frameworks is that commands don't require that the package name be appended. Eg, using the above package.yaml, use:

$ baz --version
1.1.235

Open questions

The following are considerations that may affect the above for when we build on this work: