mirror of
https://github.com/docker/cli.git
synced 2026-08-28 02:24:15 -05:00
Compare commits
49
Commits
@@ -63,7 +63,7 @@ jobs:
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.3
|
||||
go-version: 1.20.4
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG XX_VERSION=1.1.1
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
|
||||
@@ -23,6 +23,7 @@ type Metadata struct {
|
||||
// URL is a pointer to the plugin's homepage.
|
||||
URL string `json:",omitempty"`
|
||||
// Experimental specifies whether the plugin is experimental.
|
||||
//
|
||||
// Deprecated: experimental features are now always enabled in the CLI
|
||||
Experimental bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package container
|
||||
import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -23,7 +22,7 @@ func NewDiffFormat(source string) formatter.Format {
|
||||
}
|
||||
|
||||
// DiffFormatWrite writes formatted diff using the Context
|
||||
func DiffFormatWrite(ctx formatter.Context, changes []container.ContainerChangeResponseItem) error {
|
||||
func DiffFormatWrite(ctx formatter.Context, changes []container.FilesystemChange) error {
|
||||
render := func(format func(subContext formatter.SubContext) error) error {
|
||||
for _, change := range changes {
|
||||
if err := format(&diffContext{c: change}); err != nil {
|
||||
@@ -37,7 +36,7 @@ func DiffFormatWrite(ctx formatter.Context, changes []container.ContainerChangeR
|
||||
|
||||
type diffContext struct {
|
||||
formatter.HeaderContext
|
||||
c container.ContainerChangeResponseItem
|
||||
c container.FilesystemChange
|
||||
}
|
||||
|
||||
func newDiffContext() *diffContext {
|
||||
@@ -54,16 +53,7 @@ func (d *diffContext) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (d *diffContext) Type() string {
|
||||
var kind string
|
||||
switch d.c.Kind {
|
||||
case archive.ChangeModify:
|
||||
kind = "C"
|
||||
case archive.ChangeAdd:
|
||||
kind = "A"
|
||||
case archive.ChangeDelete:
|
||||
kind = "D"
|
||||
}
|
||||
return kind
|
||||
return d.c.Kind.String()
|
||||
}
|
||||
|
||||
func (d *diffContext) Path() string {
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
@@ -41,10 +40,10 @@ D: /usr/app/old_app.js
|
||||
},
|
||||
}
|
||||
|
||||
diffs := []container.ContainerChangeResponseItem{
|
||||
{Kind: archive.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: archive.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: archive.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
diffs := []container.FilesystemChange{
|
||||
{Kind: container.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: container.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -123,6 +123,7 @@ type containerOptions struct {
|
||||
runtime string
|
||||
autoRemove bool
|
||||
init bool
|
||||
annotations *opts.MapOpts
|
||||
|
||||
Image string
|
||||
Args []string
|
||||
@@ -163,6 +164,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
ulimits: opts.NewUlimitOpt(nil),
|
||||
volumes: opts.NewListOpts(nil),
|
||||
volumesFrom: opts.NewListOpts(nil),
|
||||
annotations: opts.NewMapOpts(nil, nil),
|
||||
}
|
||||
|
||||
// General purpose flags
|
||||
@@ -297,6 +299,10 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
|
||||
flags.BoolVar(&copts.init, "init", false, "Run an init inside the container that forwards signals and reaps processes")
|
||||
flags.SetAnnotation("init", "version", []string{"1.25"})
|
||||
|
||||
flags.Var(copts.annotations, "annotation", "Add an annotation to the container (passed through to the OCI runtime)")
|
||||
flags.SetAnnotation("annotation", "version", []string{"1.43"})
|
||||
|
||||
return copts
|
||||
}
|
||||
|
||||
@@ -654,6 +660,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
||||
Mounts: mounts,
|
||||
MaskedPaths: maskedPaths,
|
||||
ReadonlyPaths: readonlyPaths,
|
||||
Annotations: copts.annotations.GetAll(),
|
||||
}
|
||||
|
||||
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.VirtualSize}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
|
||||
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
|
||||
defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
|
||||
defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
|
||||
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
|
||||
@@ -296,10 +296,10 @@ func (c *diskUsageImagesContext) Reclaimable() string {
|
||||
|
||||
for _, i := range c.images {
|
||||
if i.Containers != 0 {
|
||||
if i.VirtualSize == -1 || i.SharedSize == -1 {
|
||||
if i.Size == -1 || i.SharedSize == -1 {
|
||||
continue
|
||||
}
|
||||
used += i.VirtualSize - i.SharedSize
|
||||
used += i.Size - i.SharedSize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ func newImageContext() *imageContext {
|
||||
"CreatedAt": CreatedAtHeader,
|
||||
"Size": SizeHeader,
|
||||
"Containers": containersHeader,
|
||||
"VirtualSize": SizeHeader,
|
||||
"VirtualSize": SizeHeader, // Deprecated: VirtualSize is deprecated, and equivalent to Size.
|
||||
"SharedSize": sharedSizeHeader,
|
||||
"UniqueSize": uniqueSizeHeader,
|
||||
}
|
||||
@@ -260,8 +260,13 @@ func (c *imageContext) Containers() string {
|
||||
return fmt.Sprintf("%d", c.i.Containers)
|
||||
}
|
||||
|
||||
// VirtualSize shows the virtual size of the image and all of its parent
|
||||
// images. Starting with docker 1.10, images are self-contained, and
|
||||
// the VirtualSize is identical to Size.
|
||||
//
|
||||
// Deprecated: VirtualSize is deprecated, and equivalent to [imageContext.Size].
|
||||
func (c *imageContext) VirtualSize() string {
|
||||
return units.HumanSize(float64(c.i.VirtualSize))
|
||||
return units.HumanSize(float64(c.i.Size))
|
||||
}
|
||||
|
||||
func (c *imageContext) SharedSize() string {
|
||||
@@ -272,8 +277,8 @@ func (c *imageContext) SharedSize() string {
|
||||
}
|
||||
|
||||
func (c *imageContext) UniqueSize() string {
|
||||
if c.i.VirtualSize == -1 || c.i.SharedSize == -1 {
|
||||
if c.i.Size == -1 || c.i.SharedSize == -1 {
|
||||
return "N/A"
|
||||
}
|
||||
return units.HumanSize(float64(c.i.VirtualSize - c.i.SharedSize))
|
||||
return units.HumanSize(float64(c.i.Size - c.i.SharedSize))
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.ID,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10, VirtualSize: 10}, trunc: true},
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10}, trunc: true},
|
||||
expValue: "10B",
|
||||
call: ctx.Size,
|
||||
},
|
||||
@@ -70,9 +70,9 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.Containers,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{VirtualSize: 10000}},
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10000}},
|
||||
expValue: "10kB",
|
||||
call: ctx.VirtualSize,
|
||||
call: ctx.VirtualSize, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 10000}},
|
||||
@@ -80,7 +80,7 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.SharedSize,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000}},
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, Size: 20000}},
|
||||
expValue: "15kB",
|
||||
call: ctx.UniqueSize,
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
|
||||
dockerfile := bytes.NewBufferString(`
|
||||
FROM alpine:3.6
|
||||
FROM alpine:frozen
|
||||
COPY foo /
|
||||
`)
|
||||
cli.SetIn(streams.NewIn(io.NopCloser(dockerfile)))
|
||||
@@ -66,7 +66,7 @@ func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
|
||||
dir := fs.NewDir(t, "test-build-context",
|
||||
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
|
||||
fs.WithFile("Dockerfile", `
|
||||
FROM alpine:3.6
|
||||
FROM alpine:frozen
|
||||
COPY foo bar /
|
||||
`),
|
||||
)
|
||||
@@ -155,7 +155,7 @@ func TestRunBuildFromLocalGitHubDir(t *testing.T) {
|
||||
func TestRunBuildWithSymlinkedContext(t *testing.T) {
|
||||
t.Setenv("DOCKER_BUILDKIT", "0")
|
||||
dockerfile := `
|
||||
FROM alpine:3.6
|
||||
FROM alpine:frozen
|
||||
RUN echo hello world
|
||||
`
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
@@ -39,7 +38,6 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
|
||||
+148
-140
@@ -108,7 +108,7 @@ func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error
|
||||
} else {
|
||||
// if a format is provided, print the error, as it may be hidden
|
||||
// otherwise if the template doesn't include the ServerErrors field.
|
||||
fmt.Fprintln(dockerCli.Err(), err)
|
||||
fprintln(dockerCli.Err(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error
|
||||
info.ClientInfo.APIVersion = dockerCli.CurrentVersion()
|
||||
return prettyPrintInfo(dockerCli, info)
|
||||
}
|
||||
return formatInfo(dockerCli, info, opts.format)
|
||||
return formatInfo(dockerCli.Out(), info, opts.format)
|
||||
}
|
||||
|
||||
// placeHolders does a rudimentary match for possible placeholders in a
|
||||
@@ -160,29 +160,29 @@ func needsServerInfo(template string, info info) bool {
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
func prettyPrintInfo(streams command.Streams, info info) error {
|
||||
// Only append the platform info if it's not empty, to prevent printing a trailing space.
|
||||
if p := info.clientPlatform(); p != "" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:", p)
|
||||
fprintln(streams.Out(), "Client:", p)
|
||||
} else {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
fprintln(streams.Out(), "Client:")
|
||||
}
|
||||
if info.ClientInfo != nil {
|
||||
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
|
||||
prettyPrintClientInfo(streams, *info.ClientInfo)
|
||||
}
|
||||
for _, err := range info.ClientErrors {
|
||||
fmt.Fprintln(dockerCli.Err(), "ERROR:", err)
|
||||
fprintln(streams.Err(), "ERROR:", err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out())
|
||||
fmt.Fprintln(dockerCli.Out(), "Server:")
|
||||
fprintln(streams.Out())
|
||||
fprintln(streams.Out(), "Server:")
|
||||
if info.Info != nil {
|
||||
for _, err := range prettyPrintServerInfo(dockerCli, &info) {
|
||||
for _, err := range prettyPrintServerInfo(streams, &info) {
|
||||
info.ServerErrors = append(info.ServerErrors, err.Error())
|
||||
}
|
||||
}
|
||||
for _, err := range info.ServerErrors {
|
||||
fmt.Fprintln(dockerCli.Err(), "ERROR:", err)
|
||||
fprintln(streams.Err(), "ERROR:", err)
|
||||
}
|
||||
|
||||
if len(info.ServerErrors) > 0 || len(info.ClientErrors) > 0 {
|
||||
@@ -191,18 +191,18 @@ func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", info.Version)
|
||||
fmt.Fprintln(dockerCli.Out(), " Context: ", info.Context)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
func prettyPrintClientInfo(streams command.Streams, info clientInfo) {
|
||||
fprintlnNonEmpty(streams.Out(), " Version: ", info.Version)
|
||||
fprintln(streams.Out(), " Context: ", info.Context)
|
||||
fprintln(streams.Out(), " Debug Mode:", info.Debug)
|
||||
|
||||
if len(info.Plugins) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Plugins:")
|
||||
fprintln(streams.Out(), " Plugins:")
|
||||
for _, p := range info.Plugins {
|
||||
if p.Err == nil {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s (%s)\n", p.Name, p.ShortDescription, p.Vendor)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", p.Version)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Path: ", p.Path)
|
||||
fprintf(streams.Out(), " %s: %s (%s)\n", p.Name, p.ShortDescription, p.Vendor)
|
||||
fprintlnNonEmpty(streams.Out(), " Version: ", p.Version)
|
||||
fprintlnNonEmpty(streams.Out(), " Path: ", p.Path)
|
||||
} else {
|
||||
info.Warnings = append(info.Warnings, fmt.Sprintf("WARNING: Plugin %q is not valid: %s", p.Path, p.Err))
|
||||
}
|
||||
@@ -210,59 +210,60 @@ func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
}
|
||||
|
||||
if len(info.Warnings) > 0 {
|
||||
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
|
||||
fprintln(streams.Err(), strings.Join(info.Warnings, "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func prettyPrintServerInfo(dockerCli command.Cli, info *info) []error {
|
||||
func prettyPrintServerInfo(streams command.Streams, info *info) []error {
|
||||
var errs []error
|
||||
output := streams.Out()
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Containers:", info.Containers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Running:", info.ContainersRunning)
|
||||
fmt.Fprintln(dockerCli.Out(), " Paused:", info.ContainersPaused)
|
||||
fmt.Fprintln(dockerCli.Out(), " Stopped:", info.ContainersStopped)
|
||||
fmt.Fprintln(dockerCli.Out(), " Images:", info.Images)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Storage Driver:", info.Driver)
|
||||
fprintln(output, " Containers:", info.Containers)
|
||||
fprintln(output, " Running:", info.ContainersRunning)
|
||||
fprintln(output, " Paused:", info.ContainersPaused)
|
||||
fprintln(output, " Stopped:", info.ContainersStopped)
|
||||
fprintln(output, " Images:", info.Images)
|
||||
fprintlnNonEmpty(output, " Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(output, " Storage Driver:", info.Driver)
|
||||
if info.DriverStatus != nil {
|
||||
for _, pair := range info.DriverStatus {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
fprintf(output, " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
if info.SystemStatus != nil {
|
||||
for _, pair := range info.SystemStatus {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
fprintf(output, " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Cgroup Driver:", info.CgroupDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Cgroup Version:", info.CgroupVersion)
|
||||
fprintlnNonEmpty(output, " Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(output, " Cgroup Driver:", info.CgroupDriver)
|
||||
fprintlnNonEmpty(output, " Cgroup Version:", info.CgroupVersion)
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Plugins:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
fprintln(output, " Plugins:")
|
||||
fprintln(output, " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fprintln(output, " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
|
||||
if len(info.Plugins.Authorization) != 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
fprintln(output, " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
fprintln(output, " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(dockerCli, *info.Info)
|
||||
fprintln(output, " Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(output, *info.Info)
|
||||
|
||||
if len(info.Runtimes) > 0 {
|
||||
fmt.Fprint(dockerCli.Out(), " Runtimes:")
|
||||
names := make([]string, 0, len(info.Runtimes))
|
||||
for name := range info.Runtimes {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", name)
|
||||
names = append(names, name)
|
||||
}
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Runtime:", info.DefaultRuntime)
|
||||
fprintln(output, " Runtimes:", strings.Join(names, " "))
|
||||
fprintln(output, " Default Runtime:", info.DefaultRuntime)
|
||||
}
|
||||
|
||||
if info.OSType == "linux" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Init Binary:", info.InitBinary)
|
||||
fprintln(output, " Init Binary:", info.InitBinary)
|
||||
|
||||
for _, ci := range []struct {
|
||||
Name string
|
||||
@@ -272,23 +273,23 @@ func prettyPrintServerInfo(dockerCli command.Cli, info *info) []error {
|
||||
{"runc", info.RuncCommit},
|
||||
{"init", info.InitCommit},
|
||||
} {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s version: %s", ci.Name, ci.Commit.ID)
|
||||
fprintf(output, " %s version: %s", ci.Name, ci.Commit.ID)
|
||||
if ci.Commit.ID != ci.Commit.Expected {
|
||||
fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected)
|
||||
fprintf(output, " (expected: %s)", ci.Commit.Expected)
|
||||
}
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
fprintln(output)
|
||||
}
|
||||
if len(info.SecurityOptions) != 0 {
|
||||
if kvs, err := types.DecodeSecurityOptions(info.SecurityOptions); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
fmt.Fprintln(dockerCli.Out(), " Security Options:")
|
||||
fprintln(output, " Security Options:")
|
||||
for _, so := range kvs {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+so.Name)
|
||||
fprintln(output, " "+so.Name)
|
||||
for _, o := range so.Options {
|
||||
switch o.Key {
|
||||
case "profile":
|
||||
fmt.Fprintln(dockerCli.Out(), " Profile:", o.Value)
|
||||
fprintln(output, " Profile:", o.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,159 +299,158 @@ func prettyPrintServerInfo(dockerCli command.Cli, info *info) []error {
|
||||
|
||||
// Isolation only has meaning on a Windows daemon.
|
||||
if info.OSType == "windows" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Isolation:", info.Isolation)
|
||||
fprintln(output, " Default Isolation:", info.Isolation)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " OSType:", info.OSType)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Architecture:", info.Architecture)
|
||||
fmt.Fprintln(dockerCli.Out(), " CPUs:", info.NCPU)
|
||||
fmt.Fprintln(dockerCli.Out(), " Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Name:", info.Name)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " ID:", info.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Docker Root Dir:", info.DockerRootDir)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
fprintlnNonEmpty(output, " Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(output, " Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(output, " OSType:", info.OSType)
|
||||
fprintlnNonEmpty(output, " Architecture:", info.Architecture)
|
||||
fprintln(output, " CPUs:", info.NCPU)
|
||||
fprintln(output, " Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(output, " Name:", info.Name)
|
||||
fprintlnNonEmpty(output, " ID:", info.ID)
|
||||
fprintln(output, " Docker Root Dir:", info.DockerRootDir)
|
||||
fprintln(output, " Debug Mode:", info.Debug)
|
||||
|
||||
if info.Debug {
|
||||
fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd)
|
||||
fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines)
|
||||
fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime)
|
||||
fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener)
|
||||
fprintln(output, " File Descriptors:", info.NFd)
|
||||
fprintln(output, " Goroutines:", info.NGoroutines)
|
||||
fprintln(output, " System Time:", info.SystemTime)
|
||||
fprintln(output, " EventsListeners:", info.NEventsListener)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(dockerCli.Out(), " HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " No Proxy:", info.NoProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Username:", info.UserName)
|
||||
fprintlnNonEmpty(output, " HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(output, " HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(output, " No Proxy:", info.NoProxy)
|
||||
fprintlnNonEmpty(output, " Username:", info.UserName)
|
||||
if len(info.Labels) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Labels:")
|
||||
fprintln(output, " Labels:")
|
||||
for _, lbl := range info.Labels {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+lbl)
|
||||
fprintln(output, " "+lbl)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Experimental:", info.ExperimentalBuild)
|
||||
fprintln(output, " Experimental:", info.ExperimentalBuild)
|
||||
|
||||
if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) {
|
||||
fmt.Fprintln(dockerCli.Out(), " Insecure Registries:")
|
||||
for _, registry := range info.RegistryConfig.IndexConfigs {
|
||||
if !registry.Secure {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+registry.Name)
|
||||
fprintln(output, " Insecure Registries:")
|
||||
for _, registryConfig := range info.RegistryConfig.IndexConfigs {
|
||||
if !registryConfig.Secure {
|
||||
fprintln(output, " "+registryConfig.Name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs {
|
||||
mask, _ := registry.Mask.Size()
|
||||
fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask)
|
||||
for _, registryConfig := range info.RegistryConfig.InsecureRegistryCIDRs {
|
||||
mask, _ := registryConfig.Mask.Size()
|
||||
fprintf(output, " %s/%d\n", registryConfig.IP.String(), mask)
|
||||
}
|
||||
}
|
||||
|
||||
if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Registry Mirrors:")
|
||||
fprintln(output, " Registry Mirrors:")
|
||||
for _, mirror := range info.RegistryConfig.Mirrors {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+mirror)
|
||||
fprintln(output, " "+mirror)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), " Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
fprintln(output, " Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
if info.ProductLicense != "" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Product License:", info.ProductLicense)
|
||||
fprintln(output, " Product License:", info.ProductLicense)
|
||||
}
|
||||
|
||||
if info.DefaultAddressPools != nil && len(info.DefaultAddressPools) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Address Pools:")
|
||||
fprintln(output, " Default Address Pools:")
|
||||
for _, pool := range info.DefaultAddressPools {
|
||||
fmt.Fprintf(dockerCli.Out(), " Base: %s, Size: %d\n", pool.Base, pool.Size)
|
||||
fprintf(output, " Base: %s, Size: %d\n", pool.Base, pool.Size)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
|
||||
printServerWarnings(dockerCli, info)
|
||||
fprintln(output)
|
||||
printServerWarnings(streams.Err(), info)
|
||||
return errs
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func printSwarmInfo(dockerCli command.Cli, info types.Info) {
|
||||
func printSwarmInfo(output io.Writer, info types.Info) {
|
||||
if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " NodeID:", info.Swarm.NodeID)
|
||||
fprintln(output, " NodeID:", info.Swarm.NodeID)
|
||||
if info.Swarm.Error != "" {
|
||||
fmt.Fprintln(dockerCli.Out(), " Error:", info.Swarm.Error)
|
||||
fprintln(output, " Error:", info.Swarm.Error)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Is Manager:", info.Swarm.ControlAvailable)
|
||||
fprintln(output, " Is Manager:", info.Swarm.ControlAvailable)
|
||||
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
|
||||
fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes)
|
||||
fprintln(output, " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fprintln(output, " Managers:", info.Swarm.Managers)
|
||||
fprintln(output, " Nodes:", info.Swarm.Nodes)
|
||||
var strAddrPool strings.Builder
|
||||
if info.Swarm.Cluster.DefaultAddrPool != nil {
|
||||
for _, p := range info.Swarm.Cluster.DefaultAddrPool {
|
||||
strAddrPool.WriteString(p + " ")
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Address Pool:", strAddrPool.String())
|
||||
fmt.Fprintln(dockerCli.Out(), " SubnetSize:", info.Swarm.Cluster.SubnetSize)
|
||||
fprintln(output, " Default Address Pool:", strAddrPool.String())
|
||||
fprintln(output, " SubnetSize:", info.Swarm.Cluster.SubnetSize)
|
||||
}
|
||||
if info.Swarm.Cluster.DataPathPort > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Data Path Port:", info.Swarm.Cluster.DataPathPort)
|
||||
fprintln(output, " Data Path Port:", info.Swarm.Cluster.DataPathPort)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Orchestration:")
|
||||
fprintln(output, " Orchestration:")
|
||||
|
||||
taskHistoryRetentionLimit := int64(0)
|
||||
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
|
||||
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fmt.Fprintln(dockerCli.Out(), " Raft:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
fprintln(output, " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fprintln(output, " Raft:")
|
||||
fprintln(output, " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
|
||||
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
fprintf(output, " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Dispatcher:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fmt.Fprintln(dockerCli.Out(), " CA Configuration:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fmt.Fprintln(dockerCli.Out(), " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
fprintln(output, " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fprintln(output, " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fprintln(output, " Dispatcher:")
|
||||
fprintln(output, " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fprintln(output, " CA Configuration:")
|
||||
fprintln(output, " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fprintln(output, " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
if caCert := strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert); caCert != "" {
|
||||
fmt.Fprintf(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
fprintf(output, " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
}
|
||||
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " External CAs:")
|
||||
fprintln(output, " External CAs:")
|
||||
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
|
||||
fprintf(output, " %s: %s\n", entry.Protocol, entry.URL)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
fprintln(output, " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fprintln(output, " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Node Address:", info.Swarm.NodeAddr)
|
||||
fprintln(output, " Node Address:", info.Swarm.NodeAddr)
|
||||
if len(info.Swarm.RemoteManagers) > 0 {
|
||||
managers := []string{}
|
||||
for _, entry := range info.Swarm.RemoteManagers {
|
||||
managers = append(managers, entry.Addr)
|
||||
}
|
||||
sort.Strings(managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Manager Addresses:")
|
||||
fprintln(output, " Manager Addresses:")
|
||||
for _, entry := range managers {
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
|
||||
fprintf(output, " %s\n", entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printServerWarnings(dockerCli command.Cli, info *info) {
|
||||
func printServerWarnings(stdErr io.Writer, info *info) {
|
||||
if versions.LessThan(info.ClientInfo.APIVersion, "1.42") {
|
||||
printSecurityOptionsWarnings(dockerCli, *info.Info)
|
||||
printSecurityOptionsWarnings(stdErr, *info.Info)
|
||||
}
|
||||
if len(info.Warnings) > 0 {
|
||||
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
|
||||
fprintln(stdErr, strings.Join(info.Warnings, "\n"))
|
||||
return
|
||||
}
|
||||
// daemon didn't return warnings. Fallback to old behavior
|
||||
printServerWarningsLegacy(dockerCli, *info.Info)
|
||||
printServerWarningsLegacy(stdErr, *info.Info)
|
||||
}
|
||||
|
||||
// printSecurityOptionsWarnings prints warnings based on the security options
|
||||
@@ -459,7 +459,7 @@ func printServerWarnings(dockerCli command.Cli, info *info) {
|
||||
// info.Warnings. This function is used to provide backward compatibility with
|
||||
// daemons that do not provide these warnings. No new warnings should be added
|
||||
// here.
|
||||
func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
func printSecurityOptionsWarnings(stdErr io.Writer, info types.Info) {
|
||||
if info.OSType == "windows" {
|
||||
return
|
||||
}
|
||||
@@ -470,7 +470,7 @@ func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
}
|
||||
for _, o := range so.Options {
|
||||
if o.Key == "profile" && o.Value != "default" && o.Value != "builtin" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Err(), "WARNING: You're not using the default seccomp profile")
|
||||
_, _ = fmt.Fprintln(stdErr, "WARNING: You're not using the default seccomp profile")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,43 +481,43 @@ func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
// info.Warnings. This function is used to provide backward compatibility with
|
||||
// daemons that do not provide these warnings. No new warnings should be added
|
||||
// here.
|
||||
func printServerWarningsLegacy(dockerCli command.Cli, info types.Info) {
|
||||
func printServerWarningsLegacy(stdErr io.Writer, info types.Info) {
|
||||
if info.OSType == "windows" {
|
||||
return
|
||||
}
|
||||
if !info.MemoryLimit {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
|
||||
fprintln(stdErr, "WARNING: No memory limit support")
|
||||
}
|
||||
if !info.SwapLimit {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
|
||||
fprintln(stdErr, "WARNING: No swap limit support")
|
||||
}
|
||||
if !info.OomKillDisable && info.CgroupVersion != "2" {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
|
||||
fprintln(stdErr, "WARNING: No oom kill disable support")
|
||||
}
|
||||
if !info.CPUCfsQuota {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
|
||||
fprintln(stdErr, "WARNING: No cpu cfs quota support")
|
||||
}
|
||||
if !info.CPUCfsPeriod {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
|
||||
fprintln(stdErr, "WARNING: No cpu cfs period support")
|
||||
}
|
||||
if !info.CPUShares {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
|
||||
fprintln(stdErr, "WARNING: No cpu shares support")
|
||||
}
|
||||
if !info.CPUSet {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
|
||||
fprintln(stdErr, "WARNING: No cpuset support")
|
||||
}
|
||||
if !info.IPv4Forwarding {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
|
||||
fprintln(stdErr, "WARNING: IPv4 forwarding is disabled")
|
||||
}
|
||||
if !info.BridgeNfIptables {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
|
||||
fprintln(stdErr, "WARNING: bridge-nf-call-iptables is disabled")
|
||||
}
|
||||
if !info.BridgeNfIP6tables {
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
|
||||
fprintln(stdErr, "WARNING: bridge-nf-call-ip6tables is disabled")
|
||||
}
|
||||
}
|
||||
|
||||
func formatInfo(dockerCli command.Cli, info info, format string) error {
|
||||
func formatInfo(output io.Writer, info info, format string) error {
|
||||
if format == formatter.JSONFormatKey {
|
||||
format = formatter.JSONFormat
|
||||
}
|
||||
@@ -534,13 +534,21 @@ func formatInfo(dockerCli command.Cli, info info, format string) error {
|
||||
Status: "template parsing error: " + err.Error(),
|
||||
}
|
||||
}
|
||||
err = tmpl.Execute(dockerCli.Out(), info)
|
||||
dockerCli.Out().Write([]byte{'\n'})
|
||||
err = tmpl.Execute(output, info)
|
||||
fprintln(output)
|
||||
return err
|
||||
}
|
||||
|
||||
func fprintf(w io.Writer, format string, a ...any) {
|
||||
_, _ = fmt.Fprintf(w, format, a...)
|
||||
}
|
||||
|
||||
func fprintln(w io.Writer, a ...any) {
|
||||
_, _ = fmt.Fprintln(w, a...)
|
||||
}
|
||||
|
||||
func fprintlnNonEmpty(w io.Writer, label, value string) {
|
||||
if value != "" {
|
||||
fmt.Fprintln(w, label, value)
|
||||
_, _ = fmt.Fprintln(w, label, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,12 +406,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
|
||||
if tc.jsonGolden != "" {
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
assert.NilError(t, formatInfo(cli, tc.dockerInfo, "{{json .}}"))
|
||||
assert.NilError(t, formatInfo(cli.Out(), tc.dockerInfo, "{{json .}}"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
assert.NilError(t, formatInfo(cli, tc.dockerInfo, "json"))
|
||||
assert.NilError(t, formatInfo(cli.Out(), tc.dockerInfo, "json"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
}
|
||||
@@ -419,6 +419,30 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPrettyPrintInfo(b *testing.B) {
|
||||
infoWithSwarm := sampleInfoNoSwarm
|
||||
infoWithSwarm.Swarm = sampleSwarmInfo
|
||||
|
||||
dockerInfo := info{
|
||||
Info: &infoWithSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = prettyPrintInfo(cli, dockerInfo)
|
||||
cli.ResetOutputBuffers()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatInfo(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
doc string
|
||||
@@ -449,7 +473,7 @@ func TestFormatInfo(t *testing.T) {
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{Debug: true},
|
||||
}
|
||||
err := formatInfo(cli, info, tc.template)
|
||||
err := formatInfo(cli.Out(), info, tc.template)
|
||||
if tc.expectedOut != "" {
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, cli.OutBuffer().String(), tc.expectedOut)
|
||||
|
||||
@@ -47,7 +47,12 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
|
||||
}
|
||||
return &ConnectionHelper{
|
||||
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args("docker", "system", "dial-stdio")...)...)
|
||||
args := []string{"docker"}
|
||||
if sp.Path != "" {
|
||||
args = append(args, "--host", "unix://"+sp.Path)
|
||||
}
|
||||
args = append(args, "system", "dial-stdio")
|
||||
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
|
||||
},
|
||||
Host: "http://docker.example.com",
|
||||
}, nil
|
||||
|
||||
@@ -30,9 +30,7 @@ func ParseURL(daemonURL string) (*Spec, error) {
|
||||
return nil, errors.Errorf("no host specified")
|
||||
}
|
||||
sp.Port = u.Port()
|
||||
if u.Path != "" {
|
||||
return nil, errors.Errorf("extra path after the host: %q", u.Path)
|
||||
}
|
||||
sp.Path = u.Path
|
||||
if u.RawQuery != "" {
|
||||
return nil, errors.Errorf("extra query after the host: %q", u.RawQuery)
|
||||
}
|
||||
@@ -47,6 +45,7 @@ type Spec struct {
|
||||
User string
|
||||
Host string
|
||||
Port string
|
||||
Path string
|
||||
}
|
||||
|
||||
// Args returns args except "ssh" itself combined with optional additional command args
|
||||
|
||||
@@ -32,8 +32,10 @@ func TestParseURL(t *testing.T) {
|
||||
expectedError: "plain-text password is not supported",
|
||||
},
|
||||
{
|
||||
url: "ssh://foo/bar",
|
||||
expectedError: `extra path after the host: "/bar"`,
|
||||
url: "ssh://foo/bar",
|
||||
expectedArgs: []string{
|
||||
"--", "foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "ssh://foo?bar",
|
||||
|
||||
@@ -83,7 +83,7 @@ func (o *ClientOptions) InstallFlags(flags *pflag.FlagSet) {
|
||||
|
||||
// opts.ValidateHost is not used here, so as to allow connection helpers
|
||||
hostOpt := opts.NewNamedListOptsRef("hosts", &o.Hosts, nil)
|
||||
flags.VarP(hostOpt, "host", "H", "Daemon socket(s) to connect to")
|
||||
flags.VarP(hostOpt, "host", "H", "Daemon socket to connect to")
|
||||
flags.StringVarP(&o.Context, "context", "c", "",
|
||||
`Name of the context to use to connect to the daemon (overrides `+client.EnvOverrideHost+` env var and default context set with "docker context use")`)
|
||||
}
|
||||
|
||||
@@ -1888,6 +1888,7 @@ _docker_container_run() {
|
||||
_docker_container_run_and_create() {
|
||||
local options_with_args="
|
||||
--add-host
|
||||
--annotation
|
||||
--attach -a
|
||||
--blkio-weight
|
||||
--blkio-weight-device
|
||||
|
||||
@@ -178,6 +178,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from cp' -l help -d 'Print u
|
||||
# create
|
||||
complete -c docker -f -n '__fish_docker_no_subcommand' -a create -d 'Create a new container'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l add-host -d 'Add a custom host-to-IP mapping (host:ip)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l annotation -d 'Add an annotation to the container (passed through to the OCI runtime)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s a -l attach -d 'Attach to STDIN, STDOUT or STDERR.'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l blkio-weight -d 'Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l blkio-weight-device -d 'Block IO weight (relative device weight)'
|
||||
@@ -453,6 +454,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from rmi' -a '(__fish_print_
|
||||
|
||||
# run
|
||||
complete -c docker -f -n '__fish_docker_no_subcommand' -a run -d 'Create and run a new container from an image'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l annotation -d 'Add an annotation to the container (passed through to the OCI runtime)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s a -l attach -d 'Attach to STDIN, STDOUT or STDERR.'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l add-host -d 'Add a custom host-to-IP mapping (host:ip)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s c -l cpu-shares -d 'CPU shares (relative weight)'
|
||||
|
||||
@@ -602,6 +602,7 @@ __docker_container_subcommand() {
|
||||
opts_create_run=(
|
||||
"($help -a --attach)"{-a=,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
|
||||
"($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: "
|
||||
"($help)*--annotation=[Add an annotation to the container (passed through to the OCI runtime)]:annotations: "
|
||||
"($help)*--blkio-weight-device=[Block IO (relative device weight)]:device:Block IO weight: "
|
||||
"($help)*--cap-add=[Add Linux capabilities]:capability: "
|
||||
"($help)*--cap-drop=[Drop Linux capabilities]:capability: "
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
variable "GO_VERSION" {
|
||||
default = "1.20.3"
|
||||
default = "1.20.4"
|
||||
}
|
||||
variable "VERSION" {
|
||||
default = ""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GOLANGCI_LINT_VERSION=v1.52.2
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG MODOUTDATED_VERSION=v0.8.0
|
||||
|
||||
|
||||
@@ -92,18 +92,18 @@ The base command for the Docker CLI.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------|:---------|:-------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--config` | `string` | `/root/.docker` | Location of client config files |
|
||||
| `-c`, `--context` | `string` | | Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with `docker context use`) |
|
||||
| `-D`, `--debug` | | | Enable debug mode |
|
||||
| `-H`, `--host` | `list` | | Daemon socket(s) to connect to |
|
||||
| `-l`, `--log-level` | `string` | `info` | Set the logging level (`debug`, `info`, `warn`, `error`, `fatal`) |
|
||||
| `--tls` | | | Use TLS; implied by --tlsverify |
|
||||
| `--tlscacert` | `string` | `/root/.docker/ca.pem` | Trust certs signed only by this CA |
|
||||
| `--tlscert` | `string` | `/root/.docker/cert.pem` | Path to TLS certificate file |
|
||||
| `--tlskey` | `string` | `/root/.docker/key.pem` | Path to TLS key file |
|
||||
| `--tlsverify` | | | Use TLS and verify the remote |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------|:---------|:-------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--config` | `string` | `/root/.docker` | Location of client config files |
|
||||
| `-c`, `--context` | `string` | | Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with `docker context use`) |
|
||||
| `-D`, `--debug` | | | Enable debug mode |
|
||||
| [`-H`](#host), [`--host`](#host) | `list` | | Daemon socket to connect to |
|
||||
| `-l`, `--log-level` | `string` | `info` | Set the logging level (`debug`, `info`, `warn`, `error`, `fatal`) |
|
||||
| `--tls` | | | Use TLS; implied by --tlsverify |
|
||||
| `--tlscacert` | `string` | `/root/.docker/ca.pem` | Trust certs signed only by this CA |
|
||||
| `--tlscert` | `string` | `/root/.docker/cert.pem` | Path to TLS certificate file |
|
||||
| `--tlskey` | `string` | `/root/.docker/key.pem` | Path to TLS key file |
|
||||
| `--tlsverify` | | | Use TLS and verify the remote |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -378,6 +378,56 @@ list of root Certificate Authorities.
|
||||
|
||||
## Examples
|
||||
|
||||
### <a name="host"></a> Specify daemon host (-H, --host)
|
||||
|
||||
You can use the `-H`, `--host` flag to specify a socket to use when you invoke
|
||||
a `docker` command. You can use the following protocols:
|
||||
|
||||
| Scheme | Description | Example |
|
||||
|----------------------------------------|---------------------------|----------------------------------|
|
||||
| `unix://[<path>]` | Unix socket (Linux only) | `unix:///var/run/docker.sock` |
|
||||
| `tcp://[<IP or host>[:port]]` | TCP connection | `tcp://174.17.0.1:2376` |
|
||||
| `ssh://[username@]<IP or host>[:port]` | SSH connection | `ssh://user@192.168.64.5` |
|
||||
| `npipe://[<name>]` | Named pipe (Windows only) | `npipe:////./pipe/docker_engine` |
|
||||
|
||||
If you don't specify the `-H` flag, and you're not using a custom
|
||||
[context](https://docs.docker.com/engine/context/working-with-contexts),
|
||||
commands use the following default sockets:
|
||||
|
||||
- `unix:///var/run/docker.sock` on macOS and Linux
|
||||
- `npipe:////./pipe/docker_engine` on Windows
|
||||
|
||||
To achieve a similar effect without having to specify the `-H` flag for every
|
||||
command, you could also [create a context](context_create.md),
|
||||
or alternatively, use the
|
||||
[`DOCKER_HOST` environment variable](#environment-variables).
|
||||
|
||||
For more information about the `-H` flag, see
|
||||
[Daemon socket option](dockerd.md#daemon-socket-option).
|
||||
|
||||
#### Using TCP sockets
|
||||
|
||||
The following example shows how to invoke `docker ps` over TCP, to a remote
|
||||
daemon with IP address `174.17.0.1`, listening on port `2376`:
|
||||
|
||||
```console
|
||||
$ docker -H tcp://174.17.0.1:2376 ps
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> By convention, the Docker daemon uses port `2376` for secure TLS connections,
|
||||
> and port `2375` for insecure, non-TLS connections.
|
||||
|
||||
#### Using SSH sockets
|
||||
|
||||
When you use SSH invoke a command on a remote daemon, the request gets forwarded
|
||||
to the `/var/run/docker.sock` Unix socket on the SSH host.
|
||||
|
||||
```console
|
||||
$ docker -H ssh://user@192.168.64.5 ps
|
||||
```
|
||||
|
||||
### Display help text
|
||||
|
||||
To list the help on any command just execute the command, followed by the
|
||||
|
||||
@@ -12,6 +12,7 @@ Create a new container
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--add-host` | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| `-a`, `--attach` | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -12,6 +12,7 @@ Create and run a new container from an image
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--add-host` | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| `-a`, `--attach` | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -12,6 +12,7 @@ Create a new container
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--add-host` | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| `-a`, `--attach` | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -242,6 +242,7 @@ precedence over `HTTP_PROXY`.
|
||||
The Docker client supports connecting to a remote daemon via SSH:
|
||||
|
||||
```console
|
||||
$ docker -H ssh://me@example.com:22/var/run/docker.sock ps
|
||||
$ docker -H ssh://me@example.com:22 ps
|
||||
$ docker -H ssh://me@example.com ps
|
||||
$ docker -H ssh://example.com ps
|
||||
|
||||
@@ -12,6 +12,7 @@ Create and run a new container from an image
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------------------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [`--add-host`](#add-host) | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| [`-a`](#attach), [`--attach`](#attach) | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -12,27 +12,45 @@ Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
|
||||
|
||||
## Description
|
||||
|
||||
An image name is made up of slash-separated name components, optionally prefixed
|
||||
by a registry hostname. The hostname must comply with standard DNS rules, but
|
||||
may not contain underscores. If a hostname is present, it may optionally be
|
||||
followed by a port number in the format `:8080`. If not present, the command
|
||||
uses Docker's public registry located at `registry-1.docker.io` by default. Name
|
||||
components may contain lowercase letters, digits and separators. A separator
|
||||
is defined as a period, one or two underscores, or one or more hyphens. A name
|
||||
component may not start or end with a separator.
|
||||
A full image name has the following format and components:
|
||||
|
||||
A tag name must be valid ASCII and may contain lowercase and uppercase letters,
|
||||
digits, underscores, periods and hyphens. A tag name may not start with a
|
||||
period or a hyphen and may contain a maximum of 128 characters.
|
||||
`[HOST[:PORT_NUMBER]/]PATH`
|
||||
|
||||
You can group your images together using names and tags, and then upload them
|
||||
to [*Share images on Docker Hub*](https://docs.docker.com/get-started/part3/).
|
||||
- `HOST`: The optional registry hostname specifies where the image is located.
|
||||
The hostname must comply with standard DNS rules, but may not contain
|
||||
underscores. If the hostname is not specified, the command uses Docker's public
|
||||
registry at `registry-1.docker.io` by default. Note that `docker.io` is the
|
||||
canonical reference for Docker's public registry.
|
||||
- `PORT_NUMBER`: If a hostname is present, it may optionally be followed by a
|
||||
registry port number in the format `:8080`.
|
||||
- `PATH`: The path consists consists of slash-separated components. Each
|
||||
component may contain lowercase letters, digits and separators. A separator is
|
||||
defined as a period, one or two underscores, or one or more hyphens. A component
|
||||
may not start or end with a separator. While the
|
||||
[OCI Distribution Specification](https://github.com/opencontainers/distribution-spec)
|
||||
supports more than two slash-separated components, most registries only support
|
||||
two slash-separated components. For Docker's public registry, the path format is
|
||||
as follows:
|
||||
- `[NAMESPACE/]REPOSITORY`: The first, optional component is typically a
|
||||
user's or an organization's namespace. The second, mandatory component is the
|
||||
repository name. When the namespace is not present, Docker uses `library`
|
||||
as the default namespace.
|
||||
|
||||
After the image name, the optional `TAG` is a custom, human-readable manifest
|
||||
identifier that is typically a specific version or variant of an image. The tag
|
||||
must be valid ASCII and can contain lowercase and uppercase letters, digits,
|
||||
underscores, periods, and hyphens. It cannot start with a period or hyphen and
|
||||
must be no longer than 128 characters. If the tag is not specified, the command uses `latest` by default.
|
||||
|
||||
You can group your images together using names and tags, and then
|
||||
[push](https://docs.docker.com/engine/reference/commandline/push) them to a
|
||||
registry.
|
||||
|
||||
## Examples
|
||||
|
||||
### Tag an image referenced by ID
|
||||
|
||||
To tag a local image with ID "0e5574283393" into the "fedora" repository with
|
||||
To tag a local image with ID "0e5574283393" as "fedora/httpd" with the tag
|
||||
"version1.0":
|
||||
|
||||
```console
|
||||
@@ -41,8 +59,7 @@ $ docker tag 0e5574283393 fedora/httpd:version1.0
|
||||
|
||||
### Tag an image referenced by Name
|
||||
|
||||
To tag a local image with name "httpd" into the "fedora" repository with
|
||||
"version1.0":
|
||||
To tag a local image "httpd" as "fedora/httpd" with the tag "version1.0":
|
||||
|
||||
```console
|
||||
$ docker tag httpd fedora/httpd:version1.0
|
||||
@@ -53,18 +70,18 @@ existing local version `httpd:latest`.
|
||||
|
||||
### Tag an image referenced by Name and Tag
|
||||
|
||||
To tag a local image with name "httpd" and tag "test" into the "fedora"
|
||||
repository with "version1.0.test":
|
||||
To tag a local image with the name "httpd" and the tag "test" as "fedora/httpd"
|
||||
with the tag "version1.0.test":
|
||||
|
||||
```console
|
||||
$ docker tag httpd:test fedora/httpd:version1.0.test
|
||||
```
|
||||
|
||||
### Tag an image for a private repository
|
||||
### Tag an image for a private registry
|
||||
|
||||
To push an image to a private registry and not the central Docker
|
||||
registry you must tag it with the registry hostname and port (if needed).
|
||||
To push an image to a private registry and not the public Docker registry you
|
||||
must include the registry hostname and port (if needed).
|
||||
|
||||
```console
|
||||
$ docker tag 0e5574283393 myregistryhost:5000/fedora/httpd:version1.0
|
||||
```
|
||||
```
|
||||
@@ -18,6 +18,10 @@ const registryPrefix = "registry:5000"
|
||||
func TestRunAttachedFromRemoteImageAndRemove(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
|
||||
// Digests in golden file are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
image := createRemoteImage(t)
|
||||
|
||||
result := icmd.RunCommand("docker", "run", "--rm", image,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Unable to find image 'registry:5000/alpine:test-run-pulls' locally
|
||||
test-run-pulls: Pulling from alpine
|
||||
Digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d
|
||||
Digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501
|
||||
Status: Downloaded newer image for registry:5000/alpine:test-run-pulls
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestBuildFromContextDirectoryWithTag(t *testing.T) {
|
||||
result.Assert(t, icmd.Expected{Err: buildkitDisabledWarning})
|
||||
output.Assert(t, result.Stdout(), map[int]func(string) error{
|
||||
0: output.Prefix("Sending build context to Docker daemon"),
|
||||
1: output.Suffix("Step 1/4 : FROM registry:5000/alpine:3.6"),
|
||||
1: output.Suffix("Step 1/4 : FROM registry:5000/alpine:frozen"),
|
||||
3: output.Suffix("Step 2/4 : COPY run /usr/bin/run"),
|
||||
5: output.Suffix("Step 3/4 : RUN run"),
|
||||
7: output.Suffix("running"),
|
||||
|
||||
@@ -17,6 +17,10 @@ const registryPrefix = "registry:5000"
|
||||
func TestPullWithContentTrust(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
|
||||
// Digests in golden files are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
dir := fixtures.SetupConfigFile(t)
|
||||
defer dir.Remove()
|
||||
image := fixtures.CreateMaskedTrustedRemoteImage(t, registryPrefix, "trust-pull", "latest")
|
||||
@@ -37,7 +41,7 @@ func TestPullWithContentTrust(t *testing.T) {
|
||||
func TestPullQuiet(t *testing.T) {
|
||||
result := icmd.RunCommand("docker", "pull", "--quiet", fixtures.AlpineImage)
|
||||
result.Assert(t, icmd.Success)
|
||||
assert.Check(t, is.Equal(result.Stdout(), "registry:5000/alpine:3.6\n"))
|
||||
assert.Check(t, is.Equal(result.Stdout(), "registry:5000/alpine:frozen\n"))
|
||||
assert.Check(t, is.Equal(result.Stderr(), ""))
|
||||
}
|
||||
|
||||
|
||||
+15
-7
@@ -33,6 +33,10 @@ const (
|
||||
func TestPushAllTags(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
|
||||
// Compared digests are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
_ = createImage(t, "push-all-tags", "latest", "v1", "v1.0", "v1.0.1")
|
||||
result := icmd.RunCmd(icmd.Command("docker", "push", "--all-tags", registryPrefix+"/push-all-tags"))
|
||||
|
||||
@@ -40,17 +44,21 @@ func TestPushAllTags(t *testing.T) {
|
||||
golden.Assert(t, result.Stderr(), "push-with-content-trust-err.golden")
|
||||
output.Assert(t, result.Stdout(), map[int]func(string) error{
|
||||
0: output.Equals("The push refers to repository [registry:5000/push-all-tags]"),
|
||||
1: output.Equals("5bef08742407: Preparing"),
|
||||
3: output.Equals("latest: digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d size: 528"),
|
||||
6: output.Equals("v1: digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d size: 528"),
|
||||
9: output.Equals("v1.0: digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d size: 528"),
|
||||
12: output.Equals("v1.0.1: digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d size: 528"),
|
||||
1: output.Equals("7cd52847ad77: Preparing"),
|
||||
3: output.Equals("latest: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
||||
6: output.Equals("v1: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
||||
9: output.Equals("v1.0: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
||||
12: output.Equals("v1.0.1: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
||||
})
|
||||
}
|
||||
|
||||
func TestPushWithContentTrust(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
|
||||
// Compared digests are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
dir := fixtures.SetupConfigFile(t)
|
||||
defer dir.Remove()
|
||||
image := createImage(t, "trust-push", "latest")
|
||||
@@ -65,8 +73,8 @@ func TestPushWithContentTrust(t *testing.T) {
|
||||
golden.Assert(t, result.Stderr(), "push-with-content-trust-err.golden")
|
||||
output.Assert(t, result.Stdout(), map[int]func(string) error{
|
||||
0: output.Equals("The push refers to repository [registry:5000/trust-push]"),
|
||||
1: output.Equals("5bef08742407: Preparing"),
|
||||
3: output.Equals("latest: digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d size: 528"),
|
||||
1: output.Equals("7cd52847ad77: Preparing"),
|
||||
3: output.Equals("latest: digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 size: 528"),
|
||||
4: output.Equals("Signing and pushing trust metadata"),
|
||||
5: output.Equals(`Finished initializing "registry:5000/trust-push"`),
|
||||
6: output.Equals("Successfully signed registry:5000/trust-push:latest"),
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
Tagging registry:5000/trust-pull@sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d as registry:5000/trust-pull:latest
|
||||
Tagging registry:5000/trust-pull@sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501 as registry:5000/trust-pull:latest
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
Pull (1 of 1): registry:5000/trust-pull:latest@sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d
|
||||
sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d: Pulling from trust-pull
|
||||
Digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d
|
||||
Status: Downloaded newer image for registry:5000/trust-pull@sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d
|
||||
Pull (1 of 1): registry:5000/trust-pull:latest@sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501
|
||||
sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501: Pulling from trust-pull
|
||||
Digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501
|
||||
Status: Downloaded newer image for registry:5000/trust-pull@sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501
|
||||
registry:5000/trust-pull:latest
|
||||
|
||||
@@ -15,11 +15,11 @@ const (
|
||||
// EvilNotaryURL is the location of the evil notary server
|
||||
EvilNotaryURL = "https://evil-notary-server:4444"
|
||||
// AlpineImage is an image in the test registry
|
||||
AlpineImage = "registry:5000/alpine:3.6"
|
||||
AlpineImage = "registry:5000/alpine:frozen"
|
||||
// AlpineSha is the sha of the alpine image
|
||||
AlpineSha = "641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d"
|
||||
AlpineSha = "e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501"
|
||||
// BusyboxImage is an image in the test registry
|
||||
BusyboxImage = "registry:5000/busybox:1.27.2"
|
||||
BusyboxImage = "registry:5000/busybox:frozen"
|
||||
// BusyboxSha is the sha of the busybox image
|
||||
BusyboxSha = "030fcb92e1487b18c974784dcc110a93147c9fc402188370fbfd17efabffc6af"
|
||||
)
|
||||
|
||||
Vendored
+2
-2
@@ -2,8 +2,8 @@ version: '3.3'
|
||||
|
||||
services:
|
||||
one:
|
||||
image: registry:5000/alpine:3.6
|
||||
image: registry:5000/alpine:frozen
|
||||
command: top
|
||||
two:
|
||||
image: registry:5000/alpine:3.6
|
||||
image: registry:5000/alpine:frozen
|
||||
command: top
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
version: '3.5'
|
||||
services:
|
||||
web:
|
||||
image: registry:5000/alpine:3.6
|
||||
image: registry:5000/alpine:frozen
|
||||
command: top
|
||||
networks: [network1, network2]
|
||||
volumes: [volume1, volume2]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
ARG NOTARY_VERSION=0.5.0
|
||||
ARG NOTARY_VERSION=0.6.1
|
||||
FROM notary:server-${NOTARY_VERSION}
|
||||
|
||||
COPY ./notary-evil/ /fixtures/
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG GO_VERSION=1.20.4
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine AS generated
|
||||
RUN go install github.com/dmcgowan/quicktls@master
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
ARG NOTARY_VERSION=0.5.0
|
||||
ARG NOTARY_VERSION=0.6.1
|
||||
FROM notary:server-${NOTARY_VERSION}
|
||||
|
||||
COPY ./notary/ /fixtures/
|
||||
|
||||
@@ -20,6 +20,9 @@ const (
|
||||
|
||||
func TestSignLocalImage(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
// Digests in golden files are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
dir := fixtures.SetupConfigFile(t)
|
||||
defer dir.Remove()
|
||||
@@ -35,6 +38,9 @@ func TestSignLocalImage(t *testing.T) {
|
||||
|
||||
func TestSignWithLocalFlag(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
// Digests in golden files are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
dir := fixtures.SetupConfigFile(t)
|
||||
defer dir.Remove()
|
||||
|
||||
@@ -98,3 +98,13 @@ func SkipIfCgroupNamespacesNotSupported(t *testing.T) {
|
||||
|
||||
skip.If(t, !cgroupNsFound, fmt.Sprintf("running against a daemon that doesn't support cgroup namespaces (security options: %s)", result.Stdout()))
|
||||
}
|
||||
|
||||
// SkipIfNotPlatform skips the test if the running docker daemon is not running on a specific platform.
|
||||
// platform should be in format os/arch (for example linux/arm64).
|
||||
func SkipIfNotPlatform(t *testing.T, platform string) {
|
||||
t.Helper()
|
||||
result := icmd.RunCmd(icmd.Command("docker", "version", "--format", "{{.Server.Os}}/{{.Server.Arch}}"))
|
||||
result.Assert(t, icmd.Expected{Err: icmd.None})
|
||||
daemonPlatform := strings.TrimSpace(result.Stdout())
|
||||
skip.If(t, daemonPlatform != platform, "running against a non %s daemon", platform)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ docker-run - Create and run a new container from an image
|
||||
**docker run**
|
||||
[**-a**|**--attach**[=*[]*]]
|
||||
[**--add-host**[=*[]*]]
|
||||
[**--annotation**[=*[]*]]
|
||||
[**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
|
||||
[**--blkio-weight-device**[=*[]*]]
|
||||
[**--cpu-shares**[=*0*]]
|
||||
@@ -125,6 +126,11 @@ each of stdin, stdout, and stderr.
|
||||
Add a line to /etc/hosts. The format is hostname:ip. The **--add-host**
|
||||
option can be set multiple times.
|
||||
|
||||
**--annotation**=[]
|
||||
Add an annotation to the container (passed through to the OCI runtime).
|
||||
|
||||
The annotations are provided to the OCI runtime.
|
||||
|
||||
**--blkio-weight**=*0*
|
||||
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
# Fetch images used for e2e testing
|
||||
set -eu -o pipefail
|
||||
|
||||
alpine_src=alpine@sha256:f006ecbb824d87947d0b51ab8488634bf69fe4094959d935c0c103f4820a417d
|
||||
alpine_dest=registry:5000/alpine:3.6
|
||||
alpine_src=alpine@sha256:69665d02cb32192e52e07644d76bc6f25abeb5410edc1c7a81a10ba3f0efb90a
|
||||
alpine_dest=registry:5000/alpine:frozen
|
||||
|
||||
busybox_src=busybox@sha256:3e8fa85ddfef1af9ca85a5cfb714148956984e02f00bec3f7f49d3925a91e0e7
|
||||
busybox_dest=registry:5000/busybox:1.27.2
|
||||
busybox_dest=registry:5000/busybox:frozen
|
||||
|
||||
fetch_tag_image() {
|
||||
docker pull "$1"
|
||||
|
||||
+9
-9
@@ -7,10 +7,10 @@ module github.com/docker/cli
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/containerd/containerd v1.6.20
|
||||
github.com/creack/pty v1.1.11
|
||||
github.com/docker/distribution v2.8.1+incompatible
|
||||
github.com/docker/docker v24.0.0-beta.2+incompatible
|
||||
github.com/containerd/containerd v1.6.21
|
||||
github.com/creack/pty v1.1.18
|
||||
github.com/docker/distribution v2.8.2+incompatible
|
||||
github.com/docker/docker v24.0.0-rc.3+incompatible
|
||||
github.com/docker/docker-credential-helpers v0.7.0
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
@@ -19,14 +19,14 @@ require (
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/imdario/mergo v0.3.13
|
||||
github.com/mattn/go-runewidth v0.0.13
|
||||
github.com/mattn/go-runewidth v0.0.14
|
||||
github.com/mitchellh/mapstructure v1.3.2
|
||||
github.com/moby/buildkit v0.11.5
|
||||
github.com/moby/buildkit v0.11.6
|
||||
github.com/moby/patternmatcher v0.5.0
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20230406225228-75e92ce14ff7
|
||||
github.com/moby/sys/sequential v0.5.0
|
||||
github.com/moby/sys/signal v0.7.0
|
||||
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f
|
||||
github.com/moby/term v0.5.0
|
||||
github.com/morikuni/aec v1.0.0
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||
@@ -61,7 +61,7 @@ require (
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/moby/sys/symlink v0.2.0 // indirect
|
||||
github.com/opencontainers/runc v1.1.6 // indirect
|
||||
github.com/opencontainers/runc v1.1.7 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
|
||||
+19
-19
@@ -82,22 +82,22 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
|
||||
github.com/containerd/containerd v1.6.20 h1:+itjwpdqXpzHB/QAiWc/BZCjjVfcNgw69w/oIeF4Oy0=
|
||||
github.com/containerd/containerd v1.6.20/go.mod h1:apei1/i5Ux2FzrK6+DM/suEsGuK/MeVOfy8tR2q7Wnw=
|
||||
github.com/containerd/containerd v1.6.21 h1:eSTAmnvDKRPWan+MpSSfNyrtleXd86ogK9X8fMWpe/Q=
|
||||
github.com/containerd/containerd v1.6.21/go.mod h1:apei1/i5Ux2FzrK6+DM/suEsGuK/MeVOfy8tR2q7Wnw=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.0-beta.2+incompatible h1:pTEep8tbPw11AdIS/O8P8ULyLSQAS7HuOJphmQCHrNI=
|
||||
github.com/docker/docker v24.0.0-beta.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.0-rc.3+incompatible h1:DvPU6bHqKAXC9J81HHebUPSgXEr/g0Mv84SuVPEe8TI=
|
||||
github.com/docker/docker v24.0.0-rc.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
@@ -257,8 +257,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.5.3 h1:C8fxWnhYyME3n0klPOhVM7PtYUB3eV1W3DeFmN3j53Y=
|
||||
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
@@ -269,20 +269,20 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
|
||||
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/buildkit v0.11.5 h1:S6YrFJ0bfBT2w9e8kOxqsDV8Bw+HtfqdB6eHL17BXRI=
|
||||
github.com/moby/buildkit v0.11.5/go.mod h1:P5Qi041LvCfhkfYBHry+Rwoo3Wi6H971J2ggE+PcIoo=
|
||||
github.com/moby/buildkit v0.11.6 h1:VYNdoKk5TVxN7k4RvZgdeM4GOyRvIi4Z8MXOY7xvyUs=
|
||||
github.com/moby/buildkit v0.11.6/go.mod h1:GCqKfHhz+pddzfgaR7WmHVEE3nKKZMMDPpK8mh3ZLv4=
|
||||
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
|
||||
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83 h1:jUbNDiRMDXd2rYoa4bcI+g3nIb4A1R8HNCe9wdCdh8I=
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20230315203717-e28e8ba9bc83/go.mod h1:GvjR7mC8YuUd9Mq44lrrIZPaXyKPAGEUMBpAQzaj3dI=
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20230406225228-75e92ce14ff7 h1:h6NclNly6/B9N4IdM5pcBaq/LkNLuaCmE7B44Vj+pb0=
|
||||
github.com/moby/swarmkit/v2 v2.0.0-20230406225228-75e92ce14ff7/go.mod h1:P/ha3F7UZMmuUvqrHw9cZK/BjktSngQIgRPiairNHTc=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||
github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc=
|
||||
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
||||
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f h1:J/7hjLaHLD7epG0m6TBMGmp4NQ+ibBYLfeyJWdAIFLA=
|
||||
github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f/go.mod h1:15ce4BGCFxt7I5NQKT+HV0yEDxmf6fSysfEDiVo3zFM=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@@ -303,8 +303,8 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/opencontainers/runc v1.1.6 h1:XbhB8IfG/EsnhNvZtNdLB0GBw92GYEFvKlhaJk9jUgA=
|
||||
github.com/opencontainers/runc v1.1.6/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
|
||||
github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk=
|
||||
github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
|
||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -379,7 +379,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a h1:tlJ7tGUHvcvL1v3yR6NcCc9nOqh2L+CG6HWrYQtwzQ0=
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a/go.mod h1:Y94A6rPp2OwNfP/7vmf8O2xx2IykP8pPXQ1DLouGnEw=
|
||||
github.com/tonistiigi/go-rosetta v0.0.0-20200727161949-f79598599c5d h1:wvQZpqy8p0D/FUia6ipKDhXrzPzBVJE4PZyPc5+5Ay0=
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
ARG GOVERSION=1.14
|
||||
FROM golang:${GOVERSION}
|
||||
|
||||
# Set base env.
|
||||
ARG GOOS=linux
|
||||
ARG GOARCH=amd64
|
||||
ENV GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
|
||||
|
||||
# Pre compile the stdlib for 386/arm (32bits).
|
||||
RUN go build -a std
|
||||
|
||||
# Add the code to the image.
|
||||
WORKDIR pty
|
||||
ADD . .
|
||||
|
||||
# Build the lib.
|
||||
RUN go build
|
||||
+11
-2
@@ -1,3 +1,4 @@
|
||||
# NOTE: Using 1.13 as a base to build the RISCV compiler, the resulting version is based on go1.6.
|
||||
FROM golang:1.13
|
||||
|
||||
# Clone and complie a riscv compatible version of the go compiler.
|
||||
@@ -8,7 +9,15 @@ ENV PATH=/riscv-go/misc/riscv:/riscv-go/bin:$PATH
|
||||
RUN cd /riscv-go/src && GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash
|
||||
ENV GOROOT=/riscv-go
|
||||
|
||||
# Make sure we compile.
|
||||
# Set the base env.
|
||||
ENV GOOS=linux GOARCH=riscv CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
|
||||
|
||||
# Pre compile the stdlib.
|
||||
RUN go build -a std
|
||||
|
||||
# Add the code to the image.
|
||||
WORKDIR pty
|
||||
ADD . .
|
||||
RUN GOOS=linux GOARCH=riscv go build
|
||||
|
||||
# Build the lib.
|
||||
RUN go build
|
||||
|
||||
+13
-6
@@ -4,9 +4,13 @@ Pty is a Go package for using unix pseudo-terminals.
|
||||
|
||||
## Install
|
||||
|
||||
go get github.com/creack/pty
|
||||
```sh
|
||||
go get github.com/creack/pty
|
||||
```
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
Note that those examples are for demonstration purpose only, to showcase how to use the library. They are not meant to be used in any kind of production environment.
|
||||
|
||||
### Command
|
||||
|
||||
@@ -14,10 +18,11 @@ Pty is a Go package for using unix pseudo-terminals.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/creack/pty"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -51,7 +56,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
func test() error {
|
||||
@@ -77,15 +82,17 @@ func test() error {
|
||||
}
|
||||
}()
|
||||
ch <- syscall.SIGWINCH // Initial resize.
|
||||
defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
|
||||
|
||||
// Set stdin in raw mode.
|
||||
oldState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
|
||||
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
||||
defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
||||
|
||||
// Copy stdin to the pty and the pty to stdout.
|
||||
// NOTE: The goroutine will keep reading until the next keystroke before returning.
|
||||
go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
|
||||
_, _ = io.Copy(os.Stdout, ptmx)
|
||||
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc
|
||||
//+build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
|
||||
//
|
||||
|
||||
TEXT ·sysvicall6(SB),NOSPLIT,$0-88
|
||||
JMP syscall·sysvicall6(SB)
|
||||
|
||||
TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88
|
||||
JMP syscall·rawSysvicall6(SB)
|
||||
+1
-1
@@ -10,7 +10,7 @@ import (
|
||||
// available on the current platform.
|
||||
var ErrUnsupported = errors.New("unsupported")
|
||||
|
||||
// Opens a pty and its corresponding tty.
|
||||
// Open a pty and its corresponding tty.
|
||||
func Open() (pty, tty *os.File, err error) {
|
||||
return open()
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,9 +1,15 @@
|
||||
// +build !windows,!solaris
|
||||
//go:build !windows && !solaris && !aix
|
||||
// +build !windows,!solaris,!aix
|
||||
|
||||
package pty
|
||||
|
||||
import "syscall"
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = syscall.TIOCGWINSZ
|
||||
TIOCSWINSZ = syscall.TIOCSWINSZ
|
||||
)
|
||||
|
||||
func ioctl(fd, cmd, ptr uintptr) error {
|
||||
_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
|
||||
if e != 0 {
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
|
||||
package pty
|
||||
|
||||
+27
-9
@@ -1,30 +1,48 @@
|
||||
//go:build solaris
|
||||
// +build solaris
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
|
||||
//go:linkname procioctl libc_ioctl
|
||||
var procioctl uintptr
|
||||
|
||||
const (
|
||||
// see /usr/include/sys/stropts.h
|
||||
I_PUSH = uintptr((int32('S')<<8 | 002))
|
||||
I_STR = uintptr((int32('S')<<8 | 010))
|
||||
I_FIND = uintptr((int32('S')<<8 | 013))
|
||||
I_PUSH = uintptr((int32('S')<<8 | 002))
|
||||
I_STR = uintptr((int32('S')<<8 | 010))
|
||||
I_FIND = uintptr((int32('S')<<8 | 013))
|
||||
|
||||
// see /usr/include/sys/ptms.h
|
||||
ISPTM = (int32('P') << 8) | 1
|
||||
UNLKPT = (int32('P') << 8) | 2
|
||||
PTSSTTY = (int32('P') << 8) | 3
|
||||
ZONEPT = (int32('P') << 8) | 4
|
||||
OWNERPT = (int32('P') << 8) | 5
|
||||
|
||||
// see /usr/include/sys/termios.h
|
||||
TIOCSWINSZ = (uint32('T') << 8) | 103
|
||||
TIOCGWINSZ = (uint32('T') << 8) | 104
|
||||
)
|
||||
|
||||
type strioctl struct {
|
||||
ic_cmd int32
|
||||
ic_timout int32
|
||||
ic_len int32
|
||||
ic_dp unsafe.Pointer
|
||||
icCmd int32
|
||||
icTimeout int32
|
||||
icLen int32
|
||||
icDP unsafe.Pointer
|
||||
}
|
||||
|
||||
// Defined in asm_solaris_amd64.s.
|
||||
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
func ioctl(fd, cmd, ptr uintptr) error {
|
||||
return unix.IoctlSetInt(int(fd), uint(cmd), int(ptr))
|
||||
if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, fd, cmd, ptr, 0, 0, 0); errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
//go:build aix
|
||||
// +build aix
|
||||
|
||||
package pty
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = 0
|
||||
TIOCSWINSZ = 0
|
||||
)
|
||||
|
||||
func ioctl(fd, cmd, ptr uintptr) error {
|
||||
return ErrUnsupported
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ GODEFS="go tool cgo -godefs"
|
||||
$GODEFS types.go |gofmt > ztypes_$GOARCH.go
|
||||
|
||||
case $GOOS in
|
||||
freebsd|dragonfly|openbsd)
|
||||
freebsd|dragonfly|netbsd|openbsd)
|
||||
$GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go
|
||||
;;
|
||||
esac
|
||||
|
||||
+4
-1
@@ -1,3 +1,6 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
@@ -33,7 +36,7 @@ func open() (pty, tty *os.File, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
t, err := os.OpenFile(sname, os.O_RDWR, 0)
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build dragonfly
|
||||
// +build dragonfly
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
|
||||
+6
-3
@@ -1,3 +1,6 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
@@ -28,7 +31,7 @@ func open() (pty, tty *os.File, err error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) //nolint:gosec // Expected Open from a variable.
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -37,7 +40,7 @@ func open() (pty, tty *os.File, err error) {
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
var n _C_uint
|
||||
err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n)))
|
||||
err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) //nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -47,5 +50,5 @@ func ptsname(f *os.File) (string, error) {
|
||||
func unlockpt(f *os.File) error {
|
||||
var u _C_int
|
||||
// use TIOCSPTLCK with a pointer to zero to clear the lock
|
||||
return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
|
||||
return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) //nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
//go:build netbsd
|
||||
// +build netbsd
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func open() (pty, tty *os.File, err error) {
|
||||
p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// In case of error after this point, make sure we close the ptmx fd.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = p.Close() // Best effort.
|
||||
}
|
||||
}()
|
||||
|
||||
sname, err := ptsname(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := grantpt(p); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// In NetBSD unlockpt() does nothing, so it isn't called here.
|
||||
|
||||
t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return p, t, nil
|
||||
}
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
/*
|
||||
* from ptsname(3): The ptsname() function is equivalent to:
|
||||
* struct ptmget pm;
|
||||
* ioctl(fd, TIOCPTSNAME, &pm) == -1 ? NULL : pm.sn;
|
||||
*/
|
||||
var ptm ptmget
|
||||
if err := ioctl(f.Fd(), uintptr(ioctl_TIOCPTSNAME), uintptr(unsafe.Pointer(&ptm))); err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := make([]byte, len(ptm.Sn))
|
||||
for i, c := range ptm.Sn {
|
||||
name[i] = byte(c)
|
||||
if c == 0 {
|
||||
return string(name[:i]), nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("TIOCPTSNAME string not NUL-terminated")
|
||||
}
|
||||
|
||||
func grantpt(f *os.File) error {
|
||||
/*
|
||||
* from grantpt(3): Calling grantpt() is equivalent to:
|
||||
* ioctl(fd, TIOCGRANTPT, 0);
|
||||
*/
|
||||
return ioctl(f.Fd(), uintptr(ioctl_TIOCGRANTPT), 0)
|
||||
}
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build openbsd
|
||||
// +build openbsd
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
|
||||
+83
-70
@@ -1,3 +1,6 @@
|
||||
//go:build solaris
|
||||
// +build solaris
|
||||
|
||||
package pty
|
||||
|
||||
/* based on:
|
||||
@@ -6,122 +9,134 @@ http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/pt.c
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/sys/unix"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const NODEV = ^uint64(0)
|
||||
|
||||
func open() (pty, tty *os.File, err error) {
|
||||
masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|unix.O_NOCTTY, 0)
|
||||
//masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC|unix.O_NOCTTY, 0)
|
||||
ptmxfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
p := os.NewFile(uintptr(masterfd), "/dev/ptmx")
|
||||
p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx")
|
||||
// In case of error after this point, make sure we close the ptmx fd.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = p.Close() // Best effort.
|
||||
}
|
||||
}()
|
||||
|
||||
sname, err := ptsname(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = grantpt(p)
|
||||
if err != nil {
|
||||
if err := grantpt(p); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
err = unlockpt(p)
|
||||
if err != nil {
|
||||
if err := unlockpt(p); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
slavefd, err := syscall.Open(sname, os.O_RDWR|unix.O_NOCTTY, 0)
|
||||
ptsfd, err := syscall.Open(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t := os.NewFile(uintptr(slavefd), sname)
|
||||
t := os.NewFile(uintptr(ptsfd), sname)
|
||||
|
||||
// In case of error after this point, make sure we close the pts fd.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = t.Close() // Best effort.
|
||||
}
|
||||
}()
|
||||
|
||||
// pushing terminal driver STREAMS modules as per pts(7)
|
||||
for _, mod := range([]string{"ptem", "ldterm", "ttcompat"}) {
|
||||
err = streams_push(t, mod)
|
||||
if err != nil {
|
||||
for _, mod := range []string{"ptem", "ldterm", "ttcompat"} {
|
||||
if err := streamsPush(t, mod); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return p, t, nil
|
||||
}
|
||||
|
||||
func minor(x uint64) uint64 {
|
||||
return x & 0377
|
||||
}
|
||||
|
||||
func ptsdev(fd uintptr) uint64 {
|
||||
istr := strioctl{ISPTM, 0, 0, nil}
|
||||
err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
if err != nil {
|
||||
return NODEV
|
||||
}
|
||||
var status unix.Stat_t
|
||||
err = unix.Fstat(int(fd), &status)
|
||||
if err != nil {
|
||||
return NODEV
|
||||
}
|
||||
return uint64(minor(status.Rdev))
|
||||
}
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
dev := ptsdev(f.Fd())
|
||||
if dev == NODEV {
|
||||
return "", errors.New("not a master pty")
|
||||
dev, err := ptsdev(f.Fd())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10)
|
||||
// access(2) creates the slave device (if the pty exists)
|
||||
// F_OK == 0 (unistd.h)
|
||||
err := unix.Access(fn, 0)
|
||||
if err != nil {
|
||||
|
||||
if err := syscall.Access(fn, 0); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fn, nil
|
||||
}
|
||||
|
||||
type pt_own struct {
|
||||
pto_ruid int32
|
||||
pto_rgid int32
|
||||
func unlockpt(f *os.File) error {
|
||||
istr := strioctl{
|
||||
icCmd: UNLKPT,
|
||||
icTimeout: 0,
|
||||
icLen: 0,
|
||||
icDP: nil,
|
||||
}
|
||||
return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
}
|
||||
|
||||
func minor(x uint64) uint64 { return x & 0377 }
|
||||
|
||||
func ptsdev(fd uintptr) (uint64, error) {
|
||||
istr := strioctl{
|
||||
icCmd: ISPTM,
|
||||
icTimeout: 0,
|
||||
icLen: 0,
|
||||
icDP: nil,
|
||||
}
|
||||
|
||||
if err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var status syscall.Stat_t
|
||||
if err := syscall.Fstat(int(fd), &status); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(minor(status.Rdev)), nil
|
||||
}
|
||||
|
||||
type ptOwn struct {
|
||||
rUID int32
|
||||
rGID int32
|
||||
}
|
||||
|
||||
func grantpt(f *os.File) error {
|
||||
if ptsdev(f.Fd()) == NODEV {
|
||||
return errors.New("not a master pty")
|
||||
if _, err := ptsdev(f.Fd()); err != nil {
|
||||
return err
|
||||
}
|
||||
var pto pt_own
|
||||
pto.pto_ruid = int32(os.Getuid())
|
||||
// XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty"
|
||||
pto.pto_rgid = int32(os.Getgid())
|
||||
var istr strioctl
|
||||
istr.ic_cmd = OWNERPT
|
||||
istr.ic_timout = 0
|
||||
istr.ic_len = int32(unsafe.Sizeof(istr))
|
||||
istr.ic_dp = unsafe.Pointer(&pto)
|
||||
err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
if err != nil {
|
||||
pto := ptOwn{
|
||||
rUID: int32(os.Getuid()),
|
||||
// XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty"
|
||||
rGID: int32(os.Getgid()),
|
||||
}
|
||||
istr := strioctl{
|
||||
icCmd: OWNERPT,
|
||||
icTimeout: 0,
|
||||
icLen: int32(unsafe.Sizeof(strioctl{})),
|
||||
icDP: unsafe.Pointer(&pto),
|
||||
}
|
||||
if err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
|
||||
return errors.New("access denied")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unlockpt(f *os.File) error {
|
||||
istr := strioctl{UNLKPT, 0, 0, nil}
|
||||
return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr)))
|
||||
}
|
||||
|
||||
// push STREAMS modules if not already done so
|
||||
func streams_push(f *os.File, mod string) error {
|
||||
var err error
|
||||
// streamsPush pushes STREAMS modules if not already done so.
|
||||
func streamsPush(f *os.File, mod string) error {
|
||||
buf := []byte(mod)
|
||||
|
||||
// XXX I_FIND is not returning an error when the module
|
||||
// is already pushed even though truss reports a return
|
||||
// value of 1. A bug in the Go Solaris syscall interface?
|
||||
@@ -129,11 +144,9 @@ func streams_push(f *os.File, mod string) error {
|
||||
// https://www.illumos.org/issues/9042
|
||||
// but since we are not using libc or XPG4.2, we should not be
|
||||
// double-pushing modules
|
||||
|
||||
err = ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0])))
|
||||
if err != nil {
|
||||
|
||||
if err := ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))); err != nil {
|
||||
return nil
|
||||
}
|
||||
err = ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0])))
|
||||
return err
|
||||
return ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
// +build !linux,!darwin,!freebsd,!dragonfly,!openbsd,!solaris
|
||||
//go:build !linux && !darwin && !freebsd && !dragonfly && !netbsd && !openbsd && !solaris
|
||||
// +build !linux,!darwin,!freebsd,!dragonfly,!netbsd,!openbsd,!solaris
|
||||
|
||||
package pty
|
||||
|
||||
|
||||
+6
-23
@@ -1,5 +1,3 @@
|
||||
// +build !windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
@@ -13,23 +11,8 @@ import (
|
||||
// corresponding pty.
|
||||
//
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func Start(c *exec.Cmd) (pty *os.File, err error) {
|
||||
return StartWithSize(c, nil)
|
||||
}
|
||||
|
||||
// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding pty.
|
||||
//
|
||||
// This will resize the pty to the specified size before starting the command.
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
|
||||
if c.SysProcAttr == nil {
|
||||
c.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
c.SysProcAttr.Setsid = true
|
||||
c.SysProcAttr.Setctty = true
|
||||
return StartWithAttrs(c, sz, c.SysProcAttr)
|
||||
func Start(cmd *exec.Cmd) (*os.File, error) {
|
||||
return StartWithSize(cmd, nil)
|
||||
}
|
||||
|
||||
// StartWithAttrs assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
@@ -41,16 +24,16 @@ func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
|
||||
//
|
||||
// This should generally not be needed. Used in some edge cases where it is needed to create a pty
|
||||
// without a controlling terminal.
|
||||
func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (pty *os.File, err error) {
|
||||
func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (*os.File, error) {
|
||||
pty, tty, err := Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tty.Close()
|
||||
defer func() { _ = tty.Close() }() // Best effort.
|
||||
|
||||
if sz != nil {
|
||||
if err := Setsize(pty, sz); err != nil {
|
||||
pty.Close()
|
||||
_ = pty.Close() // Best effort.
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -67,7 +50,7 @@ func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (pty *
|
||||
c.SysProcAttr = attrs
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
_ = pty.Close()
|
||||
_ = pty.Close() // Best effort.
|
||||
return nil, err
|
||||
}
|
||||
return pty, err
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding pty.
|
||||
//
|
||||
// This will resize the pty to the specified size before starting the command.
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) {
|
||||
if cmd.SysProcAttr == nil {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
cmd.SysProcAttr.Setsid = true
|
||||
cmd.SysProcAttr.Setctty = true
|
||||
return StartWithAttrs(cmd, ws, cmd.SysProcAttr)
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
|
||||
// and c.Stderr, calls c.Start, and returns the File of the tty's
|
||||
// corresponding pty.
|
||||
//
|
||||
// This will resize the pty to the specified size before starting the command.
|
||||
// Starts the process in a new session and sets the controlling terminal.
|
||||
func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
+30
-16
@@ -4,31 +4,31 @@
|
||||
# Does not actually test the logic, just the compilation so we make sure we don't break code depending on the lib.
|
||||
|
||||
echo2() {
|
||||
echo $@ >&2
|
||||
echo $@ >&2
|
||||
}
|
||||
|
||||
trap end 0
|
||||
end() {
|
||||
[ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1)
|
||||
[ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1)
|
||||
}
|
||||
|
||||
cross() {
|
||||
os=$1
|
||||
shift
|
||||
echo2 "Build for $os."
|
||||
for arch in $@; do
|
||||
echo2 " - $os/$arch"
|
||||
GOOS=$os GOARCH=$arch go build
|
||||
done
|
||||
echo2
|
||||
os=$1
|
||||
shift
|
||||
echo2 "Build for $os."
|
||||
for arch in $@; do
|
||||
echo2 " - $os/$arch"
|
||||
GOOS=$os GOARCH=$arch go build
|
||||
done
|
||||
echo2
|
||||
}
|
||||
|
||||
set -e
|
||||
|
||||
cross linux amd64 386 arm arm64 ppc64 ppc64le s390x mips mipsle mips64 mips64le
|
||||
cross darwin amd64 386 arm arm64
|
||||
cross freebsd amd64 386 arm
|
||||
cross netbsd amd64 386 arm
|
||||
cross darwin amd64 arm64
|
||||
cross freebsd amd64 386 arm arm64
|
||||
cross netbsd amd64 386 arm arm64
|
||||
cross openbsd amd64 386 arm arm64
|
||||
cross dragonfly amd64
|
||||
cross solaris amd64
|
||||
@@ -41,10 +41,24 @@ cross windows amd64 386 arm
|
||||
|
||||
# Some os/arch require a different compiler. Run in docker.
|
||||
if ! hash docker; then
|
||||
# If docker is not present, stop here.
|
||||
return
|
||||
# If docker is not present, stop here.
|
||||
return
|
||||
fi
|
||||
|
||||
echo2 "Build for linux."
|
||||
echo2 " - linux/riscv"
|
||||
docker build -t test -f Dockerfile.riscv .
|
||||
docker build -t creack-pty-test -f Dockerfile.riscv .
|
||||
|
||||
# Golang dropped support for darwin 32bits since go1.15. Make sure the lib still compile with go1.14 on those archs.
|
||||
echo2 "Build for darwin (32bits)."
|
||||
echo2 " - darwin/386"
|
||||
docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=386 .
|
||||
echo2 " - darwin/arm"
|
||||
docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=arm .
|
||||
|
||||
# Run a single test for an old go version. Would be best with go1.0, but not available on Dockerhub.
|
||||
# Using 1.6 as it is the base version for the RISCV compiler.
|
||||
# Would also be better to run all the tests, not just one, need to refactor this file to allow for specifc archs per version.
|
||||
echo2 "Build for linux - go1.6."
|
||||
echo2 " - linux/amd64"
|
||||
docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.6 --build-arg=GOOS=linux --build-arg=GOARCH=amd64 .
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
// +build !windows,!solaris
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// InheritSize applies the terminal size of pty to tty. This should be run
|
||||
// in a signal handler for syscall.SIGWINCH to automatically resize the tty when
|
||||
// the pty receives a window size change notification.
|
||||
func InheritSize(pty, tty *os.File) error {
|
||||
size, err := GetsizeFull(pty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = Setsize(tty, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(t *os.File, ws *Winsize) error {
|
||||
return windowRectCall(ws, t.Fd(), syscall.TIOCSWINSZ)
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
||||
var ws Winsize
|
||||
err = windowRectCall(&ws, t.Fd(), syscall.TIOCGWINSZ)
|
||||
return &ws, err
|
||||
}
|
||||
|
||||
// Getsize returns the number of rows (lines) and cols (positions
|
||||
// in each line) in terminal t.
|
||||
func Getsize(t *os.File) (rows, cols int, err error) {
|
||||
ws, err := GetsizeFull(t)
|
||||
return int(ws.Rows), int(ws.Cols), err
|
||||
}
|
||||
|
||||
// Winsize describes the terminal size.
|
||||
type Winsize struct {
|
||||
Rows uint16 // ws_row: Number of rows (in cells)
|
||||
Cols uint16 // ws_col: Number of columns (in cells)
|
||||
X uint16 // ws_xpixel: Width in pixels
|
||||
Y uint16 // ws_ypixel: Height in pixels
|
||||
}
|
||||
|
||||
func windowRectCall(ws *Winsize, fd, a2 uintptr) error {
|
||||
_, _, errno := syscall.Syscall(
|
||||
syscall.SYS_IOCTL,
|
||||
fd,
|
||||
a2,
|
||||
uintptr(unsafe.Pointer(ws)),
|
||||
)
|
||||
if errno != 0 {
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
//
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = 21608 // 'T' << 8 | 104
|
||||
TIOCSWINSZ = 21607 // 'T' << 8 | 103
|
||||
)
|
||||
|
||||
// Winsize describes the terminal size.
|
||||
type Winsize struct {
|
||||
Rows uint16 // ws_row: Number of rows (in cells)
|
||||
Cols uint16 // ws_col: Number of columns (in cells)
|
||||
X uint16 // ws_xpixel: Width in pixels
|
||||
Y uint16 // ws_ypixel: Height in pixels
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
||||
var wsz *unix.Winsize
|
||||
wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &Winsize{wsz.Row, wsz.Col, wsz.Xpixel, wsz.Ypixel}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get Windows Size
|
||||
func Getsize(t *os.File) (rows, cols int, err error) {
|
||||
var wsz *unix.Winsize
|
||||
wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ)
|
||||
|
||||
if err != nil {
|
||||
return 80, 25, err
|
||||
} else {
|
||||
return int(wsz.Row), int(wsz.Col), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(t *os.File, ws *Winsize) error {
|
||||
wsz := unix.Winsize{ws.Rows, ws.Cols, ws.X, ws.Y}
|
||||
return unix.IoctlSetWinsize(int(t.Fd()), TIOCSWINSZ, &wsz)
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package pty
|
||||
|
||||
import "os"
|
||||
|
||||
// InheritSize applies the terminal size of pty to tty. This should be run
|
||||
// in a signal handler for syscall.SIGWINCH to automatically resize the tty when
|
||||
// the pty receives a window size change notification.
|
||||
func InheritSize(pty, tty *os.File) error {
|
||||
size, err := GetsizeFull(pty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Setsize(tty, size); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Getsize returns the number of rows (lines) and cols (positions
|
||||
// in each line) in terminal t.
|
||||
func Getsize(t *os.File) (rows, cols int, err error) {
|
||||
ws, err := GetsizeFull(t)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(ws.Rows), int(ws.Cols), nil
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Winsize describes the terminal size.
|
||||
type Winsize struct {
|
||||
Rows uint16 // ws_row: Number of rows (in cells)
|
||||
Cols uint16 // ws_col: Number of columns (in cells)
|
||||
X uint16 // ws_xpixel: Width in pixels
|
||||
Y uint16 // ws_ypixel: Height in pixels
|
||||
}
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(t *os.File, ws *Winsize) error {
|
||||
//nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
return ioctl(t.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(ws)))
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
||||
var ws Winsize
|
||||
|
||||
//nolint:gosec // Expected unsafe pointer for Syscall call.
|
||||
if err := ioctl(t.Fd(), syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ws, nil
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package pty
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Winsize is a dummy struct to enable compilation on unsupported platforms.
|
||||
type Winsize struct {
|
||||
Rows, Cols, X, Y uint16
|
||||
}
|
||||
|
||||
// Setsize resizes t to s.
|
||||
func Setsize(*os.File, *Winsize) error {
|
||||
return ErrUnsupported
|
||||
}
|
||||
|
||||
// GetsizeFull returns the full terminal size description.
|
||||
func GetsizeFull(*os.File) (*Winsize, error) {
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build 386
|
||||
// +build 386
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build arm
|
||||
// +build arm
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
// +build arm64
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build amd64 && dragonfly
|
||||
// +build amd64,dragonfly
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_dragonfly.go
|
||||
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build 386 && freebsd
|
||||
// +build 386,freebsd
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build amd64 && freebsd
|
||||
// +build amd64,freebsd
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build arm && freebsd
|
||||
// +build arm,freebsd
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
+3
@@ -1,3 +1,6 @@
|
||||
//go:build arm64 && freebsd
|
||||
// +build arm64,freebsd
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types_freebsd.go
|
||||
|
||||
package pty
|
||||
|
||||
const (
|
||||
_C_SPECNAMELEN = 0x3f
|
||||
)
|
||||
|
||||
type fiodgnameArg struct {
|
||||
Len int32
|
||||
Pad_cgo_0 [4]byte
|
||||
Buf *byte
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
//go:build loong64
|
||||
// +build loong64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
_C_int int32
|
||||
_C_uint uint32
|
||||
)
|
||||
+4
-3
@@ -1,9 +1,10 @@
|
||||
//go:build (mips || mipsle || mips64 || mips64le) && linux
|
||||
// +build mips mipsle mips64 mips64le
|
||||
// +build linux
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
// cgo -godefs types.go
|
||||
|
||||
// +build linux
|
||||
// +build mips mipsle mips64 mips64le
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
//go:build (386 || amd64 || arm || arm64) && netbsd
|
||||
// +build 386 amd64 arm arm64
|
||||
// +build netbsd
|
||||
|
||||
package pty
|
||||
|
||||
type ptmget struct {
|
||||
Cfd int32
|
||||
Sfd int32
|
||||
Cn [1024]int8
|
||||
Sn [1024]int8
|
||||
}
|
||||
|
||||
var (
|
||||
ioctl_TIOCPTSNAME = 0x48087448
|
||||
ioctl_TIOCGRANTPT = 0x20007447
|
||||
)
|
||||
+6
-5
@@ -1,13 +1,14 @@
|
||||
//go:build (386 || amd64 || arm || arm64 || mips64) && openbsd
|
||||
// +build 386 amd64 arm arm64 mips64
|
||||
// +build openbsd
|
||||
// +build 386 amd64 arm arm64
|
||||
|
||||
package pty
|
||||
|
||||
type ptmget struct {
|
||||
Cfd int32
|
||||
Sfd int32
|
||||
Cn [16]int8
|
||||
Sn [16]int8
|
||||
Cfd int32
|
||||
Sfd int32
|
||||
Cn [16]int8
|
||||
Sn [16]int8
|
||||
}
|
||||
|
||||
var ioctl_PTMGET = 0x40287401
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//go:build ppc64
|
||||
// +build ppc64
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//go:build ppc64le
|
||||
// +build ppc64le
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
//go:build riscv || riscv64
|
||||
// +build riscv riscv64
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types.go
|
||||
|
||||
// +build riscv riscv64
|
||||
|
||||
package pty
|
||||
|
||||
type (
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
//go:build s390x
|
||||
// +build s390x
|
||||
|
||||
// Created by cgo -godefs - DO NOT EDIT
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
bin/
|
||||
+7
@@ -18,3 +18,10 @@ run:
|
||||
deadline: 2m
|
||||
skip-dirs:
|
||||
- vendor
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# io/ioutil is deprecated, but won't be removed until Go v2. It's safe to ignore for the release/2.8 branch.
|
||||
- text: "SA1019: \"io/ioutil\" has been deprecated since Go 1.16"
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
+4
-2
@@ -44,6 +44,8 @@ Thomas Berger <loki@lokis-chaos.de> Thomas Berger <tbe@users.noreply.github.com>
|
||||
Samuel Karp <skarp@amazon.com> Samuel Karp <samuelkarp@users.noreply.github.com>
|
||||
Justin Cormack <justin.cormack@docker.com>
|
||||
sayboras <sayboras@yahoo.com>
|
||||
CrazyMax <github@crazymax.dev>
|
||||
CrazyMax <github@crazymax.dev> <1951866+crazy-max@users.noreply.github.com>
|
||||
CrazyMax <github@crazymax.dev> <crazy-max@users.noreply.github.com>
|
||||
Hayley Swimelar <hswimelar@gmail.com>
|
||||
Jose D. Gomez R <jose.gomez@suse.com>
|
||||
Shengjing Zhu <zhsj@debian.org>
|
||||
Silvin Lubecki <31478878+silvin-lubecki@users.noreply.github.com>
|
||||
|
||||
+46
-36
@@ -1,49 +1,59 @@
|
||||
# syntax=docker/dockerfile:1.3
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.16.15
|
||||
ARG GORELEASER_XX_VERSION=1.2.5
|
||||
ARG GO_VERSION=1.19.9
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG XX_VERSION=1.2.1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM crazymax/goreleaser-xx:${GORELEASER_XX_VERSION} AS goreleaser-xx
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS base
|
||||
COPY --from=goreleaser-xx / /
|
||||
RUN apk add --no-cache file git
|
||||
WORKDIR /go/src/github.com/docker/distribution
|
||||
|
||||
FROM base AS build
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
|
||||
COPY --from=xx / /
|
||||
RUN apk add --no-cache bash coreutils file git
|
||||
ENV GO111MODULE=auto
|
||||
ENV CGO_ENABLED=0
|
||||
# GIT_REF is used by goreleaser-xx to handle the proper git ref when available.
|
||||
# It will fallback to the working tree info if empty and use "git tag --points-at"
|
||||
# or "git describe" to define the version info.
|
||||
ARG GIT_REF
|
||||
ARG TARGETPLATFORM
|
||||
ARG PKG="github.com/distribution/distribution"
|
||||
ARG BUILDTAGS="include_oss include_gcs"
|
||||
RUN --mount=type=bind,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=target=/go/pkg/mod,type=cache \
|
||||
goreleaser-xx --debug \
|
||||
--name="registry" \
|
||||
--dist="/out" \
|
||||
--main="./cmd/registry" \
|
||||
--flags="-v" \
|
||||
--ldflags="-s -w -X '$PKG/version.Version={{.Version}}' -X '$PKG/version.Revision={{.Commit}}' -X '$PKG/version.Package=$PKG'" \
|
||||
--tags="$BUILDTAGS" \
|
||||
--files="LICENSE" \
|
||||
--files="README.md"
|
||||
WORKDIR /go/src/github.com/docker/distribution
|
||||
|
||||
FROM scratch AS artifact
|
||||
COPY --from=build /out/*.tar.gz /
|
||||
COPY --from=build /out/*.zip /
|
||||
COPY --from=build /out/*.sha256 /
|
||||
FROM base AS version
|
||||
ARG PKG="github.com/docker/distribution"
|
||||
RUN --mount=target=. \
|
||||
VERSION=$(git describe --match 'v[0-9]*' --dirty='.m' --always --tags) REVISION=$(git rev-parse HEAD)$(if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi); \
|
||||
echo "-X ${PKG}/version.Version=${VERSION#v} -X ${PKG}/version.Revision=${REVISION} -X ${PKG}/version.Package=${PKG}" | tee /tmp/.ldflags; \
|
||||
echo -n "${VERSION}" | tee /tmp/.version;
|
||||
|
||||
FROM base AS build
|
||||
ARG TARGETPLATFORM
|
||||
ARG LDFLAGS="-s -w"
|
||||
ARG BUILDTAGS="include_oss include_gcs"
|
||||
RUN --mount=type=bind,target=/go/src/github.com/docker/distribution,rw \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=target=/go/pkg/mod,type=cache \
|
||||
--mount=type=bind,source=/tmp/.ldflags,target=/tmp/.ldflags,from=version \
|
||||
set -x ; xx-go build -trimpath -ldflags "$(cat /tmp/.ldflags) ${LDFLAGS}" -o /usr/bin/registry ./cmd/registry \
|
||||
&& xx-verify --static /usr/bin/registry
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /usr/local/bin/registry* /
|
||||
COPY --from=build /usr/bin/registry /
|
||||
|
||||
FROM alpine:3.14
|
||||
FROM base AS releaser
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
WORKDIR /work
|
||||
RUN --mount=from=binary,target=/build \
|
||||
--mount=type=bind,target=/src \
|
||||
--mount=type=bind,source=/tmp/.version,target=/tmp/.version,from=version \
|
||||
VERSION=$(cat /tmp/.version) \
|
||||
&& mkdir -p /out \
|
||||
&& cp /build/registry /src/README.md /src/LICENSE . \
|
||||
&& tar -czvf "/out/registry_${VERSION#v}_${TARGETOS}_${TARGETARCH}${TARGETVARIANT}.tar.gz" * \
|
||||
&& sha256sum -z "/out/registry_${VERSION#v}_${TARGETOS}_${TARGETARCH}${TARGETVARIANT}.tar.gz" | awk '{ print $1 }' > "/out/registry_${VERSION#v}_${TARGETOS}_${TARGETARCH}${TARGETVARIANT}.tar.gz.sha256"
|
||||
|
||||
FROM scratch AS artifact
|
||||
COPY --from=releaser /out /
|
||||
|
||||
FROM alpine:${ALPINE_VERSION}
|
||||
RUN apk add --no-cache ca-certificates
|
||||
COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml
|
||||
COPY --from=build /usr/local/bin/registry /bin/registry
|
||||
COPY --from=binary /registry /bin/registry
|
||||
VOLUME ["/var/lib/registry"]
|
||||
EXPOSE 5000
|
||||
ENTRYPOINT ["registry"]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user