This repository has been archived by the owner on Jun 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move the inspect command to "image inspect"
The inspect command needed a bunch of code that was only present in the "internal/commands" package. The patch is big but it's only moving code around: * cnab.go was split into multiple files: * credentials.go -> all things credentials * driver/docker.go -> mainly for the driver.Prepare that all the commands use * registry.go -> has the method to get insecure registries from engine Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
- Loading branch information
Showing
25 changed files
with
680 additions
and
608 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package cnab | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"strings" | ||
|
||
"github.com/deislabs/cnab-go/bundle" | ||
"github.com/docker/app/internal" | ||
"github.com/docker/app/internal/log" | ||
"github.com/docker/app/internal/packager" | ||
"github.com/docker/app/internal/store" | ||
appstore "github.com/docker/app/internal/store" | ||
"github.com/docker/cli/cli/command" | ||
"github.com/docker/cnab-to-oci/remotes" | ||
"github.com/docker/distribution/reference" | ||
) | ||
|
||
type nameKind uint | ||
|
||
const ( | ||
_ nameKind = iota | ||
nameKindEmpty | ||
nameKindFile | ||
nameKindDir | ||
nameKindReference | ||
) | ||
|
||
func getAppNameKind(name string) (string, nameKind) { | ||
if name == "" { | ||
return name, nameKindEmpty | ||
} | ||
// name can be a bundle.json or bundle.cnab file, or a dockerapp directory | ||
st, err := os.Stat(name) | ||
if os.IsNotExist(err) { | ||
// try with .dockerapp extension | ||
st, err = os.Stat(name + internal.AppExtension) | ||
if err == nil { | ||
name += internal.AppExtension | ||
} | ||
} | ||
if err != nil { | ||
return name, nameKindReference | ||
} | ||
if st.IsDir() { | ||
return name, nameKindDir | ||
} | ||
return name, nameKindFile | ||
} | ||
|
||
func extractAndLoadAppBasedBundle(dockerCli command.Cli, name string) (*bundle.Bundle, string, error) { | ||
app, err := packager.Extract(name) | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
defer app.Cleanup() | ||
bndl, err := packager.MakeBundleFromApp(dockerCli, app, nil) | ||
return bndl, "", err | ||
} | ||
|
||
func loadBundleFromFile(filename string) (*bundle.Bundle, error) { | ||
b := &bundle.Bundle{} | ||
data, err := ioutil.ReadFile(filename) | ||
if err != nil { | ||
return b, err | ||
} | ||
return bundle.Unmarshal(data) | ||
} | ||
|
||
// ResolveBundle looks for a CNAB bundle which can be in a Docker App Package format or | ||
// a bundle stored locally or in the bundle store. It returns a built or found bundle, | ||
// a reference to the bundle if it is found in the bundlestore, and an error. | ||
func ResolveBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name string) (*bundle.Bundle, string, error) { | ||
// resolution logic: | ||
// - if there is a docker-app package in working directory, or an http:// / https:// prefix, use packager.Extract result | ||
// - the name has a .json or .cnab extension and refers to an existing file or web resource: load the bundle | ||
// - name matches a bundle name:version stored in the bundle store: use it | ||
// - pull the bundle from the registry and add it to the bundle store | ||
name, kind := getAppNameKind(name) | ||
switch kind { | ||
case nameKindFile: | ||
if strings.HasSuffix(name, internal.AppExtension) { | ||
return extractAndLoadAppBasedBundle(dockerCli, name) | ||
} | ||
bndl, err := loadBundleFromFile(name) | ||
return bndl, "", err | ||
case nameKindDir, nameKindEmpty: | ||
return extractAndLoadAppBasedBundle(dockerCli, name) | ||
case nameKindReference: | ||
bndl, tagRef, err := GetBundle(dockerCli, bundleStore, name) | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
return bndl, tagRef.String(), err | ||
} | ||
return nil, "", fmt.Errorf("could not resolve bundle %q", name) | ||
} | ||
|
||
// GetBundle searches for the bundle locally and tries to pull it if not found | ||
func GetBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, name string) (*bundle.Bundle, reference.Reference, error) { | ||
ref, err := store.StringToRef(name) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
bndl, err := bundleStore.Read(ref) | ||
if err != nil { | ||
fmt.Fprintf(dockerCli.Err(), "Unable to find application image %q locally\n", reference.FamiliarString(ref)) | ||
|
||
fmt.Fprintf(dockerCli.Out(), "Pulling from registry...\n") | ||
if named, ok := ref.(reference.Named); ok { | ||
bndl, err = PullBundle(dockerCli, bundleStore, named) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
} | ||
} | ||
|
||
return bndl, ref, nil | ||
} | ||
|
||
// PullBundle pulls the bundle and stores it into the bundle store | ||
func PullBundle(dockerCli command.Cli, bundleStore appstore.BundleStore, tagRef reference.Named) (*bundle.Bundle, error) { | ||
insecureRegistries, err := internal.InsecureRegistriesFromEngine(dockerCli) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not retrieve insecure registries: %v", err) | ||
} | ||
|
||
bndl, err := remotes.Pull(log.WithLogContext(context.Background()), reference.TagNameOnly(tagRef), remotes.CreateResolver(dockerCli.ConfigFile(), insecureRegistries...)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if _, err := bundleStore.Store(tagRef, bndl); err != nil { | ||
return nil, err | ||
} | ||
return bndl, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package cnab | ||
|
||
import ( | ||
"bytes" | ||
"io" | ||
"os" | ||
"strings" | ||
|
||
"github.com/deislabs/cnab-go/claim" | ||
"github.com/deislabs/cnab-go/driver" | ||
dockerDriver "github.com/deislabs/cnab-go/driver/docker" | ||
"github.com/docker/app/internal" | ||
"github.com/docker/cli/cli/command" | ||
"github.com/docker/cli/cli/context/docker" | ||
"github.com/docker/cli/cli/context/store" | ||
"github.com/docker/docker/api/types/container" | ||
"github.com/docker/docker/api/types/mount" | ||
) | ||
|
||
// BindMount | ||
type BindMount struct { | ||
required bool | ||
endpoint string | ||
} | ||
|
||
const defaultSocketPath string = "/var/run/docker.sock" | ||
|
||
func RequiredClaimBindMount(c claim.Claim, targetContextName string, dockerCli command.Cli) (BindMount, error) { | ||
var specifiedOrchestrator string | ||
if rawOrchestrator, ok := c.Parameters[internal.ParameterOrchestratorName]; ok { | ||
specifiedOrchestrator = rawOrchestrator.(string) | ||
} | ||
|
||
return RequiredBindMount(targetContextName, specifiedOrchestrator, dockerCli.ContextStore()) | ||
} | ||
|
||
// RequiredBindMount Returns the path required to bind mount when running | ||
// the invocation image. | ||
func RequiredBindMount(targetContextName string, targetOrchestrator string, s store.Store) (BindMount, error) { | ||
if targetOrchestrator == "kubernetes" { | ||
return BindMount{}, nil | ||
} | ||
|
||
if targetContextName == "" { | ||
targetContextName = "default" | ||
} | ||
|
||
// in case of docker desktop, we want to rewrite the context in cases where it targets the local swarm or Kubernetes | ||
s = &internal.DockerDesktopAwareStore{Store: s} | ||
|
||
ctxMeta, err := s.GetMetadata(targetContextName) | ||
if err != nil { | ||
return BindMount{}, err | ||
} | ||
dockerCtx, err := command.GetDockerContext(ctxMeta) | ||
if err != nil { | ||
return BindMount{}, err | ||
} | ||
if dockerCtx.StackOrchestrator == command.OrchestratorKubernetes { | ||
return BindMount{}, nil | ||
} | ||
dockerEndpoint, err := docker.EndpointFromContext(ctxMeta) | ||
if err != nil { | ||
return BindMount{}, err | ||
} | ||
|
||
host := dockerEndpoint.Host | ||
return BindMount{isDockerHostLocal(host), socketPath(host)}, nil | ||
} | ||
|
||
func socketPath(host string) string { | ||
if strings.HasPrefix(host, "unix://") { | ||
return strings.TrimPrefix(host, "unix://") | ||
} | ||
|
||
return defaultSocketPath | ||
} | ||
|
||
func isDockerHostLocal(host string) bool { | ||
return host == "" || strings.HasPrefix(host, "unix://") || strings.HasPrefix(host, "npipe://") | ||
} | ||
|
||
// PrepareDriver prepares a driver per the user's request. | ||
func PrepareDriver(dockerCli command.Cli, bindMount BindMount, stdout io.Writer) (driver.Driver, *bytes.Buffer) { | ||
d := &dockerDriver.Driver{} | ||
errBuf := bytes.NewBuffer(nil) | ||
d.SetDockerCli(dockerCli) | ||
if stdout != nil { | ||
d.SetContainerOut(stdout) | ||
} | ||
d.SetContainerErr(errBuf) | ||
if bindMount.required { | ||
d.AddConfigurationOptions(func(config *container.Config, hostConfig *container.HostConfig) error { | ||
config.User = "0:0" | ||
mounts := []mount.Mount{ | ||
{ | ||
Type: mount.TypeBind, | ||
Source: bindMount.endpoint, | ||
Target: bindMount.endpoint, | ||
}, | ||
} | ||
hostConfig.Mounts = mounts | ||
return nil | ||
}) | ||
} | ||
|
||
// Load any driver-specific config out of the environment. | ||
driverCfg := map[string]string{} | ||
for env := range d.Config() { | ||
driverCfg[env] = os.Getenv(env) | ||
} | ||
d.SetConfig(driverCfg) | ||
|
||
return d, errBuf | ||
} |
Oops, something went wrong.