Skip to content

Commit

Permalink
tests: add new store-state make-component-installable command
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewphelpsj committed Dec 18, 2024
1 parent c877aad commit b58b2ec
Show file tree
Hide file tree
Showing 4 changed files with 280 additions and 0 deletions.
51 changes: 51 additions & 0 deletions tests/lib/fakestore/cmd/fakestore/cmd_new_snap_resource_pair.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

import (
"encoding/json"
"fmt"
"os"

"github.com/snapcore/snapd/tests/lib/fakestore/refresh"
)

type cmdNewSnapResourcePair struct {
Positional struct {
Component string `description:"Component blob file"`
SnapResourcePairJSONPath string `description:"Path to a json encoded snap resource pair revision subset"`
} `positional-args:"yes" required:"yes"`

TopDir string `long:"dir" description:"Directory to be used by the store to keep and serve snaps, <dir>/asserts is used for assertions"`
}

func (x *cmdNewSnapResourcePair) Execute(args []string) error {
content, err := os.ReadFile(x.Positional.SnapResourcePairJSONPath)
if err != nil {
return err
}

headers := make(map[string]interface{})
if err := json.Unmarshal(content, &headers); err != nil {
return err
}

p, err := refresh.NewSnapResourcePair(x.TopDir, x.Positional.Component, headers)
if err != nil {
return err
}
fmt.Println(p)
return nil
}

var shortNewSnapResourcePairHelp = "Make a new snap resource pair"

var longNewSnapResourcePairHelp = `
Generate a new snap resource pair signed with test keys. Snap ID, snap revision,
and component revision must be provided in the given JSON file. All other
headers are either derived from the component file or optional, but can be
overridden via the given JSON file.
`

