Skip to content

Commit

Permalink
internal/engine: handle Path asset type
Browse files Browse the repository at this point in the history
  • Loading branch information
jroimartin committed Nov 29, 2023
1 parent 7883ede commit ac11239
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 64 deletions.
11 changes: 6 additions & 5 deletions internal/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ func mkReport(rs *reportStore, srv *targetServer) (Report, error) {

tmAddrs := tm.Addrs()

slog.Info("applying target map", "check", checkID, "map", tm, "tmAddr", tmAddrs)
slog.Info("applying target map", "check", checkID, "tm", tm, "tmAddr", tmAddrs)

r.Target = tm.Old
r.Target = tm.OldIdentifier

var vulns []report.Vulnerability
for _, vuln := range r.Vulnerabilities {
vuln = vulnReplaceAll(vuln, tm.New, tm.Old)
vuln = vulnReplaceAll(vuln, tmAddrs.New, tmAddrs.Old)
vuln = vulnReplaceAll(vuln, tm.NewIdentifier, tm.OldIdentifier)
vuln = vulnReplaceAll(vuln, tmAddrs.NewIdentifier, tmAddrs.OldIdentifier)
vulns = append(vulns, vuln)
}
r.Vulnerabilities = vulns
Expand Down Expand Up @@ -323,7 +323,8 @@ func beforeRun(params backend.RunParams, rc *docker.RunConfig, srv *targetServer
}
if tm, err := srv.Handle(params.CheckID, target); err == nil {
if !tm.IsZero() {
rc.ContainerConfig.Env = setenv(rc.ContainerConfig.Env, "VULCAN_CHECK_TARGET", tm.New)
rc.ContainerConfig.Env = setenv(rc.ContainerConfig.Env, "VULCAN_CHECK_TARGET", tm.NewIdentifier)
rc.ContainerConfig.Env = setenv(rc.ContainerConfig.Env, "VULCAN_CHECK_ASSET_TYPE", string(tm.NewAssetType))
}
} else {
slog.Warn("could not handle target", "target", target, "err", err)
Expand Down
22 changes: 7 additions & 15 deletions internal/engine/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,15 @@ import (
"github.com/adevinta/vulcan-agent/queue"
"github.com/google/uuid"

"github.com/adevinta/lava/internal/assettype"
"github.com/adevinta/lava/internal/checktype"
"github.com/adevinta/lava/internal/config"
)

// generateJobs generates the jobs to be sent to the agent.
func generateJobs(checktypes checktype.Catalog, targets []config.Target) ([]jobrunner.Job, error) {
checks, err := generateChecks(checktypes, targets)
if err != nil {
return nil, fmt.Errorf("generate checks: %w", err)
}

var jobs []jobrunner.Job
for _, check := range checks {
for _, check := range generateChecks(checktypes, targets) {
// Convert the options to a marshalled json string.
jsonOpts, err := json.Marshal(check.options)
if err != nil {
Expand Down Expand Up @@ -74,17 +70,13 @@ type check struct {
}

// generateChecks generates a list of checks combining a map of
// checktypes and a list of targets. It returns an error if any of the
// targets has an empty or invalid asset type.
func generateChecks(checktypes checktype.Catalog, targets []config.Target) ([]check, error) {
// checktypes and a list of targets.
func generateChecks(checktypes checktype.Catalog, targets []config.Target) []check {
var checks []check
for _, t := range dedup(targets) {
if t.AssetType == "" || !t.AssetType.IsValid() {
return nil, fmt.Errorf("invalid target asset type: %v", t.AssetType)
}

for _, c := range checktypes {
if !c.Accepts(t.AssetType) {
at := assettype.ToVulcan(t.AssetType)
if !c.Accepts(at) {
continue
}

Expand All @@ -102,7 +94,7 @@ func generateChecks(checktypes checktype.Catalog, targets []config.Target) ([]ch
})
}
}
return checks, nil
return checks
}

// dedup returns a deduplicated slice.
Expand Down
67 changes: 44 additions & 23 deletions internal/engine/jobs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"

"github.com/adevinta/lava/internal/assettype"
"github.com/adevinta/lava/internal/checktype"
"github.com/adevinta/lava/internal/config"
)
Expand All @@ -21,7 +22,6 @@ func TestGenerateChecks(t *testing.T) {
checktypes checktype.Catalog
targets []config.Target
want []check
wantNilErr bool
}{
{
name: "one checktype and one target",
Expand Down Expand Up @@ -58,7 +58,6 @@ func TestGenerateChecks(t *testing.T) {
options: map[string]any{},
},
},
wantNilErr: true,
},
{
name: "target overrides checktype options",
Expand Down Expand Up @@ -115,7 +114,6 @@ func TestGenerateChecks(t *testing.T) {
},
},
},
wantNilErr: true,
},
{
name: "two checktypes and one target",
Expand Down Expand Up @@ -175,7 +173,6 @@ func TestGenerateChecks(t *testing.T) {
options: map[string]any{},
},
},
wantNilErr: true,
},
{
name: "incompatible target",
Expand All @@ -195,8 +192,7 @@ func TestGenerateChecks(t *testing.T) {
AssetType: types.GitRepository,
},
},
want: nil,
wantNilErr: true,
want: nil,
},
{
name: "invalid target asset type",
Expand All @@ -216,8 +212,7 @@ func TestGenerateChecks(t *testing.T) {
AssetType: "InvalidAssetType",
},
},
want: nil,
wantNilErr: false,
want: nil,
},
{
name: "no checktypes",
Expand All @@ -228,8 +223,7 @@ func TestGenerateChecks(t *testing.T) {
AssetType: types.GitRepository,
},
},
want: nil,
wantNilErr: true,
want: nil,
},
{
name: "no targets",
Expand All @@ -243,9 +237,8 @@ func TestGenerateChecks(t *testing.T) {
},
},
},
targets: nil,
want: nil,
wantNilErr: true,
targets: nil,
want: nil,
},
{
name: "target without asset type",
Expand All @@ -264,8 +257,7 @@ func TestGenerateChecks(t *testing.T) {
Identifier: "example.com",
},
},
want: nil,
wantNilErr: false,
want: nil,
},
{
name: "one checktype with two asset types and one target",
Expand Down Expand Up @@ -304,7 +296,6 @@ func TestGenerateChecks(t *testing.T) {
options: map[string]any{},
},
},
wantNilErr: true,
},
{
name: "one checktype with two asset types and one target identifier with two asset types",
Expand Down Expand Up @@ -363,7 +354,6 @@ func TestGenerateChecks(t *testing.T) {
options: map[string]any{},
},
},
wantNilErr: true,
},
{
name: "one target identifier with two asset types",
Expand Down Expand Up @@ -404,7 +394,6 @@ func TestGenerateChecks(t *testing.T) {
options: map[string]any{},
},
},
wantNilErr: true,
},
{
name: "duplicated targets",
Expand Down Expand Up @@ -445,16 +434,48 @@ func TestGenerateChecks(t *testing.T) {
options: map[string]any{},
},
},
wantNilErr: true,
},
{
name: "lava asset type",
checktypes: checktype.Catalog{
"checktype1": {
Name: "checktype1",
Description: "checktype1 description",
Image: "namespace/repository:tag",
Assets: []string{
"GitRepository",
},
},
},
targets: []config.Target{
{
Identifier: ".",
AssetType: assettype.Path,
},
},
want: []check{
{
checktype: checktype.Checktype{
Name: "checktype1",
Description: "checktype1 description",
Image: "namespace/repository:tag",
Assets: []string{
"GitRepository",
},
},
target: config.Target{
Identifier: ".",
AssetType: assettype.Path,
},
options: map[string]any{},
},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := generateChecks(tt.checktypes, tt.targets)
if (err == nil) != tt.wantNilErr {
t.Fatalf("unexpected error value: %v", err)
}
got := generateChecks(tt.checktypes, tt.targets)
diffOpts := []cmp.Option{
cmp.AllowUnexported(check{}),
cmpopts.SortSlices(checkLess),
Expand Down
69 changes: 48 additions & 21 deletions internal/engine/targetserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,24 @@ import (
types "github.com/adevinta/vulcan-types"
"github.com/jroimartin/proxy"

"github.com/adevinta/lava/internal/assettype"
"github.com/adevinta/lava/internal/config"
"github.com/adevinta/lava/internal/gitserver"
)

// targetMap maps a target identifier with its updated value.
type targetMap struct {
// Old is the original target identifier.
Old string
// OldIdentifier is the original target identifier.
OldIdentifier string

// New is the updated target identifier.
New string
// OldAssetType is the original asset type of the target.
OldAssetType types.AssetType

// assetType is the asset type of the target.
assetType types.AssetType
// NewIdentifier is the updated target identifier.
NewIdentifier string

// NewAssetType is the updated asset type of the target.
NewAssetType types.AssetType
}

// IsZero reports whether tm is the zero value.
Expand All @@ -43,20 +47,21 @@ func (tm targetMap) IsZero() bool {
// it is not possible to get the address of a target, then the target
// is used.
func (tm targetMap) Addrs() targetMap {
oldAddr, err := getTargetAddr(config.Target{Identifier: tm.Old, AssetType: tm.assetType})
oldAddr, err := getTargetAddr(config.Target{Identifier: tm.OldIdentifier, AssetType: tm.OldAssetType})
if err != nil {
oldAddr = tm.Old
oldAddr = tm.OldIdentifier
}

newAddr, err := getTargetAddr(config.Target{Identifier: tm.New, AssetType: tm.assetType})
newAddr, err := getTargetAddr(config.Target{Identifier: tm.NewIdentifier, AssetType: tm.NewAssetType})
if err != nil {
newAddr = tm.New
newAddr = tm.NewIdentifier
}

tmAddrs := targetMap{
Old: oldAddr,
New: newAddr,
assetType: tm.assetType,
OldIdentifier: oldAddr,
OldAssetType: tm.OldAssetType,
NewIdentifier: newAddr,
NewAssetType: tm.NewAssetType,
}
return tmAddrs
}
Expand Down Expand Up @@ -125,9 +130,12 @@ func (srv *targetServer) Handle(key string, target config.Target) (targetMap, er
tm targetMap
err error
)
if target.AssetType == types.GitRepository {
switch target.AssetType {
case types.GitRepository:
tm, err = srv.handleGitRepo(target)
} else {
case assettype.Path:
tm, err = srv.handlePath(target)
default:
tm, err = srv.handle(target)
}
if err != nil {
Expand Down Expand Up @@ -192,9 +200,10 @@ loop:
}

tm := targetMap{
Old: target.Identifier,
New: intIdentifier,
assetType: target.AssetType,
OldIdentifier: target.Identifier,
OldAssetType: target.AssetType,
NewIdentifier: intIdentifier,
NewAssetType: target.AssetType,
}
return tm, nil
}
Expand Down Expand Up @@ -224,9 +233,27 @@ func (srv *targetServer) handleGitRepo(target config.Target) (targetMap, error)
}

tm := targetMap{
Old: target.Identifier,
New: fmt.Sprintf("http://%v/%v", srv.gitAddr, repo),
assetType: target.AssetType,
OldIdentifier: target.Identifier,
OldAssetType: target.AssetType,
NewIdentifier: fmt.Sprintf("http://%v/%v", srv.gitAddr, repo),
NewAssetType: target.AssetType,
}
return tm, nil
}

// handlePath serves the provided path as a Git repository with a
// single commit.
func (srv *targetServer) handlePath(target config.Target) (targetMap, error) {
repo, err := srv.gs.AddPath(target.Identifier)
if err != nil {
return targetMap{}, fmt.Errorf("add path: %w", err)
}

tm := targetMap{
OldIdentifier: target.Identifier,
OldAssetType: target.AssetType,
NewIdentifier: fmt.Sprintf("http://%v/%v", srv.gitAddr, repo),
NewAssetType: assettype.ToVulcan(target.AssetType),
}
return tm, nil
}
Expand Down

0 comments on commit ac11239

Please sign in to comment.