Skip to content

Commit

Permalink
Mount info gatherer (#284)
Browse files Browse the repository at this point in the history
* Implement mount info gatherer

* Test the gatherer

* Add gatherer to list of standard gatherers
  • Loading branch information
arbulu89 committed Oct 30, 2023
1 parent 8a3a869 commit c4ab8e2
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
github.com/spf13/afero v1.9.5
github.com/tredoe/osutil v1.0.6
golang.org/x/mod v0.9.0
github.com/moby/sys/mountinfo v0.6.2
)

require (
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
Expand Down Expand Up @@ -414,6 +416,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
3 changes: 3 additions & 0 deletions internal/factsengine/gatherers/gatherer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func StandardGatherers() FactGatherersTree {
HostsFileGathererName: map[string]FactGatherer{
"v1": NewDefaultHostsFileGatherer(),
},
MountInfoGathererName: map[string]FactGatherer{
"v1": NewDefaultMountInfoGatherer(),
},
OSReleaseGathererName: map[string]FactGatherer{
"v1": NewDefaultOSReleaseGatherer(),
},
Expand Down
53 changes: 53 additions & 0 deletions internal/factsengine/gatherers/mocks/MountParserInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

131 changes: 131 additions & 0 deletions internal/factsengine/gatherers/mountinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package gatherers

import (
"encoding/json"
"strings"

"github.com/hashicorp/go-envparse"
"github.com/moby/sys/mountinfo"
log "github.com/sirupsen/logrus"
"github.com/trento-project/agent/pkg/factsengine/entities"
"github.com/trento-project/agent/pkg/utils"
)

const (
MountInfoGathererName = "mount_info"
)

// nolint:gochecknoglobals
var (
MountInfoParsingError = entities.FactGatheringError{
Type: "mount-info-parsing-error",
Message: "error parsing mount information",
}

MountInfoMissingArgumentError = entities.FactGatheringError{
Type: "mount-info-missing-argument",
Message: "missing required argument",
}

MountInfoDecodingError = entities.FactGatheringError{
Type: "mount-info-decoding-error",
Message: "error decoding mount information",
}
)

//go:generate mockery --name=MountParserInterface
type MountParserInterface interface {
GetMounts(f mountinfo.FilterFunc) ([]*mountinfo.Info, error)
}

type MountParser struct{}

func (x *MountParser) GetMounts(f mountinfo.FilterFunc) ([]*mountinfo.Info, error) {
return mountinfo.GetMounts(f)
}

type MountInfoGatherer struct {
mInfo MountParserInterface
executor utils.CommandExecutor
}

type MountInfoResult struct {
BlockUUID string `json:"block_uuid"`
FSType string `json:"fs_type"`
MountPoint string `json:"mount_point"`
Options string `json:"options"`
Source string `json:"source"`
}

func NewDefaultMountInfoGatherer() *MountInfoGatherer {
return NewMountInfoGatherer(&MountParser{}, utils.Executor{})
}

func NewMountInfoGatherer(mInfo MountParserInterface, executor utils.CommandExecutor) *MountInfoGatherer {
return &MountInfoGatherer{mInfo: mInfo, executor: executor}
}

func (g *MountInfoGatherer) Gather(factsRequests []entities.FactRequest) ([]entities.Fact, error) {
facts := []entities.Fact{}
log.Infof("Starting %s facts gathering process", MountInfoGathererName)
mounts, err := g.mInfo.GetMounts(nil)
if err != nil {
return nil, MountInfoParsingError.Wrap(err.Error())
}

for _, requestedFact := range factsRequests {
if requestedFact.Argument == "" {
log.Errorf("could not gather facts for %s gatherer, missing argument", MountInfoGathererName)
facts = append(facts, entities.NewFactGatheredWithError(requestedFact, &MountInfoMissingArgumentError))
continue
}

var foundMountInfoResult = MountInfoResult{}

for _, mount := range mounts {
if mount.Mountpoint == requestedFact.Argument {
foundMountInfoResult = MountInfoResult{
MountPoint: mount.Mountpoint,
Source: mount.Source,
FSType: mount.FSType,
Options: mount.Options,
}

if blkidOuptut, err := g.executor.Exec("blkid", foundMountInfoResult.Source, "-o", "export"); err != nil {
log.Warnf("blkid command failed for source %s: %s", foundMountInfoResult.Source, err)
} else if fields, err := envparse.Parse(strings.NewReader(string(blkidOuptut))); err != nil {
log.Warnf("error parsing the blkid output: %s", err)
} else {
foundMountInfoResult.BlockUUID = fields["UUID"]
}

continue
}
}

factValue, err := mountInfoResultToFactValue(foundMountInfoResult)
if err != nil {
facts = append(facts, entities.NewFactGatheredWithError(requestedFact, MountInfoDecodingError.Wrap(err.Error())))
continue
}
facts = append(facts, entities.NewFactGatheredWithRequest(requestedFact, factValue))
}

log.Infof("Requested %s facts gathered", MountInfoGathererName)
return facts, nil
}

func mountInfoResultToFactValue(result MountInfoResult) (entities.FactValue, error) {
marshalled, err := json.Marshal(&result)
if err != nil {
return nil, err
}

var unmarshalled interface{}
err = json.Unmarshal(marshalled, &unmarshalled)
if err != nil {
return nil, err
}

return entities.NewFactValue(unmarshalled)
}
Loading

0 comments on commit c4ab8e2

Please sign in to comment.