go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/discovery/docker_engine/client.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package docker_engine
     5  
     6  import (
     7  	"context"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/cockroachdb/errors"
    12  	dopts "github.com/docker/cli/opts"
    13  	"github.com/docker/docker/client"
    14  )
    15  
    16  // parseDockerCLI is doing a small part from client.FromEnv(c)
    17  // but it parses the DOCKER_HOST like the docker cli and not the docker go lib
    18  // DO NOT ASK why docker maintains two implementations
    19  func parseDockerCLIHost(c *client.Client) error {
    20  	if host := os.Getenv("DOCKER_HOST"); host != "" {
    21  		parsedHost, err := dopts.ParseHost(false, host)
    22  		if err != nil {
    23  			return err
    24  		}
    25  
    26  		if err := client.WithHost(parsedHost)(c); err != nil {
    27  			return err
    28  		}
    29  	}
    30  	return nil
    31  }
    32  
    33  func FromDockerEnv(c *client.Client) error {
    34  	err := client.FromEnv(c)
    35  
    36  	// we ignore the parse error since we are going to re-parse it anyway
    37  	if err != nil && !strings.Contains(err.Error(), "unable to parse docker host") {
    38  		return err
    39  	}
    40  
    41  	// The docker go client works different than the docker cli
    42  	// therefore we mimic the approach from the docker cli to make it easier for users
    43  	return parseDockerCLIHost(c)
    44  }
    45  
    46  func dockerClient() (*client.Client, error) {
    47  	cli, err := client.NewClientWithOpts(FromDockerEnv)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	cli.NegotiateAPIVersion(context.Background())
    52  	return cli, nil
    53  }
    54  
    55  // TODO: this implementation needs to be merged with motorcloud/docker
    56  func NewDockerEngineDiscovery() (*dockerEngineDiscovery, error) {
    57  	dc, err := dockerClient()
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	return &dockerEngineDiscovery{
    63  		Client: dc,
    64  	}, nil
    65  }
    66  
    67  type dockerEngineDiscovery struct {
    68  	Client *client.Client
    69  }
    70  
    71  func (e *dockerEngineDiscovery) client() (*client.Client, error) {
    72  	if e.Client != nil {
    73  		return e.Client, nil
    74  	}
    75  	return nil, errors.New("docker client not initialized")
    76  }