func init() {
parser.AddCommand("new-snap-resource-pair", shortNewSnapResourcePairHelp, longNewSnapResourcePairHelp,
&cmdNewSnapResourcePair{})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

import (
"encoding/json"
"fmt"
"os"

"github.com/snapcore/snapd/tests/lib/fakestore/refresh"
)

type cmdNewSnapResourceRevision struct {
Positional struct {
Component string `description:"Component blob file"`
SnapResourceRevJsonPath string `description:"Path to a json encoded snap resource revision subset"`
} `positional-args:"yes" required:"yes"`

TopDir string `long:"dir" description:"Directory to be used by the store to keep and serve snaps, <dir>/asserts is used for assertions"`
}

func (x *cmdNewSnapResourceRevision) Execute(args []string) error {
content, err := os.ReadFile(x.Positional.SnapResourceRevJsonPath)
if err != nil {
return err
}

headers := make(map[string]interface{})
if err := json.Unmarshal(content, &headers); err != nil {
return err
}

p, err := refresh.NewSnapResourceRevision(x.TopDir, x.Positional.Component, headers)
if err != nil {
return err
}
fmt.Println(p)
return nil
}

var shortNewSnapResourceRevisionHelp = "Make a new snap resource revision"

var longNewSnapResourceRevisionHelp = `
Generate a new snap resource revision signed with test keys. Snap ID and
revision must be provided in the given JSON file. All other headers are either
derived from the component file or optional, but can be overridden via the given
JSON file.
`

func init() {
parser.AddCommand("new-snap-resource-revision", shortNewSnapResourceRevisionHelp, longNewSnapResourceRevisionHelp,
&cmdNewSnapResourceRevision{})
}
98 changes: 98 additions & 0 deletions tests/lib/fakestore/refresh/snap_asserts.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (

"github.com/snapcore/snapd/asserts"
"github.com/snapcore/snapd/asserts/systestkeys"
"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/snap/snapfile"
)

func snapNameFromPath(snapPath string) string {
Expand Down Expand Up @@ -68,6 +70,102 @@ func NewSnapRevision(targetDir string, snap string, headers map[string]interface
return writeAssert(a, targetDir)
}

func NewSnapResourceRevision(targetDir string, compPath string, headers map[string]interface{}) (string, error) {
db, err := newAssertsDB(systestkeys.TestStorePrivKey)
if err != nil {
return "", err
}
digest, size, err := asserts.SnapFileSHA3_384(compPath)
if err != nil {
return "", err
}

container, err := snapfile.Open(compPath)
if err != nil {
return "", err
}

ci, err := snap.ReadComponentInfoFromContainer(container, nil, nil)
if err != nil {
return "", err
}

required := []string{"snap-id", "resource-revision"}
for _, r := range required {
if _, ok := headers[r]; !ok {
return "", fmt.Errorf("missing required header %q", r)
}
}

defaults := map[string]interface{}{
"type": "snap-resource-revision",
"authority-id": "testrootorg",
"developer-id": "testrootorg",
"resource-name": ci.Component.ComponentName,
"timestamp": time.Now().Format(time.RFC3339),
"resource-size": fmt.Sprintf("%d", size),
"resource-sha3-384": digest,
}
for k, v := range defaults {
if _, ok := headers[k]; !ok {
headers[k] = v
}
}
headers["authority-id"] = "testrootorg"
headers["snap-sha3-384"] = digest
headers["snap-size"] = fmt.Sprintf("%d", size)
headers["timestamp"] = time.Now().Format(time.RFC3339)

a, err := db.Sign(asserts.SnapResourceRevisionType, headers, nil, systestkeys.TestStoreKeyID)
if err != nil {
return "", err
}
return writeAssert(a, targetDir)
}

func NewSnapResourcePair(targetDir string, compPath string, headers map[string]interface{}) (string, error) {
db, err := newAssertsDB(systestkeys.TestStorePrivKey)
if err != nil {
return "", err
}

container, err := snapfile.Open(compPath)
if err != nil {
return "", err
}

ci, err := snap.ReadComponentInfoFromContainer(container, nil, nil)
if err != nil {
return "", err
}

required := []string{"snap-id", "resource-revision", "snap-revision"}
for _, r := range required {
if _, ok := headers[r]; !ok {
return "", fmt.Errorf("missing required header %q", r)
}
}

defaults := map[string]interface{}{
"type": "snap-resource-pair",
"authority-id": "testrootorg",
"developer-id": "testrootorg",
"resource-name": ci.Component.ComponentName,
"timestamp": time.Now().Format(time.RFC3339),
}
for k, v := range defaults {
if _, ok := headers[k]; !ok {
headers[k] = v
}
}

a, err := db.Sign(asserts.SnapResourcePairType, headers, nil, systestkeys.TestStoreKeyID)
if err != nil {
return "", err
}
return writeAssert(a, targetDir)
}

func NewSnapDeclaration(targetDir string, snap string, headers map[string]interface{}) (string, error) {
db, err := newAssertsDB(systestkeys.TestStorePrivKey)
if err != nil {
Expand Down
80 changes: 80 additions & 0 deletions tests/lib/tools/store-state
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ show_help() {
echo " store-state setup-staging-store"
echo " store-state teardown-staging-store"
echo " store-state make-snap-installable [--noack ] [--extra-decl-json FILE] <DIR> <SNAP_PATH> [SNAP_ID]"
echo " store-state make-component-installable --snap-id <ID> --component-revision <REV> --snap-revision <REV> [--noack ] <DIR> <SNAP_PATH>"
echo " store-state init-fake-refreshes <DIR>"
echo " store-state add-to-channel <DIR> <FILENAME> <CHANNEL>"
}
Expand Down Expand Up @@ -124,6 +125,85 @@ EOF
rm -f /tmp/snap-decl.json /tmp/snap-rev.json
}


make_component_installable(){
local ack=true
local component_rev="";
local snap_rev="";
local snap_id="";
while [ $# -gt 0 ]; do
case "$1" in
(--component-revision)
component_rev="$2"
shift 2
;;
(--snap-id)
snap_id="$2"
shift 2
;;
(--snap-revision)
snap_rev="$2"
shift 2
;;
(--noack)
ack=false
shift
;;
(*)
break
;;
esac
done

if [ -z "${snap_id}" ]; then
echo "snap-id must be provided"
return 1
fi

if [ -z "${component_rev}" ]; then
echo "component-revision must be provided"
return 1
fi

if [ -z "${snap_rev}" ]; then
echo "snap-revision must be provided"
return 1
fi

local dir="$1"
local path="$2"

work=$(mktemp -d)

cat > "/${work}/snap-resource-revision.json" << EOF
{
"snap-id": "${snap_id}",
"publisher-id": "developer1",
"resource-revision": "${component_rev}"
}
EOF

cat > "/${work}/snap-resource-pair.json" << EOF
{
"snap-id": "${snap_id}",
"publisher-id": "developer1",
"resource-revision": "${component_rev}",
"snap-revision": "${snap_rev}"
}
EOF

resource_rev_assert=$(fakestore new-snap-resource-revision --dir "${dir}" "${path}" "/${work}/snap-resource-revision.json")
resource_pair_assert=$(fakestore new-snap-resource-pair --dir "${dir}" "${path}" "/${work}/snap-resource-pair.json")

if [ "${ack}" = "true" ]; then
snap ack "${resource_rev_assert}"
snap ack "${resource_pair_assert}"
fi

cp -av "${path}" "${dir}/"
rm -rf "${work}"
}

setup_fake_store(){
local top_dir=$1

Expand Down

0 comments on commit b58b2ec

Please sign in to comment.