basic registry image-index-create command to create multi-architecture images

Signed-off-by: Kyle Quest <kcq.public@gmail.com>
This commit is contained in:
Kyle Quest 2023-11-21 01:46:16 -08:00
parent 13e1e1a972
commit 7ee7762713
22 changed files with 639 additions and 141 deletions

21
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"args": ["registry",
"image-index-create",
"--image-index-name",
"dslim/slim-multi-test:latest",
"--image-name", "dslim/slim-arm:latest",
"--image-name", "dslim/slim:latest" ]
}
]
}

View File

@ -152,7 +152,7 @@ func OnCommand(
imageBuildArch string,
) {
printState := true
logger := log.WithFields(log.Fields{"app": appName, "command": Name})
logger := log.WithFields(log.Fields{"app": appName, "cmd": Name})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -24,7 +24,7 @@ func OnCommand(
gparams *commands.GenericParams,
targetRef string) {
const cmdName = Name
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{"app": appName, "cmd": cmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -24,7 +24,7 @@ func OnCommand(
gparams *commands.GenericParams,
targetRef string) {
const cmdName = Name
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{"app": appName, "cmd": cmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -25,7 +25,7 @@ func OnCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams,
commandParams *CommandParams) {
logger := log.WithFields(log.Fields{"app": appName, "command": Name})
logger := log.WithFields(log.Fields{"app": appName, "cmd": Name})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -24,7 +24,7 @@ func OnCommand(
gparams *commands.GenericParams,
targetRef string) {
const cmdName = Name
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{"app": appName, "cmd": cmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -29,7 +29,7 @@ func OnCommand(
isDSImage bool,
binDir bool,
dockerCLIPlugin bool) {
logger := log.WithFields(log.Fields{"app": "slim", "command": "install"})
logger := log.WithFields(log.Fields{"app": "slim", "cmd": "install"})
appPath, err := os.Executable()
errutil.FailOn(err)

View File

@ -38,7 +38,7 @@ func OnCommand(
doShowSnippet bool,
doListChecks bool) {
const cmdName = Name
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{"app": appName, "cmd": cmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -35,7 +35,7 @@ func OnCommand(
gparams *commands.GenericParams,
cparams *CommandParams) {
const cmdName = Name
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{"app": appName, "cmd": cmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -25,7 +25,7 @@ func OnCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams,
targetRef string) {
logger := log.WithFields(log.Fields{"app": appName, "command": Name})
logger := log.WithFields(log.Fields{"app": appName, "cmd": Name})
cmdName := fmt.Sprintf("cmd=%s", Name)
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -82,7 +82,7 @@ func OnCommand(
logLevel string,
logFormat string) {
printState := true
logger := log.WithFields(log.Fields{"app": appName, "command": Name})
logger := log.WithFields(log.Fields{"app": appName, "cmd": Name})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -0,0 +1,26 @@
package registry
import (
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1/remote"
//log "github.com/sirupsen/logrus"
)
func ConfigureAuth(cparams *CommonCommandParams, remoteOpts []remote.Option) ([]remote.Option, error) {
if cparams.UseDockerCreds {
remoteOpts = append(remoteOpts, remote.WithAuthFromKeychain(authn.DefaultKeychain))
return remoteOpts, nil
}
if cparams.CredsAccount != "" && cparams.CredsSecret != "" {
remoteOpts = append(remoteOpts, remote.WithAuth(&authn.Basic{
Username: cparams.CredsAccount,
Password: cparams.CredsSecret,
}))
return remoteOpts, nil
}
//it's authn.Anonymous by default, but good to be explicit
return append(remoteOpts, remote.WithAuth(authn.Anonymous)), nil
}

View File

@ -16,25 +16,81 @@ const (
PullCmdName = "pull"
PullCmdNameUsage = "Pull a container image from registry"
PushCmdName = "push"
PushCmdNameUsage = "Push a container image to a registry"
CopyCmdName = "copy"
CopyCmdNameUsage = "Copy a container image from one registry to another"
ImageIndexCreateCmdName = "image-index-create"
ImageIndexCreateCmdNameUsage = "Create an image index (aka manifest list) with the referenced images (already in the target registry)"
)
func fullCmdName(subCmdName string) string {
return fmt.Sprintf("%s.%s", Name, subCmdName)
}
type CommonCommandParams struct {
UseDockerCreds bool
CredsAccount string
CredsSecret string
}
func CommonCommandFlagValues(ctx *cli.Context) (*CommonCommandParams, error) {
values := &CommonCommandParams{
UseDockerCreds: ctx.Bool(FlagUseDockerCreds),
CredsAccount: ctx.String(FlagCredsAccount),
//prefer env var for secret (todo: add interactive and file read modes)
CredsSecret: ctx.String(FlagCredsSecret),
}
return values, nil
}
type PullCommandParams struct {
*CommonCommandParams
TargetRef string
SaveToDocker bool
}
func PullCommandFlagValues(ctx *cli.Context) (*PullCommandParams, error) {
common, err := CommonCommandFlagValues(ctx)
if err != nil {
return nil, err
}
values := &PullCommandParams{
TargetRef: ctx.String(commands.FlagTarget),
SaveToDocker: ctx.Bool(FlagSaveToDocker),
CommonCommandParams: common,
TargetRef: ctx.String(commands.FlagTarget),
SaveToDocker: ctx.Bool(FlagSaveToDocker),
}
return values, nil
}
type ImageIndexCreateCommandParams struct {
*CommonCommandParams
ImageIndexName string
ImageNames []string
AsManifestList bool
InsecureRefs bool
DumpRawManifest bool
}
func ImageIndexCreateCommandFlagValues(ctx *cli.Context) (*ImageIndexCreateCommandParams, error) {
common, err := CommonCommandFlagValues(ctx)
if err != nil {
return nil, err
}
values := &ImageIndexCreateCommandParams{
CommonCommandParams: common,
ImageIndexName: ctx.String(FlagImageIndexName),
ImageNames: ctx.StringSlice(FlagImageName),
AsManifestList: ctx.Bool(FlagAsManifestList),
InsecureRefs: ctx.Bool(FlagInsecureRefs),
DumpRawManifest: ctx.Bool(FlagDumpRawManifest),
}
return values, nil
@ -44,6 +100,11 @@ var CLI = &cli.Command{
Name: Name,
Aliases: []string{Alias},
Usage: Usage,
Flags: []cli.Flag{
cflag(FlagUseDockerCreds),
cflag(FlagCredsAccount),
cflag(FlagCredsSecret),
},
Subcommands: []*cli.Command{
{
Name: PullCmdName,
@ -107,5 +168,31 @@ var CLI = &cli.Command{
return nil
},
},
{
Name: ImageIndexCreateCmdName,
Usage: ImageIndexCreateCmdNameUsage,
Flags: []cli.Flag{
cflag(FlagImageIndexName),
cflag(FlagImageName),
cflag(FlagAsManifestList),
cflag(FlagInsecureRefs),
cflag(FlagDumpRawManifest),
},
Action: func(ctx *cli.Context) error {
gcvalues, err := commands.GlobalFlagValues(ctx)
if err != nil {
return err
}
cparams, err := ImageIndexCreateCommandFlagValues(ctx)
if err != nil {
return err
}
xc := app.NewExecutionContext(fullCmdName(ImageIndexCreateCmdName), ctx.String(commands.FlagConsoleFormat))
OnImageIndexCreateCommand(xc, gcvalues, cparams)
return nil
},
},
},
}

View File

@ -7,21 +7,85 @@ import (
// Registry command flag names
const (
FlagSaveToDocker = "save-to-docker"
FlagUseDockerCreds = "use-docker-credentials"
FlagCredsAccount = "account"
FlagCredsSecret = "secret"
FlagSaveToDocker = "save-to-docker"
FlagImageIndexName = "image-index-name"
FlagImageName = "image-name"
FlagAsManifestList = "as-manifest-list"
FlagInsecureRefs = "insecure-refs"
FlagDumpRawManifest = "dump-raw-manifest"
)
// Registry command flag usage info
const (
FlagSaveToDockerUsage = "Save pulled image to docker"
FlagUseDockerCredsUsage = "Use the registry credentials from the default Docker config file"
FlagCredsAccountUsage = "Registry credentials account"
FlagCredsSecretUsage = "Registry credentials secret"
FlagSaveToDockerUsage = "Save pulled image to docker"
FlagImageIndexNameUsage = "Image index name to use"
FlagImageNameUsage = "Target image name to include in image index"
FlagAsManifestListUsage = "Create image index with the manifest list media type instead of the default OCI image index type"
FlagInsecureRefsUsage = "Allow the referenced images from insecure registry connections"
FlagDumpRawManifestUsage = "Dump raw manifest for the created image index"
)
var Flags = map[string]cli.Flag{
FlagUseDockerCreds: &cli.BoolFlag{
Name: FlagUseDockerCreds,
Value: false, //defaults to false
Usage: FlagUseDockerCredsUsage,
EnvVars: []string{"DSLIM_REG_DOCKER_CREDS"},
},
FlagCredsAccount: &cli.StringFlag{
Name: FlagCredsAccount,
Value: "",
Usage: FlagCredsAccountUsage,
EnvVars: []string{"DSLIM_REG_ACCOUNT"},
},
FlagCredsSecret: &cli.StringFlag{
Name: FlagCredsSecret,
Value: "",
Usage: FlagCredsSecretUsage,
EnvVars: []string{"DSLIM_REG_SECRET"},
},
FlagSaveToDocker: &cli.BoolFlag{
Name: FlagSaveToDocker,
Value: true, //defaults to true
Usage: FlagSaveToDockerUsage,
EnvVars: []string{"DSLIM_REG_PULL_SAVE_TO_DOCKER"},
},
FlagImageIndexName: &cli.StringFlag{
Name: FlagImageIndexName,
Value: "",
Usage: FlagImageIndexNameUsage,
EnvVars: []string{"DSLIM_REG_IIC_INDEX_NAME"},
},
FlagImageName: &cli.StringSliceFlag{
Name: FlagImageName,
Value: cli.NewStringSlice(),
Usage: FlagImageNameUsage,
EnvVars: []string{"DSLIM_REG_IIC_IMAGE_NAME"},
},
FlagAsManifestList: &cli.BoolFlag{
Name: FlagAsManifestList,
Value: false, //defaults to false
Usage: FlagAsManifestListUsage,
EnvVars: []string{"DSLIM_REG_IIC_AS_MLIST"},
},
FlagInsecureRefs: &cli.BoolFlag{
Name: FlagInsecureRefs,
Value: false, //defaults to false
Usage: FlagInsecureRefsUsage,
EnvVars: []string{"DSLIM_REG_IIC_INSECURE_REFS"},
},
FlagDumpRawManifest: &cli.BoolFlag{
Name: FlagDumpRawManifest,
Value: false, //defaults to false
Usage: FlagDumpRawManifestUsage,
EnvVars: []string{"DSLIM_REG_IIC_DUMP_MANIFEST"},
},
}
func cflag(name string) cli.Flag {

View File

@ -0,0 +1,79 @@
package registry
import (
//"github.com/google/go-containerregistry/pkg/crane"
//"github.com/google/go-containerregistry/pkg/name"
//gocrv1 "github.com/google/go-containerregistry/pkg/v1"
//"github.com/google/go-containerregistry/pkg/v1/daemon"
log "github.com/sirupsen/logrus"
"github.com/slimtoolkit/slim/pkg/app"
"github.com/slimtoolkit/slim/pkg/app/master/commands"
"github.com/slimtoolkit/slim/pkg/app/master/version"
"github.com/slimtoolkit/slim/pkg/command"
"github.com/slimtoolkit/slim/pkg/docker/dockerclient"
"github.com/slimtoolkit/slim/pkg/report"
"github.com/slimtoolkit/slim/pkg/util/errutil"
"github.com/slimtoolkit/slim/pkg/util/fsutil"
v "github.com/slimtoolkit/slim/pkg/version"
)
// OnCopyCommand implements the 'registry copy' command
func OnCopyCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams) {
cmdName := fullCmdName(CopyCmdName)
logger := log.WithFields(log.Fields{
"app": appName,
"cmd": cmdName,
"sub": CopyCmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)
cmdReport := report.NewRegistryCommand(gparams.ReportLocation, gparams.InContainer)
cmdReport.State = command.StateStarted
xc.Out.State("started")
client, err := dockerclient.New(gparams.ClientConfig)
if err == dockerclient.ErrNoDockerInfo {
exitMsg := "missing Docker connection info"
if gparams.InContainer && gparams.IsDSImage {
exitMsg = "make sure to pass the Docker connect parameters to the docker-slim container"
}
xc.Out.Info("docker.connect.error",
ovars{
"message": exitMsg,
})
exitCode := commands.ECTCommon | commands.ECCNoDockerConnectInfo
xc.Out.State("exited",
ovars{
"exit.code": exitCode,
"version": v.Current(),
"location": fsutil.ExeDir(),
})
xc.Exit(exitCode)
}
errutil.FailOn(err)
if gparams.Debug {
version.Print(xc, cmdName, logger, client, false, gparams.InContainer, gparams.IsDSImage)
}
xc.Out.State("completed")
cmdReport.State = command.StateCompleted
xc.Out.State("done")
vinfo := <-viChan
version.PrintCheckVersion(xc, "", vinfo)
cmdReport.State = command.StateDone
if cmdReport.Save() {
xc.Out.Info("report",
ovars{
"file": cmdReport.ReportLocation(),
})
}
}

View File

@ -0,0 +1,255 @@
package registry
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
"github.com/google/go-containerregistry/pkg/v1/types"
log "github.com/sirupsen/logrus"
"github.com/slimtoolkit/slim/pkg/app"
"github.com/slimtoolkit/slim/pkg/app/master/commands"
"github.com/slimtoolkit/slim/pkg/app/master/version"
"github.com/slimtoolkit/slim/pkg/command"
"github.com/slimtoolkit/slim/pkg/docker/dockerclient"
"github.com/slimtoolkit/slim/pkg/report"
"github.com/slimtoolkit/slim/pkg/util/fsutil"
v "github.com/slimtoolkit/slim/pkg/version"
)
// OnImageIndexCreateCommand implements the 'registry image-index-create' command
func OnImageIndexCreateCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams,
cparams *ImageIndexCreateCommandParams) {
cmdName := fullCmdName(CopyCmdName)
logger := log.WithFields(log.Fields{
"app": appName,
"cmd": cmdName,
"sub": ImageIndexCreateCmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)
cmdReport := report.NewRegistryCommand(gparams.ReportLocation, gparams.InContainer)
cmdReport.State = command.StateStarted
xc.Out.State("started")
client, err := dockerclient.New(gparams.ClientConfig)
if err == dockerclient.ErrNoDockerInfo {
exitMsg := "missing Docker connection info"
if gparams.InContainer && gparams.IsDSImage {
exitMsg = "make sure to pass the Docker connect parameters to the docker-slim container"
}
xc.Out.Info("docker.connect.error",
ovars{
"message": exitMsg,
})
exitCode := commands.ECTCommon | commands.ECCNoDockerConnectInfo
xc.Out.State("exited",
ovars{
"exit.code": exitCode,
"version": v.Current(),
"location": fsutil.ExeDir(),
})
xc.Exit(exitCode)
}
xc.FailOn(err)
if gparams.Debug {
version.Print(xc, cmdName, logger, client, false, gparams.InContainer, gparams.IsDSImage)
}
//========================================
if len(cparams.ImageNames) == 0 {
xc.FailOn(fmt.Errorf("no image references for image index"))
}
if !cparams.UseDockerCreds &&
!(cparams.CredsAccount != "" && cparams.CredsSecret != "") {
xc.FailOn(fmt.Errorf("missing auth params"))
}
remoteOpts := []remote.Option{
remote.WithContext(context.Background()),
}
remoteOpts, err = ConfigureAuth(cparams.CommonCommandParams, remoteOpts)
xc.FailOn(err)
nameOpts := []name.Option{
name.WeakValidation,
}
if cparams.InsecureRefs {
nameOpts = append(nameOpts, name.Insecure)
}
imageIndexRef, err := name.ParseReference(cparams.ImageIndexName, nameOpts...)
if err != nil {
xc.FailOn(fmt.Errorf("malformed image index reference - %s (%v)", cparams.ImageIndexName, err))
}
if _, err := remote.Head(imageIndexRef, remoteOpts...); err != nil {
if _, ok := err.(*transport.Error); ok {
logger.Debug("no image index in registry (ok)")
} else {
logger.Debugf("error checking image index in registry - %v", err)
}
} else {
logger.Debug("image index is already in the registry")
}
imageIndex := v1.ImageIndex(empty.Index)
indexImageImgRefs := make([]mutate.IndexAddendum, 0, len(cparams.ImageNames))
for _, imageName := range cparams.ImageNames {
imgRef, err := name.ParseReference(imageName, nameOpts...)
if err != nil {
xc.FailOn(fmt.Errorf("malformed image reference - %s (%v)", imageName, err))
}
meta, err := remote.Get(imgRef, remoteOpts...)
if err != nil {
xc.FailOn(fmt.Errorf("image reference metadata get error - %s (%v)", imageName, err))
}
if meta.MediaType.IsImage() {
imgMeta, err := meta.Image()
xc.FailOn(err)
basicImageInfo(xc, imgMeta)
imgConfig, err := imgMeta.ConfigFile()
if err != nil {
xc.FailOn(err)
}
imgRefMeta, err := partial.Descriptor(imgMeta)
if err != nil {
xc.FailOn(err)
}
imgRefMeta.Platform = imgConfig.Platform()
indexImageImgRefs = append(indexImageImgRefs,
mutate.IndexAddendum{
Add: imgMeta,
Descriptor: *imgRefMeta,
})
} else {
xc.FailOn(fmt.Errorf("unexpected target image type - %s (%v)", imageName, meta.MediaType))
}
}
if cparams.AsManifestList {
imageIndex = mutate.IndexMediaType(imageIndex, types.DockerManifestList)
}
imageIndex = mutate.AppendManifests(imageIndex, indexImageImgRefs...)
if err := remote.WriteIndex(imageIndexRef, imageIndex, remoteOpts...); err != nil {
var terr *transport.Error
if errors.As(err, &terr) && terr.StatusCode == http.StatusUnauthorized {
xc.Out.Info("registry.auth.error",
ovars{
"message": "need to authenticate",
})
exitCode := -111
xc.Out.State("exited",
ovars{
"exit.code": exitCode,
"version": v.Current(),
})
xc.Exit(exitCode)
} else {
xc.FailOn(fmt.Errorf("saving image index error - %s (%v)", cparams.ImageIndexName, err))
}
}
indexMeta, err := remote.Index(imageIndexRef, remoteOpts...)
if err != nil {
xc.FailOn(fmt.Errorf("index reference metadata get error - %s (%v)", cparams.ImageIndexName, err))
}
indexMediaType, err := indexMeta.MediaType()
xc.FailOn(err)
if !indexMediaType.IsIndex() {
xc.FailOn(fmt.Errorf("unexpected media type for index"))
}
indexDigest, err := indexMeta.Digest()
xc.FailOn(err)
indexManifest, err := indexMeta.IndexManifest()
xc.FailOn(err)
xc.Out.Info("index.info",
ovars{
"reference": imageIndexRef,
"digest": indexDigest.String(),
"manifest.schema": indexManifest.SchemaVersion,
"manifest.media_type": indexManifest.MediaType,
"manifest.image.ref.count": len(indexManifest.Manifests),
})
if cparams.DumpRawManifest {
if rm, err := indexMeta.RawManifest(); err == nil {
//todo: reformat to pretty print
fmt.Printf("\n\n%s\n\n", string(rm))
}
}
xc.Out.State("completed")
cmdReport.State = command.StateCompleted
xc.Out.State("done")
vinfo := <-viChan
version.PrintCheckVersion(xc, "", vinfo)
cmdReport.State = command.StateDone
if cmdReport.Save() {
xc.Out.Info("report",
ovars{
"file": cmdReport.ReportLocation(),
})
}
}
func basicImageInfo(
xc *app.ExecutionContext,
targetImage v1.Image) {
cn, err := targetImage.ConfigName()
xc.FailOn(err)
d, err := targetImage.Digest()
xc.FailOn(err)
cf, err := targetImage.ConfigFile()
xc.FailOn(err)
m, err := targetImage.Manifest()
xc.FailOn(err)
xc.Out.Info("image.info",
ovars{
"id": fmt.Sprintf("%s:%s", cn.Algorithm, cn.Hex),
"digest": fmt.Sprintf("%s:%s", d.Algorithm, d.Hex),
"architecture": cf.Architecture,
"os": cf.OS,
"manifest.schema": m.SchemaVersion,
"manifest.media_type": m.MediaType,
"manifest.config.media_type": m.Config.MediaType,
"manifest.config.size": fmt.Sprintf("%v", m.Config.Size),
"manifest.config.digest": fmt.Sprintf("%s:%s", m.Config.Digest.Algorithm, m.Config.Digest.Hex),
"manifest.layers.count": fmt.Sprintf("%v", len(m.Layers)),
})
}

View File

@ -5,7 +5,7 @@ import (
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
gocrv1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/daemon"
log "github.com/sirupsen/logrus"
@ -30,7 +30,10 @@ func OnPullCommand(
gparams *commands.GenericParams,
cparams *PullCommandParams) {
cmdName := fullCmdName(PullCmdName)
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{
"app": appName,
"cmd": cmdName,
"sub": PullCmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)
@ -105,136 +108,20 @@ func OnPullCommand(
}
}
// OnPushCommand implements the 'registry push' docker-slim command
func OnPushCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams) {
cmdName := fullCmdName(PushCmdName)
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
Name := fmt.Sprintf("cmd=%s", cmdName)
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)
cmdReport := report.NewRegistryCommand(gparams.ReportLocation, gparams.InContainer)
cmdReport.State = command.StateStarted
xc.Out.State("started")
client, err := dockerclient.New(gparams.ClientConfig)
if err == dockerclient.ErrNoDockerInfo {
exitMsg := "missing Docker connection info"
if gparams.InContainer && gparams.IsDSImage {
exitMsg = "make sure to pass the Docker connect parameters to the docker-slim container"
}
xc.Out.Info("docker.connect.error",
ovars{
"message": exitMsg,
})
exitCode := commands.ECTCommon | commands.ECCNoDockerConnectInfo
xc.Out.State("exited",
ovars{
"exit.code": exitCode,
"version": v.Current(),
"location": fsutil.ExeDir(),
})
xc.Exit(exitCode)
}
errutil.FailOn(err)
if gparams.Debug {
version.Print(xc, Name, logger, client, false, gparams.InContainer, gparams.IsDSImage)
}
xc.Out.State("completed")
cmdReport.State = command.StateCompleted
xc.Out.State("done")
vinfo := <-viChan
version.PrintCheckVersion(xc, "", vinfo)
cmdReport.State = command.StateDone
if cmdReport.Save() {
xc.Out.Info("report",
ovars{
"file": cmdReport.ReportLocation(),
})
}
}
// OnCopyCommand implements the 'registry copy' docker-slim command
func OnCopyCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams) {
cmdName := fullCmdName(CopyCmdName)
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
Name := fmt.Sprintf("cmd=%s", cmdName)
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)
cmdReport := report.NewRegistryCommand(gparams.ReportLocation, gparams.InContainer)
cmdReport.State = command.StateStarted
xc.Out.State("started")
client, err := dockerclient.New(gparams.ClientConfig)
if err == dockerclient.ErrNoDockerInfo {
exitMsg := "missing Docker connection info"
if gparams.InContainer && gparams.IsDSImage {
exitMsg = "make sure to pass the Docker connect parameters to the docker-slim container"
}
xc.Out.Info("docker.connect.error",
ovars{
"message": exitMsg,
})
exitCode := commands.ECTCommon | commands.ECCNoDockerConnectInfo
xc.Out.State("exited",
ovars{
"exit.code": exitCode,
"version": v.Current(),
"location": fsutil.ExeDir(),
})
xc.Exit(exitCode)
}
errutil.FailOn(err)
if gparams.Debug {
version.Print(xc, Name, logger, client, false, gparams.InContainer, gparams.IsDSImage)
}
xc.Out.State("completed")
cmdReport.State = command.StateCompleted
xc.Out.State("done")
vinfo := <-viChan
version.PrintCheckVersion(xc, "", vinfo)
cmdReport.State = command.StateDone
if cmdReport.Save() {
xc.Out.Info("report",
ovars{
"file": cmdReport.ReportLocation(),
})
}
}
func outImageInfo(
xc *app.ExecutionContext,
targetImage gocrv1.Image) {
targetImage v1.Image) {
cn, err := targetImage.ConfigName()
errutil.FailOn(err)
xc.FailOn(err)
d, err := targetImage.Digest()
errutil.FailOn(err)
xc.FailOn(err)
cf, err := targetImage.ConfigFile()
errutil.FailOn(err)
xc.FailOn(err)
m, err := targetImage.Manifest()
errutil.FailOn(err)
xc.FailOn(err)
xc.Out.Info("image.info",
ovars{

View File

@ -0,0 +1,79 @@
package registry
import (
//"github.com/google/go-containerregistry/pkg/crane"
//"github.com/google/go-containerregistry/pkg/name"
//gocrv1 "github.com/google/go-containerregistry/pkg/v1"
//"github.com/google/go-containerregistry/pkg/v1/daemon"
log "github.com/sirupsen/logrus"
"github.com/slimtoolkit/slim/pkg/app"
"github.com/slimtoolkit/slim/pkg/app/master/commands"
"github.com/slimtoolkit/slim/pkg/app/master/version"
"github.com/slimtoolkit/slim/pkg/command"
"github.com/slimtoolkit/slim/pkg/docker/dockerclient"
"github.com/slimtoolkit/slim/pkg/report"
"github.com/slimtoolkit/slim/pkg/util/errutil"
"github.com/slimtoolkit/slim/pkg/util/fsutil"
v "github.com/slimtoolkit/slim/pkg/version"
)
// OnPushCommand implements the 'registry push' command
func OnPushCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams) {
cmdName := fullCmdName(PushCmdName)
logger := log.WithFields(log.Fields{
"app": appName,
"cmd": cmdName,
"sub": PushCmdName})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)
cmdReport := report.NewRegistryCommand(gparams.ReportLocation, gparams.InContainer)
cmdReport.State = command.StateStarted
xc.Out.State("started")
client, err := dockerclient.New(gparams.ClientConfig)
if err == dockerclient.ErrNoDockerInfo {
exitMsg := "missing Docker connection info"
if gparams.InContainer && gparams.IsDSImage {
exitMsg = "make sure to pass the Docker connect parameters to the docker-slim container"
}
xc.Out.Info("docker.connect.error",
ovars{
"message": exitMsg,
})
exitCode := commands.ECTCommon | commands.ECCNoDockerConnectInfo
xc.Out.State("exited",
ovars{
"exit.code": exitCode,
"version": v.Current(),
"location": fsutil.ExeDir(),
})
xc.Exit(exitCode)
}
errutil.FailOn(err)
if gparams.Debug {
version.Print(xc, cmdName, logger, client, false, gparams.InContainer, gparams.IsDSImage)
}
xc.Out.State("completed")
cmdReport.State = command.StateCompleted
xc.Out.State("done")
vinfo := <-viChan
version.PrintCheckVersion(xc, "", vinfo)
cmdReport.State = command.StateDone
if cmdReport.Save() {
xc.Out.Info("report",
ovars{
"file": cmdReport.ReportLocation(),
})
}
}

View File

@ -34,7 +34,7 @@ func OnCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams,
cparams *CommandParams) {
logger := log.WithFields(log.Fields{"app": appName, "command": Name})
logger := log.WithFields(log.Fields{"app": appName, "cmd": Name})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -22,7 +22,7 @@ type ovars = app.OutVars
func OnCommand(
xc *app.ExecutionContext,
gparams *commands.GenericParams) {
logger := log.WithFields(log.Fields{"app": appName, "command": Name})
logger := log.WithFields(log.Fields{"app": appName, "cmd": Name})
viChan := version.CheckAsync(gparams.CheckVersion, gparams.InContainer, gparams.IsDSImage)

View File

@ -21,7 +21,7 @@ func OnCommand(
xc *app.ExecutionContext,
doDebug, inContainer, isDSImage bool,
clientConfig *config.DockerClient) {
logger := log.WithFields(log.Fields{"app": "slim", "command": command.Version})
logger := log.WithFields(log.Fields{"app": "slim", "cmd": command.Version})
client, err := dockerclient.New(clientConfig)
if err == dockerclient.ErrNoDockerInfo {

View File

@ -83,7 +83,7 @@ func OnCommand(
xdArtifactsPath string,
) {
const cmdName = Name
logger := log.WithFields(log.Fields{"app": appName, "command": cmdName})
logger := log.WithFields(log.Fields{"app": appName, "cmd": cmdName})
changeDataMatchers := map[string]*dockerimage.ChangeDataMatcher{}
for _, cdm := range changeDataMatcherList {