diff --git a/providers/os/connection/container/image_connection.go b/providers/os/connection/container/image_connection.go index 68a0fd11a7..41f08393f8 100644 --- a/providers/os/connection/container/image_connection.go +++ b/providers/os/connection/container/image_connection.go @@ -19,8 +19,8 @@ import ( "go.mondoo.com/cnquery/v10/providers/os/id/containerid" ) -// NewContainerImageConnection uses a container image reference as input and creates a tar connection -func NewContainerImageConnection(id uint32, conf *inventory.Config, asset *inventory.Asset, img v1.Image) (*tar.TarConnection, error) { +// NewImageConnection uses a container image reference as input and creates a tar connection +func NewImageConnection(id uint32, conf *inventory.Config, asset *inventory.Asset, img v1.Image) (*tar.Connection, error) { f, err := tar.RandomFile() if err != nil { return nil, err @@ -28,11 +28,11 @@ func NewContainerImageConnection(id uint32, conf *inventory.Config, asset *inven conf.Options[tar.OPTION_FILE] = f.Name() - return tar.NewTarConnection(id, conf, asset, + return tar.NewConnection(id, conf, asset, tar.WithFetchFn(func() (string, error) { err = tar.StreamToTmpFile(mutate.Extract(img), f) if err != nil { - os.Remove(f.Name()) + _ = os.Remove(f.Name()) return "", err } log.Debug().Msg("tar> extracted image to temporary file") @@ -40,13 +40,13 @@ func NewContainerImageConnection(id uint32, conf *inventory.Config, asset *inven }), tar.WithCloseFn(func() { log.Debug().Str("tar", f.Name()).Msg("tar> remove temporary tar file on connection close") - os.Remove(f.Name()) + _ = os.Remove(f.Name()) }), ) } -// NewContainerRegistryImage loads a container image from a remote registry -func NewContainerRegistryImage(id uint32, conf *inventory.Config, asset *inventory.Asset) (*tar.TarConnection, error) { +// NewRegistryImage loads a container image from a remote registry +func NewRegistryImage(id uint32, conf *inventory.Config, asset *inventory.Asset) (*tar.Connection, error) { ref, err := name.ParseReference(conf.Host, name.WeakValidation) if err != nil { return nil, errors.New("invalid container registry reference: " + conf.Host) @@ -65,7 +65,7 @@ func NewContainerRegistryImage(id uint32, conf *inventory.Config, asset *invento conf.Options = map[string]string{} } - conn, err := NewContainerImageConnection(id, conf, asset, img) + conn, err := NewImageConnection(id, conf, asset, img) if err != nil { return nil, err } @@ -81,9 +81,9 @@ func NewContainerRegistryImage(id uint32, conf *inventory.Config, asset *invento repoName := ref.Context().Name() imgDigest := hash.String() - name := repoName + "@" + containerid.ShortContainerImageID(imgDigest) + containerAssetName := repoName + "@" + containerid.ShortContainerImageID(imgDigest) if asset.Name == "" { - asset.Name = name + asset.Name = containerAssetName } if len(asset.PlatformIds) == 0 { asset.PlatformIds = []string{identifier} @@ -111,7 +111,7 @@ func NewContainerRegistryImage(id uint32, conf *inventory.Config, asset *invento return conn, err } -func NewContainerFromTar(id uint32, conf *inventory.Config, asset *inventory.Asset) (*tar.TarConnection, error) { +func NewFromTar(id uint32, conf *inventory.Config, asset *inventory.Asset) (*tar.Connection, error) { if conf == nil || len(conf.Options[tar.OPTION_FILE]) == 0 { return nil, errors.New("tar provider requires a valid tar file") } @@ -141,11 +141,11 @@ func NewContainerFromTar(id uint32, conf *inventory.Config, asset *inventory.Ass imageFilename = f.Name() conf.Options[tar.OPTION_FILE] = imageFilename - c, err := tar.NewTarConnection(id, conf, asset, + c, err := tar.NewConnection(id, conf, asset, tar.WithFetchFn(func() (string, error) { err = tar.StreamToTmpFile(mutate.Extract(img), f) if err != nil { - os.Remove(imageFilename) + _ = os.Remove(imageFilename) return imageFilename, err } return imageFilename, nil @@ -153,7 +153,7 @@ func NewContainerFromTar(id uint32, conf *inventory.Config, asset *inventory.Ass tar.WithCloseFn(func() { // remove temporary file on stream close log.Debug().Str("tar", imageFilename).Msg("tar> remove temporary flattened image file on connection close") - os.Remove(imageFilename) + _ = os.Remove(imageFilename) }), ) if err != nil { diff --git a/providers/os/connection/container/image_connection_test.go b/providers/os/connection/container/image_connection_test.go index 849e545a44..c1348251f5 100644 --- a/providers/os/connection/container/image_connection_test.go +++ b/providers/os/connection/container/image_connection_test.go @@ -4,7 +4,6 @@ package container_test import ( - "go.mondoo.com/cnquery/v10/providers/os/connection/container" "io" "net/http" "os" @@ -18,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.mondoo.com/cnquery/v10/providers-sdk/v1/inventory" + "go.mondoo.com/cnquery/v10/providers/os/connection/container" "go.mondoo.com/cnquery/v10/providers/os/connection/tar" ) @@ -64,22 +64,23 @@ func cacheCentos() error { type dockerConnTest struct { name string - conn *tar.TarConnection + conn *tar.Connection testfile string } func TestImageConnections(t *testing.T) { - testConnections := []dockerConnTest{} + var testConnections []dockerConnTest // create a connection to ta downloaded alpine image err := cacheAlpine() require.NoError(t, err, "should create tar without error") - alpineConn, err := container.NewContainerFromTar(0, &inventory.Config{ + alpineConn, err := container.NewFromTar(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, }, }, &inventory.Asset{}) + require.NoError(t, err, "should create connection without error") testConnections = append(testConnections, dockerConnTest{ name: "alpine", conn: alpineConn, @@ -89,12 +90,13 @@ func TestImageConnections(t *testing.T) { // create a connection to ta downloaded centos image err = cacheCentos() require.NoError(t, err, "should create tar without error") - centosConn, err := container.NewContainerFromTar(0, &inventory.Config{ + centosConn, err := container.NewFromTar(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: centosContainerPath, }, }, &inventory.Asset{}) + require.NoError(t, err, "should create connection without error") testConnections = append(testConnections, dockerConnTest{ name: "centos", conn: centosConn, @@ -102,7 +104,7 @@ func TestImageConnections(t *testing.T) { }) // create a connection to a remote alpine image - alpineRemoteConn, err := container.NewContainerRegistryImage(0, &inventory.Config{ + alpineRemoteConn, err := container.NewRegistryImage(0, &inventory.Config{ Type: "docker-image", Host: alpineImage, }, &inventory.Asset{}) @@ -219,7 +221,7 @@ func TestTarSymlinkFile(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - c, err := container.NewContainerFromTar(0, &inventory.Config{ + c, err := container.NewFromTar(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, @@ -237,11 +239,11 @@ func TestTarSymlinkFile(t *testing.T) { stat, err := f.Stat() assert.Equal(t, nil, err, "should stat without error") - assert.Equal(t, int64(796240), stat.Size(), "should read file size") + assert.True(t, stat.Size() > 0, "should read file size") content, err := io.ReadAll(f) assert.Equal(t, nil, err, "should execute without error") - assert.Equal(t, 796240, len(content), "should read the full content") + assert.True(t, len(content) > 0, "should read the full content") } } @@ -251,7 +253,7 @@ func TestTarRelativeSymlinkFileCentos(t *testing.T) { err := cacheCentos() require.NoError(t, err, "should create tar without error") - c, err := container.NewContainerFromTar(0, &inventory.Config{ + c, err := container.NewFromTar(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: centosContainerPath, diff --git a/providers/os/connection/docker/container_connection.go b/providers/os/connection/docker/container_connection.go index 779c2562c0..92a903784c 100644 --- a/providers/os/connection/docker/container_connection.go +++ b/providers/os/connection/docker/container_connection.go @@ -23,16 +23,16 @@ import ( "go.mondoo.com/cnquery/v10/providers/os/connection/ssh/cat" "go.mondoo.com/cnquery/v10/providers/os/connection/tar" "go.mondoo.com/cnquery/v10/providers/os/id/containerid" - docker_discovery "go.mondoo.com/cnquery/v10/providers/os/resources/discovery/docker_engine" + dockerDiscovery "go.mondoo.com/cnquery/v10/providers/os/resources/discovery/docker_engine" ) const ( - DockerContainer shared.ConnectionType = "docker-container" + ContainerConnectionType shared.ConnectionType = "docker-container" ) -var _ shared.Connection = &DockerContainerConnection{} +var _ shared.Connection = &ContainerConnection{} -type DockerContainerConnection struct { +type ContainerConnection struct { plugin.Connection asset *inventory.Asset @@ -52,7 +52,7 @@ type DockerContainerConnection struct { runtime string } -func NewDockerContainerConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*DockerContainerConnection, error) { +func NewContainerConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*ContainerConnection, error) { // expect unix shell by default dockerClient, err := GetDockerClient() if err != nil { @@ -69,7 +69,7 @@ func NewDockerContainerConnection(id uint32, conf *inventory.Config, asset *inve return nil, errors.New("container " + data.ID + " is not running") } - conn := &DockerContainerConnection{ + conn := &ContainerConnection{ Connection: plugin.NewConnection(id, asset), asset: asset, Client: dockerClient, @@ -105,27 +105,27 @@ func GetDockerClient() (*client.Client, error) { return cli, nil } -func (c *DockerContainerConnection) Name() string { - return string(DockerContainer) +func (c *ContainerConnection) Name() string { + return string(ContainerConnectionType) } -func (c *DockerContainerConnection) Type() shared.ConnectionType { - return DockerContainer +func (c *ContainerConnection) Type() shared.ConnectionType { + return ContainerConnectionType } -func (c *DockerContainerConnection) Asset() *inventory.Asset { +func (c *ContainerConnection) Asset() *inventory.Asset { return c.asset } -func (c *DockerContainerConnection) ContainerId() string { +func (c *ContainerConnection) ContainerId() string { return c.container } -func (c *DockerContainerConnection) Capabilities() shared.Capabilities { +func (c *ContainerConnection) Capabilities() shared.Capabilities { return shared.Capability_File | shared.Capability_RunCommand } -func (c *DockerContainerConnection) FileInfo(path string) (shared.FileInfoDetails, error) { +func (c *ContainerConnection) FileInfo(path string) (shared.FileInfoDetails, error) { fs := c.FileSystem() afs := &afero.Afero{Fs: fs} stat, err := afs.Stat(path) @@ -151,11 +151,11 @@ func (c *DockerContainerConnection) FileInfo(path string) (shared.FileInfoDetail }, nil } -func (c *DockerContainerConnection) FileSystem() afero.Fs { +func (c *ContainerConnection) FileSystem() afero.Fs { return c.Fs } -func (c *DockerContainerConnection) RunCommand(command string) (*shared.Command, error) { +func (c *ContainerConnection) RunCommand(command string) (*shared.Command, error) { log.Debug().Str("command", command).Msg("docker> run command") cmd := &Command{Client: c.Client, Container: c.container} res, err := cmd.Exec(command) @@ -174,7 +174,7 @@ func (c *DockerContainerConnection) RunCommand(command string) (*shared.Command, func NewDockerEngineContainer(id uint32, conf *inventory.Config, asset *inventory.Asset) (shared.Connection, error) { // could be an image id/name, container id/name or a short reference to an image in docker engine - ded, err := docker_discovery.NewDockerEngineDiscovery() + ded, err := dockerDiscovery.NewDockerEngineDiscovery() if err != nil { return nil, err } @@ -187,7 +187,7 @@ func NewDockerEngineContainer(id uint32, conf *inventory.Config, asset *inventor if ci.Running { log.Debug().Msg("found running container " + ci.ID) - conn, err := NewDockerContainerConnection(id, &inventory.Config{ + conn, err := NewContainerConnection(id, &inventory.Config{ Host: ci.ID, }, asset) if err != nil { @@ -201,7 +201,7 @@ func NewDockerEngineContainer(id uint32, conf *inventory.Config, asset *inventor return conn, nil } else { log.Debug().Msg("found stopped container " + ci.ID) - conn, err := NewFromDockerEngine(id, &inventory.Config{ + conn, err := NewSnapshotConnection(id, &inventory.Config{ Host: ci.ID, }, asset) if err != nil { @@ -216,7 +216,7 @@ func NewDockerEngineContainer(id uint32, conf *inventory.Config, asset *inventor } } -func NewDockerContainerImageConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*tar.TarConnection, error) { +func NewDockerContainerImageConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*tar.Connection, error) { disableInmemoryCache := false if _, ok := conf.Options["disable-cache"]; ok { var err error @@ -226,7 +226,7 @@ func NewDockerContainerImageConnection(id uint32, conf *inventory.Config, asset } } // Determine whether the image is locally present or not. - resolver := docker_discovery.Resolver{} + resolver := dockerDiscovery.Resolver{} resolvedAssets, err := resolver.Resolve(context.Background(), asset, conf, nil) if err != nil { return nil, err @@ -241,11 +241,11 @@ func NewDockerContainerImageConnection(id uint32, conf *inventory.Config, asset asset.Name = resolvedAssets[0].Name asset.PlatformIds = resolvedAssets[0].PlatformIds asset.Labels = resolvedAssets[0].Labels - return container.NewContainerRegistryImage(id, conf, asset) + return container.NewRegistryImage(id, conf, asset) } // could be an image id/name, container id/name or a short reference to an image in docker engine - ded, err := docker_discovery.NewDockerEngineDiscovery() + ded, err := dockerDiscovery.NewDockerEngineDiscovery() if err != nil { return nil, err } @@ -296,7 +296,7 @@ func NewDockerContainerImageConnection(id uint32, conf *inventory.Config, asset // 2. a locally present image, referenced by tag or digest // 3. a remote image, referenced by tag or digest func FetchConnectionType(target string) (string, error) { - ded, err := docker_discovery.NewDockerEngineDiscovery() + ded, err := dockerDiscovery.NewDockerEngineDiscovery() if err != nil { return "", err } @@ -321,7 +321,7 @@ func FetchConnectionType(target string) (string, error) { // Used with docker snapshots // NewWithReader provides a tar provider from a container image stream -func NewWithReader(id uint32, conf *inventory.Config, asset *inventory.Asset, rc io.ReadCloser) (*tar.TarConnection, error) { +func NewWithReader(id uint32, conf *inventory.Config, asset *inventory.Asset, rc io.ReadCloser) (*tar.Connection, error) { filename := "" if x, ok := rc.(*os.File); ok { filename = x.Name() @@ -337,12 +337,12 @@ func NewWithReader(id uint32, conf *inventory.Config, asset *inventory.Asset, rc err = tar.StreamToTmpFile(rc, f) if err != nil { - os.Remove(filename) + _ = os.Remove(filename) return nil, err } } - return tar.NewTarConnection( + return tar.NewConnection( id, &inventory.Config{ Type: "tar", @@ -354,6 +354,6 @@ func NewWithReader(id uint32, conf *inventory.Config, asset *inventory.Asset, rc asset, tar.WithCloseFn(func() { log.Debug().Str("tar", filename).Msg("tar> remove temporary tar file on connection close") - os.Remove(filename) + _ = os.Remove(filename) })) } diff --git a/providers/os/connection/docker/container_connection_test.go b/providers/os/connection/docker/container_connection_test.go index e22440f3f1..92ab51a768 100644 --- a/providers/os/connection/docker/container_connection_test.go +++ b/providers/os/connection/docker/container_connection_test.go @@ -6,6 +6,7 @@ package docker import ( "context" "fmt" + "github.com/docker/docker/client" "io" "os" "testing" @@ -25,7 +26,7 @@ import ( // To test this specific case, we cannot use a stored image, we need to call remote.Get func TestAssetNameForRemoteImages(t *testing.T) { var err error - var conn *tar.TarConnection + var conn *tar.Connection var asset *inventory.Asset retries := 3 counter := 0 @@ -51,21 +52,20 @@ func TestAssetNameForRemoteImages(t *testing.T) { assert.Contains(t, asset.PlatformIds, "//platformid.api.mondoo.app/runtime/docker/images/545e6a6310a27636260920bc07b994a299b6708a1b26910cfefd335fdfb60d2b") } -// TestDockerContainerConnection creates a new running container and tests the connection -func TestDockerContainerConnection(t *testing.T) { - image := "docker.io/nginx:stable" - ctx := context.Background() - dClient, err := GetDockerClient() - assert.NoError(t, err) - +func fetchAndCreateImage(t *testing.T, ctx context.Context, dClient *client.Client, image string) container.CreateResponse { // If docker is not available, then skip the test. - _, err = dClient.ServerVersion(ctx) + _, err := dClient.ServerVersion(ctx) if err != nil { t.SkipNow() } responseBody, err := dClient.ImagePull(ctx, image, types.ImagePullOptions{}) - defer responseBody.Close() + defer func() { + err = responseBody.Close() + if err != nil { + panic(err) + } + }() require.NoError(t, err) _, err = io.Copy(os.Stdout, responseBody) @@ -73,8 +73,11 @@ func TestDockerContainerConnection(t *testing.T) { // Make sure the docker image is cleaned up defer func() { - _, err := dClient.ImageRemove(ctx, image, types.ImageRemoveOptions{}) - require.NoError(t, err, "failed to cleanup pre-pulled docker image") + _, err := dClient.ImageRemove(ctx, image, types.ImageRemoveOptions{ + Force: true, + }) + // ignore error, worst case is that the image is not removed but parallel tests may fail otherwise + fmt.Printf("failed to cleanup pre-pulled docker image: %v", err) }() cfg := &container.Config{ @@ -85,21 +88,43 @@ func TestDockerContainerConnection(t *testing.T) { Image: image, } - uuid := uuid.New() - created, err := dClient.ContainerCreate(ctx, cfg, &container.HostConfig{}, &network.NetworkingConfig{}, &specs.Platform{}, uuid.String()) + uuidVal := uuid.New() + created, err := dClient.ContainerCreate(ctx, cfg, &container.HostConfig{}, &network.NetworkingConfig{}, &specs.Platform{}, uuidVal.String()) require.NoError(t, err) - require.NoError(t, dClient.ContainerStart(ctx, created.ID, types.ContainerStartOptions{})) + require.NoError(t, dClient.ContainerStart(ctx, created.ID, container.StartOptions{})) + + return created +} + +// TestDockerContainerConnection creates a new running container and tests the connection +func TestDockerContainerConnection(t *testing.T) { + ctx := context.Background() + image := "docker.io/nginx:stable" + dClient, err := GetDockerClient() + assert.NoError(t, err) + created := fetchAndCreateImage(t, ctx, dClient, image) // Make sure the container is cleaned up defer func() { - err := dClient.ContainerRemove(ctx, created.ID, types.ContainerRemoveOptions{Force: true}) + err := dClient.ContainerRemove(ctx, created.ID, container.RemoveOptions{ + Force: true, + }) require.NoError(t, err) }() fmt.Println("inject: " + created.ID) - conn, err := NewDockerContainerConnection(0, nil, nil) - assert.NoError(t, err) + conn, err := NewContainerConnection(0, &inventory.Config{ + Host: created.ID, + }, &inventory.Asset{ + // for the test we need to set the platform + Platform: &inventory.Platform{ + Name: "debian", + Version: "11", + Family: []string{"debian", "linux"}, + }, + }) + require.NoError(t, err) cmd, err := conn.RunCommand("ls /") require.NoError(t, err) diff --git a/providers/os/connection/docker/file.go b/providers/os/connection/docker/file.go index d3bb115442..2ee658abbf 100644 --- a/providers/os/connection/docker/file.go +++ b/providers/os/connection/docker/file.go @@ -20,7 +20,7 @@ import ( "go.mondoo.com/cnquery/v10/providers/os/fsutil" ) -func FileOpen(dockerClient *client.Client, path string, container string, conn *DockerContainerConnection, catFs *cat.Fs) (afero.File, error) { +func FileOpen(dockerClient *client.Client, path string, container string, conn *ContainerConnection, catFs *cat.Fs) (afero.File, error) { f := &File{ path: path, dockerClient: dockerClient, @@ -36,7 +36,7 @@ type File struct { path string container string dockerClient *client.Client - connection *DockerContainerConnection + connection *ContainerConnection reader *bytes.Reader catFs *cat.Fs } diff --git a/providers/os/connection/docker/filesytem.go b/providers/os/connection/docker/filesytem.go index 479970e086..e5630cdbcf 100644 --- a/providers/os/connection/docker/filesytem.go +++ b/providers/os/connection/docker/filesytem.go @@ -17,7 +17,7 @@ import ( type FS struct { Container string dockerClient *client.Client - Connection *DockerContainerConnection + Connection *ContainerConnection catFS *cat.Fs } diff --git a/providers/os/connection/docker/snapshot_connection.go b/providers/os/connection/docker/snapshot_connection.go index 05ba0bf2b1..10abd03138 100644 --- a/providers/os/connection/docker/snapshot_connection.go +++ b/providers/os/connection/docker/snapshot_connection.go @@ -12,37 +12,21 @@ import ( "go.mondoo.com/cnquery/v10/providers/os/connection/tar" ) -var _ shared.Connection = &DockerSnapshotConnection{} +var _ shared.Connection = &SnapshotConnection{} -type DockerSnapshotConnection struct { - tar.TarConnection +type SnapshotConnection struct { + tar.Connection } -func NewDockerSnapshotConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*DockerSnapshotConnection, error) { - tarConnection, err := tar.NewTarConnection(id, conf, asset) - if err != nil { - return nil, err - } - - // FIXME: ??? use NewFromDockerEngine - - return &DockerSnapshotConnection{*tarConnection}, nil -} - -// NewFromDockerEngine creates a snapshot for a docker engine container and opens it -func NewFromDockerEngine(id uint32, conf *inventory.Config, asset *inventory.Asset) (*DockerSnapshotConnection, error) { +// NewSnapshotConnection creates a snapshot for a docker engine container and opens it +func NewSnapshotConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*SnapshotConnection, error) { // cache container on local disk f, err := tar.RandomFile() if err != nil { return nil, err } - err = ExportSnapshot(conf.Host, f) - if err != nil { - return nil, err - } - - tarConnection, err := tar.NewTarConnection( + tarConnection, err := tar.NewConnection( id, &inventory.Config{ Type: "tar", @@ -51,19 +35,27 @@ func NewFromDockerEngine(id uint32, conf *inventory.Config, asset *inventory.Ass }, }, asset, + tar.WithFetchFn(func() (string, error) { + err := exportSnapshot(conf.Host, f) + if err != nil { + return "", err + } + + return f.Name(), nil + }), tar.WithCloseFn(func() { // remove temporary file on stream close - os.Remove(f.Name()) + _ = os.Remove(f.Name()) })) if err != nil { return nil, err } - return &DockerSnapshotConnection{*tarConnection}, nil + return &SnapshotConnection{*tarConnection}, nil } // ExportSnapshot exports a given container from docker engine to a tar file -func ExportSnapshot(containerid string, f *os.File) error { +func exportSnapshot(containerid string, f *os.File) error { dc, err := GetDockerClient() if err != nil { return err @@ -77,10 +69,10 @@ func ExportSnapshot(containerid string, f *os.File) error { return tar.StreamToTmpFile(rc, f) } -func (p *DockerSnapshotConnection) Name() string { +func (p *SnapshotConnection) Name() string { return string(shared.Type_DockerSnapshot) } -func (p *DockerSnapshotConnection) Type() shared.ConnectionType { +func (p *SnapshotConnection) Type() shared.ConnectionType { return shared.Type_DockerSnapshot } diff --git a/providers/os/connection/docker/snapshot_connection_test.go b/providers/os/connection/docker/snapshot_connection_test.go new file mode 100644 index 0000000000..e27eecaf1e --- /dev/null +++ b/providers/os/connection/docker/snapshot_connection_test.go @@ -0,0 +1,45 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package docker + +import ( + "context" + "github.com/docker/docker/api/types/container" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.mondoo.com/cnquery/v10/providers-sdk/v1/inventory" + "testing" +) + +func TestSnapshotConnection(t *testing.T) { + ctx := context.Background() + image := "docker.io/nginx:stable" + dClient, err := GetDockerClient() + assert.NoError(t, err) + created := fetchAndCreateImage(t, ctx, dClient, image) + // Make sure the container is cleaned up + defer func() { + err := dClient.ContainerRemove(ctx, created.ID, container.RemoveOptions{ + Force: true, + }) + require.NoError(t, err) + }() + + conn, err := NewSnapshotConnection(0, &inventory.Config{ + Host: created.ID, + }, &inventory.Asset{ + // for the test we need to set the platform + Platform: &inventory.Platform{ + Name: "debian", + Version: "11", + Family: []string{"debian", "linux"}, + }, + }) + require.NoError(t, err) + + fi, err := conn.FileInfo("/etc/os-release") + require.NoError(t, err) + assert.NotNil(t, fi) + assert.True(t, fi.Size > 0) +} diff --git a/providers/os/connection/ssh/ssh.go b/providers/os/connection/ssh/ssh.go index 7ea8a3819f..e4072fe206 100644 --- a/providers/os/connection/ssh/ssh.go +++ b/providers/os/connection/ssh/ssh.go @@ -38,11 +38,11 @@ import ( ) var ( - _ shared.Connection = (*SshConnection)(nil) - _ plugin.Closer = (*SshConnection)(nil) + _ shared.Connection = (*Connection)(nil) + _ plugin.Closer = (*Connection)(nil) ) -type SshConnection struct { +type Connection struct { plugin.Connection conf *inventory.Config asset *inventory.Asset @@ -56,8 +56,8 @@ type SshConnection struct { SSHClient *ssh.Client } -func NewSshConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*SshConnection, error) { - res := SshConnection{ +func NewConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*Connection, error) { + res := Connection{ Connection: plugin.NewConnection(id, asset), conf: conf, asset: asset, @@ -119,30 +119,30 @@ func NewSshConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) return &res, nil } -func (c *SshConnection) Name() string { +func (c *Connection) Name() string { return "ssh" } -func (c *SshConnection) Type() shared.ConnectionType { +func (c *Connection) Type() shared.ConnectionType { return shared.Type_SSH } -func (p *SshConnection) Asset() *inventory.Asset { +func (p *Connection) Asset() *inventory.Asset { return p.asset } -func (p *SshConnection) Capabilities() shared.Capabilities { +func (p *Connection) Capabilities() shared.Capabilities { return shared.Capability_File | shared.Capability_RunCommand } -func (c *SshConnection) RunCommand(command string) (*shared.Command, error) { +func (c *Connection) RunCommand(command string) (*shared.Command, error) { if c.Sudo != nil && c.Sudo.Active { command = shared.BuildSudoCommand(c.Sudo, command) } return c.runRawCommand(command) } -func (c *SshConnection) runRawCommand(command string) (*shared.Command, error) { +func (c *Connection) runRawCommand(command string) (*shared.Command, error) { log.Debug().Str("command", command).Str("provider", "ssh").Msg("run command") if c.SSHClient == nil { @@ -197,7 +197,7 @@ func (c *SshConnection) runRawCommand(command string) (*shared.Command, error) { return &res, err } -func (c *SshConnection) FileSystem() afero.Fs { +func (c *Connection) FileSystem() afero.Fs { if c.fs != nil { return c.fs } @@ -244,7 +244,7 @@ func (c *SshConnection) FileSystem() afero.Fs { return c.fs } -func (c *SshConnection) FileInfo(path string) (shared.FileInfoDetails, error) { +func (c *Connection) FileInfo(path string) (shared.FileInfoDetails, error) { fs := c.FileSystem() afs := &afero.Afero{Fs: fs} stat, err := afs.Stat(path) @@ -276,14 +276,14 @@ func (c *SshConnection) FileInfo(path string) (shared.FileInfoDetails, error) { }, nil } -func (c *SshConnection) Close() { +func (c *Connection) Close() { if c.SSHClient != nil { c.SSHClient.Close() } } // checks the connection config and set default values if not provided by the user -func (c *SshConnection) setDefaultSettings() { +func (c *Connection) setDefaultSettings() { // we always want to ensure we use the default port if nothing was specified if c.conf.Port == 0 { c.conf.Port = 22 @@ -295,7 +295,7 @@ func (c *SshConnection) setDefaultSettings() { } } -func (c *SshConnection) Connect() error { +func (c *Connection) Connect() error { cc := c.conf c.setDefaultSettings() @@ -353,7 +353,7 @@ func (c *SshConnection) Connect() error { return nil } -func (c *SshConnection) PlatformID() (string, error) { +func (c *Connection) PlatformID() (string, error) { return PlatformIdentifier(c.HostKey), nil } @@ -666,7 +666,7 @@ func prepareConnection(conf *inventory.Config) ([]ssh.AuthMethod, []io.Closer, e return auths, closer, nil } -func (c *SshConnection) verify() error { +func (c *Connection) verify() error { var out *shared.Command var err error if c.Sudo != nil { diff --git a/providers/os/connection/ssh/ssh_test.go b/providers/os/connection/ssh/ssh_test.go index b0baf8530f..f52919f526 100644 --- a/providers/os/connection/ssh/ssh_test.go +++ b/providers/os/connection/ssh/ssh_test.go @@ -12,7 +12,7 @@ import ( ) func TestSSHDefaultSettings(t *testing.T) { - conn := &SshConnection{ + conn := &Connection{ conf: &inventory.Config{ Sudo: &inventory.Sudo{ Active: true, @@ -25,12 +25,12 @@ func TestSSHDefaultSettings(t *testing.T) { } func TestSSHProviderError(t *testing.T) { - _, err := NewSshConnection(0, &inventory.Config{Type: shared.Type_Local.String(), Host: "example.local"}, &inventory.Asset{}) + _, err := NewConnection(0, &inventory.Config{Type: shared.Type_Local.String(), Host: "example.local"}, &inventory.Asset{}) assert.Equal(t, "provider type does not match", err.Error()) } func TestSSHAuthError(t *testing.T) { - _, err := NewSshConnection(0, &inventory.Config{Type: shared.Type_SSH.String(), Host: "example.local"}, &inventory.Asset{}) + _, err := NewConnection(0, &inventory.Config{Type: shared.Type_SSH.String(), Host: "example.local"}, &inventory.Asset{}) assert.True(t, // local testing if ssh agent is available err.Error() == "dial tcp: lookup example.local: no such host" || diff --git a/providers/os/connection/tar/tar_connection.go b/providers/os/connection/tar/connection.go similarity index 78% rename from providers/os/connection/tar/tar_connection.go rename to providers/os/connection/tar/connection.go index bd7388e6ae..b6120b6b3d 100644 --- a/providers/os/connection/tar/tar_connection.go +++ b/providers/os/connection/tar/connection.go @@ -24,11 +24,11 @@ const ( ) var ( - _ shared.Connection = (*TarConnection)(nil) - _ plugin.Closer = (*TarConnection)(nil) + _ shared.Connection = (*Connection)(nil) + _ plugin.Closer = (*Connection)(nil) ) -type TarConnection struct { +type Connection struct { plugin.Connection asset *inventory.Asset conf *inventory.Config @@ -49,36 +49,36 @@ type TarConnection struct { } } -func (p *TarConnection) Name() string { +func (p *Connection) Name() string { return string(shared.Type_Tar) } -func (p *TarConnection) Type() shared.ConnectionType { +func (p *Connection) Type() shared.ConnectionType { return shared.Type_Tar } -func (p *TarConnection) Asset() *inventory.Asset { +func (p *Connection) Asset() *inventory.Asset { return p.asset } -func (p *TarConnection) Conf() *inventory.Config { +func (p *Connection) Conf() *inventory.Config { return p.conf } -func (c *TarConnection) Identifier() (string, error) { +func (c *Connection) Identifier() (string, error) { return c.PlatformIdentifier, nil } -func (c *TarConnection) Capabilities() shared.Capabilities { +func (c *Connection) Capabilities() shared.Capabilities { return shared.Capability_File | shared.Capability_FileSearch | shared.Capability_FindFile } -func (p *TarConnection) RunCommand(command string) (*shared.Command, error) { +func (p *Connection) RunCommand(command string) (*shared.Command, error) { res := shared.Command{Command: command, Stdout: &bytes.Buffer{}, Stderr: &bytes.Buffer{}, ExitStatus: -1} return &res, nil } -func (p *TarConnection) EnsureLoaded() { +func (p *Connection) EnsureLoaded() { if p.fetchFn != nil { p.fetchOnce.Do(func() { f, err := p.fetchFn() @@ -94,12 +94,12 @@ func (p *TarConnection) EnsureLoaded() { } } -func (p *TarConnection) FileSystem() afero.Fs { +func (p *Connection) FileSystem() afero.Fs { p.EnsureLoaded() return p.fs } -func (c *TarConnection) FileInfo(path string) (shared.FileInfoDetails, error) { +func (c *Connection) FileInfo(path string) (shared.FileInfoDetails, error) { fs := c.FileSystem() afs := &afero.Afero{Fs: fs} stat, err := afs.Stat(path) @@ -123,13 +123,13 @@ func (c *TarConnection) FileInfo(path string) (shared.FileInfoDetails, error) { }, nil } -func (c *TarConnection) Close() { +func (c *Connection) Close() { if c.closeFN != nil { c.closeFN() } } -func (c *TarConnection) Load(stream io.Reader) error { +func (c *Connection) Load(stream io.Reader) error { tr := tar.NewReader(stream) for { h, err := tr.Next() @@ -148,7 +148,7 @@ func (c *TarConnection) Load(stream io.Reader) error { return nil } -func (c *TarConnection) LoadFile(path string) error { +func (c *Connection) LoadFile(path string) error { log.Debug().Str("path", path).Msg("tar> load tar file into backend") f, err := os.Open(path) @@ -159,11 +159,11 @@ func (c *TarConnection) LoadFile(path string) error { return c.Load(f) } -func (c *TarConnection) Kind() string { +func (c *Connection) Kind() string { return c.PlatformKind } -func (c *TarConnection) Runtime() string { +func (c *Connection) Runtime() string { return c.PlatformRuntime } @@ -188,12 +188,10 @@ func WithFetchFn(fetchFn func() (string, error)) tarClientOption { } } -func WithCustomFileSystem() {} - -// NewTarConnection is opening a tar file and creating a new tar connection. The tar file is expected to be a valid +// NewConnection is opening a tar file and creating a new tar connection. The tar file is expected to be a valid // tar file and contains a flattened file structure. Nested tar files as used in docker images are not supported and // need to be extracted before using this connection. -func NewTarConnection(id uint32, conf *inventory.Config, asset *inventory.Asset, opts ...tarClientOption) (*TarConnection, error) { +func NewConnection(id uint32, conf *inventory.Config, asset *inventory.Asset, opts ...tarClientOption) (*Connection, error) { if conf == nil || len(conf.Options[OPTION_FILE]) == 0 { return nil, errors.New("tar provider requires a valid tar file") } @@ -212,7 +210,7 @@ func NewTarConnection(id uint32, conf *inventory.Config, asset *inventory.Asset, o(params) } - c := &TarConnection{ + c := &Connection{ Connection: plugin.NewConnection(id, asset), asset: asset, fs: NewFs(filename), diff --git a/providers/os/connection/tar/tar_connection_test.go b/providers/os/connection/tar/connection_test.go similarity index 95% rename from providers/os/connection/tar/tar_connection_test.go rename to providers/os/connection/tar/connection_test.go index cb174d7981..f5414d945b 100644 --- a/providers/os/connection/tar/tar_connection_test.go +++ b/providers/os/connection/tar/connection_test.go @@ -33,7 +33,7 @@ func TestTarCommand(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - c, err := tar.NewTarConnection(0, &inventory.Config{ + c, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, @@ -57,7 +57,7 @@ func TestPlatformIdentifier(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - conn, err := tar.NewTarConnection(0, &inventory.Config{ + conn, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, @@ -74,7 +74,7 @@ func TestTarSymlinkFile(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - c, err := tar.NewTarConnection(0, &inventory.Config{ + c, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, @@ -106,7 +106,7 @@ func TestTarRelativeSymlinkFileCentos(t *testing.T) { err := cacheCentos() require.NoError(t, err, "should create tar without error") - c, err := tar.NewTarConnection(0, &inventory.Config{ + c, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: centosContainerPath, @@ -137,7 +137,7 @@ func TestTarFile(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - c, err := tar.NewTarConnection(0, &inventory.Config{ + c, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, @@ -167,7 +167,7 @@ func TestFilePermissions(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - c, err := tar.NewTarConnection(0, &inventory.Config{ + c, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, @@ -224,7 +224,7 @@ func TestTarFileFind(t *testing.T) { err := cacheAlpine() require.NoError(t, err, "should create tar without error") - c, err := tar.NewTarConnection(0, &inventory.Config{ + c, err := tar.NewConnection(0, &inventory.Config{ Type: "tar", Options: map[string]string{ tar.OPTION_FILE: alpineContainerPath, diff --git a/providers/os/connection/vagrant/vagrant.go b/providers/os/connection/vagrant/vagrant.go index ec94e0c7f2..3f6f815143 100644 --- a/providers/os/connection/vagrant/vagrant.go +++ b/providers/os/connection/vagrant/vagrant.go @@ -22,7 +22,7 @@ const ( var _ shared.Connection = (*VagrantConnection)(nil) type VagrantConnection struct { - ssh.SshConnection + ssh.Connection } func NewVagrantConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*VagrantConnection, error) { @@ -32,7 +32,7 @@ func NewVagrantConnection(id uint32, conf *inventory.Config, asset *inventory.As return nil, err } res := VagrantConnection{ - SshConnection: *conn, + Connection: *conn, } return &res, nil @@ -46,7 +46,7 @@ func (p *VagrantConnection) Type() shared.ConnectionType { return Vagrant } -func resolveVagrantSshConf(id uint32, conf *inventory.Config, root *inventory.Asset) (*ssh.SshConnection, error) { +func resolveVagrantSshConf(id uint32, conf *inventory.Config, root *inventory.Asset) (*ssh.Connection, error) { // For now, we do not provide the conf to the local connection // conf might include sudo, which is only intended for the actual vagrant connection // local currently does not need it. Quite the contrary, it cause issues. @@ -88,7 +88,7 @@ func resolveVagrantSshConf(id uint32, conf *inventory.Config, root *inventory.As if err != nil { return nil, err } - return ssh.NewSshConnection(id, root.Connections[0], root) + return ssh.NewConnection(id, root.Connections[0], root) } func migrateVagrantAssetToSsh(id uint32, sshConfig *VagrantVmSSHConfig, rootTransportConfig *inventory.Config, asset *inventory.Asset) error { diff --git a/providers/os/connection/winrm/winrm.go b/providers/os/connection/winrm/winrm.go index 73e28c0608..dad88e6f87 100644 --- a/providers/os/connection/winrm/winrm.go +++ b/providers/os/connection/winrm/winrm.go @@ -19,7 +19,7 @@ import ( "go.mondoo.com/cnquery/v10/providers/os/connection/winrm/cat" ) -var _ shared.Connection = (*WinrmConnection)(nil) +var _ shared.Connection = (*Connection)(nil) func VerifyConfig(config *inventory.Config) (*winrm.Endpoint, error) { if config.Type != string(shared.Type_Winrm) { @@ -39,8 +39,8 @@ func VerifyConfig(config *inventory.Config) (*winrm.Endpoint, error) { return winrmEndpoint, nil } -// NewWinrmConnection creates a winrm client and establishes a connection to verify the connection -func NewWinrmConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*WinrmConnection, error) { +// NewConnection creates a winrm client and establishes a connection to verify the connection +func NewConnection(id uint32, conf *inventory.Config, asset *inventory.Asset) (*Connection, error) { // ensure all required configs are set winrmEndpoint, err := VerifyConfig(conf) if err != nil { @@ -77,7 +77,7 @@ func NewWinrmConnection(id uint32, conf *inventory.Config, asset *inventory.Asse } log.Debug().Msg("winrm> connection established") - return &WinrmConnection{ + return &Connection{ Connection: plugin.NewConnection(id, asset), conf: conf, asset: asset, @@ -86,7 +86,7 @@ func NewWinrmConnection(id uint32, conf *inventory.Config, asset *inventory.Asse }, nil } -type WinrmConnection struct { +type Connection struct { plugin.Connection conf *inventory.Config asset *inventory.Asset @@ -97,23 +97,23 @@ type WinrmConnection struct { Client *winrm.Client } -func (c *WinrmConnection) Name() string { +func (c *Connection) Name() string { return "ssh" } -func (c *WinrmConnection) Type() shared.ConnectionType { +func (c *Connection) Type() shared.ConnectionType { return shared.Type_Winrm } -func (p *WinrmConnection) Asset() *inventory.Asset { +func (p *Connection) Asset() *inventory.Asset { return p.asset } -func (p *WinrmConnection) Capabilities() shared.Capabilities { +func (p *Connection) Capabilities() shared.Capabilities { return shared.Capability_File | shared.Capability_RunCommand } -func (p *WinrmConnection) RunCommand(command string) (*shared.Command, error) { +func (p *Connection) RunCommand(command string) (*shared.Command, error) { log.Debug().Str("command", command).Str("provider", "winrm").Msg("winrm> run command") stdoutBuffer := &bytes.Buffer{} @@ -142,7 +142,7 @@ func (p *WinrmConnection) RunCommand(command string) (*shared.Command, error) { return res, nil } -func (p *WinrmConnection) FileInfo(path string) (shared.FileInfoDetails, error) { +func (p *Connection) FileInfo(path string) (shared.FileInfoDetails, error) { fs := p.FileSystem() afs := &afero.Afero{Fs: fs} stat, err := afs.Stat(path) @@ -162,7 +162,7 @@ func (p *WinrmConnection) FileInfo(path string) (shared.FileInfoDetails, error) }, nil } -func (p *WinrmConnection) FileSystem() afero.Fs { +func (p *Connection) FileSystem() afero.Fs { if p.fs == nil { p.fs = cat.New(p) } diff --git a/providers/os/connection/winrm/winrm_test.go b/providers/os/connection/winrm/winrm_test.go index b53ad517d5..ecc3804116 100644 --- a/providers/os/connection/winrm/winrm_test.go +++ b/providers/os/connection/winrm/winrm_test.go @@ -24,7 +24,7 @@ func TestWinrmConnection(t *testing.T) { } cred.PreProcess() - conn, err := NewWinrmConnection(0, &inventory.Config{ + conn, err := NewConnection(0, &inventory.Config{ Type: shared.Type_Winrm.String(), Host: "192.168.1.111", Credentials: []*vault.Credential{cred}, diff --git a/providers/os/detector/platform_resolver.go b/providers/os/detector/platform_resolver.go index 7ca5570abe..72b5268d48 100644 --- a/providers/os/detector/platform_resolver.go +++ b/providers/os/detector/platform_resolver.go @@ -30,7 +30,7 @@ func (r *PlatformResolver) Resolve(conn shared.Connection) (*inventory.Platform, // if we have a container image use the architecture specified in the transport as it is resolved // using the container image properties - tarConn, ok := conn.(*tar.TarConnection) + tarConn, ok := conn.(*tar.Connection) if resolved && ok { pi.Arch = tarConn.PlatformArchitecture di.Runtime = "docker-image" @@ -44,7 +44,7 @@ func (r *PlatformResolver) Resolve(conn shared.Connection) (*inventory.Platform, } } - containerConn, ok := conn.(*docker.DockerContainerConnection) + containerConn, ok := conn.(*docker.ContainerConnection) if resolved && ok { pi.Arch = containerConn.PlatformArchitecture di.Runtime = string(containerConn.Type()) diff --git a/providers/os/id/sshhostkey/sshhostkey.go b/providers/os/id/sshhostkey/sshhostkey.go index da3f98ee80..66706c3a08 100644 --- a/providers/os/id/sshhostkey/sshhostkey.go +++ b/providers/os/id/sshhostkey/sshhostkey.go @@ -17,7 +17,7 @@ import ( func Detect(t shared.Connection, p *inventory.Platform) ([]string, error) { // if we are using an ssh connection we can read the hostkey from the connection - if sshTransport, ok := t.(*sshconn.SshConnection); ok { + if sshTransport, ok := t.(*sshconn.Connection); ok { identifier, err := sshTransport.PlatformID() if err != nil { return nil, err diff --git a/providers/os/provider/provider.go b/providers/os/provider/provider.go index c73b8dbb9f..b468b2c2b5 100644 --- a/providers/os/provider/provider.go +++ b/providers/os/provider/provider.go @@ -235,7 +235,7 @@ func (s *Service) Connect(req *plugin.ConnectReq, callback plugin.ProviderCallba connType := conn.Asset().Connections[0].Type switch connType { case "docker-registry": - tarConn := conn.(*tar.TarConnection) + tarConn := conn.(*tar.Connection) inv, err = s.discoverRegistry(tarConn) if err != nil { return nil, err @@ -308,7 +308,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba } case shared.Type_SSH.String(): - conn, err = ssh.NewSshConnection(connId, conf, asset) + conn, err = ssh.NewConnection(connId, conf, asset) if err != nil { return nil, err } @@ -323,7 +323,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba } case shared.Type_Winrm.String(): - conn, err = winrm.NewWinrmConnection(connId, conf, asset) + conn, err = winrm.NewConnection(connId, conf, asset) if err != nil { return nil, err } @@ -336,7 +336,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba } case shared.Type_Tar.String(): - conn, err = tar.NewTarConnection(connId, conf, asset) + conn, err = tar.NewConnection(connId, conf, asset) if err != nil { return nil, err } @@ -349,7 +349,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba } case shared.Type_DockerSnapshot.String(): - conn, err = docker.NewDockerSnapshotConnection(connId, conf, asset) + conn, err = docker.NewSnapshotConnection(connId, conf, asset) if err != nil { return nil, err } @@ -380,10 +380,10 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba conn, err = docker.NewDockerEngineContainer(connId, conf, asset) case shared.Type_DockerRegistry.String(), shared.Type_ContainerRegistry.String(): - conn, err = container.NewContainerRegistryImage(connId, conf, asset) + conn, err = container.NewRegistryImage(connId, conf, asset) case shared.Type_RegistryImage.String(): - conn, err = container.NewContainerRegistryImage(connId, conf, asset) + conn, err = container.NewRegistryImage(connId, conf, asset) case shared.Type_FileSystem.String(): conn, err = fs.NewConnection(connId, conf, asset) @@ -444,7 +444,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba return runtime.Connection.(shared.Connection), nil } -func (s *Service) discoverRegistry(conn *tar.TarConnection) (*inventory.Inventory, error) { +func (s *Service) discoverRegistry(conn *tar.Connection) (*inventory.Inventory, error) { conf := conn.Asset().Connections[0] if conf == nil { return nil, nil diff --git a/providers/os/resources/container.go b/providers/os/resources/container.go index 1a039edc76..0c45464ec6 100644 --- a/providers/os/resources/container.go +++ b/providers/os/resources/container.go @@ -14,7 +14,7 @@ func initContainerImage(runtime *plugin.Runtime, args map[string]*llx.RawData) ( if len(args) > 1 { return args, nil, nil } - conn := runtime.Connection.(*tar.TarConnection) + conn := runtime.Connection.(*tar.Connection) reference := conn.Metadata.Labels["docker.io/digests"] ref, err := name.ParseReference(reference) diff --git a/providers/os/resources/os.go b/providers/os/resources/os.go index e34e8f44ad..5105801f5d 100644 --- a/providers/os/resources/os.go +++ b/providers/os/resources/os.go @@ -27,9 +27,9 @@ import ( func (p *mqlOs) rebootpending() (bool, error) { switch p.MqlRuntime.Connection.(type) { - case *docker.DockerSnapshotConnection: + case *docker.SnapshotConnection: return false, nil - case *tar.TarConnection: + case *tar.Connection: return false, nil } @@ -325,9 +325,9 @@ func (p *mqlOsBase) id() (string, error) { func (p *mqlOsBase) rebootpending() (bool, error) { // it is a container image, a reboot is never required switch p.MqlRuntime.Connection.(type) { - case *docker.DockerSnapshotConnection: + case *docker.SnapshotConnection: return false, nil - case *tar.TarConnection: + case *tar.Connection: return false, nil } diff --git a/providers/os/resources/processes/docker_test.go b/providers/os/resources/processes/docker_test.go index 8d40f14414..7dbf1f8a46 100644 --- a/providers/os/resources/processes/docker_test.go +++ b/providers/os/resources/processes/docker_test.go @@ -34,7 +34,12 @@ func TestDockerProcsList(t *testing.T) { } responseBody, err := dClient.ImagePull(ctx, image, types.ImagePullOptions{}) - defer responseBody.Close() + defer func() { + err = responseBody.Close() + if err != nil { + panic(err) + } + }() require.NoError(t, err) _, err = io.Copy(os.Stdout, responseBody) @@ -42,8 +47,11 @@ func TestDockerProcsList(t *testing.T) { // Make sure the docker image is cleaned up defer func() { - _, err := dClient.ImageRemove(ctx, image, types.ImageRemoveOptions{}) - require.NoError(t, err, "failed to cleanup pre-pulled docker image") + _, err := dClient.ImageRemove(ctx, image, types.ImageRemoveOptions{ + Force: true, + }) + // ignore error, worst case is that the image is not removed but parallel tests may fail otherwise + fmt.Printf("failed to cleanup pre-pulled docker image: %v", err) }() cfg := &container.Config{ @@ -54,20 +62,20 @@ func TestDockerProcsList(t *testing.T) { Image: image, } - uuid := uuid.New() - created, err := dClient.ContainerCreate(ctx, cfg, &container.HostConfig{}, &network.NetworkingConfig{}, &specs.Platform{}, uuid.String()) + uuidVal := uuid.New() + created, err := dClient.ContainerCreate(ctx, cfg, &container.HostConfig{}, &network.NetworkingConfig{}, &specs.Platform{}, uuidVal.String()) require.NoError(t, err) - require.NoError(t, dClient.ContainerStart(ctx, created.ID, types.ContainerStartOptions{})) + require.NoError(t, dClient.ContainerStart(ctx, created.ID, container.StartOptions{})) // Make sure the container is cleaned up defer func() { - err := dClient.ContainerRemove(ctx, created.ID, types.ContainerRemoveOptions{Force: true}) + err := dClient.ContainerRemove(ctx, created.ID, container.RemoveOptions{Force: true}) require.NoError(t, err) }() fmt.Println("inject: " + created.ID) - conn, err := docker.NewDockerContainerConnection(0, &inventory.Config{ + conn, err := docker.NewContainerConnection(0, &inventory.Config{ Host: created.ID, }, &inventory.Asset{ // for the test we need to set the platform @@ -77,7 +85,7 @@ func TestDockerProcsList(t *testing.T) { Family: []string{"debian", "linux"}, }, }) - assert.NoError(t, err) + require.NoError(t, err) pMan, err := ResolveManager(conn) assert.NoError(t, err) diff --git a/providers/os/resources/processes/dockertop.go b/providers/os/resources/processes/dockertop.go index 35f2ae26fa..ce4e5a8e3f 100644 --- a/providers/os/resources/processes/dockertop.go +++ b/providers/os/resources/processes/dockertop.go @@ -24,7 +24,7 @@ func (lpm *DockerTopManager) Name() string { // List lists the processes running in a Docker container. Note that currently this function returns child // processes as well. func (lpm *DockerTopManager) List() ([]*OSProcess, error) { - dockerConn, ok := lpm.conn.(*docker.DockerContainerConnection) + dockerConn, ok := lpm.conn.(*docker.ContainerConnection) if !ok { return nil, fmt.Errorf("wrong transport type") } diff --git a/providers/os/resources/processes/manager.go b/providers/os/resources/processes/manager.go index 46cca2f942..5700b856d9 100644 --- a/providers/os/resources/processes/manager.go +++ b/providers/os/resources/processes/manager.go @@ -41,7 +41,7 @@ func ResolveManager(conn shared.Connection) (OSProcessManager, error) { // procfs over ssh is super slow, lets deactivate until we have a faster approach disableProcFs := false switch conn.(type) { - case *ssh.SshConnection: + case *ssh.Connection: disableProcFs = true case *mock.Connection: disableProcFs = true