github.com/justincormack/cli@v0.0.0-20201215022714-831ebeae9675/cli/command/image/build_session.go (about)

     1  package image
     2  
     3  import (
     4  	"context"
     5  	"crypto/rand"
     6  	"crypto/sha256"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  
    13  	"github.com/docker/cli/cli/command"
    14  	cliconfig "github.com/docker/cli/cli/config"
    15  	"github.com/docker/docker/api/types/versions"
    16  	"github.com/moby/buildkit/session"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  const clientSessionRemote = "client-session"
    21  
    22  func isSessionSupported(dockerCli command.Cli, forStream bool) bool {
    23  	if !forStream && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.39") {
    24  		return true
    25  	}
    26  	return dockerCli.ServerInfo().HasExperimental && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.31")
    27  }
    28  
    29  func trySession(dockerCli command.Cli, contextDir string, forStream bool) (*session.Session, error) {
    30  	if !isSessionSupported(dockerCli, forStream) {
    31  		return nil, nil
    32  	}
    33  	sharedKey := getBuildSharedKey(contextDir)
    34  	s, err := session.NewSession(context.Background(), filepath.Base(contextDir), sharedKey)
    35  	if err != nil {
    36  		return nil, errors.Wrap(err, "failed to create session")
    37  	}
    38  	return s, nil
    39  }
    40  
    41  func getBuildSharedKey(dir string) string {
    42  	// build session is hash of build dir with node based randomness
    43  	s := sha256.Sum256([]byte(fmt.Sprintf("%s:%s", tryNodeIdentifier(), dir)))
    44  	return hex.EncodeToString(s[:])
    45  }
    46  
    47  func tryNodeIdentifier() string {
    48  	out := cliconfig.Dir() // return config dir as default on permission error
    49  	if err := os.MkdirAll(cliconfig.Dir(), 0700); err == nil {
    50  		sessionFile := filepath.Join(cliconfig.Dir(), ".buildNodeID")
    51  		if _, err := os.Lstat(sessionFile); err != nil {
    52  			if os.IsNotExist(err) { // create a new file with stored randomness
    53  				b := make([]byte, 32)
    54  				if _, err := rand.Read(b); err != nil {
    55  					return out
    56  				}
    57  				if err := ioutil.WriteFile(sessionFile, []byte(hex.EncodeToString(b)), 0600); err != nil {
    58  					return out
    59  				}
    60  			}
    61  		}
    62  
    63  		dt, err := ioutil.ReadFile(sessionFile)
    64  		if err == nil {
    65  			return string(dt)
    66  		}
    67  	}
    68  	return out
    69  }