Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 45 additions & 41 deletions internal/health/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package health

import (
"context"
"fmt"

"github.com/arm/topo/internal/runner"
"github.com/arm/topo/internal/ssh"
"github.com/arm/topo/internal/version"
)

Expand Down Expand Up @@ -83,55 +85,57 @@ var HostRequiredDependencies = []Dependency{
},
}

var TargetRequiredDependencies = []Dependency{
{
Binary: "docker",
Label: "Container Engine",
SoftwareEnumID: Docker,
Checks: []Check{
BinaryExists{},
CommandSuccessful{
Cmd: "docker info",
Fix: &Fix{Description: "Ensure current user can run docker commands"},
func TargetRequiredDependencies(target ssh.Destination) []Dependency {
return []Dependency{
{
Binary: "docker",
Label: "Container Engine",
SoftwareEnumID: Docker,
Checks: []Check{
BinaryExists{},
CommandSuccessful{
Cmd: "docker info",
Fix: &Fix{Description: "Ensure current user can run docker commands"},
},
},
},
},
{
Binary: "remoteproc-runtime",
Label: "Remoteproc Runtime",
SoftwarePrerequisites: []SoftwareDependency{Docker},
HardwarePrerequisite: []HardwareCapability{Remoteproc},
Checks: []Check{
BinaryExists{
Severity: SeverityWarning,
Fix: &Fix{
Description: "Install the remoteproc runtime",
Command: "topo install remoteproc-runtime",
{
Binary: "remoteproc-runtime",
Label: "Remoteproc Runtime",
SoftwarePrerequisites: []SoftwareDependency{Docker},
HardwarePrerequisite: []HardwareCapability{Remoteproc},
Checks: []Check{
BinaryExists{
Severity: SeverityWarning,
Fix: &Fix{
Description: "Install the remoteproc runtime",
Command: fmt.Sprintf("topo install remoteproc-runtime --target %s", target),
},
},
},
},
},
{
Binary: "containerd-shim-remoteproc-v1",
Label: "Remoteproc Shim",
SoftwarePrerequisites: []SoftwareDependency{Docker},
HardwarePrerequisite: []HardwareCapability{Remoteproc},
Checks: []Check{
BinaryExists{
Severity: SeverityWarning,
Fix: &Fix{
Description: "Install the remoteproc runtime",
Command: "topo install remoteproc-runtime",
{
Binary: "containerd-shim-remoteproc-v1",
Label: "Remoteproc Shim",
SoftwarePrerequisites: []SoftwareDependency{Docker},
HardwarePrerequisite: []HardwareCapability{Remoteproc},
Checks: []Check{
BinaryExists{
Severity: SeverityWarning,
Fix: &Fix{
Description: "Install the remoteproc runtime",
Command: fmt.Sprintf("topo install remoteproc-runtime --target %s", target),
},
},
},
},
},
{
Binary: "lscpu",
Label: "Hardware Info",
SoftwareEnumID: Lscpu,
Checks: []Check{BinaryExists{}},
},
{
Binary: "lscpu",
Label: "Hardware Info",
SoftwareEnumID: Lscpu,
Checks: []Check{BinaryExists{}},
},
}
}

type DependencyStatus struct {
Expand Down
36 changes: 33 additions & 3 deletions internal/health/dependencies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/arm/topo/internal/command"
"github.com/arm/topo/internal/health"
"github.com/arm/topo/internal/runner"
"github.com/arm/topo/internal/ssh"
"github.com/stretchr/testify/assert"
)

Expand All @@ -19,7 +20,7 @@ func TestDependencyFormat(t *testing.T) {
})

t.Run("target dependencies are of the correct format", func(t *testing.T) {
for _, dep := range health.TargetRequiredDependencies {
for _, dep := range health.TargetRequiredDependencies(ssh.NewDestination("does-not-matter-for-this-test")) {
assert.NoError(t, command.ValidateBinaryName(dep.Binary))
}
})
Expand All @@ -29,7 +30,7 @@ func TestDependencyFormat(t *testing.T) {
seenEnums := make(map[health.SoftwareDependency]string)

t.Run("There are no duplicate SoftwareEnumID assignments", func(t *testing.T) {
for _, dep := range health.TargetRequiredDependencies {
for _, dep := range health.TargetRequiredDependencies(ssh.NewDestination("user@my-target")) {
if dep.SoftwareEnumID != health.UnsetSoftwareDependency {
if existingDep, exists := seenEnums[dep.SoftwareEnumID]; exists {
t.Errorf("Duplicate SoftwareEnumID %d assigned to both %q and %q", dep.SoftwareEnumID, existingDep, dep.Binary)
Expand All @@ -41,7 +42,7 @@ func TestDependencyFormat(t *testing.T) {
})

t.Run("all SoftwarePrerequisites reference valid SoftwareEnumID", func(t *testing.T) {
for _, dep := range health.TargetRequiredDependencies {
for _, dep := range health.TargetRequiredDependencies(ssh.NewDestination("user@my-target")) {
for _, prereq := range dep.SoftwarePrerequisites {
assert.True(t, availableEnums[prereq], "%q has SoftwarePrerequisites %v which is not provided by any dependency's SoftwareEnumID", dep.Binary, prereq)
}
Expand All @@ -50,6 +51,23 @@ func TestDependencyFormat(t *testing.T) {
})
}

func TestTargetRequiredDependencies(t *testing.T) {
t.Run("remoteproc install fix command includes the target", func(t *testing.T) {
deps := health.TargetRequiredDependencies(ssh.NewDestination("user@my-target"))

dep, err := findDependencyByBinary(t, deps, "remoteproc-runtime")
assert.NoError(t, err)
wantBinaryExistsCheck := health.BinaryExists{
Severity: health.SeverityWarning,
Fix: &health.Fix{
Description: "Install the remoteproc runtime",
Command: "topo install remoteproc-runtime --target ssh://user@my-target",
},
}
assert.Contains(t, dep.Checks, wantBinaryExistsCheck)
})
}

func TestPerformChecks(t *testing.T) {
t.Run("when no dependencies are found, statuses show not installed", func(t *testing.T) {
fooDependency := health.Dependency{Binary: "foo", Label: "bar", Checks: []health.Check{health.BinaryExists{}}}
Expand Down Expand Up @@ -311,3 +329,15 @@ func TestFilterByHardware(t *testing.T) {
assert.Equal(t, want, got)
})
}

func findDependencyByBinary(t *testing.T, deps []health.Dependency, binary string) (health.Dependency, error) {
t.Helper()

for _, dep := range deps {
if dep.Binary == binary {
return dep, nil
}
}

return health.Dependency{}, errors.New("dependency not found")
}
2 changes: 1 addition & 1 deletion internal/health/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func CheckTarget(ctx context.Context, dest ssh.Destination, acceptNewHostKeys bo
r, connErr := prepareRunner(ctx, dest, acceptNewHostKeys)
status := Status{Connection: ConnectionStatus{Destination: dest, Error: connErr}}
if connErr == nil {
hs := ProbeHealthStatus(ctx, r)
hs := ProbeHealthStatus(ctx, r, dest)
status.Dependencies = hs.Dependencies
status.Hardware = hs.Hardware
}
Expand Down
5 changes: 3 additions & 2 deletions internal/health/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/arm/topo/internal/probe"
"github.com/arm/topo/internal/runner"
"github.com/arm/topo/internal/ssh"
)

type HardwareProfile struct {
Expand All @@ -25,14 +26,14 @@ type HealthStatus struct {
Hardware HardwareProfile
}

func ProbeHealthStatus(ctx context.Context, r runner.Runner) HealthStatus {
func ProbeHealthStatus(ctx context.Context, r runner.Runner, target ssh.Destination) HealthStatus {
var hs HealthStatus

remoteProcessors, err := probe.Remoteproc(ctx, r)
hs.Hardware.RemoteProcessors = remoteProcessors
hs.Hardware.Err = err

dependenciesToCheck := FilterByHardware(TargetRequiredDependencies, hs.Hardware.Capabilities())
dependenciesToCheck := FilterByHardware(TargetRequiredDependencies(target), hs.Hardware.Capabilities())
hs.Dependencies = PerformChecks(ctx, dependenciesToCheck, r)

return hs
Expand Down
Loading