Skip to content

Commit

Permalink
a/snapasserts: report missing components when snaps are required
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewphelpsj committed Sep 20, 2024
1 parent 95d03f6 commit 5982ca6
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
15 changes: 11 additions & 4 deletions asserts/snapasserts/validation_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,12 @@ func (v *ValidationSets) CheckInstalledSnaps(snaps []*InstalledSnap, ignoreValid
return err
}

vcerrs, err := v.checkInstalledComponents(installed, ignoreValidation)
missingSnapNames := make(map[string]bool, len(missing))
for name := range missing {
missingSnapNames[name] = true
}

vcerrs, err := v.checkInstalledComponents(installed, ignoreValidation, missingSnapNames)
if err != nil {
return err
}
Expand All @@ -768,7 +773,7 @@ func (v *ValidationSets) CheckInstalledSnaps(snaps []*InstalledSnap, ignoreValid
return nil
}

func (v *ValidationSets) checkInstalledComponents(installedSnaps installedSnapSet, ignore map[string]bool) (map[string]*ValidationSetsComponentValidationError, error) {
func (v *ValidationSets) checkInstalledComponents(installedSnaps installedSnapSet, ignore map[string]bool, missingSnaps map[string]bool) (map[string]*ValidationSetsComponentValidationError, error) {
componentInstalled := func(cstrs constraints) (snap.Revision, error) {
if cstrs.compRef == nil || cstrs.snapRef == nil {
return snap.Revision{}, errors.New("internal error: component constraint should have component and snap refs")
Expand All @@ -787,11 +792,13 @@ func (v *ValidationSets) checkInstalledComponents(installedSnaps installedSnapSe
// if we're ignoring the snap, then we don't consider its components
//
// if the snap is not installed, then nothing can be wrong with the
// components, since none will be installed.
// components, since none will be installed. however, for error
// reporting reasons, we consider components for snaps that are required
// by the validation sets.
//
// note that we consider "required" components to only be required if
// the snap itself is installed.
if ignore[sc.name] || !installedSnaps.Contains(sc.snapRef) {
if ignore[sc.name] || (!installedSnaps.Contains(sc.snapRef) && !missingSnaps[sc.name]) {
continue
}

Expand Down
47 changes: 46 additions & 1 deletion asserts/snapasserts/validation_sets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,25 @@ func (s *validationSetsSuite) TestCheckInstalledSnapsWithComponents(c *C) {
},
},
},
"four": {
map[string]interface{}{
"name": "snap-a",
"id": snaptest.AssertedSnapID("snap-a"),
"presence": "required",
"components": map[string]interface{}{
"comp-3": map[string]interface{}{
"presence": "required",
},
"comp-4": map[string]interface{}{
"presence": "required",
"revision": "2",
},
"comp-5": map[string]interface{}{
"presence": "optional",
},
},
},
},
}

assertions := make(map[string]*asserts.ValidationSet)
Expand Down Expand Up @@ -862,14 +881,40 @@ func (s *validationSetsSuite) TestCheckInstalledSnapsWithComponents(c *C) {
"snap-a": {
MissingComponents: map[string]map[snap.Revision][]string{
"comp-2": {
{}: {"acme/three"},
snap.R(0): {"acme/three"},
snap.R(3): {"acme/one"},
},
},
},
},
},
},
{
summary: "missing required snap and required component",
assertions: []string{"four"},
verr: &snapasserts.ValidationSetsValidationError{
Sets: map[string]*asserts.ValidationSet{
"acme/four": assertions["four"],
},
ComponentErrors: map[string]*snapasserts.ValidationSetsComponentValidationError{
"snap-a": {
MissingComponents: map[string]map[snap.Revision][]string{
"comp-3": {
snap.R(0): {"acme/four"},
},
"comp-4": {
snap.R(2): {"acme/four"},
},
},
},
},
MissingSnaps: map[string]map[snap.Revision][]string{
"snap-a": {
snap.R(0): {"acme/four"},
},
},
},
},
}

for i, tc := range cases {
Expand Down

0 comments on commit 5982ca6

Please sign in to comment.