Browse Source

Implement context loading

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 5 years ago
parent
commit
3dac4df803
4 changed files with 146 additions and 0 deletions
  1. 10 0
      cmd/main.go
  2. 38 0
      context/config.go
  3. 33 0
      context/flags.go
  4. 65 0
      context/store.go

+ 10 - 0
cmd/main.go

@@ -32,6 +32,7 @@ import (
 	"os"
 	"path/filepath"
 
+	"github.com/docker/api/context"
 	"github.com/sirupsen/logrus"
 	"github.com/urfave/cli"
 )
@@ -57,11 +58,20 @@ func main() {
 			Name:  "debug",
 			Usage: "enable debug output in the logs",
 		},
+		context.ConfigFlag,
+		context.ContextFlag,
 	}
 	app.Before = func(clix *cli.Context) error {
 		if clix.GlobalBool("debug") {
 			logrus.SetLevel(logrus.DebugLevel)
 		}
+
+		context, err := context.GetContext()
+		if err != nil {
+			return err
+		}
+		fmt.Println(context.Metadata.Type)
+		// TODO select backend based on context.Metadata.Type or delegate to legacy CLI if == "Moby"
 		return nil
 	}
 	app.Commands = []cli.Command{

+ 38 - 0
context/config.go

@@ -0,0 +1,38 @@
+package context
+
+import (
+	"encoding/json"
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+func LoadConfigFile() (*ConfigFile, error) {
+	filename := filepath.Join(ConfigDir, ConfigFileName)
+	configFile := &ConfigFile{
+		Filename: filename,
+	}
+
+	if _, err := os.Stat(filename); err == nil {
+		file, err := os.Open(filename)
+		if err != nil {
+			return nil, fmt.Errorf("can't read %s: %w", filename, err)
+		}
+		defer file.Close()
+		err = json.NewDecoder(file).Decode(&configFile)
+		if err != nil {
+			err = fmt.Errorf("can't read %s: %w", filename, err)
+		}
+		return configFile, err
+	} else if !os.IsNotExist(err) {
+		// if file is there but we can't stat it for any reason other
+		// than it doesn't exist then stop
+		return nil, fmt.Errorf("can't read %s: %w", filename, err)
+	}
+	return configFile, nil
+}
+
+type ConfigFile struct {
+	Filename       string `json:"-"` // Note: for internal use only
+	CurrentContext string `json:"currentContext,omitempty"`
+}

+ 33 - 0
context/flags.go

@@ -0,0 +1,33 @@
+package context
+
+import (
+	"path/filepath"
+
+	"github.com/docker/docker/pkg/homedir"
+	"github.com/urfave/cli"
+)
+
+const (
+	// ConfigFileName is the name of config file
+	ConfigFileName = "config.json"
+	configFileDir  = ".docker"
+)
+
+var (
+	ConfigDir  string
+	ConfigFlag = cli.StringFlag{
+		Name:        "config",
+		Usage:       "Location of client config files",
+		EnvVar:      "DOCKER_CONFIG",
+		Value:       filepath.Join(homedir.Get(), configFileDir),
+		Destination: &ConfigDir,
+	}
+
+	ContextName string
+	ContextFlag = cli.StringFlag{
+		Name:        "context, c",
+		Usage:       `Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")`,
+		EnvVar:      "DOCKER_CONTEXT",
+		Destination: &ContextName,
+	}
+)

+ 65 - 0
context/store.go

@@ -0,0 +1,65 @@
+package context
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"path/filepath"
+
+	"github.com/opencontainers/go-digest"
+)
+
+const (
+	contextsDir = "contexts"
+	metadataDir = "meta"
+	metaFile    = "meta.json"
+)
+
+// ContextStoreDir returns the directory the docker contexts are stored in
+func ContextStoreDir() string {
+	return filepath.Join(ConfigDir, contextsDir)
+}
+
+type Metadata struct {
+	Name      string                 `json:",omitempty"`
+	Metadata  TypeContext            `json:",omitempty"`
+	Endpoints map[string]interface{} `json:",omitempty"`
+}
+
+type TypeContext struct {
+	Type string
+}
+
+func GetContext() (*Metadata, error) {
+	config, err := LoadConfigFile()
+	if err != nil {
+		return nil, err
+	}
+	r := &Metadata{
+		Endpoints: make(map[string]interface{}),
+	}
+
+	if ContextName == "" {
+		ContextName = config.CurrentContext
+	}
+	if ContextName == "" || ContextName == "default" {
+		r.Metadata.Type = "Moby"
+		return r, nil
+	}
+
+	meta := filepath.Join(ConfigDir, contextsDir, metadataDir, contextdirOf(ContextName), metaFile)
+	bytes, err := ioutil.ReadFile(meta)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := json.Unmarshal(bytes, r); err != nil {
+		return r, err
+	}
+
+	r.Name = ContextName
+	return r, nil
+}
+
+func contextdirOf(name string) string {
+	return digest.FromString(name).Encoded()
+}