Snap Config overrider

This commit is contained in:
David Imola 2022-05-25 16:49:21 -06:00
parent 8160993b1d
commit 25be0637b3

View file

@ -0,0 +1,82 @@
package snapconfig
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/snapcore/snapd/client"
"github.com/snapcore/snapd/dirs"
)
var (
ErrSnapctl = errors.New("snapctl system call failed")
ErrJSONUnmarshal = errors.New("couldn't unmarhsal json")
)
// This variable copied from
// Vogt, Michael, et al. “Snapd.” Github.com, 2.54.4, Snapcore, 25 Nov. 2020,
// https://github.com/snapcore/snapd/blob/67901c9dd5c22f4ece95b53f43fb0acc73e81a23/cmd/snapctl/main.go.
// Accessed 8 Mar. 2022
var clientConfig = client.Config{
// snapctl should not try to read $HOME/.snap/auth.json, this will
// result in apparmor denials and configure task failures
// (LP: #1660941)
DisableAuth: true,
// we need the less privileged snap socket in snapctl
Socket: dirs.SnapSocket,
}
// This function modified from
// Vogt, Michael, et al. “Snapd.” Github.com, 2.54.4, Snapcore, 25 Nov. 2020,
// https://github.com/snapcore/snapd/blob/67901c9dd5c22f4ece95b53f43fb0acc73e81a23/cmd/snapctl/main.go.
// Accessed 8 Mar. 2022.
func runSnapCtl(args []string) (stdout []byte, stderr []byte, err error) {
cli := client.New(&clientConfig)
cookie := os.Getenv("SNAP_COOKIE")
// for compatibility, if re-exec is not enabled and facing older snapd.
if cookie == "" {
cookie = os.Getenv("SNAP_CONTEXT")
}
return cli.RunSnapctl(&client.SnapCtlOptions{
ContextID: cookie,
Args: args,
}, nil)
}
func get(key string) (string, error) {
stdout, _, err := runSnapCtl([]string{"get", "-d", key})
if err != nil {
return "", fmt.Errorf("%w for %s: %v", ErrSnapctl, key, err)
}
var result map[string]string
if err = json.Unmarshal(stdout, &result); err != nil {
return "", fmt.Errorf("%w for %s: %v", ErrJSONUnmarshal, key, err)
}
if len(result) == 0 {
return "", nil
}
return result[key], nil
}
type snapConfigOverrider struct {
ErrHandler func(error)
}
func (o *snapConfigOverrider) Get(lowerCaseKey string) (string, bool) {
result, err := get(lowerCaseKey)
if err != nil {
o.ErrHandler(err)
}
return result, err == nil && len(result) > 0
}
//nolint:revive // we dont want to give access to snapConfigOverrider type without constructor
func Overrider(errHandler func(error)) *snapConfigOverrider {
return &snapConfigOverrider{
ErrHandler: errHandler,
}
}