Merge component 'engine' from git@github.com:docker/engine master
This commit is contained in:
@@ -3,6 +3,7 @@ package volume // import "github.com/docker/docker/api/server/router/volume"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/volume/service/opts"
|
||||
// TODO return types need to be refactored into pkg
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
@@ -11,9 +12,9 @@ import (
|
||||
// Backend is the methods that need to be implemented to provide
|
||||
// volume specific functionality
|
||||
type Backend interface {
|
||||
Volumes(filter string) ([]*types.Volume, []string, error)
|
||||
VolumeInspect(name string) (*types.Volume, error)
|
||||
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
||||
VolumeRm(name string, force bool) error
|
||||
VolumesPrune(ctx context.Context, pruneFilters filters.Args) (*types.VolumesPruneReport, error)
|
||||
List(ctx context.Context, filter filters.Args) ([]*types.Volume, []string, error)
|
||||
Get(ctx context.Context, name string, opts ...opts.GetOption) (*types.Volume, error)
|
||||
Create(ctx context.Context, name, driverName string, opts ...opts.CreateOption) (*types.Volume, error)
|
||||
Remove(ctx context.Context, name string, opts ...opts.RemoveOption) error
|
||||
Prune(ctx context.Context, pruneFilters filters.Args) (*types.VolumesPruneReport, error)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package volume // import "github.com/docker/docker/api/server/router/volume"
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
@@ -11,6 +10,8 @@ import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
volumetypes "github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/volume/service/opts"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (v *volumeRouter) getVolumesList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
@@ -18,7 +19,11 @@ func (v *volumeRouter) getVolumesList(ctx context.Context, w http.ResponseWriter
|
||||
return err
|
||||
}
|
||||
|
||||
volumes, warnings, err := v.backend.Volumes(r.Form.Get("filters"))
|
||||
filters, err := filters.FromJSON(r.Form.Get("filters"))
|
||||
if err != nil {
|
||||
return errdefs.InvalidParameter(errors.Wrap(err, "error reading volume filters"))
|
||||
}
|
||||
volumes, warnings, err := v.backend.List(ctx, filters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -30,7 +35,7 @@ func (v *volumeRouter) getVolumeByName(ctx context.Context, w http.ResponseWrite
|
||||
return err
|
||||
}
|
||||
|
||||
volume, err := v.backend.VolumeInspect(vars["name"])
|
||||
volume, err := v.backend.Get(ctx, vars["name"], opts.WithGetResolveStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -54,7 +59,7 @@ func (v *volumeRouter) postVolumesCreate(ctx context.Context, w http.ResponseWri
|
||||
return err
|
||||
}
|
||||
|
||||
volume, err := v.backend.VolumeCreate(req.Name, req.Driver, req.DriverOpts, req.Labels)
|
||||
volume, err := v.backend.Create(ctx, req.Name, req.Driver, opts.WithCreateOptions(req.DriverOpts), opts.WithCreateLabels(req.Labels))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,7 +71,7 @@ func (v *volumeRouter) deleteVolumes(ctx context.Context, w http.ResponseWriter,
|
||||
return err
|
||||
}
|
||||
force := httputils.BoolValue(r, "force")
|
||||
if err := v.backend.VolumeRm(vars["name"], force); err != nil {
|
||||
if err := v.backend.Remove(ctx, vars["name"], opts.WithPurgeOnError(force)); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
@@ -83,7 +88,7 @@ func (v *volumeRouter) postVolumesPrune(ctx context.Context, w http.ResponseWrit
|
||||
return err
|
||||
}
|
||||
|
||||
pruneReport, err := v.backend.VolumesPrune(ctx, pruneFilters)
|
||||
pruneReport, err := v.backend.Prune(ctx, pruneFilters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ func initRouter(opts routerOptions) {
|
||||
container.NewRouter(opts.daemon, decoder),
|
||||
image.NewRouter(opts.daemon.ImageService()),
|
||||
systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache),
|
||||
volume.NewRouter(opts.daemon),
|
||||
volume.NewRouter(opts.daemon.VolumesService()),
|
||||
build.NewRouter(opts.buildBackend, opts.daemon),
|
||||
sessionrouter.NewRouter(opts.sessionManager),
|
||||
swarmrouter.NewRouter(opts.cluster),
|
||||
@@ -595,6 +595,7 @@ func createAndStartCluster(cli *DaemonCli, d *daemon.Daemon) (*cluster.Cluster,
|
||||
Root: cli.Config.Root,
|
||||
Name: name,
|
||||
Backend: d,
|
||||
VolumeBackend: d.VolumesService(),
|
||||
ImageBackend: d.ImageService(),
|
||||
PluginBackend: d.PluginManager(),
|
||||
NetworkSubnetsProvider: d,
|
||||
|
||||
@@ -128,7 +128,7 @@ func (container *Container) CopyImagePathContent(v volume.Volume, destination st
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = ioutil.ReadDir(rootfs); err != nil {
|
||||
if _, err := os.Stat(rootfs); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ type Config struct {
|
||||
Backend executorpkg.Backend
|
||||
ImageBackend executorpkg.ImageBackend
|
||||
PluginBackend plugin.Backend
|
||||
VolumeBackend executorpkg.VolumeBackend
|
||||
NetworkSubnetsProvider NetworkSubnetsProvider
|
||||
|
||||
// DefaultAdvertiseAddr is the default host/IP or network interface to use
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
||||
networkSettings "github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/plugin"
|
||||
volumeopts "github.com/docker/docker/volume/service/opts"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/cluster"
|
||||
networktypes "github.com/docker/libnetwork/types"
|
||||
@@ -47,7 +48,6 @@ type Backend interface {
|
||||
SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error
|
||||
SetContainerConfigReferences(name string, refs []*swarmtypes.ConfigReference) error
|
||||
SystemInfo() (*types.Info, error)
|
||||
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
||||
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
||||
DaemonJoinsCluster(provider cluster.Provider)
|
||||
@@ -62,6 +62,11 @@ type Backend interface {
|
||||
GetAttachmentStore() *networkSettings.AttachmentStore
|
||||
}
|
||||
|
||||
// VolumeBackend is used by an executor to perform volume operations
|
||||
type VolumeBackend interface {
|
||||
Create(ctx context.Context, name, driverName string, opts ...volumeopts.CreateOption) (*types.Volume, error)
|
||||
}
|
||||
|
||||
// ImageBackend is used by an executor to perform image operations
|
||||
type ImageBackend interface {
|
||||
PullImage(ctx context.Context, image, tag, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/docker/docker/daemon"
|
||||
"github.com/docker/docker/daemon/cluster/convert"
|
||||
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
||||
volumeopts "github.com/docker/docker/volume/service/opts"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/swarmkit/agent/exec"
|
||||
"github.com/docker/swarmkit/api"
|
||||
@@ -36,23 +37,25 @@ import (
|
||||
// are mostly naked calls to the client API, seeded with information from
|
||||
// containerConfig.
|
||||
type containerAdapter struct {
|
||||
backend executorpkg.Backend
|
||||
imageBackend executorpkg.ImageBackend
|
||||
container *containerConfig
|
||||
dependencies exec.DependencyGetter
|
||||
backend executorpkg.Backend
|
||||
imageBackend executorpkg.ImageBackend
|
||||
volumeBackend executorpkg.VolumeBackend
|
||||
container *containerConfig
|
||||
dependencies exec.DependencyGetter
|
||||
}
|
||||
|
||||
func newContainerAdapter(b executorpkg.Backend, i executorpkg.ImageBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*containerAdapter, error) {
|
||||
func newContainerAdapter(b executorpkg.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*containerAdapter, error) {
|
||||
ctnr, err := newContainerConfig(task, node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &containerAdapter{
|
||||
container: ctnr,
|
||||
backend: b,
|
||||
imageBackend: i,
|
||||
dependencies: dependencies,
|
||||
container: ctnr,
|
||||
backend: b,
|
||||
imageBackend: i,
|
||||
volumeBackend: v,
|
||||
dependencies: dependencies,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -388,7 +391,10 @@ func (c *containerAdapter) createVolumes(ctx context.Context) error {
|
||||
req := c.container.volumeCreateRequest(&mount)
|
||||
|
||||
// Check if this volume exists on the engine
|
||||
if _, err := c.backend.VolumeCreate(req.Name, req.Driver, req.DriverOpts, req.Labels); err != nil {
|
||||
if _, err := c.volumeBackend.Create(ctx, req.Name, req.Driver,
|
||||
volumeopts.WithCreateOptions(req.DriverOpts),
|
||||
volumeopts.WithCreateLabels(req.Labels),
|
||||
); err != nil {
|
||||
// TODO(amitshukla): Today, volume create through the engine api does not return an error
|
||||
// when the named volume with the same parameters already exists.
|
||||
// It returns an error if the driver name is different - that is a valid error
|
||||
|
||||
@@ -21,8 +21,8 @@ type networkAttacherController struct {
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
func newNetworkAttacherController(b executorpkg.Backend, i executorpkg.ImageBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*networkAttacherController, error) {
|
||||
adapter, err := newContainerAdapter(b, i, task, node, dependencies)
|
||||
func newNetworkAttacherController(b executorpkg.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*networkAttacherController, error) {
|
||||
adapter, err := newContainerAdapter(b, i, v, task, node, dependencies)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ type controller struct {
|
||||
var _ exec.Controller = &controller{}
|
||||
|
||||
// NewController returns a docker exec runner for the provided task.
|
||||
func newController(b executorpkg.Backend, i executorpkg.ImageBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*controller, error) {
|
||||
adapter, err := newContainerAdapter(b, i, task, node, dependencies)
|
||||
func newController(b executorpkg.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*controller, error) {
|
||||
adapter, err := newContainerAdapter(b, i, v, task, node, dependencies)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -28,17 +28,19 @@ type executor struct {
|
||||
backend executorpkg.Backend
|
||||
imageBackend executorpkg.ImageBackend
|
||||
pluginBackend plugin.Backend
|
||||
volumeBackend executorpkg.VolumeBackend
|
||||
dependencies exec.DependencyManager
|
||||
mutex sync.Mutex // This mutex protects the following node field
|
||||
node *api.NodeDescription
|
||||
}
|
||||
|
||||
// NewExecutor returns an executor from the docker client.
|
||||
func NewExecutor(b executorpkg.Backend, p plugin.Backend, i executorpkg.ImageBackend) exec.Executor {
|
||||
func NewExecutor(b executorpkg.Backend, p plugin.Backend, i executorpkg.ImageBackend, v executorpkg.VolumeBackend) exec.Executor {
|
||||
return &executor{
|
||||
backend: b,
|
||||
pluginBackend: p,
|
||||
imageBackend: i,
|
||||
volumeBackend: v,
|
||||
dependencies: agent.NewDependencyManager(),
|
||||
}
|
||||
}
|
||||
@@ -211,7 +213,7 @@ func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
|
||||
e.mutex.Unlock()
|
||||
|
||||
if t.Spec.GetAttachment() != nil {
|
||||
return newNetworkAttacherController(e.backend, e.imageBackend, t, nodeDescription, dependencyGetter)
|
||||
return newNetworkAttacherController(e.backend, e.imageBackend, e.volumeBackend, t, nodeDescription, dependencyGetter)
|
||||
}
|
||||
|
||||
var ctlr exec.Controller
|
||||
@@ -240,7 +242,7 @@ func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
|
||||
return ctlr, fmt.Errorf("unsupported runtime type: %q", runtimeKind)
|
||||
}
|
||||
case *api.TaskSpec_Container:
|
||||
c, err := newController(e.backend, e.imageBackend, t, nodeDescription, dependencyGetter)
|
||||
c, err := newController(e.backend, e.imageBackend, e.volumeBackend, t, nodeDescription, dependencyGetter)
|
||||
if err != nil {
|
||||
return ctlr, err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestHealthStates(t *testing.T) {
|
||||
EventsService: e,
|
||||
}
|
||||
|
||||
controller, err := newController(daemon, nil, task, nil, nil)
|
||||
controller, err := newController(daemon, nil, nil, task, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("create controller fail %v", err)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func newTestControllerWithMount(m api.Mount) (*controller, error) {
|
||||
return newController(&daemon.Daemon{}, nil, &api.Task{
|
||||
return newController(&daemon.Daemon{}, nil, nil, &api.Task{
|
||||
ID: stringid.GenerateRandomID(),
|
||||
ServiceID: stringid.GenerateRandomID(),
|
||||
Spec: api.TaskSpec{
|
||||
|
||||
@@ -123,7 +123,9 @@ func (n *nodeRunner) start(conf nodeStartConfig) error {
|
||||
Executor: container.NewExecutor(
|
||||
n.cluster.config.Backend,
|
||||
n.cluster.config.PluginBackend,
|
||||
n.cluster.config.ImageBackend),
|
||||
n.cluster.config.ImageBackend,
|
||||
n.cluster.config.VolumeBackend,
|
||||
),
|
||||
HeartbeatTick: n.cluster.config.RaftHeartbeatTick,
|
||||
// Recommended value in etcd/raft is 10 x (HeartbeatTick).
|
||||
// Lower values were seen to have caused instability because of
|
||||
|
||||
@@ -7,8 +7,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
networktypes "github.com/docker/docker/api/types/network"
|
||||
@@ -16,10 +14,10 @@ import (
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -255,24 +253,6 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// VolumeCreate creates a volume with the specified name, driver, and opts
|
||||
// This is called directly from the Engine API
|
||||
func (daemon *Daemon) VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error) {
|
||||
if name == "" {
|
||||
name = stringid.GenerateNonCryptoID()
|
||||
}
|
||||
|
||||
v, err := daemon.volumes.Create(name, driverName, opts, labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
daemon.LogVolumeEvent(v.Name(), "create", map[string]string{"driver": v.DriverName()})
|
||||
apiV := volumeToAPIType(v)
|
||||
apiV.Mountpoint = v.Path()
|
||||
return apiV, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error {
|
||||
if img != nil && img.Config != nil {
|
||||
if err := merge(config, img.Config); err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
mounttypes "github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
volumeopts "github.com/docker/docker/volume/service/opts"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -46,16 +48,16 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
|
||||
return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
|
||||
}
|
||||
|
||||
v, err := daemon.volumes.CreateWithRef(name, hostConfig.VolumeDriver, container.ID, nil, nil)
|
||||
v, err := daemon.volumes.Create(context.TODO(), name, hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := label.Relabel(v.Path(), container.MountLabel, true); err != nil {
|
||||
if err := label.Relabel(v.Mountpoint, container.MountLabel, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
container.AddMountPointWithVolume(destination, v, true)
|
||||
container.AddMountPointWithVolume(destination, &volumeWrapper{v: v, s: daemon.volumes}, true)
|
||||
}
|
||||
return daemon.populateVolumes(container)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
volumeopts "github.com/docker/docker/volume/service/opts"
|
||||
)
|
||||
|
||||
// createContainerOSSpecificSettings performs host-OS specific container create functionality
|
||||
@@ -49,7 +51,7 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
|
||||
|
||||
// Create the volume in the volume driver. If it doesn't exist,
|
||||
// a new one will be created.
|
||||
v, err := daemon.volumes.CreateWithRef(mp.Name, volumeDriver, container.ID, nil, nil)
|
||||
v, err := daemon.volumes.Create(context.TODO(), mp.Name, volumeDriver, volumeopts.WithCreateReference(container.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -85,7 +87,7 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
|
||||
// }
|
||||
|
||||
// Add it to container.MountPoints
|
||||
container.AddMountPointWithVolume(mp.Destination, v, mp.RW)
|
||||
container.AddMountPointWithVolume(mp.Destination, &volumeWrapper{v: v, s: daemon.volumes}, mp.RW)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -52,9 +52,7 @@ import (
|
||||
refstore "github.com/docker/docker/reference"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/docker/runconfig"
|
||||
volumedrivers "github.com/docker/docker/volume/drivers"
|
||||
"github.com/docker/docker/volume/local"
|
||||
"github.com/docker/docker/volume/store"
|
||||
volumesservice "github.com/docker/docker/volume/service"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/cluster"
|
||||
nwconfig "github.com/docker/libnetwork/config"
|
||||
@@ -83,7 +81,7 @@ type Daemon struct {
|
||||
RegistryService registry.Service
|
||||
EventsService *events.Events
|
||||
netController libnetwork.NetworkController
|
||||
volumes *store.VolumeStore
|
||||
volumes *volumesservice.VolumesService
|
||||
discoveryWatcher discovery.Reloader
|
||||
root string
|
||||
seccompEnabled bool
|
||||
@@ -784,8 +782,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Configure the volumes driver
|
||||
volStore, err := d.configureVolumes(rootIDs)
|
||||
d.volumes, err = volumesservice.NewVolumeService(config.Root, d.PluginStore, rootIDs, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -855,7 +852,6 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
|
||||
d.statsCollector = d.newStatsCollector(1 * time.Second)
|
||||
|
||||
d.EventsService = events.New()
|
||||
d.volumes = volStore
|
||||
d.root = config.Root
|
||||
d.idMappings = idMappings
|
||||
d.seccompEnabled = sysInfo.Seccomp
|
||||
@@ -1144,18 +1140,6 @@ func setDefaultMtu(conf *config.Config) {
|
||||
conf.Mtu = config.DefaultNetworkMtu
|
||||
}
|
||||
|
||||
func (daemon *Daemon) configureVolumes(rootIDs idtools.IDPair) (*store.VolumeStore, error) {
|
||||
volumeDriver, err := local.New(daemon.configStore.Root, rootIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
drivers := volumedrivers.NewStore(daemon.PluginStore)
|
||||
if !drivers.Register(volumeDriver, volumeDriver.Name()) {
|
||||
return nil, errors.New("local volume driver could not be registered")
|
||||
}
|
||||
return store.New(daemon.configStore.Root, drivers)
|
||||
}
|
||||
|
||||
// IsShuttingDown tells whether the daemon is shutting down or not
|
||||
func (daemon *Daemon) IsShuttingDown() bool {
|
||||
return daemon.shutdown
|
||||
|
||||
@@ -13,9 +13,7 @@ import (
|
||||
_ "github.com/docker/docker/pkg/discovery/memory"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/truncindex"
|
||||
volumedrivers "github.com/docker/docker/volume/drivers"
|
||||
"github.com/docker/docker/volume/local"
|
||||
"github.com/docker/docker/volume/store"
|
||||
volumesservice "github.com/docker/docker/volume/service"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
@@ -120,18 +118,10 @@ func initDaemonWithVolumeStore(tmp string) (*Daemon, error) {
|
||||
repository: tmp,
|
||||
root: tmp,
|
||||
}
|
||||
drivers := volumedrivers.NewStore(nil)
|
||||
daemon.volumes, err = store.New(tmp, drivers)
|
||||
daemon.volumes, err = volumesservice.NewVolumeService(tmp, nil, idtools.IDPair{UID: 0, GID: 0}, daemon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
volumesDriver, err := local.New(tmp, idtools.IDPair{UID: 0, GID: 0})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
drivers.Register(volumesDriver, volumesDriver.Name())
|
||||
|
||||
return daemon, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/volume"
|
||||
volumestore "github.com/docker/docker/volume/store"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -152,35 +150,3 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
|
||||
daemon.LogContainerEvent(container, "destroy")
|
||||
return nil
|
||||
}
|
||||
|
||||
// VolumeRm removes the volume with the given name.
|
||||
// If the volume is referenced by a container it is not removed
|
||||
// This is called directly from the Engine API
|
||||
func (daemon *Daemon) VolumeRm(name string, force bool) error {
|
||||
v, err := daemon.volumes.Get(name)
|
||||
if err != nil {
|
||||
if force && volumestore.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
err = daemon.volumeRm(v)
|
||||
if err != nil && volumestore.IsInUse(err) {
|
||||
return errdefs.Conflict(err)
|
||||
}
|
||||
|
||||
if err == nil || force {
|
||||
daemon.volumes.Purge(name)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (daemon *Daemon) volumeRm(v volume.Volume) error {
|
||||
if err := daemon.volumes.Remove(v); err != nil {
|
||||
return errors.Wrap(err, "unable to remove volume")
|
||||
}
|
||||
daemon.LogVolumeEvent(v.Name(), "destroy", map[string]string{"driver": v.DriverName()})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/pkg/directory"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// SystemDiskUsage returns information about the daemon data disk usage
|
||||
@@ -34,39 +31,11 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er
|
||||
return nil, fmt.Errorf("failed to retrieve image list: %v", err)
|
||||
}
|
||||
|
||||
volumes, err := daemon.volumes.FilterByDriver(volume.DefaultDriverName)
|
||||
localVolumes, err := daemon.volumes.LocalVolumesSize(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var allVolumes []*types.Volume
|
||||
for _, v := range volumes {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
if d, ok := v.(volume.DetailedVolume); ok {
|
||||
if len(d.Options()) > 0 {
|
||||
// skip local volumes with mount options since these could have external
|
||||
// mounted filesystems that will be slow to enumerate.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
name := v.Name()
|
||||
refs := daemon.volumes.Refs(v)
|
||||
|
||||
tv := volumeToAPIType(v)
|
||||
sz, err := directory.Size(ctx, v.Path())
|
||||
if err != nil {
|
||||
logrus.Warnf("failed to determine size of volume %v", name)
|
||||
sz = -1
|
||||
}
|
||||
tv.UsageData = &types.VolumeUsageData{Size: sz, RefCount: int64(len(refs))}
|
||||
allVolumes = append(allVolumes, tv)
|
||||
}
|
||||
|
||||
allLayersSize, err := daemon.imageService.LayerDiskUsage(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -75,7 +44,7 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er
|
||||
return &types.DiskUsage{
|
||||
LayersSize: allLayersSize,
|
||||
Containers: allContainers,
|
||||
Volumes: allVolumes,
|
||||
Volumes: localVolumes,
|
||||
Images: allImages,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -18,10 +18,6 @@ func containerNotFound(id string) error {
|
||||
return objNotFoundError{"container", id}
|
||||
}
|
||||
|
||||
func volumeNotFound(id string) error {
|
||||
return objNotFoundError{"volume", id}
|
||||
}
|
||||
|
||||
type objNotFoundError struct {
|
||||
object string
|
||||
id string
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -26,7 +27,7 @@ var imagesAcceptedFilters = map[string]bool{
|
||||
|
||||
// errPruneRunning is returned when a prune request is received while
|
||||
// one is in progress
|
||||
var errPruneRunning = fmt.Errorf("a prune operation is already running")
|
||||
var errPruneRunning = errdefs.Conflict(errors.New("a prune operation is already running"))
|
||||
|
||||
// ImagesPrune removes unused images
|
||||
func (i *ImageService) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/errdefs"
|
||||
volumestore "github.com/docker/docker/volume/store"
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
@@ -236,22 +235,6 @@ func (daemon *Daemon) ContainerExecInspect(id string) (*backend.ExecInspect, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
// VolumeInspect looks up a volume by name. An error is returned if
|
||||
// the volume cannot be found.
|
||||
func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) {
|
||||
v, err := daemon.volumes.Get(name)
|
||||
if err != nil {
|
||||
if volumestore.IsNotExist(err) {
|
||||
return nil, volumeNotFound(name)
|
||||
}
|
||||
return nil, errdefs.System(err)
|
||||
}
|
||||
apiV := volumeToAPIType(v)
|
||||
apiV.Mountpoint = v.Path()
|
||||
apiV.Status = v.Status()
|
||||
return apiV, nil
|
||||
}
|
||||
|
||||
func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings {
|
||||
result := &v1p20.NetworkSettings{
|
||||
NetworkSettingsBase: types.NetworkSettingsBase{
|
||||
|
||||
@@ -12,19 +12,11 @@ import (
|
||||
"github.com/docker/docker/daemon/images"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var acceptedVolumeFilterTags = map[string]bool{
|
||||
"dangling": true,
|
||||
"name": true,
|
||||
"driver": true,
|
||||
"label": true,
|
||||
}
|
||||
|
||||
var acceptedPsFilterTags = map[string]bool{
|
||||
"ancestor": true,
|
||||
"before": true,
|
||||
@@ -605,87 +597,6 @@ func (daemon *Daemon) refreshImage(s *container.Snapshot, ctx *listContext) (*ty
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// Volumes lists known volumes, using the filter to restrict the range
|
||||
// of volumes returned.
|
||||
func (daemon *Daemon) Volumes(filter string) ([]*types.Volume, []string, error) {
|
||||
var (
|
||||
volumesOut []*types.Volume
|
||||
)
|
||||
volFilters, err := filters.FromJSON(filter)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := volFilters.Validate(acceptedVolumeFilterTags); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
volumes, warnings, err := daemon.volumes.List()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
filterVolumes, err := daemon.filterVolumes(volumes, volFilters)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, v := range filterVolumes {
|
||||
apiV := volumeToAPIType(v)
|
||||
if vv, ok := v.(interface {
|
||||
CachedPath() string
|
||||
}); ok {
|
||||
apiV.Mountpoint = vv.CachedPath()
|
||||
} else {
|
||||
apiV.Mountpoint = v.Path()
|
||||
}
|
||||
volumesOut = append(volumesOut, apiV)
|
||||
}
|
||||
return volumesOut, warnings, nil
|
||||
}
|
||||
|
||||
// filterVolumes filters volume list according to user specified filter
|
||||
// and returns user chosen volumes
|
||||
func (daemon *Daemon) filterVolumes(vols []volume.Volume, filter filters.Args) ([]volume.Volume, error) {
|
||||
// if filter is empty, return original volume list
|
||||
if filter.Len() == 0 {
|
||||
return vols, nil
|
||||
}
|
||||
|
||||
var retVols []volume.Volume
|
||||
for _, vol := range vols {
|
||||
if filter.Contains("name") {
|
||||
if !filter.Match("name", vol.Name()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if filter.Contains("driver") {
|
||||
if !filter.ExactMatch("driver", vol.DriverName()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if filter.Contains("label") {
|
||||
v, ok := vol.(volume.DetailedVolume)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !filter.MatchKVList("label", v.Labels()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
retVols = append(retVols, vol)
|
||||
}
|
||||
danglingOnly := false
|
||||
if filter.Contains("dangling") {
|
||||
if filter.ExactMatch("dangling", "true") || filter.ExactMatch("dangling", "1") {
|
||||
danglingOnly = true
|
||||
} else if !filter.ExactMatch("dangling", "false") && !filter.ExactMatch("dangling", "0") {
|
||||
return nil, invalidFilter{"dangling", filter.Get("dangling")}
|
||||
}
|
||||
retVols = daemon.volumes.FilterByUsed(retVols, !danglingOnly)
|
||||
}
|
||||
return retVols, nil
|
||||
}
|
||||
|
||||
func populateImageFilterByParents(ancestorMap map[image.ID]bool, imageID image.ID, getChildren func(image.ID) []image.ID) {
|
||||
if !ancestorMap[imageID] {
|
||||
for _, id := range getChildren(imageID) {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
mounttypes "github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/container"
|
||||
volumestore "github.com/docker/docker/volume/store"
|
||||
volumesservice "github.com/docker/docker/volume/service"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) prepareMountPoints(container *container.Container) error {
|
||||
@@ -20,11 +21,12 @@ func (daemon *Daemon) prepareMountPoints(container *container.Container) error {
|
||||
|
||||
func (daemon *Daemon) removeMountPoints(container *container.Container, rm bool) error {
|
||||
var rmErrors []string
|
||||
ctx := context.TODO()
|
||||
for _, m := range container.MountPoints {
|
||||
if m.Type != mounttypes.TypeVolume || m.Volume == nil {
|
||||
continue
|
||||
}
|
||||
daemon.volumes.Dereference(m.Volume, container.ID)
|
||||
daemon.volumes.Release(ctx, m.Volume.Name(), container.ID)
|
||||
if !rm {
|
||||
continue
|
||||
}
|
||||
@@ -35,13 +37,13 @@ func (daemon *Daemon) removeMountPoints(container *container.Container, rm bool)
|
||||
continue
|
||||
}
|
||||
|
||||
err := daemon.volumes.Remove(m.Volume)
|
||||
err := daemon.volumes.Remove(ctx, m.Volume.Name())
|
||||
// Ignore volume in use errors because having this
|
||||
// volume being referenced by other container is
|
||||
// not an error, but an implementation detail.
|
||||
// This prevents docker from logging "ERROR: Volume in use"
|
||||
// where there is another container using the volume.
|
||||
if err != nil && !volumestore.IsInUse(err) {
|
||||
if err != nil && !volumesservice.IsInUse(err) {
|
||||
rmErrors = append(rmErrors, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,27 +10,23 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
timetypes "github.com/docker/docker/api/types/time"
|
||||
"github.com/docker/docker/pkg/directory"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
// errPruneRunning is returned when a prune request is received while
|
||||
// one is in progress
|
||||
errPruneRunning = fmt.Errorf("a prune operation is already running")
|
||||
errPruneRunning = errdefs.Conflict(errors.New("a prune operation is already running"))
|
||||
|
||||
containersAcceptedFilters = map[string]bool{
|
||||
"label": true,
|
||||
"label!": true,
|
||||
"until": true,
|
||||
}
|
||||
volumesAcceptedFilters = map[string]bool{
|
||||
"label": true,
|
||||
"label!": true,
|
||||
}
|
||||
|
||||
networksAcceptedFilters = map[string]bool{
|
||||
"label": true,
|
||||
@@ -92,67 +88,6 @@ func (daemon *Daemon) ContainersPrune(ctx context.Context, pruneFilters filters.
|
||||
return rep, nil
|
||||
}
|
||||
|
||||
// VolumesPrune removes unused local volumes
|
||||
func (daemon *Daemon) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (*types.VolumesPruneReport, error) {
|
||||
if !atomic.CompareAndSwapInt32(&daemon.pruneRunning, 0, 1) {
|
||||
return nil, errPruneRunning
|
||||
}
|
||||
defer atomic.StoreInt32(&daemon.pruneRunning, 0)
|
||||
|
||||
// make sure that only accepted filters have been received
|
||||
err := pruneFilters.Validate(volumesAcceptedFilters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rep := &types.VolumesPruneReport{}
|
||||
|
||||
volumes, err := daemon.volumes.FilterByDriver(volume.DefaultDriverName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range volumes {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
logrus.Debugf("VolumesPrune operation cancelled: %#v", *rep)
|
||||
err := ctx.Err()
|
||||
if err == context.Canceled {
|
||||
return rep, nil
|
||||
}
|
||||
return rep, err
|
||||
default:
|
||||
}
|
||||
|
||||
name := v.Name()
|
||||
refs := daemon.volumes.Refs(v)
|
||||
|
||||
if len(refs) == 0 {
|
||||
detailedVolume, ok := v.(volume.DetailedVolume)
|
||||
if ok {
|
||||
if !matchLabels(pruneFilters, detailedVolume.Labels()) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
vSize, err := directory.Size(ctx, v.Path())
|
||||
if err != nil {
|
||||
logrus.Warnf("could not determine size of volume %s: %v", name, err)
|
||||
}
|
||||
err = daemon.volumeRm(v)
|
||||
if err != nil {
|
||||
logrus.Warnf("could not remove volume %s: %v", name, err)
|
||||
continue
|
||||
}
|
||||
rep.SpaceReclaimed += uint64(vSize)
|
||||
rep.VolumesDeleted = append(rep.VolumesDeleted, name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rep, nil
|
||||
}
|
||||
|
||||
// localNetworksPrune removes unused local networks
|
||||
func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filters.Args) *types.NetworksPruneReport {
|
||||
rep := &types.NetworksPruneReport{}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@@ -15,6 +16,8 @@ import (
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/volume"
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
"github.com/docker/docker/volume/service"
|
||||
volumeopts "github.com/docker/docker/volume/service/opts"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -27,23 +30,6 @@ var (
|
||||
|
||||
type mounts []container.Mount
|
||||
|
||||
// volumeToAPIType converts a volume.Volume to the type used by the Engine API
|
||||
func volumeToAPIType(v volume.Volume) *types.Volume {
|
||||
createdAt, _ := v.CreatedAt()
|
||||
tv := &types.Volume{
|
||||
Name: v.Name(),
|
||||
Driver: v.DriverName(),
|
||||
CreatedAt: createdAt.Format(time.RFC3339),
|
||||
}
|
||||
if v, ok := v.(volume.DetailedVolume); ok {
|
||||
tv.Labels = v.Labels()
|
||||
tv.Options = v.Options()
|
||||
tv.Scope = v.Scope()
|
||||
}
|
||||
|
||||
return tv
|
||||
}
|
||||
|
||||
// Len returns the number of mounts. Used in sorting.
|
||||
func (m mounts) Len() int {
|
||||
return len(m)
|
||||
@@ -78,6 +64,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
mountPoints := map[string]*volumemounts.MountPoint{}
|
||||
parser := volumemounts.NewParser(container.OS)
|
||||
|
||||
ctx := context.TODO()
|
||||
defer func() {
|
||||
// clean up the container mountpoints once return with error
|
||||
if retErr != nil {
|
||||
@@ -85,7 +72,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
if m.Volume == nil {
|
||||
continue
|
||||
}
|
||||
daemon.volumes.Dereference(m.Volume, container.ID)
|
||||
daemon.volumes.Release(ctx, m.Volume.Name(), container.ID)
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -94,7 +81,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
if v, ok := mountPoints[destination]; ok {
|
||||
logrus.Debugf("Duplicate mount point '%s'", destination)
|
||||
if v.Volume != nil {
|
||||
daemon.volumes.Dereference(v.Volume, container.ID)
|
||||
daemon.volumes.Release(ctx, v.Volume.Name(), container.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,11 +117,11 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
}
|
||||
|
||||
if len(cp.Source) == 0 {
|
||||
v, err := daemon.volumes.GetWithRef(cp.Name, cp.Driver, container.ID)
|
||||
v, err := daemon.volumes.Get(ctx, cp.Name, volumeopts.WithGetDriver(cp.Driver), volumeopts.WithGetReference(container.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cp.Volume = v
|
||||
cp.Volume = &volumeWrapper{v: v, s: daemon.volumes}
|
||||
}
|
||||
dereferenceIfExists(cp.Destination)
|
||||
mountPoints[cp.Destination] = cp
|
||||
@@ -163,14 +150,14 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
|
||||
if bind.Type == mounttypes.TypeVolume {
|
||||
// create the volume
|
||||
v, err := daemon.volumes.CreateWithRef(bind.Name, bind.Driver, container.ID, nil, nil)
|
||||
v, err := daemon.volumes.Create(ctx, bind.Name, bind.Driver, volumeopts.WithCreateReference(container.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bind.Volume = v
|
||||
bind.Source = v.Path()
|
||||
bind.Volume = &volumeWrapper{v: v, s: daemon.volumes}
|
||||
bind.Source = v.Mountpoint
|
||||
// bind.Name is an already existing volume, we need to use that here
|
||||
bind.Driver = v.DriverName()
|
||||
bind.Driver = v.Driver
|
||||
if bind.Driver == volume.DefaultDriverName {
|
||||
setBindModeIfNull(bind)
|
||||
}
|
||||
@@ -199,30 +186,30 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
}
|
||||
|
||||
if mp.Type == mounttypes.TypeVolume {
|
||||
var v volume.Volume
|
||||
var v *types.Volume
|
||||
if cfg.VolumeOptions != nil {
|
||||
var driverOpts map[string]string
|
||||
if cfg.VolumeOptions.DriverConfig != nil {
|
||||
driverOpts = cfg.VolumeOptions.DriverConfig.Options
|
||||
}
|
||||
v, err = daemon.volumes.CreateWithRef(mp.Name, mp.Driver, container.ID, driverOpts, cfg.VolumeOptions.Labels)
|
||||
v, err = daemon.volumes.Create(ctx,
|
||||
mp.Name,
|
||||
mp.Driver,
|
||||
volumeopts.WithCreateReference(container.ID),
|
||||
volumeopts.WithCreateOptions(driverOpts),
|
||||
volumeopts.WithCreateLabels(cfg.VolumeOptions.Labels),
|
||||
)
|
||||
} else {
|
||||
v, err = daemon.volumes.CreateWithRef(mp.Name, mp.Driver, container.ID, nil, nil)
|
||||
v, err = daemon.volumes.Create(ctx, mp.Name, mp.Driver, volumeopts.WithCreateReference(container.ID))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mp.Volume = v
|
||||
mp.Name = v.Name()
|
||||
mp.Driver = v.DriverName()
|
||||
mp.Volume = &volumeWrapper{v: v, s: daemon.volumes}
|
||||
mp.Name = v.Name
|
||||
mp.Driver = v.Driver
|
||||
|
||||
// only use the cached path here since getting the path is not necessary right now and calling `Path()` may be slow
|
||||
if cv, ok := v.(interface {
|
||||
CachedPath() string
|
||||
}); ok {
|
||||
mp.Source = cv.CachedPath()
|
||||
}
|
||||
if mp.Driver == volume.DefaultDriverName {
|
||||
setBindModeIfNull(mp)
|
||||
}
|
||||
@@ -239,7 +226,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
for _, m := range mountPoints {
|
||||
if parser.IsBackwardCompatible(m) {
|
||||
if mp, exists := container.MountPoints[m.Destination]; exists && mp.Volume != nil {
|
||||
daemon.volumes.Dereference(mp.Volume, container.ID)
|
||||
daemon.volumes.Release(ctx, mp.Volume.Name(), container.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,11 +241,11 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
||||
// This happens after a daemon restart.
|
||||
func (daemon *Daemon) lazyInitializeVolume(containerID string, m *volumemounts.MountPoint) error {
|
||||
if len(m.Driver) > 0 && m.Volume == nil {
|
||||
v, err := daemon.volumes.GetWithRef(m.Name, m.Driver, containerID)
|
||||
v, err := daemon.volumes.Get(context.TODO(), m.Name, volumeopts.WithGetDriver(m.Driver), volumeopts.WithGetReference(containerID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Volume = v
|
||||
m.Volume = &volumeWrapper{v: v, s: daemon.volumes}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -385,3 +372,46 @@ func (daemon *Daemon) backportMountSpec(container *container.Container) {
|
||||
cm.Spec.ReadOnly = !cm.RW
|
||||
}
|
||||
}
|
||||
|
||||
// VolumesService is used to perform volume operations
|
||||
func (daemon *Daemon) VolumesService() *service.VolumesService {
|
||||
return daemon.volumes
|
||||
}
|
||||
|
||||
type volumeMounter interface {
|
||||
Mount(ctx context.Context, v *types.Volume, ref string) (string, error)
|
||||
Unmount(ctx context.Context, v *types.Volume, ref string) error
|
||||
}
|
||||
|
||||
type volumeWrapper struct {
|
||||
v *types.Volume
|
||||
s volumeMounter
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) Name() string {
|
||||
return v.v.Name
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) DriverName() string {
|
||||
return v.v.Driver
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) Path() string {
|
||||
return v.v.Mountpoint
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) Mount(ref string) (string, error) {
|
||||
return v.s.Mount(context.TODO(), v.v, ref)
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) Unmount(ref string) error {
|
||||
return v.s.Unmount(context.TODO(), v.v, ref)
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) CreatedAt() (time.Time, error) {
|
||||
return time.Time{}, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (v *volumeWrapper) Status() map[string]interface{} {
|
||||
return v.v.Status
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# containerd is also pinned in vendor.conf. When updating the binary
|
||||
# version you may also need to update the vendor version to pick up bug
|
||||
# fixes or new APIs.
|
||||
CONTAINERD_COMMIT=773c489c9c1b21a6d78b5c538cd395416ec50f88 # v1.0.3
|
||||
CONTAINERD_COMMIT=395068d2b7256518259816ae19e45824b15da071 # v1.1.1-rc.0
|
||||
|
||||
install_containerd() {
|
||||
echo "Install containerd version $CONTAINERD_COMMIT"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# When updating RUNC_COMMIT, also update runc in vendor.conf accordingly
|
||||
RUNC_COMMIT=4fc53a81fb7c994640722ac585fa9ca548971871
|
||||
RUNC_COMMIT=69663f0bd4b60df09991c08812a60108003fa340
|
||||
|
||||
install_runc() {
|
||||
# Do not build with ambient capabilities support
|
||||
|
||||
@@ -185,11 +185,12 @@ func (s *DockerSuite) TestVolumeEvents(c *check.C) {
|
||||
c.Assert(len(events), checker.GreaterThan, 4)
|
||||
|
||||
volumeEvents := eventActionsByIDAndType(c, events, "test-event-volume-local", "volume")
|
||||
c.Assert(volumeEvents, checker.HasLen, 4)
|
||||
c.Assert(volumeEvents, checker.HasLen, 5)
|
||||
c.Assert(volumeEvents[0], checker.Equals, "create")
|
||||
c.Assert(volumeEvents[1], checker.Equals, "mount")
|
||||
c.Assert(volumeEvents[2], checker.Equals, "unmount")
|
||||
c.Assert(volumeEvents[3], checker.Equals, "destroy")
|
||||
c.Assert(volumeEvents[1], checker.Equals, "create")
|
||||
c.Assert(volumeEvents[2], checker.Equals, "mount")
|
||||
c.Assert(volumeEvents[3], checker.Equals, "unmount")
|
||||
c.Assert(volumeEvents[4], checker.Equals, "destroy")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetworkEvents(c *check.C) {
|
||||
|
||||
@@ -517,22 +517,20 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverGetEmptyResponse(c *
|
||||
}
|
||||
|
||||
// Ensure only cached paths are used in volume list to prevent N+1 calls to `VolumeDriver.Path`
|
||||
//
|
||||
// TODO(@cpuguy83): This test is testing internal implementation. In all the cases here, there may not even be a path
|
||||
// available because the volume is not even mounted. Consider removing this test.
|
||||
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverPathCalls(c *check.C) {
|
||||
s.d.Start(c)
|
||||
c.Assert(s.ec.paths, checker.Equals, 0)
|
||||
|
||||
out, err := s.d.Cmd("volume", "create", "test", "--driver=test-external-volume-driver")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(s.ec.paths, checker.Equals, 1)
|
||||
c.Assert(s.ec.paths, checker.Equals, 0)
|
||||
|
||||
out, err = s.d.Cmd("volume", "ls")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(s.ec.paths, checker.Equals, 1)
|
||||
|
||||
out, err = s.d.Cmd("volume", "inspect", "--format='{{.Mountpoint}}'", "test")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
||||
c.Assert(s.ec.paths, checker.Equals, 1)
|
||||
c.Assert(s.ec.paths, checker.Equals, 0)
|
||||
}
|
||||
|
||||
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverMountID(c *check.C) {
|
||||
|
||||
@@ -619,7 +619,8 @@ func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
defer close(errChan)
|
||||
out, exitCode, _ := dockerCmdWithError("run", "-m", "4MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done")
|
||||
// memory limit lower than 8MB will raise an error of "device or resource busy" from docker-runc.
|
||||
out, exitCode, _ := dockerCmdWithError("run", "-m", "8MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done")
|
||||
if expected := 137; exitCode != expected {
|
||||
errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func testBuildWithSession(t *testing.T, client dclient.APIClient, daemonHost str
|
||||
})
|
||||
sess.Allow(fsProvider)
|
||||
|
||||
g, ctx := errgroup.WithContext(context.Background())
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
g.Go(func() error {
|
||||
return sess.Run(ctx, client.DialSession)
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestSecretInspect(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_secret"
|
||||
testName := "test_secret_" + t.Name()
|
||||
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
secret, _, err := client.SecretInspectWithRaw(context.Background(), secretID)
|
||||
@@ -51,8 +51,8 @@ func TestSecretList(t *testing.T) {
|
||||
defer client.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
testName0 := "test0"
|
||||
testName1 := "test1"
|
||||
testName0 := "test0_" + t.Name()
|
||||
testName1 := "test1_" + t.Name()
|
||||
testNames := []string{testName0, testName1}
|
||||
sort.Strings(testNames)
|
||||
|
||||
@@ -137,7 +137,7 @@ func TestSecretsCreateAndDelete(t *testing.T) {
|
||||
defer client.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_secret"
|
||||
testName := "test_secret_" + t.Name()
|
||||
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
// create an already existin secret, daemon should return a status code of 409
|
||||
@@ -160,7 +160,7 @@ func TestSecretsCreateAndDelete(t *testing.T) {
|
||||
assert.Check(t, is.ErrorContains(err, "No such secret: non-existin"))
|
||||
|
||||
// Ported from original TestSecretsCreteaWithLabels
|
||||
testName = "test_secret_with_labels"
|
||||
testName = "test_secret_with_labels_" + t.Name()
|
||||
secretID = createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
@@ -184,7 +184,7 @@ func TestSecretsUpdate(t *testing.T) {
|
||||
defer client.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
testName := "test_secret"
|
||||
testName := "test_secret_" + t.Name()
|
||||
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
||||
|
||||
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
|
||||
@@ -232,27 +232,30 @@ func TestTemplatedSecret(t *testing.T) {
|
||||
defer client.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
referencedSecretName := "referencedsecret_" + t.Name()
|
||||
referencedSecretSpec := swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "referencedsecret",
|
||||
Name: referencedSecretName,
|
||||
},
|
||||
Data: []byte("this is a secret"),
|
||||
}
|
||||
referencedSecret, err := client.SecretCreate(ctx, referencedSecretSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
referencedConfigName := "referencedconfig_" + t.Name()
|
||||
referencedConfigSpec := swarmtypes.ConfigSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "referencedconfig",
|
||||
Name: referencedConfigName,
|
||||
},
|
||||
Data: []byte("this is a config"),
|
||||
}
|
||||
referencedConfig, err := client.ConfigCreate(ctx, referencedConfigSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
templatedSecretName := "templated_secret_" + t.Name()
|
||||
secretSpec := swarmtypes.SecretSpec{
|
||||
Annotations: swarmtypes.Annotations{
|
||||
Name: "templated_secret",
|
||||
Name: templatedSecretName,
|
||||
},
|
||||
Templating: &swarmtypes.Driver{
|
||||
Name: "golang",
|
||||
@@ -265,6 +268,7 @@ func TestTemplatedSecret(t *testing.T) {
|
||||
templatedSecret, err := client.SecretCreate(ctx, secretSpec)
|
||||
assert.Check(t, err)
|
||||
|
||||
serviceName := "svc_" + t.Name()
|
||||
serviceID := swarm.CreateService(t, d,
|
||||
swarm.ServiceWithSecret(
|
||||
&swarmtypes.SecretReference{
|
||||
@@ -275,7 +279,7 @@ func TestTemplatedSecret(t *testing.T) {
|
||||
Mode: 0600,
|
||||
},
|
||||
SecretID: templatedSecret.ID,
|
||||
SecretName: "templated_secret",
|
||||
SecretName: templatedSecretName,
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithConfig(
|
||||
@@ -287,7 +291,7 @@ func TestTemplatedSecret(t *testing.T) {
|
||||
Mode: 0600,
|
||||
},
|
||||
ConfigID: referencedConfig.ID,
|
||||
ConfigName: "referencedconfig",
|
||||
ConfigName: referencedConfigName,
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithSecret(
|
||||
@@ -299,10 +303,10 @@ func TestTemplatedSecret(t *testing.T) {
|
||||
Mode: 0600,
|
||||
},
|
||||
SecretID: referencedSecret.ID,
|
||||
SecretName: "referencedsecret",
|
||||
SecretName: referencedSecretName,
|
||||
},
|
||||
),
|
||||
swarm.ServiceWithName("svc"),
|
||||
swarm.ServiceWithName(serviceName),
|
||||
)
|
||||
|
||||
var tasks []swarmtypes.Task
|
||||
@@ -325,7 +329,7 @@ func TestTemplatedSecret(t *testing.T) {
|
||||
AttachStderr: true,
|
||||
})
|
||||
|
||||
expect := "SERVICE_NAME=svc\n" +
|
||||
expect := "SERVICE_NAME=" + serviceName + "\n" +
|
||||
"this is a secret\n" +
|
||||
"this is a config\n"
|
||||
assertAttachedStream(t, attach, expect)
|
||||
|
||||
@@ -16,18 +16,17 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/api/events"
|
||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||
apievents "github.com/containerd/containerd/api/events"
|
||||
"github.com/containerd/containerd/api/types"
|
||||
"github.com/containerd/containerd/archive"
|
||||
"github.com/containerd/containerd/cio"
|
||||
"github.com/containerd/containerd/content"
|
||||
containerderrors "github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/events"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/linux/runctypes"
|
||||
"github.com/containerd/typeurl"
|
||||
@@ -295,7 +294,8 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
|
||||
t, err = ctr.ctr.NewTask(ctx,
|
||||
func(id string) (cio.IO, error) {
|
||||
fifos := newFIFOSet(ctr.bundleDir, InitProcessName, withStdin, spec.Process.Terminal)
|
||||
rio, err = c.createIO(fifos, id, InitProcessName, stdinCloseSync, attachStdio)
|
||||
|
||||
rio, err = c.createIO(fifos, id, InitProcessName, stdinCloseSync, attachStdio, spec.Process.Terminal)
|
||||
return rio, err
|
||||
},
|
||||
func(_ context.Context, _ *containerd.Client, info *containerd.TaskInfo) error {
|
||||
@@ -366,7 +366,7 @@ func (c *client) Exec(ctx context.Context, containerID, processID string, spec *
|
||||
}()
|
||||
|
||||
p, err = t.Exec(ctx, processID, spec, func(id string) (cio.IO, error) {
|
||||
rio, err = c.createIO(fifos, containerID, processID, stdinCloseSync, attachStdio)
|
||||
rio, err = c.createIO(fifos, containerID, processID, stdinCloseSync, attachStdio, spec.Terminal)
|
||||
return rio, err
|
||||
})
|
||||
if err != nil {
|
||||
@@ -645,8 +645,16 @@ func (c *client) getProcess(containerID, processID string) (containerd.Process,
|
||||
|
||||
// createIO creates the io to be used by a process
|
||||
// This needs to get a pointer to interface as upon closure the process may not have yet been registered
|
||||
func (c *client) createIO(fifos *cio.FIFOSet, containerID, processID string, stdinCloseSync chan struct{}, attachStdio StdioCallback) (cio.IO, error) {
|
||||
io, err := cio.NewDirectIO(context.Background(), fifos)
|
||||
func (c *client) createIO(fifos *cio.FIFOSet, containerID, processID string, stdinCloseSync chan struct{}, attachStdio StdioCallback, terminal bool) (cio.IO, error) {
|
||||
var (
|
||||
io *cio.DirectIO
|
||||
err error
|
||||
)
|
||||
if terminal {
|
||||
io, err = cio.NewDirectIOWithTerminal(context.Background(), fifos)
|
||||
} else {
|
||||
io, err = cio.NewDirectIO(context.Background(), fifos)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -729,137 +737,123 @@ func (c *client) processEvent(ctr *container, et EventType, ei EventInfo) {
|
||||
|
||||
func (c *client) processEventStream(ctx context.Context) {
|
||||
var (
|
||||
err error
|
||||
eventStream eventsapi.Events_SubscribeClient
|
||||
ev *eventsapi.Envelope
|
||||
et EventType
|
||||
ei EventInfo
|
||||
ctr *container
|
||||
err error
|
||||
ev *events.Envelope
|
||||
et EventType
|
||||
ei EventInfo
|
||||
ctr *container
|
||||
)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
c.logger.WithError(ctx.Err()).
|
||||
Info("stopping event stream following graceful shutdown")
|
||||
default:
|
||||
go c.processEventStream(ctx)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
eventStream, err = c.getRemote().EventService().Subscribe(ctx, &eventsapi.SubscribeRequest{
|
||||
Filters: []string{
|
||||
// Filter on both namespace *and* topic. To create an "and" filter,
|
||||
// this must be a single, comma-separated string
|
||||
"namespace==" + c.namespace + ",topic~=|^/tasks/|",
|
||||
},
|
||||
}, grpc.FailFast(false))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Filter on both namespace *and* topic. To create an "and" filter,
|
||||
// this must be a single, comma-separated string
|
||||
eventStream, errC := c.getRemote().EventService().Subscribe(ctx, "namespace=="+c.namespace+",topic~=|^/tasks/|")
|
||||
|
||||
c.logger.WithField("namespace", c.namespace).Debug("processing event stream")
|
||||
|
||||
var oomKilled bool
|
||||
for {
|
||||
ev, err = eventStream.Recv()
|
||||
if err != nil {
|
||||
errStatus, ok := status.FromError(err)
|
||||
if !ok || errStatus.Code() != codes.Canceled {
|
||||
c.logger.WithError(err).Error("failed to get event")
|
||||
select {
|
||||
case err = <-errC:
|
||||
if err != nil {
|
||||
errStatus, ok := status.FromError(err)
|
||||
if !ok || errStatus.Code() != codes.Canceled {
|
||||
c.logger.WithError(err).Error("failed to get event")
|
||||
go c.processEventStream(ctx)
|
||||
} else {
|
||||
c.logger.WithError(ctx.Err()).Info("stopping event stream following graceful shutdown")
|
||||
}
|
||||
}
|
||||
return
|
||||
case ev = <-eventStream:
|
||||
if ev.Event == nil {
|
||||
c.logger.WithField("event", ev).Warn("invalid event")
|
||||
continue
|
||||
}
|
||||
|
||||
v, err := typeurl.UnmarshalAny(ev.Event)
|
||||
if err != nil {
|
||||
c.logger.WithError(err).WithField("event", ev).Warn("failed to unmarshal event")
|
||||
continue
|
||||
}
|
||||
|
||||
c.logger.WithField("topic", ev.Topic).Debug("event")
|
||||
|
||||
switch t := v.(type) {
|
||||
case *apievents.TaskCreate:
|
||||
et = EventCreate
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ContainerID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
case *apievents.TaskStart:
|
||||
et = EventStart
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ContainerID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
case *apievents.TaskExit:
|
||||
et = EventExit
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ID,
|
||||
Pid: t.Pid,
|
||||
ExitCode: t.ExitStatus,
|
||||
ExitedAt: t.ExitedAt,
|
||||
}
|
||||
case *apievents.TaskOOM:
|
||||
et = EventOOM
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
OOMKilled: true,
|
||||
}
|
||||
oomKilled = true
|
||||
case *apievents.TaskExecAdded:
|
||||
et = EventExecAdded
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ExecID,
|
||||
}
|
||||
case *apievents.TaskExecStarted:
|
||||
et = EventExecStarted
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ExecID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
case *apievents.TaskPaused:
|
||||
et = EventPaused
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
}
|
||||
case *apievents.TaskResumed:
|
||||
et = EventResumed
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
}
|
||||
default:
|
||||
c.logger.WithFields(logrus.Fields{
|
||||
"topic": ev.Topic,
|
||||
"type": reflect.TypeOf(t)},
|
||||
).Info("ignoring event")
|
||||
continue
|
||||
}
|
||||
|
||||
ctr = c.getContainer(ei.ContainerID)
|
||||
if ctr == nil {
|
||||
c.logger.WithField("container", ei.ContainerID).Warn("unknown container")
|
||||
continue
|
||||
}
|
||||
|
||||
if oomKilled {
|
||||
ctr.setOOMKilled(true)
|
||||
oomKilled = false
|
||||
}
|
||||
ei.OOMKilled = ctr.getOOMKilled()
|
||||
|
||||
c.processEvent(ctr, et, ei)
|
||||
}
|
||||
|
||||
if ev.Event == nil {
|
||||
c.logger.WithField("event", ev).Warn("invalid event")
|
||||
continue
|
||||
}
|
||||
|
||||
v, err := typeurl.UnmarshalAny(ev.Event)
|
||||
if err != nil {
|
||||
c.logger.WithError(err).WithField("event", ev).Warn("failed to unmarshal event")
|
||||
continue
|
||||
}
|
||||
|
||||
c.logger.WithField("topic", ev.Topic).Debug("event")
|
||||
|
||||
switch t := v.(type) {
|
||||
case *events.TaskCreate:
|
||||
et = EventCreate
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ContainerID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
case *events.TaskStart:
|
||||
et = EventStart
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ContainerID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
case *events.TaskExit:
|
||||
et = EventExit
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ID,
|
||||
Pid: t.Pid,
|
||||
ExitCode: t.ExitStatus,
|
||||
ExitedAt: t.ExitedAt,
|
||||
}
|
||||
case *events.TaskOOM:
|
||||
et = EventOOM
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
OOMKilled: true,
|
||||
}
|
||||
oomKilled = true
|
||||
case *events.TaskExecAdded:
|
||||
et = EventExecAdded
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ExecID,
|
||||
}
|
||||
case *events.TaskExecStarted:
|
||||
et = EventExecStarted
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ExecID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
case *events.TaskPaused:
|
||||
et = EventPaused
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
}
|
||||
case *events.TaskResumed:
|
||||
et = EventResumed
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
}
|
||||
default:
|
||||
c.logger.WithFields(logrus.Fields{
|
||||
"topic": ev.Topic,
|
||||
"type": reflect.TypeOf(t)},
|
||||
).Info("ignoring event")
|
||||
continue
|
||||
}
|
||||
|
||||
ctr = c.getContainer(ei.ContainerID)
|
||||
if ctr == nil {
|
||||
c.logger.WithField("container", ei.ContainerID).Warn("unknown container")
|
||||
continue
|
||||
}
|
||||
|
||||
if oomKilled {
|
||||
ctr.setOOMKilled(true)
|
||||
oomKilled = false
|
||||
}
|
||||
ei.OOMKilled = ctr.getOOMKilled()
|
||||
|
||||
c.processEvent(ctr, et, ei)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/server"
|
||||
"github.com/containerd/containerd/services/server"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/defaults"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
)
|
||||
|
||||
@@ -18,6 +19,12 @@ func (r *remote) setDefaults() {
|
||||
if r.GRPC.Address == "" {
|
||||
r.GRPC.Address = filepath.Join(r.stateDir, sockFile)
|
||||
}
|
||||
if r.GRPC.MaxRecvMsgSize == 0 {
|
||||
r.GRPC.MaxRecvMsgSize = defaults.DefaultMaxRecvMsgSize
|
||||
}
|
||||
if r.GRPC.MaxSendMsgSize == 0 {
|
||||
r.GRPC.MaxSendMsgSize = defaults.DefaultMaxSendMsgSize
|
||||
}
|
||||
if r.Debug.Address == "" {
|
||||
r.Debug.Address = filepath.Join(r.stateDir, debugSockFile)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build linux freebsd
|
||||
// +build linux freebsd darwin
|
||||
|
||||
package directory // import "github.com/docker/docker/pkg/directory"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# the following lines are in sorted order, FYI
|
||||
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
|
||||
github.com/Microsoft/hcsshim v0.6.11
|
||||
github.com/Microsoft/go-winio v0.4.6
|
||||
github.com/Microsoft/go-winio v0.4.7
|
||||
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
|
||||
github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a
|
||||
@@ -27,7 +27,7 @@ github.com/imdario/mergo 0.2.1
|
||||
golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5
|
||||
|
||||
# buildkit
|
||||
github.com/moby/buildkit b14fd548fe80c0399b105aeec5dbd96ccd2f7720
|
||||
github.com/moby/buildkit 43e758232a0ac7d50c6a11413186e16684fc1e4f
|
||||
github.com/tonistiigi/fsutil dc68c74458923f357474a9178bd198aa3ed11a5f
|
||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
||||
@@ -70,10 +70,10 @@ github.com/opencontainers/go-digest v1.0.0-rc1
|
||||
github.com/mistifyio/go-zfs 22c9b32c84eb0d0c6f4043b6e90fc94073de92fa
|
||||
github.com/pborman/uuid v1.0
|
||||
|
||||
google.golang.org/grpc v1.3.0
|
||||
google.golang.org/grpc v1.12.0
|
||||
|
||||
# When updating, also update RUNC_COMMIT in hack/dockerfile/install/runc accordingly
|
||||
github.com/opencontainers/runc 4fc53a81fb7c994640722ac585fa9ca548971871
|
||||
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
||||
github.com/opencontainers/runtime-spec v1.0.1
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||
@@ -82,7 +82,7 @@ github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||
github.com/coreos/go-systemd v17
|
||||
github.com/godbus/dbus v4.0.0
|
||||
github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
|
||||
github.com/golang/protobuf 7a211bcf3bce0e3f1d74f9894916e6f116ae83b4
|
||||
github.com/golang/protobuf v1.1.0
|
||||
|
||||
# gelf logging driver deps
|
||||
github.com/Graylog2/go-gelf 4143646226541087117ff2f83334ea48b3201841
|
||||
@@ -104,26 +104,27 @@ github.com/jmespath/go-jmespath 0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74
|
||||
github.com/bsphere/le_go 7a984a84b5492ae539b79b62fb4a10afc63c7bcf
|
||||
|
||||
# gcplogs deps
|
||||
golang.org/x/oauth2 96382aa079b72d8c014eb0c50f6c223d1e6a2de0
|
||||
google.golang.org/api 3cc2e591b550923a2c5f0ab5a803feda924d5823
|
||||
cloud.google.com/go 9d965e63e8cceb1b5d7977a202f0fcb8866d6525
|
||||
github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7
|
||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||
golang.org/x/oauth2 ec22f46f877b4505e0117eeaab541714644fdd28
|
||||
google.golang.org/api de943baf05a022a8f921b544b7827bacaba1aed5
|
||||
go.opencensus.io v0.11.0
|
||||
cloud.google.com/go v0.23.0
|
||||
github.com/googleapis/gax-go v2.0.0
|
||||
google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
|
||||
|
||||
# containerd
|
||||
github.com/containerd/containerd 4ac4fd0b6a268fe6f38b2b2e32e40daa7e424fac
|
||||
github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6
|
||||
github.com/containerd/continuity 2d3749b4da569ac97ca63dccba5eee4f5ee2beab
|
||||
github.com/containerd/containerd c7083eed5d8633d54c25fe81aa609010a4f2e495
|
||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||
github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
|
||||
github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130
|
||||
github.com/containerd/console 2748ece16665b45a47f884001d5831ec79703880
|
||||
github.com/containerd/go-runc 4f6e87ae043f859a38255247b49c9abc262d002f
|
||||
github.com/containerd/console cb7008ab3d8359b78c5f464cb7cf160107ad5925
|
||||
github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd
|
||||
github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788
|
||||
github.com/dmcgowan/go-tar go1.10
|
||||
github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577
|
||||
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
|
||||
|
||||
# cluster
|
||||
github.com/docker/swarmkit bd69f6e8e301645afd344913fa1ede53a0a111fb
|
||||
github.com/gogo/protobuf v0.4
|
||||
github.com/docker/swarmkit edd5641391926a50bc5f7040e20b7efc05003c26
|
||||
github.com/gogo/protobuf v1.0.0
|
||||
github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
|
||||
github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
|
||||
github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Google Inc.
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
+348
-140
@@ -1,159 +1,283 @@
|
||||
# Google Cloud for Go
|
||||
# Google Cloud Client Libraries for Go
|
||||
|
||||
[](https://travis-ci.org/GoogleCloudPlatform/google-cloud-go)
|
||||
[](https://godoc.org/cloud.google.com/go)
|
||||
|
||||
Go packages for [Google Cloud Platform](https://cloud.google.com) services.
|
||||
|
||||
``` go
|
||||
import "cloud.google.com/go"
|
||||
```
|
||||
|
||||
Go packages for Google Cloud Platform services.
|
||||
|
||||
To install the packages on your system,
|
||||
|
||||
```
|
||||
$ go get -u cloud.google.com/go/...
|
||||
```
|
||||
|
||||
**NOTE:** These packages are under development, and may occasionally make
|
||||
backwards-incompatible changes.
|
||||
**NOTE:** Some of these packages are under development, and may occasionally
|
||||
make backwards-incompatible changes.
|
||||
|
||||
**NOTE:** Github repo is a mirror of [https://code.googlesource.com/gocloud](https://code.googlesource.com/gocloud).
|
||||
|
||||
* [News](#news)
|
||||
* [Supported APIs](#supported-apis)
|
||||
* [Go Versions Supported](#go-versions-supported)
|
||||
* [Authorization](#authorization)
|
||||
* [Cloud Datastore](#cloud-datastore-)
|
||||
* [Cloud Storage](#cloud-storage-)
|
||||
* [Cloud Pub/Sub](#cloud-pub-sub-)
|
||||
* [Cloud BigQuery](#cloud-bigquery-)
|
||||
* [Stackdriver Logging](#stackdriver-logging-)
|
||||
* [Cloud Spanner](#cloud-spanner-)
|
||||
|
||||
|
||||
## News
|
||||
|
||||
_December 5, 2016_
|
||||
_May 18, 2018_
|
||||
|
||||
More changes to BigQuery:
|
||||
*v0.23.0*
|
||||
|
||||
* The `ValueList` type was removed. It is no longer necessary. Instead of
|
||||
```go
|
||||
var v ValueList
|
||||
... it.Next(&v) ..
|
||||
```
|
||||
use
|
||||
- bigquery: Add DDL stats to query statistics.
|
||||
- bigtable:
|
||||
- cbt: Add cells-per-column limit for row lookup.
|
||||
- cbt: Make it possible to combine read filters.
|
||||
- dlp: v2beta2 client removed. Use the v2 client instead.
|
||||
- firestore, spanner: Fix compilation errors due to protobuf changes.
|
||||
|
||||
```go
|
||||
var v []Value
|
||||
... it.Next(&v) ...
|
||||
```
|
||||
_May 8, 2018_
|
||||
|
||||
* Previously, repeatedly calling `RowIterator.Next` on the same `[]Value` or
|
||||
`ValueList` would append to the slice. Now each call resets the size to zero first.
|
||||
*v0.22.0*
|
||||
|
||||
* Schema inference will infer the SQL type BYTES for a struct field of
|
||||
type []byte. Previously it inferred STRING.
|
||||
- bigtable:
|
||||
- cbt: Support cells per column limit for row read.
|
||||
- bttest: Correctly handle empty RowSet.
|
||||
- Fix ReadModifyWrite operation in emulator.
|
||||
- Fix API path in GetCluster.
|
||||
|
||||
* The types `uint`, `uint64` and `uintptr` are no longer supported in schema
|
||||
inference. BigQuery's integer type is INT64, and those types may hold values
|
||||
that are not correctly represented in a 64-bit signed integer.
|
||||
- bigquery:
|
||||
- BEHAVIOR CHANGE: Retry on 503 status code.
|
||||
- Add dataset.DeleteWithContents.
|
||||
- Add SchemaUpdateOptions for query jobs.
|
||||
- Add Timeline to QueryStatistics.
|
||||
- Add more stats to ExplainQueryStage.
|
||||
- Support Parquet data format.
|
||||
|
||||
* The SQL types DATE, TIME and DATETIME are now supported. They correspond to
|
||||
the `Date`, `Time` and `DateTime` types in the new `cloud.google.com/go/civil`
|
||||
package.
|
||||
- datastore:
|
||||
- Support omitempty for times.
|
||||
|
||||
_November 17, 2016_
|
||||
- dlp:
|
||||
- **BREAKING CHANGE:** Remove v1beta1 client. Please migrate to the v2 client,
|
||||
which is now out of beta.
|
||||
- Add v2 client.
|
||||
|
||||
Change to BigQuery: values from INTEGER columns will now be returned as int64,
|
||||
not int. This will avoid errors arising from large values on 32-bit systems.
|
||||
- firestore:
|
||||
- BEHAVIOR CHANGE: Treat set({}, MergeAll) as valid.
|
||||
|
||||
_November 8, 2016_
|
||||
- iam:
|
||||
- Support JWT signing via SignJwt callopt.
|
||||
|
||||
New datastore feature: datastore now encodes your nested Go structs as Entity values,
|
||||
instead of a flattened list of the embedded struct's fields.
|
||||
This means that you may now have twice-nested slices, eg.
|
||||
```go
|
||||
type State struct {
|
||||
Cities []struct{
|
||||
Populations []int
|
||||
}
|
||||
}
|
||||
```
|
||||
- profiler:
|
||||
- BEHAVIOR CHANGE: PollForSerialOutput returns an error when context.Done.
|
||||
- BEHAVIOR CHANGE: Increase the initial backoff to 1 minute.
|
||||
- Avoid returning empty serial port output.
|
||||
|
||||
See [the announcement](https://groups.google.com/forum/#!topic/google-api-go-announce/79jtrdeuJAg) for
|
||||
more details.
|
||||
- pubsub:
|
||||
- BEHAVIOR CHANGE: Don't backoff during next retryable error once stream is healthy.
|
||||
- BEHAVIOR CHANGE: Don't backoff on EOF.
|
||||
- pstest: Support Acknowledge and ModifyAckDeadline RPCs.
|
||||
|
||||
_November 8, 2016_
|
||||
- redis:
|
||||
- Add v1 beta Redis client.
|
||||
|
||||
Breaking changes to datastore: contexts no longer hold namespaces; instead you
|
||||
must set a key's namespace explicitly. Also, key functions have been changed
|
||||
and renamed.
|
||||
- spanner:
|
||||
- Support SessionLabels.
|
||||
|
||||
* The WithNamespace function has been removed. To specify a namespace in a Query, use the Query.Namespace method:
|
||||
```go
|
||||
q := datastore.NewQuery("Kind").Namespace("ns")
|
||||
```
|
||||
- speech:
|
||||
- Add api v1 beta1 client.
|
||||
|
||||
* All the fields of Key are exported. That means you can construct any Key with a struct literal:
|
||||
```go
|
||||
k := &Key{Kind: "Kind", ID: 37, Namespace: "ns"}
|
||||
```
|
||||
- storage:
|
||||
- BEHAVIOR CHANGE: Retry reads when retryable error occurs.
|
||||
- Fix delete of object in requester-pays bucket.
|
||||
- Support KMS integration.
|
||||
|
||||
* As a result of the above, the Key methods Kind, ID, d.Name, Parent, SetParent and Namespace have been removed.
|
||||
_April 9, 2018_
|
||||
|
||||
* `NewIncompleteKey` has been removed, replaced by `IncompleteKey`. Replace
|
||||
```go
|
||||
NewIncompleteKey(ctx, kind, parent)
|
||||
```
|
||||
with
|
||||
```go
|
||||
IncompleteKey(kind, parent)
|
||||
```
|
||||
and if you do use namespaces, make sure you set the namespace on the returned key.
|
||||
*v0.21.0*
|
||||
|
||||
* `NewKey` has been removed, replaced by `NameKey` and `IDKey`. Replace
|
||||
```go
|
||||
NewKey(ctx, kind, name, 0, parent)
|
||||
NewKey(ctx, kind, "", id, parent)
|
||||
```
|
||||
with
|
||||
```go
|
||||
NameKey(kind, name, parent)
|
||||
IDKey(kind, id, parent)
|
||||
```
|
||||
and if you do use namespaces, make sure you set the namespace on the returned key.
|
||||
- bigquery:
|
||||
- Add OpenCensus tracing.
|
||||
|
||||
* The `Done` variable has been removed. Replace `datastore.Done` with `iterator.Done`, from the package `google.golang.org/api/iterator`.
|
||||
- firestore:
|
||||
- **BREAKING CHANGE:** If a document does not exist, return a DocumentSnapshot
|
||||
whose Exists method returns false. DocumentRef.Get and Transaction.Get
|
||||
return the non-nil DocumentSnapshot in addition to a NotFound error.
|
||||
**DocumentRef.GetAll and Transaction.GetAll return a non-nil
|
||||
DocumentSnapshot instead of nil.**
|
||||
- Add DocumentIterator.Stop. **Call Stop whenever you are done with a
|
||||
DocumentIterator.**
|
||||
- Added Query.Snapshots and DocumentRef.Snapshots, which provide realtime
|
||||
notification of updates. See https://cloud.google.com/firestore/docs/query-data/listen.
|
||||
- Canceling an RPC now always returns a grpc.Status with codes.Canceled.
|
||||
|
||||
* The `Client.Close` method will have a return type of error. It will return the result of closing the underlying gRPC connection.
|
||||
- spanner:
|
||||
- Add `CommitTimestamp`, which supports inserting the commit timestamp of a
|
||||
transaction into a column.
|
||||
|
||||
See [the announcement](https://groups.google.com/forum/#!topic/google-api-go-announce/hqXtM_4Ix-0) for
|
||||
more details.
|
||||
_March 22, 2018_
|
||||
|
||||
_October 27, 2016_
|
||||
*v0.20.0*
|
||||
|
||||
Breaking change to bigquery: `NewGCSReference` is now a function,
|
||||
not a method on `Client`.
|
||||
- bigquery: Support SchemaUpdateOptions for load jobs.
|
||||
|
||||
New bigquery feature: `Table.LoaderFrom` now accepts a `ReaderSource`, enabling
|
||||
loading data into a table from a file or any `io.Reader`.
|
||||
- bigtable:
|
||||
- Add SampleRowKeys.
|
||||
- cbt: Support union, intersection GCPolicy.
|
||||
- Retry admin RPCS.
|
||||
- Add trace spans to retries.
|
||||
|
||||
_October 21, 2016_
|
||||
- datastore: Add OpenCensus tracing.
|
||||
|
||||
Breaking change to pubsub: removed `pubsub.Done`.
|
||||
- firestore:
|
||||
- Fix queries involving Null and NaN.
|
||||
- Allow Timestamp protobuffers for time values.
|
||||
|
||||
Use `iterator.Done` instead, where `iterator` is the package
|
||||
`google.golang.org/api/iterator`.
|
||||
- logging: Add a WriteTimeout option.
|
||||
|
||||
- spanner: Support Batch API.
|
||||
|
||||
- storage: Add OpenCensus tracing.
|
||||
|
||||
|
||||
_February 26, 2018_
|
||||
|
||||
*v0.19.0*
|
||||
|
||||
- bigquery:
|
||||
- Support customer-managed encryption keys.
|
||||
|
||||
- bigtable:
|
||||
- Improved emulator support.
|
||||
- Support GetCluster.
|
||||
|
||||
- datastore:
|
||||
- Add general mutations.
|
||||
- Support pointer struct fields.
|
||||
- Support transaction options.
|
||||
|
||||
- firestore:
|
||||
- Add Transaction.GetAll.
|
||||
- Support document cursors.
|
||||
|
||||
- logging:
|
||||
- Support concurrent RPCs to the service.
|
||||
- Support per-entry resources.
|
||||
|
||||
- profiler:
|
||||
- Add config options to disable heap and thread profiling.
|
||||
- Read the project ID from $GOOGLE_CLOUD_PROJECT when it's set.
|
||||
|
||||
- pubsub:
|
||||
- BEHAVIOR CHANGE: Release flow control after ack/nack (instead of after the
|
||||
callback returns).
|
||||
- Add SubscriptionInProject.
|
||||
- Add OpenCensus instrumentation for streaming pull.
|
||||
|
||||
- storage:
|
||||
- Support CORS.
|
||||
|
||||
|
||||
_January 18, 2018_
|
||||
|
||||
*v0.18.0*
|
||||
|
||||
- bigquery:
|
||||
- Marked stable.
|
||||
- Schema inference of nullable fields supported.
|
||||
- Added TimePartitioning to QueryConfig.
|
||||
|
||||
- firestore: Data provided to DocumentRef.Set with a Merge option can contain
|
||||
Delete sentinels.
|
||||
|
||||
- logging: Clients can accept parent resources other than projects.
|
||||
|
||||
- pubsub:
|
||||
- pubsub/pstest: A lighweight fake for pubsub. Experimental; feedback welcome.
|
||||
- Support updating more subscription metadata: AckDeadline,
|
||||
RetainAckedMessages and RetentionDuration.
|
||||
|
||||
- oslogin/apiv1beta: New client for the Cloud OS Login API.
|
||||
|
||||
- rpcreplay: A package for recording and replaying gRPC traffic.
|
||||
|
||||
- spanner:
|
||||
- Add a ReadWithOptions that supports a row limit, as well as an index.
|
||||
- Support query plan and execution statistics.
|
||||
- Added [OpenCensus](http://opencensus.io) support.
|
||||
|
||||
- storage: Clarify checksum validation for gzipped files (it is not validated
|
||||
when the file is served uncompressed).
|
||||
|
||||
|
||||
_December 11, 2017_
|
||||
|
||||
*v0.17.0*
|
||||
|
||||
- firestore BREAKING CHANGES:
|
||||
- Remove UpdateMap and UpdateStruct; rename UpdatePaths to Update.
|
||||
Change
|
||||
`docref.UpdateMap(ctx, map[string]interface{}{"a.b", 1})`
|
||||
to
|
||||
`docref.Update(ctx, []firestore.Update{{Path: "a.b", Value: 1}})`
|
||||
|
||||
Change
|
||||
`docref.UpdateStruct(ctx, []string{"Field"}, aStruct)`
|
||||
to
|
||||
`docref.Update(ctx, []firestore.Update{{Path: "Field", Value: aStruct.Field}})`
|
||||
- Rename MergePaths to Merge; require args to be FieldPaths
|
||||
- A value stored as an integer can be read into a floating-point field, and vice versa.
|
||||
- bigtable/cmd/cbt:
|
||||
- Support deleting a column.
|
||||
- Add regex option for row read.
|
||||
- spanner: Mark stable.
|
||||
- storage:
|
||||
- Add Reader.ContentEncoding method.
|
||||
- Fix handling of SignedURL headers.
|
||||
- bigquery:
|
||||
- If Uploader.Put is called with no rows, it returns nil without making a
|
||||
call.
|
||||
- Schema inference supports the "nullable" option in struct tags for
|
||||
non-required fields.
|
||||
- TimePartitioning supports "Field".
|
||||
|
||||
|
||||
[Older news](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/old-news.md)
|
||||
|
||||
## Supported APIs
|
||||
|
||||
Google API | Status | Package
|
||||
-------------------------------|--------------|-----------------------------------------------------------
|
||||
[Datastore][cloud-datastore] | beta | [`cloud.google.com/go/datastore`][cloud-datastore-ref]
|
||||
[Storage][cloud-storage] | beta | [`cloud.google.com/go/storage`][cloud-storage-ref]
|
||||
[Bigtable][cloud-bigtable] | beta | [`cloud.google.com/go/bigtable`][cloud-bigtable-ref]
|
||||
[BigQuery][cloud-bigquery] | beta | [`cloud.google.com/go/bigquery`][cloud-bigquery-ref]
|
||||
[Logging][cloud-logging] | beta | [`cloud.google.com/go/logging`][cloud-logging-ref]
|
||||
[Pub/Sub][cloud-pubsub] | experimental | [`cloud.google.com/go/pubsub`][cloud-pubsub-ref]
|
||||
[Vision][cloud-vision] | experimental | [`cloud.google.com/go/vision`][cloud-vision-ref]
|
||||
[Language][cloud-language] | experimental | [`cloud.google.com/go/language/apiv1beta1`][cloud-language-ref]
|
||||
[Speech][cloud-speech] | experimental | [`cloud.google.com/go/speech/apiv1beta`][cloud-speech-ref]
|
||||
Google API | Status | Package
|
||||
---------------------------------|--------------|-----------------------------------------------------------
|
||||
[BigQuery][cloud-bigquery] | stable | [`cloud.google.com/go/bigquery`][cloud-bigquery-ref]
|
||||
[Bigtable][cloud-bigtable] | stable | [`cloud.google.com/go/bigtable`][cloud-bigtable-ref]
|
||||
[Container][cloud-container] | alpha | [`cloud.google.com/go/container/apiv1`][cloud-container-ref]
|
||||
[Data Loss Prevention][cloud-dlp]| alpha | [`cloud.google.com/go/dlp/apiv2beta1`][cloud-dlp-ref]
|
||||
[Datastore][cloud-datastore] | stable | [`cloud.google.com/go/datastore`][cloud-datastore-ref]
|
||||
[Debugger][cloud-debugger] | alpha | [`cloud.google.com/go/debugger/apiv2`][cloud-debugger-ref]
|
||||
[ErrorReporting][cloud-errors] | alpha | [`cloud.google.com/go/errorreporting`][cloud-errors-ref]
|
||||
[Firestore][cloud-firestore] | beta | [`cloud.google.com/go/firestore`][cloud-firestore-ref]
|
||||
[Language][cloud-language] | stable | [`cloud.google.com/go/language/apiv1`][cloud-language-ref]
|
||||
[Logging][cloud-logging] | stable | [`cloud.google.com/go/logging`][cloud-logging-ref]
|
||||
[Monitoring][cloud-monitoring] | beta | [`cloud.google.com/go/monitoring/apiv3`][cloud-monitoring-ref]
|
||||
[OS Login][cloud-oslogin] | alpha | [`cloud.google.com/compute/docs/oslogin/rest`][cloud-oslogin-ref]
|
||||
[Pub/Sub][cloud-pubsub] | beta | [`cloud.google.com/go/pubsub`][cloud-pubsub-ref]
|
||||
[Spanner][cloud-spanner] | stable | [`cloud.google.com/go/spanner`][cloud-spanner-ref]
|
||||
[Speech][cloud-speech] | stable | [`cloud.google.com/go/speech/apiv1`][cloud-speech-ref]
|
||||
[Storage][cloud-storage] | stable | [`cloud.google.com/go/storage`][cloud-storage-ref]
|
||||
[Translation][cloud-translation] | stable | [`cloud.google.com/go/translate`][cloud-translation-ref]
|
||||
[Video Intelligence][cloud-video]| beta | [`cloud.google.com/go/videointelligence/apiv1beta1`][cloud-video-ref]
|
||||
[Vision][cloud-vision] | stable | [`cloud.google.com/go/vision/apiv1`][cloud-vision-ref]
|
||||
|
||||
|
||||
> **Experimental status**: the API is still being actively developed. As a
|
||||
> **Alpha status**: the API is still being actively developed. As a
|
||||
> result, it might change in backward-incompatible ways and is not recommended
|
||||
> for production use.
|
||||
>
|
||||
@@ -184,12 +308,18 @@ By default, each API will use [Google Application Default Credentials][default-c
|
||||
for authorization credentials used in calling the API endpoints. This will allow your
|
||||
application to run in many environments without requiring explicit configuration.
|
||||
|
||||
[snip]:# (auth)
|
||||
```go
|
||||
client, err := storage.NewClient(ctx)
|
||||
```
|
||||
|
||||
To authorize using a
|
||||
[JSON key file](https://cloud.google.com/iam/docs/managing-service-account-keys),
|
||||
pass
|
||||
[`option.WithServiceAccountFile`](https://godoc.org/google.golang.org/api/option#WithServiceAccountFile)
|
||||
to the `NewClient` function of the desired package. For example:
|
||||
|
||||
[snip]:# (auth-JSON)
|
||||
```go
|
||||
client, err := storage.NewClient(ctx, option.WithServiceAccountFile("path/to/keyfile.json"))
|
||||
```
|
||||
@@ -199,6 +329,7 @@ You can exert more control over authorization by using the
|
||||
create an `oauth2.TokenSource`. Then pass
|
||||
[`option.WithTokenSource`](https://godoc.org/google.golang.org/api/option#WithTokenSource)
|
||||
to the `NewClient` function:
|
||||
[snip]:# (auth-ts)
|
||||
```go
|
||||
tokenSource := ...
|
||||
client, err := storage.NewClient(ctx, option.WithTokenSource(tokenSource))
|
||||
@@ -216,6 +347,7 @@ client, err := storage.NewClient(ctx, option.WithTokenSource(tokenSource))
|
||||
|
||||
First create a `datastore.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (datastore-1)
|
||||
```go
|
||||
client, err := datastore.NewClient(ctx, "my-project-id")
|
||||
if err != nil {
|
||||
@@ -225,6 +357,7 @@ if err != nil {
|
||||
|
||||
Then use that client to interact with the API:
|
||||
|
||||
[snip]:# (datastore-2)
|
||||
```go
|
||||
type Post struct {
|
||||
Title string
|
||||
@@ -232,8 +365,8 @@ type Post struct {
|
||||
PublishedAt time.Time
|
||||
}
|
||||
keys := []*datastore.Key{
|
||||
datastore.NewKey(ctx, "Post", "post1", 0, nil),
|
||||
datastore.NewKey(ctx, "Post", "post2", 0, nil),
|
||||
datastore.NameKey("Post", "post1", nil),
|
||||
datastore.NameKey("Post", "post2", nil),
|
||||
}
|
||||
posts := []*Post{
|
||||
{Title: "Post 1", Body: "...", PublishedAt: time.Now()},
|
||||
@@ -255,6 +388,7 @@ if _, err := client.PutMulti(ctx, keys, posts); err != nil {
|
||||
|
||||
First create a `storage.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (storage-1)
|
||||
```go
|
||||
client, err := storage.NewClient(ctx)
|
||||
if err != nil {
|
||||
@@ -262,6 +396,7 @@ if err != nil {
|
||||
}
|
||||
```
|
||||
|
||||
[snip]:# (storage-2)
|
||||
```go
|
||||
// Read the object1 from bucket.
|
||||
rc, err := client.Bucket("bucket").Object("object1").NewReader(ctx)
|
||||
@@ -286,6 +421,7 @@ if err != nil {
|
||||
|
||||
First create a `pubsub.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (pubsub-1)
|
||||
```go
|
||||
client, err := pubsub.NewClient(ctx, "project-id")
|
||||
if err != nil {
|
||||
@@ -293,36 +429,32 @@ if err != nil {
|
||||
}
|
||||
```
|
||||
|
||||
Then use the client to publish and subscribe:
|
||||
|
||||
[snip]:# (pubsub-2)
|
||||
```go
|
||||
// Publish "hello world" on topic1.
|
||||
topic := client.Topic("topic1")
|
||||
msgIDs, err := topic.Publish(ctx, &pubsub.Message{
|
||||
res := topic.Publish(ctx, &pubsub.Message{
|
||||
Data: []byte("hello world"),
|
||||
})
|
||||
// The publish happens asynchronously.
|
||||
// Later, you can get the result from res:
|
||||
...
|
||||
msgID, err := res.Get(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Create an iterator to pull messages via subscription1.
|
||||
it, err := client.Subscription("subscription1").Pull(ctx)
|
||||
// Use a callback to receive messages via subscription1.
|
||||
sub := client.Subscription("subscription1")
|
||||
err = sub.Receive(ctx, func(ctx context.Context, m *pubsub.Message) {
|
||||
fmt.Println(m.Data)
|
||||
m.Ack() // Acknowledge that we've consumed the message.
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
defer it.Stop()
|
||||
|
||||
// Consume N messages from the iterator.
|
||||
for i := 0; i < N; i++ {
|
||||
msg, err := it.Next()
|
||||
if err == iterator.Done {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to retrieve message: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Message %d: %s\n", i, msg.Data)
|
||||
msg.Done(true) // Acknowledge that we've consumed the message.
|
||||
}
|
||||
```
|
||||
|
||||
## Cloud BigQuery [](https://godoc.org/cloud.google.com/go/bigquery)
|
||||
@@ -335,13 +467,16 @@ for i := 0; i < N; i++ {
|
||||
### Example Usage
|
||||
|
||||
First create a `bigquery.Client` to use throughout your application:
|
||||
[snip]:# (bq-1)
|
||||
```go
|
||||
c, err := bigquery.NewClient(ctx, "my-project-ID")
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
// TODO: Handle error.
|
||||
}
|
||||
```
|
||||
|
||||
Then use that client to interact with the API:
|
||||
[snip]:# (bq-2)
|
||||
```go
|
||||
// Construct a query.
|
||||
q := c.Query(`
|
||||
@@ -354,19 +489,19 @@ q := c.Query(`
|
||||
// Execute the query.
|
||||
it, err := q.Read(ctx)
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
// TODO: Handle error.
|
||||
}
|
||||
// Iterate through the results.
|
||||
for {
|
||||
var values bigquery.ValueList
|
||||
err := it.Next(&values)
|
||||
if err == iterator.Done {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
fmt.Println(values)
|
||||
var values []bigquery.Value
|
||||
err := it.Next(&values)
|
||||
if err == iterator.Done {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
fmt.Println(values)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -381,28 +516,68 @@ for {
|
||||
### Example Usage
|
||||
|
||||
First create a `logging.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (logging-1)
|
||||
```go
|
||||
ctx := context.Background()
|
||||
client, err := logging.NewClient(ctx, "my-project")
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
// TODO: Handle error.
|
||||
}
|
||||
```
|
||||
|
||||
Usually, you'll want to add log entries to a buffer to be periodically flushed
|
||||
(automatically and asynchronously) to the Stackdriver Logging service.
|
||||
[snip]:# (logging-2)
|
||||
```go
|
||||
logger := client.Logger("my-log")
|
||||
logger.Log(logging.Entry{Payload: "something happened!"})
|
||||
```
|
||||
|
||||
Close your client before your program exits, to flush any buffered log entries.
|
||||
[snip]:# (logging-3)
|
||||
```go
|
||||
err = client.Close()
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
// TODO: Handle error.
|
||||
}
|
||||
```
|
||||
|
||||
## Cloud Spanner [](https://godoc.org/cloud.google.com/go/spanner)
|
||||
|
||||
- [About Cloud Spanner][cloud-spanner]
|
||||
- [API documentation][cloud-spanner-docs]
|
||||
- [Go client documentation](https://godoc.org/cloud.google.com/go/spanner)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `spanner.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (spanner-1)
|
||||
```go
|
||||
client, err := spanner.NewClient(ctx, "projects/P/instances/I/databases/D")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
[snip]:# (spanner-2)
|
||||
```go
|
||||
// Simple Reads And Writes
|
||||
_, err = client.Apply(ctx, []*spanner.Mutation{
|
||||
spanner.Insert("Users",
|
||||
[]string{"name", "email"},
|
||||
[]interface{}{"alice", "a@example.com"})})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
row, err := client.Single().ReadRow(ctx, "Users",
|
||||
spanner.Key{"alice"}, []string{"email"})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome. Please, see the
|
||||
@@ -420,6 +595,11 @@ for more information.
|
||||
[cloud-datastore-docs]: https://cloud.google.com/datastore/docs
|
||||
[cloud-datastore-activation]: https://cloud.google.com/datastore/docs/activate
|
||||
|
||||
[cloud-firestore]: https://cloud.google.com/firestore/
|
||||
[cloud-firestore-ref]: https://godoc.org/cloud.google.com/go/firestore
|
||||
[cloud-firestore-docs]: https://cloud.google.com/firestore/docs
|
||||
[cloud-firestore-activation]: https://cloud.google.com/firestore/docs/activate
|
||||
|
||||
[cloud-pubsub]: https://cloud.google.com/pubsub/
|
||||
[cloud-pubsub-ref]: https://godoc.org/cloud.google.com/go/pubsub
|
||||
[cloud-pubsub-docs]: https://cloud.google.com/pubsub/docs
|
||||
@@ -440,13 +620,41 @@ for more information.
|
||||
[cloud-logging-docs]: https://cloud.google.com/logging/docs
|
||||
[cloud-logging-ref]: https://godoc.org/cloud.google.com/go/logging
|
||||
|
||||
[cloud-vision]: https://cloud.google.com/vision/
|
||||
[cloud-vision-ref]: https://godoc.org/cloud.google.com/go/vision
|
||||
[cloud-monitoring]: https://cloud.google.com/monitoring/
|
||||
[cloud-monitoring-ref]: https://godoc.org/cloud.google.com/go/monitoring/apiv3
|
||||
|
||||
[cloud-vision]: https://cloud.google.com/vision
|
||||
[cloud-vision-ref]: https://godoc.org/cloud.google.com/go/vision/apiv1
|
||||
|
||||
[cloud-language]: https://cloud.google.com/natural-language
|
||||
[cloud-language-ref]: https://godoc.org/cloud.google.com/go/language/apiv1beta1
|
||||
[cloud-language-ref]: https://godoc.org/cloud.google.com/go/language/apiv1
|
||||
|
||||
[cloud-oslogin]: https://cloud.google.com/compute/docs/oslogin/rest
|
||||
[cloud-oslogin-ref]: https://cloud.google.com/compute/docs/oslogin/rest
|
||||
|
||||
[cloud-speech]: https://cloud.google.com/speech
|
||||
[cloud-speech-ref]: https://godoc.org/cloud.google.com/go/speech/apiv1beta1
|
||||
[cloud-speech-ref]: https://godoc.org/cloud.google.com/go/speech/apiv1
|
||||
|
||||
[cloud-spanner]: https://cloud.google.com/spanner/
|
||||
[cloud-spanner-ref]: https://godoc.org/cloud.google.com/go/spanner
|
||||
[cloud-spanner-docs]: https://cloud.google.com/spanner/docs
|
||||
|
||||
[cloud-translation]: https://cloud.google.com/translation
|
||||
[cloud-translation-ref]: https://godoc.org/cloud.google.com/go/translation
|
||||
|
||||
[cloud-video]: https://cloud.google.com/video-intelligence/
|
||||
[cloud-video-ref]: https://godoc.org/cloud.google.com/go/videointelligence/apiv1beta1
|
||||
|
||||
[cloud-errors]: https://cloud.google.com/error-reporting/
|
||||
[cloud-errors-ref]: https://godoc.org/cloud.google.com/go/errorreporting
|
||||
|
||||
[cloud-container]: https://cloud.google.com/containers/
|
||||
[cloud-container-ref]: https://godoc.org/cloud.google.com/go/container/apiv1
|
||||
|
||||
[cloud-debugger]: https://cloud.google.com/debugger/
|
||||
[cloud-debugger-ref]: https://godoc.org/cloud.google.com/go/debugger/apiv2
|
||||
|
||||
[cloud-dlp]: https://cloud.google.com/dlp/
|
||||
[cloud-dlp-ref]: https://godoc.org/cloud.google.com/go/dlp/apiv2beta1
|
||||
|
||||
[default-creds]: https://developers.google.com/identity/protocols/application-default-credentials
|
||||
|
||||
+17
-18
@@ -34,8 +34,6 @@ import (
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
|
||||
"cloud.google.com/go/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,6 +46,8 @@ const (
|
||||
// This is variable name is not defined by any spec, as far as
|
||||
// I know; it was made up for the Go package.
|
||||
metadataHostEnv = "GCE_METADATA_HOST"
|
||||
|
||||
userAgent = "gcloud-golang/0.1"
|
||||
)
|
||||
|
||||
type cachedValue struct {
|
||||
@@ -65,24 +65,20 @@ var (
|
||||
|
||||
var (
|
||||
metaClient = &http.Client{
|
||||
Transport: &internal.Transport{
|
||||
Base: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
ResponseHeaderTimeout: 2 * time.Second,
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
ResponseHeaderTimeout: 2 * time.Second,
|
||||
},
|
||||
}
|
||||
subscribeClient = &http.Client{
|
||||
Transport: &internal.Transport{
|
||||
Base: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -132,6 +128,7 @@ func getETag(client *http.Client, suffix string) (value, etag string, err error)
|
||||
url := "http://" + host + "/computeMetadata/v1/" + suffix
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
req.Header.Set("Metadata-Flavor", "Google")
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
@@ -202,7 +199,9 @@ func testOnGCE() bool {
|
||||
// Try two strategies in parallel.
|
||||
// See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
|
||||
go func() {
|
||||
res, err := ctxhttp.Get(ctx, metaClient, "http://"+metadataIP)
|
||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := ctxhttp.Do(ctx, metaClient, req)
|
||||
if err != nil {
|
||||
resc <- false
|
||||
return
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package internal provides support for the cloud packages.
|
||||
//
|
||||
// Users should not import this package directly.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const userAgent = "gcloud-golang/0.1"
|
||||
|
||||
// Transport is an http.RoundTripper that appends Google Cloud client's
|
||||
// user-agent to the original request's user-agent header.
|
||||
type Transport struct {
|
||||
// TODO(bradfitz): delete internal.Transport. It's too wrappy for what it does.
|
||||
// Do User-Agent some other way.
|
||||
|
||||
// Base is the actual http.RoundTripper
|
||||
// requests will use. It must not be nil.
|
||||
Base http.RoundTripper
|
||||
}
|
||||
|
||||
// RoundTrip appends a user-agent to the existing user-agent
|
||||
// header and delegates the request to the base http.RoundTripper.
|
||||
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
req = cloneRequest(req)
|
||||
ua := req.Header.Get("User-Agent")
|
||||
if ua == "" {
|
||||
ua = userAgent
|
||||
} else {
|
||||
ua = fmt.Sprintf("%s %s", ua, userAgent)
|
||||
}
|
||||
req.Header.Set("User-Agent", ua)
|
||||
return t.Base.RoundTrip(req)
|
||||
}
|
||||
|
||||
// cloneRequest returns a clone of the provided *http.Request.
|
||||
// The clone is a shallow copy of the struct and its Header map.
|
||||
func cloneRequest(r *http.Request) *http.Request {
|
||||
// shallow copy of the struct
|
||||
r2 := new(http.Request)
|
||||
*r2 = *r
|
||||
// deep copy of the Header
|
||||
r2.Header = make(http.Header)
|
||||
for k, s := range r.Header {
|
||||
r2.Header[k] = s
|
||||
}
|
||||
return r2
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
gax "github.com/googleapis/gax-go"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Retry calls the supplied function f repeatedly according to the provided
|
||||
// backoff parameters. It returns when one of the following occurs:
|
||||
// When f's first return value is true, Retry immediately returns with f's second
|
||||
// return value.
|
||||
// When the provided context is done, Retry returns with ctx.Err().
|
||||
func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
|
||||
return retry(ctx, bo, f, gax.Sleep)
|
||||
}
|
||||
|
||||
func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
|
||||
sleep func(context.Context, time.Duration) error) error {
|
||||
var lastErr error
|
||||
for {
|
||||
stop, err := f()
|
||||
if stop {
|
||||
return err
|
||||
}
|
||||
// Remember the last "real" error from f.
|
||||
if err != nil && err != context.Canceled && err != context.DeadlineExceeded {
|
||||
lastErr = err
|
||||
}
|
||||
p := bo.Pause()
|
||||
if cerr := sleep(ctx, p); cerr != nil {
|
||||
if lastErr != nil {
|
||||
return fmt.Errorf("%v; last function err: %v", cerr, lastErr)
|
||||
}
|
||||
return cerr
|
||||
}
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:generate ./update_version.sh
|
||||
|
||||
// Package version contains version information for Google Cloud Client
|
||||
// Libraries for Go, as reported in request headers.
|
||||
package version
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Repo is the current version of the client libraries in this
|
||||
// repo. It should be a date in YYYYMMDD format.
|
||||
const Repo = "20180226"
|
||||
|
||||
// Go returns the Go runtime version. The returned string
|
||||
// has no whitespace.
|
||||
func Go() string {
|
||||
return goVersion
|
||||
}
|
||||
|
||||
var goVersion = goVer(runtime.Version())
|
||||
|
||||
const develPrefix = "devel +"
|
||||
|
||||
func goVer(s string) string {
|
||||
if strings.HasPrefix(s, develPrefix) {
|
||||
s = s[len(develPrefix):]
|
||||
if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
|
||||
s = s[:p]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
if strings.HasPrefix(s, "go1") {
|
||||
s = s[2:]
|
||||
var prerelease string
|
||||
if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
|
||||
s, prerelease = s[:p], s[p:]
|
||||
}
|
||||
if strings.HasSuffix(s, ".") {
|
||||
s += "0"
|
||||
} else if strings.Count(s, ".") < 2 {
|
||||
s += ".0"
|
||||
}
|
||||
if prerelease != "" {
|
||||
s += "-" + prerelease
|
||||
}
|
||||
return s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func notSemverRune(r rune) bool {
|
||||
return strings.IndexRune("0123456789.", r) < 0
|
||||
}
|
||||
+211
-90
@@ -1,10 +1,10 @@
|
||||
// Copyright 2016, Google Inc. All rights reserved.
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,12 +17,10 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/internal/version"
|
||||
gax "github.com/googleapis/gax-go"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/iterator"
|
||||
@@ -34,30 +32,24 @@ import (
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
configParentPathTemplate = gax.MustCompilePathTemplate("projects/{project}")
|
||||
configSinkPathTemplate = gax.MustCompilePathTemplate("projects/{project}/sinks/{sink}")
|
||||
)
|
||||
|
||||
// ConfigCallOptions contains the retry settings for each method of ConfigClient.
|
||||
type ConfigCallOptions struct {
|
||||
ListSinks []gax.CallOption
|
||||
GetSink []gax.CallOption
|
||||
CreateSink []gax.CallOption
|
||||
UpdateSink []gax.CallOption
|
||||
DeleteSink []gax.CallOption
|
||||
ListSinks []gax.CallOption
|
||||
GetSink []gax.CallOption
|
||||
CreateSink []gax.CallOption
|
||||
UpdateSink []gax.CallOption
|
||||
DeleteSink []gax.CallOption
|
||||
ListExclusions []gax.CallOption
|
||||
GetExclusion []gax.CallOption
|
||||
CreateExclusion []gax.CallOption
|
||||
UpdateExclusion []gax.CallOption
|
||||
DeleteExclusion []gax.CallOption
|
||||
}
|
||||
|
||||
func defaultConfigClientOptions() []option.ClientOption {
|
||||
return []option.ClientOption{
|
||||
option.WithEndpoint("logging.googleapis.com:443"),
|
||||
option.WithScopes(
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/cloud-platform.read-only",
|
||||
"https://www.googleapis.com/auth/logging.admin",
|
||||
"https://www.googleapis.com/auth/logging.read",
|
||||
"https://www.googleapis.com/auth/logging.write",
|
||||
),
|
||||
option.WithScopes(DefaultAuthScopes()...),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +59,7 @@ func defaultConfigCallOptions() *ConfigCallOptions {
|
||||
gax.WithRetry(func() gax.Retryer {
|
||||
return gax.OnCodes([]codes.Code{
|
||||
codes.DeadlineExceeded,
|
||||
codes.Internal,
|
||||
codes.Unavailable,
|
||||
}, gax.Backoff{
|
||||
Initial: 100 * time.Millisecond,
|
||||
@@ -77,11 +70,16 @@ func defaultConfigCallOptions() *ConfigCallOptions {
|
||||
},
|
||||
}
|
||||
return &ConfigCallOptions{
|
||||
ListSinks: retry[[2]string{"default", "idempotent"}],
|
||||
GetSink: retry[[2]string{"default", "idempotent"}],
|
||||
CreateSink: retry[[2]string{"default", "non_idempotent"}],
|
||||
UpdateSink: retry[[2]string{"default", "non_idempotent"}],
|
||||
DeleteSink: retry[[2]string{"default", "idempotent"}],
|
||||
ListSinks: retry[[2]string{"default", "idempotent"}],
|
||||
GetSink: retry[[2]string{"default", "idempotent"}],
|
||||
CreateSink: retry[[2]string{"default", "non_idempotent"}],
|
||||
UpdateSink: retry[[2]string{"default", "non_idempotent"}],
|
||||
DeleteSink: retry[[2]string{"default", "idempotent"}],
|
||||
ListExclusions: retry[[2]string{"default", "idempotent"}],
|
||||
GetExclusion: retry[[2]string{"default", "idempotent"}],
|
||||
CreateExclusion: retry[[2]string{"default", "non_idempotent"}],
|
||||
UpdateExclusion: retry[[2]string{"default", "non_idempotent"}],
|
||||
DeleteExclusion: retry[[2]string{"default", "idempotent"}],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,8 +94,8 @@ type ConfigClient struct {
|
||||
// The call options for this service.
|
||||
CallOptions *ConfigCallOptions
|
||||
|
||||
// The metadata to be sent with each request.
|
||||
metadata metadata.MD
|
||||
// The x-goog-* metadata to be sent with each request.
|
||||
xGoogMetadata metadata.MD
|
||||
}
|
||||
|
||||
// NewConfigClient creates a new config service v2 client.
|
||||
@@ -115,7 +113,7 @@ func NewConfigClient(ctx context.Context, opts ...option.ClientOption) (*ConfigC
|
||||
|
||||
configClient: loggingpb.NewConfigServiceV2Client(conn),
|
||||
}
|
||||
c.SetGoogleClientInfo("gax", gax.Version)
|
||||
c.SetGoogleClientInfo()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -133,39 +131,16 @@ func (c *ConfigClient) Close() error {
|
||||
// SetGoogleClientInfo sets the name and version of the application in
|
||||
// the `x-goog-api-client` header passed on each request. Intended for
|
||||
// use by Google-written clients.
|
||||
func (c *ConfigClient) SetGoogleClientInfo(name, version string) {
|
||||
goVersion := strings.Replace(runtime.Version(), " ", "_", -1)
|
||||
v := fmt.Sprintf("%s/%s %s gax/%s go/%s", name, version, gapicNameVersion, gax.Version, goVersion)
|
||||
c.metadata = metadata.Pairs("x-goog-api-client", v)
|
||||
}
|
||||
|
||||
// ConfigParentPath returns the path for the parent resource.
|
||||
func ConfigParentPath(project string) string {
|
||||
path, err := configParentPathTemplate.Render(map[string]string{
|
||||
"project": project,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// ConfigSinkPath returns the path for the sink resource.
|
||||
func ConfigSinkPath(project, sink string) string {
|
||||
path, err := configSinkPathTemplate.Render(map[string]string{
|
||||
"project": project,
|
||||
"sink": sink,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return path
|
||||
func (c *ConfigClient) SetGoogleClientInfo(keyval ...string) {
|
||||
kv := append([]string{"gl-go", version.Go()}, keyval...)
|
||||
kv = append(kv, "gapic", version.Repo, "gax", gax.Version, "grpc", grpc.Version)
|
||||
c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
|
||||
}
|
||||
|
||||
// ListSinks lists sinks.
|
||||
func (c *ConfigClient) ListSinks(ctx context.Context, req *loggingpb.ListSinksRequest) *LogSinkIterator {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
func (c *ConfigClient) ListSinks(ctx context.Context, req *loggingpb.ListSinksRequest, opts ...gax.CallOption) *LogSinkIterator {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.ListSinks[0:len(c.CallOptions.ListSinks):len(c.CallOptions.ListSinks)], opts...)
|
||||
it := &LogSinkIterator{}
|
||||
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogSink, string, error) {
|
||||
var resp *loggingpb.ListSinksResponse
|
||||
@@ -175,11 +150,11 @@ func (c *ConfigClient) ListSinks(ctx context.Context, req *loggingpb.ListSinksRe
|
||||
} else {
|
||||
req.PageSize = int32(pageSize)
|
||||
}
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.ListSinks(ctx, req)
|
||||
resp, err = c.configClient.ListSinks(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.ListSinks...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -198,65 +173,211 @@ func (c *ConfigClient) ListSinks(ctx context.Context, req *loggingpb.ListSinksRe
|
||||
}
|
||||
|
||||
// GetSink gets a sink.
|
||||
func (c *ConfigClient) GetSink(ctx context.Context, req *loggingpb.GetSinkRequest) (*loggingpb.LogSink, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
func (c *ConfigClient) GetSink(ctx context.Context, req *loggingpb.GetSinkRequest, opts ...gax.CallOption) (*loggingpb.LogSink, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.GetSink[0:len(c.CallOptions.GetSink):len(c.CallOptions.GetSink)], opts...)
|
||||
var resp *loggingpb.LogSink
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.GetSink(ctx, req)
|
||||
resp, err = c.configClient.GetSink(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.GetSink...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// CreateSink creates a sink.
|
||||
func (c *ConfigClient) CreateSink(ctx context.Context, req *loggingpb.CreateSinkRequest) (*loggingpb.LogSink, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
// CreateSink creates a sink that exports specified log entries to a destination. The
|
||||
// export of newly-ingested log entries begins immediately, unless the sink's
|
||||
// writer_identity is not permitted to write to the destination. A sink can
|
||||
// export log entries only from the resource owning the sink.
|
||||
func (c *ConfigClient) CreateSink(ctx context.Context, req *loggingpb.CreateSinkRequest, opts ...gax.CallOption) (*loggingpb.LogSink, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.CreateSink[0:len(c.CallOptions.CreateSink):len(c.CallOptions.CreateSink)], opts...)
|
||||
var resp *loggingpb.LogSink
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.CreateSink(ctx, req)
|
||||
resp, err = c.configClient.CreateSink(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.CreateSink...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// UpdateSink updates or creates a sink.
|
||||
func (c *ConfigClient) UpdateSink(ctx context.Context, req *loggingpb.UpdateSinkRequest) (*loggingpb.LogSink, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
// UpdateSink updates a sink. This method replaces the following fields in the existing
|
||||
// sink with values from the new sink: destination, and filter.
|
||||
// The updated sink might also have a new writer_identity; see the
|
||||
// unique_writer_identity field.
|
||||
func (c *ConfigClient) UpdateSink(ctx context.Context, req *loggingpb.UpdateSinkRequest, opts ...gax.CallOption) (*loggingpb.LogSink, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.UpdateSink[0:len(c.CallOptions.UpdateSink):len(c.CallOptions.UpdateSink)], opts...)
|
||||
var resp *loggingpb.LogSink
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.UpdateSink(ctx, req)
|
||||
resp, err = c.configClient.UpdateSink(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.UpdateSink...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeleteSink deletes a sink.
|
||||
func (c *ConfigClient) DeleteSink(ctx context.Context, req *loggingpb.DeleteSinkRequest) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
// DeleteSink deletes a sink. If the sink has a unique writer_identity, then that
|
||||
// service account is also deleted.
|
||||
func (c *ConfigClient) DeleteSink(ctx context.Context, req *loggingpb.DeleteSinkRequest, opts ...gax.CallOption) error {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.DeleteSink[0:len(c.CallOptions.DeleteSink):len(c.CallOptions.DeleteSink)], opts...)
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
_, err = c.configClient.DeleteSink(ctx, req)
|
||||
_, err = c.configClient.DeleteSink(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.DeleteSink...)
|
||||
}, opts...)
|
||||
return err
|
||||
}
|
||||
|
||||
// ListExclusions lists all the exclusions in a parent resource.
|
||||
func (c *ConfigClient) ListExclusions(ctx context.Context, req *loggingpb.ListExclusionsRequest, opts ...gax.CallOption) *LogExclusionIterator {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.ListExclusions[0:len(c.CallOptions.ListExclusions):len(c.CallOptions.ListExclusions)], opts...)
|
||||
it := &LogExclusionIterator{}
|
||||
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogExclusion, string, error) {
|
||||
var resp *loggingpb.ListExclusionsResponse
|
||||
req.PageToken = pageToken
|
||||
if pageSize > math.MaxInt32 {
|
||||
req.PageSize = math.MaxInt32
|
||||
} else {
|
||||
req.PageSize = int32(pageSize)
|
||||
}
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.ListExclusions(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return resp.Exclusions, resp.NextPageToken, nil
|
||||
}
|
||||
fetch := func(pageSize int, pageToken string) (string, error) {
|
||||
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
it.items = append(it.items, items...)
|
||||
return nextPageToken, nil
|
||||
}
|
||||
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
|
||||
return it
|
||||
}
|
||||
|
||||
// GetExclusion gets the description of an exclusion.
|
||||
func (c *ConfigClient) GetExclusion(ctx context.Context, req *loggingpb.GetExclusionRequest, opts ...gax.CallOption) (*loggingpb.LogExclusion, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.GetExclusion[0:len(c.CallOptions.GetExclusion):len(c.CallOptions.GetExclusion)], opts...)
|
||||
var resp *loggingpb.LogExclusion
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.GetExclusion(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// CreateExclusion creates a new exclusion in a specified parent resource.
|
||||
// Only log entries belonging to that resource can be excluded.
|
||||
// You can have up to 10 exclusions in a resource.
|
||||
func (c *ConfigClient) CreateExclusion(ctx context.Context, req *loggingpb.CreateExclusionRequest, opts ...gax.CallOption) (*loggingpb.LogExclusion, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.CreateExclusion[0:len(c.CallOptions.CreateExclusion):len(c.CallOptions.CreateExclusion)], opts...)
|
||||
var resp *loggingpb.LogExclusion
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.CreateExclusion(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// UpdateExclusion changes one or more properties of an existing exclusion.
|
||||
func (c *ConfigClient) UpdateExclusion(ctx context.Context, req *loggingpb.UpdateExclusionRequest, opts ...gax.CallOption) (*loggingpb.LogExclusion, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.UpdateExclusion[0:len(c.CallOptions.UpdateExclusion):len(c.CallOptions.UpdateExclusion)], opts...)
|
||||
var resp *loggingpb.LogExclusion
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.configClient.UpdateExclusion(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DeleteExclusion deletes an exclusion.
|
||||
func (c *ConfigClient) DeleteExclusion(ctx context.Context, req *loggingpb.DeleteExclusionRequest, opts ...gax.CallOption) error {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.DeleteExclusion[0:len(c.CallOptions.DeleteExclusion):len(c.CallOptions.DeleteExclusion)], opts...)
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
_, err = c.configClient.DeleteExclusion(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, opts...)
|
||||
return err
|
||||
}
|
||||
|
||||
// LogExclusionIterator manages a stream of *loggingpb.LogExclusion.
|
||||
type LogExclusionIterator struct {
|
||||
items []*loggingpb.LogExclusion
|
||||
pageInfo *iterator.PageInfo
|
||||
nextFunc func() error
|
||||
|
||||
// InternalFetch is for use by the Google Cloud Libraries only.
|
||||
// It is not part of the stable interface of this package.
|
||||
//
|
||||
// InternalFetch returns results from a single call to the underlying RPC.
|
||||
// The number of results is no greater than pageSize.
|
||||
// If there are no more results, nextPageToken is empty and err is nil.
|
||||
InternalFetch func(pageSize int, pageToken string) (results []*loggingpb.LogExclusion, nextPageToken string, err error)
|
||||
}
|
||||
|
||||
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
|
||||
func (it *LogExclusionIterator) PageInfo() *iterator.PageInfo {
|
||||
return it.pageInfo
|
||||
}
|
||||
|
||||
// Next returns the next result. Its second return value is iterator.Done if there are no more
|
||||
// results. Once Next returns Done, all subsequent calls will return Done.
|
||||
func (it *LogExclusionIterator) Next() (*loggingpb.LogExclusion, error) {
|
||||
var item *loggingpb.LogExclusion
|
||||
if err := it.nextFunc(); err != nil {
|
||||
return item, err
|
||||
}
|
||||
item = it.items[0]
|
||||
it.items = it.items[1:]
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (it *LogExclusionIterator) bufLen() int {
|
||||
return len(it.items)
|
||||
}
|
||||
|
||||
func (it *LogExclusionIterator) takeBuf() interface{} {
|
||||
b := it.items
|
||||
it.items = nil
|
||||
return b
|
||||
}
|
||||
|
||||
// LogSinkIterator manages a stream of *loggingpb.LogSink.
|
||||
type LogSinkIterator struct {
|
||||
items []*loggingpb.LogSink
|
||||
|
||||
+33
-7
@@ -1,10 +1,10 @@
|
||||
// Copyright 2016, Google Inc. All rights reserved.
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -14,13 +14,39 @@
|
||||
|
||||
// AUTO-GENERATED CODE. DO NOT EDIT.
|
||||
|
||||
// Package logging is an experimental, auto-generated package for the
|
||||
// logging API.
|
||||
// Package logging is an auto-generated package for the
|
||||
// Stackdriver Logging API.
|
||||
//
|
||||
// The Stackdriver Logging API lets you write log entries and manage your
|
||||
// logs, log sinks and logs-based metrics.
|
||||
// NOTE: This package is in alpha. It is not stable, and is likely to change.
|
||||
//
|
||||
// Writes log entries and manages your Stackdriver Logging configuration.
|
||||
//
|
||||
// Use the client at cloud.google.com/go/logging in preference to this.
|
||||
package logging // import "cloud.google.com/go/logging/apiv2"
|
||||
|
||||
const gapicNameVersion = "gapic/0.1.0"
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
func insertMetadata(ctx context.Context, mds ...metadata.MD) context.Context {
|
||||
out, _ := metadata.FromOutgoingContext(ctx)
|
||||
out = out.Copy()
|
||||
for _, md := range mds {
|
||||
for k, v := range md {
|
||||
out[k] = append(out[k], v...)
|
||||
}
|
||||
}
|
||||
return metadata.NewOutgoingContext(ctx, out)
|
||||
}
|
||||
|
||||
// DefaultAuthScopes reports the default set of authentication scopes to use with this package.
|
||||
func DefaultAuthScopes() []string {
|
||||
return []string{
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/cloud-platform.read-only",
|
||||
"https://www.googleapis.com/auth/logging.admin",
|
||||
"https://www.googleapis.com/auth/logging.read",
|
||||
"https://www.googleapis.com/auth/logging.write",
|
||||
}
|
||||
}
|
||||
|
||||
+131
-77
@@ -1,10 +1,10 @@
|
||||
// Copyright 2016, Google Inc. All rights reserved.
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,12 +17,10 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/internal/version"
|
||||
gax "github.com/googleapis/gax-go"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/iterator"
|
||||
@@ -35,29 +33,19 @@ import (
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
loggingParentPathTemplate = gax.MustCompilePathTemplate("projects/{project}")
|
||||
loggingLogPathTemplate = gax.MustCompilePathTemplate("projects/{project}/logs/{log}")
|
||||
)
|
||||
|
||||
// CallOptions contains the retry settings for each method of Client.
|
||||
type CallOptions struct {
|
||||
DeleteLog []gax.CallOption
|
||||
WriteLogEntries []gax.CallOption
|
||||
ListLogEntries []gax.CallOption
|
||||
ListMonitoredResourceDescriptors []gax.CallOption
|
||||
ListLogs []gax.CallOption
|
||||
}
|
||||
|
||||
func defaultClientOptions() []option.ClientOption {
|
||||
return []option.ClientOption{
|
||||
option.WithEndpoint("logging.googleapis.com:443"),
|
||||
option.WithScopes(
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/cloud-platform.read-only",
|
||||
"https://www.googleapis.com/auth/logging.admin",
|
||||
"https://www.googleapis.com/auth/logging.read",
|
||||
"https://www.googleapis.com/auth/logging.write",
|
||||
),
|
||||
option.WithScopes(DefaultAuthScopes()...),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +55,7 @@ func defaultCallOptions() *CallOptions {
|
||||
gax.WithRetry(func() gax.Retryer {
|
||||
return gax.OnCodes([]codes.Code{
|
||||
codes.DeadlineExceeded,
|
||||
codes.Internal,
|
||||
codes.Unavailable,
|
||||
}, gax.Backoff{
|
||||
Initial: 100 * time.Millisecond,
|
||||
@@ -79,6 +68,7 @@ func defaultCallOptions() *CallOptions {
|
||||
gax.WithRetry(func() gax.Retryer {
|
||||
return gax.OnCodes([]codes.Code{
|
||||
codes.DeadlineExceeded,
|
||||
codes.Internal,
|
||||
codes.Unavailable,
|
||||
}, gax.Backoff{
|
||||
Initial: 100 * time.Millisecond,
|
||||
@@ -93,6 +83,7 @@ func defaultCallOptions() *CallOptions {
|
||||
WriteLogEntries: retry[[2]string{"default", "non_idempotent"}],
|
||||
ListLogEntries: retry[[2]string{"list", "idempotent"}],
|
||||
ListMonitoredResourceDescriptors: retry[[2]string{"default", "idempotent"}],
|
||||
ListLogs: retry[[2]string{"default", "idempotent"}],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +98,8 @@ type Client struct {
|
||||
// The call options for this service.
|
||||
CallOptions *CallOptions
|
||||
|
||||
// The metadata to be sent with each request.
|
||||
metadata metadata.MD
|
||||
// The x-goog-* metadata to be sent with each request.
|
||||
xGoogMetadata metadata.MD
|
||||
}
|
||||
|
||||
// NewClient creates a new logging service v2 client.
|
||||
@@ -125,7 +116,7 @@ func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error
|
||||
|
||||
client: loggingpb.NewLoggingServiceV2Client(conn),
|
||||
}
|
||||
c.SetGoogleClientInfo("gax", gax.Version)
|
||||
c.SetGoogleClientInfo()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -143,71 +134,55 @@ func (c *Client) Close() error {
|
||||
// SetGoogleClientInfo sets the name and version of the application in
|
||||
// the `x-goog-api-client` header passed on each request. Intended for
|
||||
// use by Google-written clients.
|
||||
func (c *Client) SetGoogleClientInfo(name, version string) {
|
||||
goVersion := strings.Replace(runtime.Version(), " ", "_", -1)
|
||||
v := fmt.Sprintf("%s/%s %s gax/%s go/%s", name, version, gapicNameVersion, gax.Version, goVersion)
|
||||
c.metadata = metadata.Pairs("x-goog-api-client", v)
|
||||
}
|
||||
|
||||
// LoggingParentPath returns the path for the parent resource.
|
||||
func LoggingParentPath(project string) string {
|
||||
path, err := loggingParentPathTemplate.Render(map[string]string{
|
||||
"project": project,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// LoggingLogPath returns the path for the log resource.
|
||||
func LoggingLogPath(project, log string) string {
|
||||
path, err := loggingLogPathTemplate.Render(map[string]string{
|
||||
"project": project,
|
||||
"log": log,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return path
|
||||
func (c *Client) SetGoogleClientInfo(keyval ...string) {
|
||||
kv := append([]string{"gl-go", version.Go()}, keyval...)
|
||||
kv = append(kv, "gapic", version.Repo, "gax", gax.Version, "grpc", grpc.Version)
|
||||
c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
|
||||
}
|
||||
|
||||
// DeleteLog deletes all the log entries in a log.
|
||||
// The log reappears if it receives new entries.
|
||||
func (c *Client) DeleteLog(ctx context.Context, req *loggingpb.DeleteLogRequest) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
// Log entries written shortly before the delete operation might not be
|
||||
// deleted.
|
||||
func (c *Client) DeleteLog(ctx context.Context, req *loggingpb.DeleteLogRequest, opts ...gax.CallOption) error {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.DeleteLog[0:len(c.CallOptions.DeleteLog):len(c.CallOptions.DeleteLog)], opts...)
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
_, err = c.client.DeleteLog(ctx, req)
|
||||
_, err = c.client.DeleteLog(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.DeleteLog...)
|
||||
}, opts...)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteLogEntries writes log entries to Stackdriver Logging. All log entries are
|
||||
// written by this method.
|
||||
func (c *Client) WriteLogEntries(ctx context.Context, req *loggingpb.WriteLogEntriesRequest) (*loggingpb.WriteLogEntriesResponse, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
// WriteLogEntries ## Log entry resources
|
||||
//
|
||||
// Writes log entries to Stackdriver Logging. This API method is the
|
||||
// only way to send log entries to Stackdriver Logging. This method
|
||||
// is used, directly or indirectly, by the Stackdriver Logging agent
|
||||
// (fluentd) and all logging libraries configured to use Stackdriver
|
||||
// Logging.
|
||||
func (c *Client) WriteLogEntries(ctx context.Context, req *loggingpb.WriteLogEntriesRequest, opts ...gax.CallOption) (*loggingpb.WriteLogEntriesResponse, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.WriteLogEntries[0:len(c.CallOptions.WriteLogEntries):len(c.CallOptions.WriteLogEntries)], opts...)
|
||||
var resp *loggingpb.WriteLogEntriesResponse
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.client.WriteLogEntries(ctx, req)
|
||||
resp, err = c.client.WriteLogEntries(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.WriteLogEntries...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ListLogEntries lists log entries. Use this method to retrieve log entries from Cloud
|
||||
// Logging. For ways to export log entries, see
|
||||
// [Exporting Logs](/logging/docs/export).
|
||||
func (c *Client) ListLogEntries(ctx context.Context, req *loggingpb.ListLogEntriesRequest) *LogEntryIterator {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
// ListLogEntries lists log entries. Use this method to retrieve log entries from
|
||||
// Stackdriver Logging. For ways to export log entries, see
|
||||
// Exporting Logs (at /logging/docs/export).
|
||||
func (c *Client) ListLogEntries(ctx context.Context, req *loggingpb.ListLogEntriesRequest, opts ...gax.CallOption) *LogEntryIterator {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.ListLogEntries[0:len(c.CallOptions.ListLogEntries):len(c.CallOptions.ListLogEntries)], opts...)
|
||||
it := &LogEntryIterator{}
|
||||
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogEntry, string, error) {
|
||||
var resp *loggingpb.ListLogEntriesResponse
|
||||
@@ -217,11 +192,11 @@ func (c *Client) ListLogEntries(ctx context.Context, req *loggingpb.ListLogEntri
|
||||
} else {
|
||||
req.PageSize = int32(pageSize)
|
||||
}
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.client.ListLogEntries(ctx, req)
|
||||
resp, err = c.client.ListLogEntries(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.ListLogEntries...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -239,10 +214,11 @@ func (c *Client) ListLogEntries(ctx context.Context, req *loggingpb.ListLogEntri
|
||||
return it
|
||||
}
|
||||
|
||||
// ListMonitoredResourceDescriptors lists the monitored resource descriptors used by Stackdriver Logging.
|
||||
func (c *Client) ListMonitoredResourceDescriptors(ctx context.Context, req *loggingpb.ListMonitoredResourceDescriptorsRequest) *MonitoredResourceDescriptorIterator {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
// ListMonitoredResourceDescriptors lists the descriptors for monitored resource types used by Stackdriver
|
||||
// Logging.
|
||||
func (c *Client) ListMonitoredResourceDescriptors(ctx context.Context, req *loggingpb.ListMonitoredResourceDescriptorsRequest, opts ...gax.CallOption) *MonitoredResourceDescriptorIterator {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.ListMonitoredResourceDescriptors[0:len(c.CallOptions.ListMonitoredResourceDescriptors):len(c.CallOptions.ListMonitoredResourceDescriptors)], opts...)
|
||||
it := &MonitoredResourceDescriptorIterator{}
|
||||
it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoredrespb.MonitoredResourceDescriptor, string, error) {
|
||||
var resp *loggingpb.ListMonitoredResourceDescriptorsResponse
|
||||
@@ -252,11 +228,11 @@ func (c *Client) ListMonitoredResourceDescriptors(ctx context.Context, req *logg
|
||||
} else {
|
||||
req.PageSize = int32(pageSize)
|
||||
}
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.client.ListMonitoredResourceDescriptors(ctx, req)
|
||||
resp, err = c.client.ListMonitoredResourceDescriptors(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.ListMonitoredResourceDescriptors...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -274,6 +250,42 @@ func (c *Client) ListMonitoredResourceDescriptors(ctx context.Context, req *logg
|
||||
return it
|
||||
}
|
||||
|
||||
// ListLogs lists the logs in projects, organizations, folders, or billing accounts.
|
||||
// Only logs that have entries are listed.
|
||||
func (c *Client) ListLogs(ctx context.Context, req *loggingpb.ListLogsRequest, opts ...gax.CallOption) *StringIterator {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.ListLogs[0:len(c.CallOptions.ListLogs):len(c.CallOptions.ListLogs)], opts...)
|
||||
it := &StringIterator{}
|
||||
it.InternalFetch = func(pageSize int, pageToken string) ([]string, string, error) {
|
||||
var resp *loggingpb.ListLogsResponse
|
||||
req.PageToken = pageToken
|
||||
if pageSize > math.MaxInt32 {
|
||||
req.PageSize = math.MaxInt32
|
||||
} else {
|
||||
req.PageSize = int32(pageSize)
|
||||
}
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.client.ListLogs(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return resp.LogNames, resp.NextPageToken, nil
|
||||
}
|
||||
fetch := func(pageSize int, pageToken string) (string, error) {
|
||||
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
it.items = append(it.items, items...)
|
||||
return nextPageToken, nil
|
||||
}
|
||||
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
|
||||
return it
|
||||
}
|
||||
|
||||
// LogEntryIterator manages a stream of *loggingpb.LogEntry.
|
||||
type LogEntryIterator struct {
|
||||
items []*loggingpb.LogEntry
|
||||
@@ -357,3 +369,45 @@ func (it *MonitoredResourceDescriptorIterator) takeBuf() interface{} {
|
||||
it.items = nil
|
||||
return b
|
||||
}
|
||||
|
||||
// StringIterator manages a stream of string.
|
||||
type StringIterator struct {
|
||||
items []string
|
||||
pageInfo *iterator.PageInfo
|
||||
nextFunc func() error
|
||||
|
||||
// InternalFetch is for use by the Google Cloud Libraries only.
|
||||
// It is not part of the stable interface of this package.
|
||||
//
|
||||
// InternalFetch returns results from a single call to the underlying RPC.
|
||||
// The number of results is no greater than pageSize.
|
||||
// If there are no more results, nextPageToken is empty and err is nil.
|
||||
InternalFetch func(pageSize int, pageToken string) (results []string, nextPageToken string, err error)
|
||||
}
|
||||
|
||||
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
|
||||
func (it *StringIterator) PageInfo() *iterator.PageInfo {
|
||||
return it.pageInfo
|
||||
}
|
||||
|
||||
// Next returns the next result. Its second return value is iterator.Done if there are no more
|
||||
// results. Once Next returns Done, all subsequent calls will return Done.
|
||||
func (it *StringIterator) Next() (string, error) {
|
||||
var item string
|
||||
if err := it.nextFunc(); err != nil {
|
||||
return item, err
|
||||
}
|
||||
item = it.items[0]
|
||||
it.items = it.items[1:]
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (it *StringIterator) bufLen() int {
|
||||
return len(it.items)
|
||||
}
|
||||
|
||||
func (it *StringIterator) takeBuf() interface{} {
|
||||
b := it.items
|
||||
it.items = nil
|
||||
return b
|
||||
}
|
||||
|
||||
+42
-77
@@ -1,10 +1,10 @@
|
||||
// Copyright 2016, Google Inc. All rights reserved.
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,12 +17,10 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/internal/version"
|
||||
gax "github.com/googleapis/gax-go"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/iterator"
|
||||
@@ -34,11 +32,6 @@ import (
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
metricsParentPathTemplate = gax.MustCompilePathTemplate("projects/{project}")
|
||||
metricsMetricPathTemplate = gax.MustCompilePathTemplate("projects/{project}/metrics/{metric}")
|
||||
)
|
||||
|
||||
// MetricsCallOptions contains the retry settings for each method of MetricsClient.
|
||||
type MetricsCallOptions struct {
|
||||
ListLogMetrics []gax.CallOption
|
||||
@@ -51,13 +44,7 @@ type MetricsCallOptions struct {
|
||||
func defaultMetricsClientOptions() []option.ClientOption {
|
||||
return []option.ClientOption{
|
||||
option.WithEndpoint("logging.googleapis.com:443"),
|
||||
option.WithScopes(
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/cloud-platform.read-only",
|
||||
"https://www.googleapis.com/auth/logging.admin",
|
||||
"https://www.googleapis.com/auth/logging.read",
|
||||
"https://www.googleapis.com/auth/logging.write",
|
||||
),
|
||||
option.WithScopes(DefaultAuthScopes()...),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +54,7 @@ func defaultMetricsCallOptions() *MetricsCallOptions {
|
||||
gax.WithRetry(func() gax.Retryer {
|
||||
return gax.OnCodes([]codes.Code{
|
||||
codes.DeadlineExceeded,
|
||||
codes.Internal,
|
||||
codes.Unavailable,
|
||||
}, gax.Backoff{
|
||||
Initial: 100 * time.Millisecond,
|
||||
@@ -96,8 +84,8 @@ type MetricsClient struct {
|
||||
// The call options for this service.
|
||||
CallOptions *MetricsCallOptions
|
||||
|
||||
// The metadata to be sent with each request.
|
||||
metadata metadata.MD
|
||||
// The x-goog-* metadata to be sent with each request.
|
||||
xGoogMetadata metadata.MD
|
||||
}
|
||||
|
||||
// NewMetricsClient creates a new metrics service v2 client.
|
||||
@@ -114,7 +102,7 @@ func NewMetricsClient(ctx context.Context, opts ...option.ClientOption) (*Metric
|
||||
|
||||
metricsClient: loggingpb.NewMetricsServiceV2Client(conn),
|
||||
}
|
||||
c.SetGoogleClientInfo("gax", gax.Version)
|
||||
c.SetGoogleClientInfo()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -132,39 +120,16 @@ func (c *MetricsClient) Close() error {
|
||||
// SetGoogleClientInfo sets the name and version of the application in
|
||||
// the `x-goog-api-client` header passed on each request. Intended for
|
||||
// use by Google-written clients.
|
||||
func (c *MetricsClient) SetGoogleClientInfo(name, version string) {
|
||||
goVersion := strings.Replace(runtime.Version(), " ", "_", -1)
|
||||
v := fmt.Sprintf("%s/%s %s gax/%s go/%s", name, version, gapicNameVersion, gax.Version, goVersion)
|
||||
c.metadata = metadata.Pairs("x-goog-api-client", v)
|
||||
}
|
||||
|
||||
// MetricsParentPath returns the path for the parent resource.
|
||||
func MetricsParentPath(project string) string {
|
||||
path, err := metricsParentPathTemplate.Render(map[string]string{
|
||||
"project": project,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// MetricsMetricPath returns the path for the metric resource.
|
||||
func MetricsMetricPath(project, metric string) string {
|
||||
path, err := metricsMetricPathTemplate.Render(map[string]string{
|
||||
"project": project,
|
||||
"metric": metric,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return path
|
||||
func (c *MetricsClient) SetGoogleClientInfo(keyval ...string) {
|
||||
kv := append([]string{"gl-go", version.Go()}, keyval...)
|
||||
kv = append(kv, "gapic", version.Repo, "gax", gax.Version, "grpc", grpc.Version)
|
||||
c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
|
||||
}
|
||||
|
||||
// ListLogMetrics lists logs-based metrics.
|
||||
func (c *MetricsClient) ListLogMetrics(ctx context.Context, req *loggingpb.ListLogMetricsRequest) *LogMetricIterator {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
func (c *MetricsClient) ListLogMetrics(ctx context.Context, req *loggingpb.ListLogMetricsRequest, opts ...gax.CallOption) *LogMetricIterator {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.ListLogMetrics[0:len(c.CallOptions.ListLogMetrics):len(c.CallOptions.ListLogMetrics)], opts...)
|
||||
it := &LogMetricIterator{}
|
||||
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogMetric, string, error) {
|
||||
var resp *loggingpb.ListLogMetricsResponse
|
||||
@@ -174,11 +139,11 @@ func (c *MetricsClient) ListLogMetrics(ctx context.Context, req *loggingpb.ListL
|
||||
} else {
|
||||
req.PageSize = int32(pageSize)
|
||||
}
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.metricsClient.ListLogMetrics(ctx, req)
|
||||
resp, err = c.metricsClient.ListLogMetrics(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.ListLogMetrics...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -197,15 +162,15 @@ func (c *MetricsClient) ListLogMetrics(ctx context.Context, req *loggingpb.ListL
|
||||
}
|
||||
|
||||
// GetLogMetric gets a logs-based metric.
|
||||
func (c *MetricsClient) GetLogMetric(ctx context.Context, req *loggingpb.GetLogMetricRequest) (*loggingpb.LogMetric, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
func (c *MetricsClient) GetLogMetric(ctx context.Context, req *loggingpb.GetLogMetricRequest, opts ...gax.CallOption) (*loggingpb.LogMetric, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.GetLogMetric[0:len(c.CallOptions.GetLogMetric):len(c.CallOptions.GetLogMetric)], opts...)
|
||||
var resp *loggingpb.LogMetric
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.metricsClient.GetLogMetric(ctx, req)
|
||||
resp, err = c.metricsClient.GetLogMetric(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.GetLogMetric...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -213,15 +178,15 @@ func (c *MetricsClient) GetLogMetric(ctx context.Context, req *loggingpb.GetLogM
|
||||
}
|
||||
|
||||
// CreateLogMetric creates a logs-based metric.
|
||||
func (c *MetricsClient) CreateLogMetric(ctx context.Context, req *loggingpb.CreateLogMetricRequest) (*loggingpb.LogMetric, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
func (c *MetricsClient) CreateLogMetric(ctx context.Context, req *loggingpb.CreateLogMetricRequest, opts ...gax.CallOption) (*loggingpb.LogMetric, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.CreateLogMetric[0:len(c.CallOptions.CreateLogMetric):len(c.CallOptions.CreateLogMetric)], opts...)
|
||||
var resp *loggingpb.LogMetric
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.metricsClient.CreateLogMetric(ctx, req)
|
||||
resp, err = c.metricsClient.CreateLogMetric(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.CreateLogMetric...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -229,15 +194,15 @@ func (c *MetricsClient) CreateLogMetric(ctx context.Context, req *loggingpb.Crea
|
||||
}
|
||||
|
||||
// UpdateLogMetric creates or updates a logs-based metric.
|
||||
func (c *MetricsClient) UpdateLogMetric(ctx context.Context, req *loggingpb.UpdateLogMetricRequest) (*loggingpb.LogMetric, error) {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
func (c *MetricsClient) UpdateLogMetric(ctx context.Context, req *loggingpb.UpdateLogMetricRequest, opts ...gax.CallOption) (*loggingpb.LogMetric, error) {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.UpdateLogMetric[0:len(c.CallOptions.UpdateLogMetric):len(c.CallOptions.UpdateLogMetric)], opts...)
|
||||
var resp *loggingpb.LogMetric
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
resp, err = c.metricsClient.UpdateLogMetric(ctx, req)
|
||||
resp, err = c.metricsClient.UpdateLogMetric(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.UpdateLogMetric...)
|
||||
}, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -245,14 +210,14 @@ func (c *MetricsClient) UpdateLogMetric(ctx context.Context, req *loggingpb.Upda
|
||||
}
|
||||
|
||||
// DeleteLogMetric deletes a logs-based metric.
|
||||
func (c *MetricsClient) DeleteLogMetric(ctx context.Context, req *loggingpb.DeleteLogMetricRequest) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
ctx = metadata.NewContext(ctx, metadata.Join(md, c.metadata))
|
||||
err := gax.Invoke(ctx, func(ctx context.Context) error {
|
||||
func (c *MetricsClient) DeleteLogMetric(ctx context.Context, req *loggingpb.DeleteLogMetricRequest, opts ...gax.CallOption) error {
|
||||
ctx = insertMetadata(ctx, c.xGoogMetadata)
|
||||
opts = append(c.CallOptions.DeleteLogMetric[0:len(c.CallOptions.DeleteLogMetric):len(c.CallOptions.DeleteLogMetric)], opts...)
|
||||
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
|
||||
var err error
|
||||
_, err = c.metricsClient.DeleteLogMetric(ctx, req)
|
||||
_, err = c.metricsClient.DeleteLogMetric(ctx, req, settings.GRPC...)
|
||||
return err
|
||||
}, c.CallOptions.DeleteLogMetric...)
|
||||
}, opts...)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// Copyright 2018 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logging
|
||||
|
||||
// ConfigProjectPath returns the path for the project resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s", project)
|
||||
// instead.
|
||||
func ConfigProjectPath(project string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
""
|
||||
}
|
||||
|
||||
// ConfigSinkPath returns the path for the sink resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s/sinks/%s", project, sink)
|
||||
// instead.
|
||||
func ConfigSinkPath(project, sink string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
"/sinks/" +
|
||||
sink +
|
||||
""
|
||||
}
|
||||
|
||||
// ConfigExclusionPath returns the path for the exclusion resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s/exclusions/%s", project, exclusion)
|
||||
// instead.
|
||||
func ConfigExclusionPath(project, exclusion string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
"/exclusions/" +
|
||||
exclusion +
|
||||
""
|
||||
}
|
||||
|
||||
// ProjectPath returns the path for the project resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s", project)
|
||||
// instead.
|
||||
func ProjectPath(project string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
""
|
||||
}
|
||||
|
||||
// LogPath returns the path for the log resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s/logs/%s", project, log)
|
||||
// instead.
|
||||
func LogPath(project, log string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
"/logs/" +
|
||||
log +
|
||||
""
|
||||
}
|
||||
|
||||
// MetricsProjectPath returns the path for the project resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s", project)
|
||||
// instead.
|
||||
func MetricsProjectPath(project string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
""
|
||||
}
|
||||
|
||||
// MetricsMetricPath returns the path for the metric resource.
|
||||
//
|
||||
// Deprecated: Use
|
||||
// fmt.Sprintf("projects/%s/metrics/%s", project, metric)
|
||||
// instead.
|
||||
func MetricsMetricPath(project, metric string) string {
|
||||
return "" +
|
||||
"projects/" +
|
||||
project +
|
||||
"/metrics/" +
|
||||
metric +
|
||||
""
|
||||
}
|
||||
+31
-3
@@ -20,7 +20,8 @@ see package cloud.google.com/go/logging/logadmin.
|
||||
This client uses Logging API v2.
|
||||
See https://cloud.google.com/logging/docs/api/v2/ for an introduction to the API.
|
||||
|
||||
This package is experimental and subject to API changes.
|
||||
|
||||
Note: This package is in beta. Some backwards-incompatible changes may occur.
|
||||
|
||||
|
||||
Creating a Client
|
||||
@@ -37,7 +38,7 @@ Use a Client to interact with the Stackdriver Logging API.
|
||||
|
||||
Basic Usage
|
||||
|
||||
For most use-cases, you'll want to add log entries to a buffer to be periodically
|
||||
For most use cases, you'll want to add log entries to a buffer to be periodically
|
||||
flushed (automatically and asynchronously) to the Stackdriver Logging service.
|
||||
|
||||
// Initialize a logger
|
||||
@@ -62,11 +63,28 @@ Synchronous Logging
|
||||
|
||||
For critical errors, you may want to send your log entries immediately.
|
||||
LogSync is slow and will block until the log entry has been sent, so it is
|
||||
not recommended for basic use.
|
||||
not recommended for normal use.
|
||||
|
||||
lg.LogSync(ctx, logging.Entry{Payload: "ALERT! Something critical happened!"})
|
||||
|
||||
|
||||
Payloads
|
||||
|
||||
An entry payload can be a string, as in the examples above. It can also be any value
|
||||
that can be marshaled to a JSON object, like a map[string]interface{} or a struct:
|
||||
|
||||
type MyEntry struct {
|
||||
Name string
|
||||
Count int
|
||||
}
|
||||
lg.Log(logging.Entry{Payload: MyEntry{Name: "Bob", Count: 3}})
|
||||
|
||||
If you have a []byte of JSON, wrap it in json.RawMessage:
|
||||
|
||||
j := []byte(`{"Name": "Bob", "Count": 3}`)
|
||||
lg.Log(logging.Entry{Payload: json.RawMessage(j)})
|
||||
|
||||
|
||||
The Standard Logger Interface
|
||||
|
||||
You may want use a standard log.Logger in your program.
|
||||
@@ -85,5 +103,15 @@ An Entry may have one of a number of severity levels associated with it.
|
||||
Severity: logging.Critical,
|
||||
}
|
||||
|
||||
|
||||
Viewing Logs
|
||||
|
||||
You can view Stackdriver logs for projects at
|
||||
https://console.cloud.google.com/logs/viewer. Use the dropdown at the top left. When
|
||||
running from a Google Cloud Platform VM, select "GCE VM Instance". Otherwise, select
|
||||
"Google Project" and then the project ID. Logs for organizations, folders and billing
|
||||
accounts can be viewed on the command line with the "gcloud logging read" command.
|
||||
|
||||
|
||||
*/
|
||||
package logging // import "cloud.google.com/go/logging"
|
||||
|
||||
+9
@@ -28,3 +28,12 @@ func LogPath(parent, logID string) string {
|
||||
logID = strings.Replace(logID, "/", "%2F", -1)
|
||||
return fmt.Sprintf("%s/logs/%s", parent, logID)
|
||||
}
|
||||
|
||||
func LogIDFromPath(parent, path string) string {
|
||||
start := len(parent) + len("/logs/")
|
||||
if len(path) < start {
|
||||
return ""
|
||||
}
|
||||
logID := path[start:]
|
||||
return strings.Replace(logID, "%2F", "/", -1)
|
||||
}
|
||||
|
||||
+220
-80
@@ -36,6 +36,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"cloud.google.com/go/internal/version"
|
||||
vkit "cloud.google.com/go/logging/apiv2"
|
||||
"cloud.google.com/go/logging/internal"
|
||||
"github.com/golang/protobuf/proto"
|
||||
@@ -77,6 +79,12 @@ const (
|
||||
|
||||
// DefaultBufferedByteLimit is the default value for the BufferedByteLimit LoggerOption.
|
||||
DefaultBufferedByteLimit = 1 << 30 // 1GiB
|
||||
|
||||
// defaultWriteTimeout is the timeout for the underlying write API calls. As
|
||||
// write API calls are not idempotent, they are not retried on timeout. This
|
||||
// timeout is to allow clients to degrade gracefully if underlying logging
|
||||
// service is temporarily impaired for some reason.
|
||||
defaultWriteTimeout = 10 * time.Minute
|
||||
)
|
||||
|
||||
// For testing:
|
||||
@@ -84,16 +92,24 @@ var now = time.Now
|
||||
|
||||
// ErrOverflow signals that the number of buffered entries for a Logger
|
||||
// exceeds its BufferLimit.
|
||||
var ErrOverflow = errors.New("logging: log entry overflowed buffer limits")
|
||||
var ErrOverflow = bundler.ErrOverflow
|
||||
|
||||
// ErrOversizedEntry signals that an entry's size exceeds the maximum number of
|
||||
// bytes that will be sent in a single call to the logging service.
|
||||
var ErrOversizedEntry = bundler.ErrOversizedItem
|
||||
|
||||
// Client is a Logging client. A Client is associated with a single Cloud project.
|
||||
type Client struct {
|
||||
client *vkit.Client // client for the logging service
|
||||
projectID string
|
||||
errc chan error // should be buffered to minimize dropped errors
|
||||
donec chan struct{} // closed on Client.Close to close Logger bundlers
|
||||
loggers sync.WaitGroup // so we can wait for loggers to close
|
||||
closed bool
|
||||
client *vkit.Client // client for the logging service
|
||||
parent string // e.g. "projects/proj-id"
|
||||
errc chan error // should be buffered to minimize dropped errors
|
||||
donec chan struct{} // closed on Client.Close to close Logger bundlers
|
||||
loggers sync.WaitGroup // so we can wait for loggers to close
|
||||
closed bool
|
||||
|
||||
mu sync.Mutex
|
||||
nErrs int // number of errors we saw
|
||||
lastErr error // last error we saw
|
||||
|
||||
// OnError is called when an error occurs in a call to Log or Flush. The
|
||||
// error may be due to an invalid Entry, an overflow because BufferLimit
|
||||
@@ -107,15 +123,20 @@ type Client struct {
|
||||
OnError func(err error)
|
||||
}
|
||||
|
||||
// NewClient returns a new logging client associated with the provided project ID.
|
||||
// NewClient returns a new logging client associated with the provided parent.
|
||||
// A parent can take any of the following forms:
|
||||
// projects/PROJECT_ID
|
||||
// folders/FOLDER_ID
|
||||
// billingAccounts/ACCOUNT_ID
|
||||
// organizations/ORG_ID
|
||||
// for backwards compatibility, a string with no '/' is also allowed and is interpreted
|
||||
// as a project ID.
|
||||
//
|
||||
// By default NewClient uses WriteScope. To use a different scope, call
|
||||
// NewClient using a WithScopes option (see https://godoc.org/google.golang.org/api/option#WithScopes).
|
||||
func NewClient(ctx context.Context, projectID string, opts ...option.ClientOption) (*Client, error) {
|
||||
// Check for '/' in project ID to reserve the ability to support various owning resources,
|
||||
// in the form "{Collection}/{Name}", for instance "organizations/my-org".
|
||||
if strings.ContainsRune(projectID, '/') {
|
||||
return nil, errors.New("logging: project ID contains '/'")
|
||||
func NewClient(ctx context.Context, parent string, opts ...option.ClientOption) (*Client, error) {
|
||||
if !strings.ContainsRune(parent, '/') {
|
||||
parent = "projects/" + parent
|
||||
}
|
||||
opts = append([]option.ClientOption{
|
||||
option.WithEndpoint(internal.ProdAddr),
|
||||
@@ -125,13 +146,13 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.SetGoogleClientInfo("logging", internal.Version)
|
||||
c.SetGoogleClientInfo("gccl", version.Repo)
|
||||
client := &Client{
|
||||
client: c,
|
||||
projectID: projectID,
|
||||
errc: make(chan error, defaultErrorCapacity), // create a small buffer for errors
|
||||
donec: make(chan struct{}),
|
||||
OnError: func(e error) { log.Printf("logging client: %v", e) },
|
||||
client: c,
|
||||
parent: parent,
|
||||
errc: make(chan error, defaultErrorCapacity), // create a small buffer for errors
|
||||
donec: make(chan struct{}),
|
||||
OnError: func(e error) { log.Printf("logging client: %v", e) },
|
||||
}
|
||||
// Call the user's function synchronously, to make life easier for them.
|
||||
go func() {
|
||||
@@ -143,18 +164,13 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio
|
||||
if fn := client.OnError; fn != nil {
|
||||
fn(err)
|
||||
} else {
|
||||
log.Printf("logging (project ID %q): %v", projectID, err)
|
||||
log.Printf("logging (parent %q): %v", parent, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// parent returns the string used in many RPCs to denote the parent resource of the log.
|
||||
func (c *Client) parent() string {
|
||||
return "projects/" + c.projectID
|
||||
}
|
||||
|
||||
var unixZeroTimestamp *tspb.Timestamp
|
||||
|
||||
func init() {
|
||||
@@ -170,18 +186,43 @@ func init() {
|
||||
// log entry "ping" to a log named "ping".
|
||||
func (c *Client) Ping(ctx context.Context) error {
|
||||
ent := &logpb.LogEntry{
|
||||
Payload: &logpb.LogEntry_TextPayload{"ping"},
|
||||
Payload: &logpb.LogEntry_TextPayload{TextPayload: "ping"},
|
||||
Timestamp: unixZeroTimestamp, // Identical timestamps and insert IDs are both
|
||||
InsertId: "ping", // necessary for the service to dedup these entries.
|
||||
}
|
||||
_, err := c.client.WriteLogEntries(ctx, &logpb.WriteLogEntriesRequest{
|
||||
LogName: internal.LogPath(c.parent(), "ping"),
|
||||
Resource: &mrpb.MonitoredResource{Type: "global"},
|
||||
LogName: internal.LogPath(c.parent, "ping"),
|
||||
Resource: monitoredResource(c.parent),
|
||||
Entries: []*logpb.LogEntry{ent},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// error puts the error on the client's error channel
|
||||
// without blocking, and records summary error info.
|
||||
func (c *Client) error(err error) {
|
||||
select {
|
||||
case c.errc <- err:
|
||||
default:
|
||||
}
|
||||
c.mu.Lock()
|
||||
c.lastErr = err
|
||||
c.nErrs++
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *Client) extractErrorInfo() error {
|
||||
var err error
|
||||
c.mu.Lock()
|
||||
if c.lastErr != nil {
|
||||
err = fmt.Errorf("saw %d errors; last: %v", c.nErrs, c.lastErr)
|
||||
c.nErrs = 0
|
||||
c.lastErr = nil
|
||||
}
|
||||
c.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// A Logger is used to write log messages to a single log. It can be configured
|
||||
// with a log ID, common monitored resource, and a set of common labels.
|
||||
type Logger struct {
|
||||
@@ -193,6 +234,7 @@ type Logger struct {
|
||||
// Options
|
||||
commonResource *mrpb.MonitoredResource
|
||||
commonLabels map[string]string
|
||||
writeTimeout time.Duration
|
||||
}
|
||||
|
||||
// A LoggerOption is a configuration option for a Logger.
|
||||
@@ -201,14 +243,80 @@ type LoggerOption interface {
|
||||
}
|
||||
|
||||
// CommonResource sets the monitored resource associated with all log entries
|
||||
// written from a Logger. If not provided, a resource of type "global" is used.
|
||||
// This value can be overridden by setting an Entry's Resource field.
|
||||
// written from a Logger. If not provided, the resource is automatically
|
||||
// detected based on the running environment. This value can be overridden
|
||||
// per-entry by setting an Entry's Resource field.
|
||||
func CommonResource(r *mrpb.MonitoredResource) LoggerOption { return commonResource{r} }
|
||||
|
||||
type commonResource struct{ *mrpb.MonitoredResource }
|
||||
|
||||
func (r commonResource) set(l *Logger) { l.commonResource = r.MonitoredResource }
|
||||
|
||||
var detectedResource struct {
|
||||
pb *mrpb.MonitoredResource
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func detectResource() *mrpb.MonitoredResource {
|
||||
detectedResource.once.Do(func() {
|
||||
if !metadata.OnGCE() {
|
||||
return
|
||||
}
|
||||
projectID, err := metadata.ProjectID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id, err := metadata.InstanceID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
zone, err := metadata.Zone()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
detectedResource.pb = &mrpb.MonitoredResource{
|
||||
Type: "gce_instance",
|
||||
Labels: map[string]string{
|
||||
"project_id": projectID,
|
||||
"instance_id": id,
|
||||
"zone": zone,
|
||||
},
|
||||
}
|
||||
})
|
||||
return detectedResource.pb
|
||||
}
|
||||
|
||||
var resourceInfo = map[string]struct{ rtype, label string }{
|
||||
"organizations": {"organization", "organization_id"},
|
||||
"folders": {"folder", "folder_id"},
|
||||
"projects": {"project", "project_id"},
|
||||
"billingAccounts": {"billing_account", "account_id"},
|
||||
}
|
||||
|
||||
func monitoredResource(parent string) *mrpb.MonitoredResource {
|
||||
parts := strings.SplitN(parent, "/", 2)
|
||||
if len(parts) != 2 {
|
||||
return globalResource(parent)
|
||||
}
|
||||
info, ok := resourceInfo[parts[0]]
|
||||
if !ok {
|
||||
return globalResource(parts[1])
|
||||
}
|
||||
return &mrpb.MonitoredResource{
|
||||
Type: info.rtype,
|
||||
Labels: map[string]string{info.label: parts[1]},
|
||||
}
|
||||
}
|
||||
|
||||
func globalResource(projectID string) *mrpb.MonitoredResource {
|
||||
return &mrpb.MonitoredResource{
|
||||
Type: "global",
|
||||
Labels: map[string]string{
|
||||
"project_id": projectID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// CommonLabels are labels that apply to all log entries written from a Logger,
|
||||
// so that you don't have to repeat them in each log entry's Labels field. If
|
||||
// any of the log entries contains a (key, value) with the same key that is in
|
||||
@@ -220,6 +328,15 @@ type commonLabels map[string]string
|
||||
|
||||
func (c commonLabels) set(l *Logger) { l.commonLabels = c }
|
||||
|
||||
// ConcurrentWriteLimit determines how many goroutines will send log entries to the
|
||||
// underlying service. The default is 1. Set ConcurrentWriteLimit to a higher value to
|
||||
// increase throughput.
|
||||
func ConcurrentWriteLimit(n int) LoggerOption { return concurrentWriteLimit(n) }
|
||||
|
||||
type concurrentWriteLimit int
|
||||
|
||||
func (c concurrentWriteLimit) set(l *Logger) { l.bundler.HandlerLimit = int(c) }
|
||||
|
||||
// DelayThreshold is the maximum amount of time that an entry should remain
|
||||
// buffered in memory before a call to the logging service is triggered. Larger
|
||||
// values of DelayThreshold will generally result in fewer calls to the logging
|
||||
@@ -256,10 +373,10 @@ type entryByteThreshold int
|
||||
func (e entryByteThreshold) set(l *Logger) { l.bundler.BundleByteThreshold = int(e) }
|
||||
|
||||
// EntryByteLimit is the maximum number of bytes of entries that will be sent
|
||||
// in a single call to the logging service. This option limits the size of a
|
||||
// single RPC payload, to account for network or service issues with large
|
||||
// RPCs. If EntryByteLimit is smaller than EntryByteThreshold, the latter has
|
||||
// no effect.
|
||||
// in a single call to the logging service. ErrOversizedEntry is returned if an
|
||||
// entry exceeds EntryByteLimit. This option limits the size of a single RPC
|
||||
// payload, to account for network or service issues with large RPCs. If
|
||||
// EntryByteLimit is smaller than EntryByteThreshold, the latter has no effect.
|
||||
// The default is zero, meaning there is no limit.
|
||||
func EntryByteLimit(n int) LoggerOption { return entryByteLimit(n) }
|
||||
|
||||
@@ -287,15 +404,17 @@ func (b bufferedByteLimit) set(l *Logger) { l.bundler.BufferedByteLimit = int(b)
|
||||
// characters: [A-Za-z0-9]; and punctuation characters: forward-slash,
|
||||
// underscore, hyphen, and period.
|
||||
func (c *Client) Logger(logID string, opts ...LoggerOption) *Logger {
|
||||
r := detectResource()
|
||||
if r == nil {
|
||||
r = monitoredResource(c.parent)
|
||||
}
|
||||
l := &Logger{
|
||||
client: c,
|
||||
logName: internal.LogPath(c.parent(), logID),
|
||||
commonResource: &mrpb.MonitoredResource{Type: "global"},
|
||||
logName: internal.LogPath(c.parent, logID),
|
||||
commonResource: r,
|
||||
}
|
||||
// TODO(jba): determine the right context for the bundle handler.
|
||||
ctx := context.TODO()
|
||||
l.bundler = bundler.NewBundler(&logpb.LogEntry{}, func(entries interface{}) {
|
||||
l.writeLogEntries(ctx, entries.([]*logpb.LogEntry))
|
||||
l.writeLogEntries(entries.([]*logpb.LogEntry))
|
||||
})
|
||||
l.bundler.DelayThreshold = DefaultDelayThreshold
|
||||
l.bundler.BundleCountThreshold = DefaultEntryCountThreshold
|
||||
@@ -304,16 +423,18 @@ func (c *Client) Logger(logID string, opts ...LoggerOption) *Logger {
|
||||
for _, opt := range opts {
|
||||
opt.set(l)
|
||||
}
|
||||
|
||||
l.stdLoggers = map[Severity]*log.Logger{}
|
||||
for s := range severityName {
|
||||
l.stdLoggers[s] = log.New(severityWriter{l, s}, "", 0)
|
||||
}
|
||||
|
||||
c.loggers.Add(1)
|
||||
// Start a goroutine that cleans up the bundler, its channel
|
||||
// and the writer goroutines when the client is closed.
|
||||
go func() {
|
||||
defer c.loggers.Done()
|
||||
<-c.donec
|
||||
l.bundler.Close()
|
||||
l.bundler.Flush()
|
||||
}()
|
||||
return l
|
||||
}
|
||||
@@ -331,7 +452,7 @@ func (w severityWriter) Write(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Close closes the client.
|
||||
// Close waits for all opened loggers to be flushed and closes the client.
|
||||
func (c *Client) Close() error {
|
||||
if c.closed {
|
||||
return nil
|
||||
@@ -340,9 +461,12 @@ func (c *Client) Close() error {
|
||||
c.loggers.Wait() // wait for all bundlers to flush and close
|
||||
// Now there can be no more errors.
|
||||
close(c.errc) // terminate error goroutine
|
||||
// Return only the first error. Since all clients share an underlying connection,
|
||||
// Closes after the first always report a "connection is closing" error.
|
||||
err := c.client.Close()
|
||||
// Prefer errors arising from logging to the error returned from Close.
|
||||
err := c.extractErrorInfo()
|
||||
err2 := c.client.Close()
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
c.closed = true
|
||||
return err
|
||||
}
|
||||
@@ -417,9 +541,8 @@ type Entry struct {
|
||||
// The zero value is Default.
|
||||
Severity Severity
|
||||
|
||||
// Payload must be either a string or something that
|
||||
// marshals via the encoding/json package to a JSON object
|
||||
// (and not any other type of JSON value).
|
||||
// Payload must be either a string, or something that marshals via the
|
||||
// encoding/json package to a JSON object (and not any other type of JSON value).
|
||||
Payload interface{}
|
||||
|
||||
// Labels optionally specifies key/value labels for the log entry.
|
||||
@@ -448,10 +571,13 @@ type Entry struct {
|
||||
// reading entries. It is an error to set it when writing entries.
|
||||
LogName string
|
||||
|
||||
// Resource is the monitored resource associated with the entry. It is set
|
||||
// by the client when reading entries. It is an error to set it when
|
||||
// writing entries.
|
||||
// Resource is the monitored resource associated with the entry.
|
||||
Resource *mrpb.MonitoredResource
|
||||
|
||||
// Trace is the resource name of the trace associated with the log entry,
|
||||
// if any. If it contains a relative resource name, the name is assumed to
|
||||
// be relative to //tracing.googleapis.com.
|
||||
Trace string
|
||||
}
|
||||
|
||||
// HTTPRequest contains an http.Request as well as additional
|
||||
@@ -476,6 +602,10 @@ type HTTPRequest struct {
|
||||
// received until the response was sent.
|
||||
Latency time.Duration
|
||||
|
||||
// LocalIP is the IP address (IPv4 or IPv6) of the origin server that the request
|
||||
// was sent to.
|
||||
LocalIP string
|
||||
|
||||
// RemoteIP is the IP address (IPv4 or IPv6) of the client that issued the
|
||||
// HTTP request. Examples: "192.168.1.1", "FE80::0202:B3FF:FE1E:8329".
|
||||
RemoteIP string
|
||||
@@ -499,19 +629,23 @@ func fromHTTPRequest(r *HTTPRequest) *logtypepb.HttpRequest {
|
||||
}
|
||||
u := *r.Request.URL
|
||||
u.Fragment = ""
|
||||
return &logtypepb.HttpRequest{
|
||||
pb := &logtypepb.HttpRequest{
|
||||
RequestMethod: r.Request.Method,
|
||||
RequestUrl: u.String(),
|
||||
RequestSize: r.RequestSize,
|
||||
Status: int32(r.Status),
|
||||
ResponseSize: r.ResponseSize,
|
||||
Latency: ptypes.DurationProto(r.Latency),
|
||||
UserAgent: r.Request.UserAgent(),
|
||||
ServerIp: r.LocalIP,
|
||||
RemoteIp: r.RemoteIP, // TODO(jba): attempt to parse http.Request.RemoteAddr?
|
||||
Referer: r.Request.Referer(),
|
||||
CacheHit: r.CacheHit,
|
||||
CacheValidatedWithOriginServer: r.CacheValidatedWithOriginServer,
|
||||
}
|
||||
if r.Latency != 0 {
|
||||
pb.Latency = ptypes.DurationProto(r.Latency)
|
||||
}
|
||||
return pb
|
||||
}
|
||||
|
||||
// toProtoStruct converts v, which must marshal into a JSON object,
|
||||
@@ -521,13 +655,19 @@ func toProtoStruct(v interface{}) (*structpb.Struct, error) {
|
||||
if s, ok := v.(*structpb.Struct); ok {
|
||||
return s, nil
|
||||
}
|
||||
// v is a Go struct that supports JSON marshalling. We want a Struct
|
||||
// v is a Go value that supports JSON marshalling. We want a Struct
|
||||
// protobuf. Some day we may have a more direct way to get there, but right
|
||||
// now the only way is to marshal the Go struct to JSON, unmarshal into a
|
||||
// now the only way is to marshal the Go value to JSON, unmarshal into a
|
||||
// map, and then build the Struct proto from the map.
|
||||
jb, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("logging: json.Marshal: %v", err)
|
||||
var jb []byte
|
||||
var err error
|
||||
if raw, ok := v.(json.RawMessage); ok { // needed for Go 1.7 and below
|
||||
jb = []byte(raw)
|
||||
} else {
|
||||
jb, err = json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("logging: json.Marshal: %v", err)
|
||||
}
|
||||
}
|
||||
var m map[string]interface{}
|
||||
err = json.Unmarshal(jb, &m)
|
||||
@@ -548,21 +688,21 @@ func jsonMapToProtoStruct(m map[string]interface{}) *structpb.Struct {
|
||||
func jsonValueToStructValue(v interface{}) *structpb.Value {
|
||||
switch x := v.(type) {
|
||||
case bool:
|
||||
return &structpb.Value{Kind: &structpb.Value_BoolValue{x}}
|
||||
return &structpb.Value{Kind: &structpb.Value_BoolValue{BoolValue: x}}
|
||||
case float64:
|
||||
return &structpb.Value{Kind: &structpb.Value_NumberValue{x}}
|
||||
return &structpb.Value{Kind: &structpb.Value_NumberValue{NumberValue: x}}
|
||||
case string:
|
||||
return &structpb.Value{Kind: &structpb.Value_StringValue{x}}
|
||||
return &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: x}}
|
||||
case nil:
|
||||
return &structpb.Value{Kind: &structpb.Value_NullValue{}}
|
||||
case map[string]interface{}:
|
||||
return &structpb.Value{Kind: &structpb.Value_StructValue{jsonMapToProtoStruct(x)}}
|
||||
return &structpb.Value{Kind: &structpb.Value_StructValue{StructValue: jsonMapToProtoStruct(x)}}
|
||||
case []interface{}:
|
||||
var vals []*structpb.Value
|
||||
for _, e := range x {
|
||||
vals = append(vals, jsonValueToStructValue(e))
|
||||
}
|
||||
return &structpb.Value{Kind: &structpb.Value_ListValue{&structpb.ListValue{vals}}}
|
||||
return &structpb.Value{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{Values: vals}}}
|
||||
default:
|
||||
panic(fmt.Sprintf("bad type %T for JSON value", v))
|
||||
}
|
||||
@@ -590,38 +730,37 @@ func (l *Logger) LogSync(ctx context.Context, e Entry) error {
|
||||
func (l *Logger) Log(e Entry) {
|
||||
ent, err := toLogEntry(e)
|
||||
if err != nil {
|
||||
l.error(err)
|
||||
l.client.error(err)
|
||||
return
|
||||
}
|
||||
if err := l.bundler.Add(ent, proto.Size(ent)); err != nil {
|
||||
l.error(err)
|
||||
l.client.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Flush blocks until all currently buffered log entries are sent.
|
||||
func (l *Logger) Flush() {
|
||||
//
|
||||
// If any errors occurred since the last call to Flush from any Logger, or the
|
||||
// creation of the client if this is the first call, then Flush returns a non-nil
|
||||
// error with summary information about the errors. This information is unlikely to
|
||||
// be actionable. For more accurate error reporting, set Client.OnError.
|
||||
func (l *Logger) Flush() error {
|
||||
l.bundler.Flush()
|
||||
return l.client.extractErrorInfo()
|
||||
}
|
||||
|
||||
func (l *Logger) writeLogEntries(ctx context.Context, entries []*logpb.LogEntry) {
|
||||
func (l *Logger) writeLogEntries(entries []*logpb.LogEntry) {
|
||||
req := &logpb.WriteLogEntriesRequest{
|
||||
LogName: l.logName,
|
||||
Resource: l.commonResource,
|
||||
Labels: l.commonLabels,
|
||||
Entries: entries,
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultWriteTimeout)
|
||||
defer cancel()
|
||||
_, err := l.client.client.WriteLogEntries(ctx, req)
|
||||
if err != nil {
|
||||
l.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// error puts the error on the client's error channel
|
||||
// without blocking.
|
||||
func (l *Logger) error(err error) {
|
||||
select {
|
||||
case l.client.errc <- err:
|
||||
default:
|
||||
l.client.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,17 +797,18 @@ func toLogEntry(e Entry) (*logpb.LogEntry, error) {
|
||||
HttpRequest: fromHTTPRequest(e.HTTPRequest),
|
||||
Operation: e.Operation,
|
||||
Labels: e.Labels,
|
||||
Trace: e.Trace,
|
||||
Resource: e.Resource,
|
||||
}
|
||||
|
||||
switch p := e.Payload.(type) {
|
||||
case string:
|
||||
ent.Payload = &logpb.LogEntry_TextPayload{p}
|
||||
ent.Payload = &logpb.LogEntry_TextPayload{TextPayload: p}
|
||||
default:
|
||||
s, err := toProtoStruct(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ent.Payload = &logpb.LogEntry_JsonPayload{s}
|
||||
ent.Payload = &logpb.LogEntry_JsonPayload{JsonPayload: s}
|
||||
}
|
||||
return ent, nil
|
||||
}
|
||||
|
||||
-3
@@ -16,7 +16,6 @@ import (
|
||||
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
|
||||
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
|
||||
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
|
||||
//sys timeBeginPeriod(period uint32) (n int32) = winmm.timeBeginPeriod
|
||||
|
||||
type atomicBool int32
|
||||
|
||||
@@ -153,8 +152,6 @@ func (f *win32File) prepareIo() (*ioOperation, error) {
|
||||
|
||||
// ioCompletionProcessor processes completed async IOs forever
|
||||
func ioCompletionProcessor(h syscall.Handle) {
|
||||
// Set the timer resolution to 1. This fixes a performance regression in golang 1.6.
|
||||
timeBeginPeriod(1)
|
||||
for {
|
||||
var bytes uint32
|
||||
var key uintptr
|
||||
|
||||
-8
@@ -38,14 +38,12 @@ func errnoErr(e syscall.Errno) error {
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modwinmm = windows.NewLazySystemDLL("winmm.dll")
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
@@ -122,12 +120,6 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
|
||||
return
|
||||
}
|
||||
|
||||
func timeBeginPeriod(period uint32) (n int32) {
|
||||
r0, _, _ := syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0)
|
||||
n = int32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
|
||||
+16
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+16
@@ -1,5 +1,21 @@
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
// +build darwin freebsd linux solaris
|
||||
// +build darwin freebsd linux openbsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
|
||||
+16
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+16
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+16
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+16
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// +build openbsd,cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
//#include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TIOCGETA
|
||||
cmdTcSet = unix.TIOCSETA
|
||||
)
|
||||
|
||||
// ptsname retrieves the name of the first available pts for the given master.
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
ptspath, err := C.ptsname(C.int(f.Fd()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return C.GoString(ptspath), nil
|
||||
}
|
||||
|
||||
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
|
||||
// unlockpt should be called before opening the slave side of a pty.
|
||||
func unlockpt(f *os.File) error {
|
||||
if _, err := C.grantpt(C.int(f.Fd())); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// +build openbsd,!cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Implementing the functions below requires cgo support. Non-cgo stubs
|
||||
// versions are defined below to enable cross-compilation of source code
|
||||
// that depends on these functions, but the resultant cross-compiled
|
||||
// binaries cannot actually be used. If the stub function(s) below are
|
||||
// actually invoked they will display an error message and cause the
|
||||
// calling process to exit.
|
||||
//
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TIOCGETA
|
||||
cmdTcSet = unix.TIOCSETA
|
||||
)
|
||||
|
||||
func ptsname(f *os.File) (string, error) {
|
||||
panic("ptsname() support requires cgo.")
|
||||
}
|
||||
|
||||
func unlockpt(f *os.File) error {
|
||||
panic("unlockpt() support requires cgo.")
|
||||
}
|
||||
+16
@@ -1,5 +1,21 @@
|
||||
// +build solaris,cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
|
||||
+16
@@ -1,5 +1,21 @@
|
||||
// +build solaris,!cgo
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Implementing the functions below requires cgo support. Non-cgo stubs
|
||||
// versions are defined below to enable cross-compilation of source code
|
||||
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
// +build darwin freebsd linux solaris
|
||||
// +build darwin freebsd linux openbsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package console
|
||||
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2013-2016 Docker, Inc.
|
||||
Copyright The containerd Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
-395
@@ -1,395 +0,0 @@
|
||||
Attribution 4.0 International
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More_considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Attribution 4.0 International Public License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution 4.0 International Public License ("Public License"). To the
|
||||
extent this Public License may be interpreted as a contract, You are
|
||||
granted the Licensed Rights in consideration of Your acceptance of
|
||||
these terms and conditions, and the Licensor grants You such rights in
|
||||
consideration of benefits the Licensor receives from making the
|
||||
Licensed Material available under these terms and conditions.
|
||||
|
||||
|
||||
Section 1 -- Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
|
||||
c. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
|
||||
d. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
|
||||
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
|
||||
f. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
|
||||
g. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
h. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
|
||||
i. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
|
||||
j. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
|
||||
k. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
|
||||
|
||||
Section 2 -- Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part; and
|
||||
|
||||
b. produce, reproduce, and Share Adapted Material.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
|
||||
b. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties.
|
||||
|
||||
|
||||
Section 3 -- License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
|
||||
4. If You Share Adapted Material You produce, the Adapter's
|
||||
License You apply must not prevent recipients of the Adapted
|
||||
Material from complying with this Public License.
|
||||
|
||||
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of the database;
|
||||
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material; and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
|
||||
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
|
||||
|
||||
Section 6 -- Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
|
||||
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
|
||||
|
||||
Section 8 -- Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
+3
-4
@@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
[](https://godoc.org/github.com/containerd/containerd)
|
||||
[](https://travis-ci.org/containerd/containerd)
|
||||
@@ -211,6 +211,5 @@ __If you are reporting a security issue, please reach out discreetly at security
|
||||
|
||||
The containerd codebase is released under the [Apache 2.0 license](LICENSE.code).
|
||||
The README.md file, and files in the "docs" folder are licensed under the
|
||||
Creative Commons Attribution 4.0 International License under the terms and
|
||||
conditions set forth in the file "[LICENSE.docs](LICENSE.docs)". You may obtain a duplicate
|
||||
copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.
|
||||
Creative Commons Attribution 4.0 International License. You may obtain a
|
||||
copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.
|
||||
|
||||
Generated
Vendored
+4
-4
@@ -48,11 +48,11 @@ import google_protobuf "github.com/gogo/protobuf/types"
|
||||
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
|
||||
// skipping weak import containerd_plugin "github.com/containerd/containerd/protobuf/plugin"
|
||||
|
||||
import github_com_containerd_typeurl "github.com/containerd/typeurl"
|
||||
import typeurl "github.com/containerd/typeurl"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -153,7 +153,7 @@ func (m *ContainerCreate_Runtime) Field(fieldpath []string) (string, bool) {
|
||||
case "name":
|
||||
return string(m.Name), len(m.Name) > 0
|
||||
case "options":
|
||||
decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Options)
|
||||
decoded, err := typeurl.UnmarshalAny(m.Options)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
@@ -478,7 +478,7 @@ func (this *ContainerUpdate) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ import math "math"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -291,7 +291,7 @@ func (this *ImageCreate) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -312,7 +312,7 @@ func (this *ImageUpdate) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
|
||||
Generated
Vendored
+3
-3
@@ -12,7 +12,7 @@ import math "math"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -292,7 +292,7 @@ func (this *NamespaceCreate) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -313,7 +313,7 @@ func (this *NamespaceUpdate) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
|
||||
+9
-9
@@ -15,7 +15,7 @@ import containerd_types "github.com/containerd/containerd/api/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
@@ -468,8 +468,8 @@ func (m *TaskDelete) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintTask(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)))
|
||||
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
i = encodeVarintTask(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
|
||||
n2, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -562,8 +562,8 @@ func (m *TaskExit) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x2a
|
||||
i++
|
||||
i = encodeVarintTask(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)))
|
||||
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
i = encodeVarintTask(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
|
||||
n3, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -804,7 +804,7 @@ func (m *TaskDelete) Size() (n int) {
|
||||
if m.ExitStatus != 0 {
|
||||
n += 1 + sovTask(uint64(m.ExitStatus))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)
|
||||
l = types.SizeOfStdTime(m.ExitedAt)
|
||||
n += 1 + l + sovTask(uint64(l))
|
||||
return n
|
||||
}
|
||||
@@ -847,7 +847,7 @@ func (m *TaskExit) Size() (n int) {
|
||||
if m.ExitStatus != 0 {
|
||||
n += 1 + sovTask(uint64(m.ExitStatus))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)
|
||||
l = types.SizeOfStdTime(m.ExitedAt)
|
||||
n += 1 + l + sovTask(uint64(l))
|
||||
return n
|
||||
}
|
||||
@@ -1518,7 +1518,7 @@ func (m *TaskDelete) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -1851,7 +1851,7 @@ func (m *TaskExit) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+14
-16
@@ -33,16 +33,14 @@ import _ "github.com/gogo/protobuf/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -516,16 +514,16 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x42
|
||||
i++
|
||||
i = encodeVarintContainers(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)))
|
||||
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
i = encodeVarintContainers(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
|
||||
n3, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n3
|
||||
dAtA[i] = 0x4a
|
||||
i++
|
||||
i = encodeVarintContainers(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
i = encodeVarintContainers(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n4, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -888,9 +886,9 @@ func (m *Container) Size() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sovContainers(uint64(l))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)
|
||||
l = types.SizeOfStdTime(m.CreatedAt)
|
||||
n += 1 + l + sovContainers(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
|
||||
l = types.SizeOfStdTime(m.UpdatedAt)
|
||||
n += 1 + l + sovContainers(uint64(l))
|
||||
if len(m.Extensions) > 0 {
|
||||
for k, v := range m.Extensions {
|
||||
@@ -1027,7 +1025,7 @@ func (this *Container) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -1037,7 +1035,7 @@ func (this *Container) String() string {
|
||||
for k, _ := range this.Extensions {
|
||||
keysForExtensions = append(keysForExtensions, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForExtensions)
|
||||
sortkeys.Strings(keysForExtensions)
|
||||
mapStringForExtensions := "map[string]google_protobuf1.Any{"
|
||||
for _, k := range keysForExtensions {
|
||||
mapStringForExtensions += fmt.Sprintf("%v: %v,", k, this.Extensions[k])
|
||||
@@ -1523,7 +1521,7 @@ func (m *Container) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -1553,7 +1551,7 @@ func (m *Container) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+30
-32
@@ -41,16 +41,14 @@ import google_protobuf3 "github.com/gogo/protobuf/types"
|
||||
import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
|
||||
import time "time"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -936,16 +934,16 @@ func (m *Info) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)))
|
||||
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
|
||||
n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n2, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1249,16 +1247,16 @@ func (m *Status) MarshalTo(dAtA []byte) (int, error) {
|
||||
_ = l
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt)))
|
||||
n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
|
||||
i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.StartedAt)))
|
||||
n7, err := types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n7
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n8, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1493,16 +1491,16 @@ func (m *WriteContentResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt)))
|
||||
n10, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
|
||||
i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.StartedAt)))
|
||||
n10, err := types.StdTimeMarshalTo(m.StartedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n10
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintContent(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n11, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
i = encodeVarintContent(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n11, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1569,9 +1567,9 @@ func (m *Info) Size() (n int) {
|
||||
if m.Size_ != 0 {
|
||||
n += 1 + sovContent(uint64(m.Size_))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)
|
||||
l = types.SizeOfStdTime(m.CreatedAt)
|
||||
n += 1 + l + sovContent(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
|
||||
l = types.SizeOfStdTime(m.UpdatedAt)
|
||||
n += 1 + l + sovContent(uint64(l))
|
||||
if len(m.Labels) > 0 {
|
||||
for k, v := range m.Labels {
|
||||
@@ -1688,9 +1686,9 @@ func (m *ReadContentResponse) Size() (n int) {
|
||||
func (m *Status) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt)
|
||||
l = types.SizeOfStdTime(m.StartedAt)
|
||||
n += 1 + l + sovContent(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
|
||||
l = types.SizeOfStdTime(m.UpdatedAt)
|
||||
n += 1 + l + sovContent(uint64(l))
|
||||
l = len(m.Ref)
|
||||
if l > 0 {
|
||||
@@ -1794,9 +1792,9 @@ func (m *WriteContentResponse) Size() (n int) {
|
||||
if m.Action != 0 {
|
||||
n += 1 + sovContent(uint64(m.Action))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartedAt)
|
||||
l = types.SizeOfStdTime(m.StartedAt)
|
||||
n += 1 + l + sovContent(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
|
||||
l = types.SizeOfStdTime(m.UpdatedAt)
|
||||
n += 1 + l + sovContent(uint64(l))
|
||||
if m.Offset != 0 {
|
||||
n += 1 + sovContent(uint64(m.Offset))
|
||||
@@ -1842,7 +1840,7 @@ func (this *Info) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -2015,7 +2013,7 @@ func (this *WriteContentRequest) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -2169,7 +2167,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -2199,7 +2197,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -3205,7 +3203,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -3235,7 +3233,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -4066,7 +4064,7 @@ func (m *WriteContentResponse) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.StartedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -4096,7 +4094,7 @@ func (m *WriteContentResponse) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+4
-6
@@ -23,14 +23,12 @@ import math "math"
|
||||
import containerd_types "github.com/containerd/containerd/api/types"
|
||||
import containerd_types1 "github.com/containerd/containerd/api/types"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -507,7 +505,7 @@ func (this *DiffRequest) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
|
||||
Generated
Vendored
+9
-11
@@ -27,14 +27,12 @@ import _ "github.com/gogo/protobuf/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import github_com_containerd_typeurl "github.com/containerd/typeurl"
|
||||
import typeurl "github.com/containerd/typeurl"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
@@ -110,7 +108,7 @@ func (m *Envelope) Field(fieldpath []string) (string, bool) {
|
||||
case "topic":
|
||||
return string(m.Topic), len(m.Topic) > 0
|
||||
case "event":
|
||||
decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Event)
|
||||
decoded, err := typeurl.UnmarshalAny(m.Event)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
@@ -434,8 +432,8 @@ func (m *Envelope) MarshalTo(dAtA []byte) (int, error) {
|
||||
_ = l
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintEvents(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
|
||||
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
|
||||
i = encodeVarintEvents(dAtA, i, uint64(types.SizeOfStdTime(m.Timestamp)))
|
||||
n3, err := types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -513,7 +511,7 @@ func (m *SubscribeRequest) Size() (n int) {
|
||||
func (m *Envelope) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)
|
||||
l = types.SizeOfStdTime(m.Timestamp)
|
||||
n += 1 + l + sovEvents(uint64(l))
|
||||
l = len(m.Namespace)
|
||||
if l > 0 {
|
||||
@@ -924,7 +922,7 @@ func (m *Envelope) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+13
-15
@@ -33,16 +33,14 @@ import containerd_types "github.com/containerd/containerd/api/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -455,16 +453,16 @@ func (m *Image) MarshalTo(dAtA []byte) (int, error) {
|
||||
i += n1
|
||||
dAtA[i] = 0x3a
|
||||
i++
|
||||
i = encodeVarintImages(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)))
|
||||
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
i = encodeVarintImages(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
|
||||
n2, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n2
|
||||
dAtA[i] = 0x42
|
||||
i++
|
||||
i = encodeVarintImages(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
i = encodeVarintImages(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n3, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -761,9 +759,9 @@ func (m *Image) Size() (n int) {
|
||||
}
|
||||
l = m.Target.Size()
|
||||
n += 1 + l + sovImages(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)
|
||||
l = types.SizeOfStdTime(m.CreatedAt)
|
||||
n += 1 + l + sovImages(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
|
||||
l = types.SizeOfStdTime(m.UpdatedAt)
|
||||
n += 1 + l + sovImages(uint64(l))
|
||||
return n
|
||||
}
|
||||
@@ -882,7 +880,7 @@ func (this *Image) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -1230,7 +1228,7 @@ func (m *Image) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -1260,7 +1258,7 @@ func (m *Image) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+5
-7
@@ -18,18 +18,16 @@ import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import containerd_types "github.com/containerd/containerd/api/types"
|
||||
import google_rpc "github.com/containerd/containerd/protobuf/google/rpc"
|
||||
import google_rpc "github.com/gogo/googleapis/google/rpc"
|
||||
|
||||
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -460,7 +458,7 @@ func (this *Plugin) String() string {
|
||||
for k, _ := range this.Exports {
|
||||
keysForExports = append(keysForExports, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForExports)
|
||||
sortkeys.Strings(keysForExports)
|
||||
mapStringForExports := "map[string]string{"
|
||||
for _, k := range keysForExports {
|
||||
mapStringForExports += fmt.Sprintf("%v: %v,", k, this.Exports[k])
|
||||
|
||||
Generated
Vendored
+10
-12
@@ -27,16 +27,14 @@ import _ "github.com/gogo/protobuf/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -290,8 +288,8 @@ func (m *Lease) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintLeases(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)))
|
||||
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
i = encodeVarintLeases(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
|
||||
n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -488,7 +486,7 @@ func (m *Lease) Size() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sovLeases(uint64(l))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)
|
||||
l = types.SizeOfStdTime(m.CreatedAt)
|
||||
n += 1 + l + sovLeases(uint64(l))
|
||||
if len(m.Labels) > 0 {
|
||||
for k, v := range m.Labels {
|
||||
@@ -584,7 +582,7 @@ func (this *Lease) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -606,7 +604,7 @@ func (this *CreateRequest) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -751,7 +749,7 @@ func (m *Lease) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
components/engine/vendor/github.com/containerd/containerd/api/services/namespaces/v1/namespace.pb.go
Generated
Vendored
+4
-6
@@ -29,14 +29,12 @@ import math "math"
|
||||
import google_protobuf1 "github.com/gogo/protobuf/types"
|
||||
import google_protobuf2 "github.com/gogo/protobuf/types"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -787,7 +785,7 @@ func (this *Namespace) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
|
||||
Generated
Vendored
+16
-18
@@ -40,16 +40,14 @@ import containerd_types "github.com/containerd/containerd/api/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -1027,16 +1025,16 @@ func (m *Info) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintSnapshots(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)))
|
||||
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
i = encodeVarintSnapshots(dAtA, i, uint64(types.SizeOfStdTime(m.CreatedAt)))
|
||||
n1, err := types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
dAtA[i] = 0x2a
|
||||
i++
|
||||
i = encodeVarintSnapshots(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
i = encodeVarintSnapshots(dAtA, i, uint64(types.SizeOfStdTime(m.UpdatedAt)))
|
||||
n2, err := types.StdTimeMarshalTo(m.UpdatedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1446,9 +1444,9 @@ func (m *Info) Size() (n int) {
|
||||
if m.Kind != 0 {
|
||||
n += 1 + sovSnapshots(uint64(m.Kind))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt)
|
||||
l = types.SizeOfStdTime(m.CreatedAt)
|
||||
n += 1 + l + sovSnapshots(uint64(l))
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
|
||||
l = types.SizeOfStdTime(m.UpdatedAt)
|
||||
n += 1 + l + sovSnapshots(uint64(l))
|
||||
if len(m.Labels) > 0 {
|
||||
for k, v := range m.Labels {
|
||||
@@ -1562,7 +1560,7 @@ func (this *PrepareSnapshotRequest) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -1595,7 +1593,7 @@ func (this *ViewSnapshotRequest) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -1660,7 +1658,7 @@ func (this *CommitSnapshotRequest) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -1694,7 +1692,7 @@ func (this *Info) String() string {
|
||||
for k, _ := range this.Labels {
|
||||
keysForLabels = append(keysForLabels, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
|
||||
sortkeys.Strings(keysForLabels)
|
||||
mapStringForLabels := "map[string]string{"
|
||||
for _, k := range keysForLabels {
|
||||
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
|
||||
@@ -3257,7 +3255,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -3287,7 +3285,7 @@ func (m *Info) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.UpdatedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+11
-13
@@ -54,12 +54,10 @@ import _ "github.com/gogo/protobuf/types"
|
||||
import time "time"
|
||||
import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
@@ -1198,8 +1196,8 @@ func (m *DeleteResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintTasks(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)))
|
||||
n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
i = encodeVarintTasks(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
|
||||
n3, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1881,8 +1879,8 @@ func (m *WaitResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintTasks(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)))
|
||||
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
i = encodeVarintTasks(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
|
||||
n8, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -1997,7 +1995,7 @@ func (m *DeleteResponse) Size() (n int) {
|
||||
if m.ExitStatus != 0 {
|
||||
n += 1 + sovTasks(uint64(m.ExitStatus))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)
|
||||
l = types.SizeOfStdTime(m.ExitedAt)
|
||||
n += 1 + l + sovTasks(uint64(l))
|
||||
return n
|
||||
}
|
||||
@@ -2288,7 +2286,7 @@ func (m *WaitResponse) Size() (n int) {
|
||||
if m.ExitStatus != 0 {
|
||||
n += 1 + sovTasks(uint64(m.ExitStatus))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)
|
||||
l = types.SizeOfStdTime(m.ExitedAt)
|
||||
n += 1 + l + sovTasks(uint64(l))
|
||||
return n
|
||||
}
|
||||
@@ -3375,7 +3373,7 @@ func (m *DeleteResponse) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
@@ -5572,7 +5570,7 @@ func (m *WaitResponse) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+2
-4
@@ -19,10 +19,8 @@ import google_protobuf "github.com/gogo/protobuf/types"
|
||||
|
||||
// skipping weak import gogoproto "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
|
||||
Generated
Vendored
+5
-5
@@ -13,7 +13,7 @@ import _ "github.com/gogo/protobuf/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types1 "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
@@ -56,8 +56,8 @@ func (m *Metric) MarshalTo(dAtA []byte) (int, error) {
|
||||
_ = l
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintMetrics(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
|
||||
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
|
||||
i = encodeVarintMetrics(dAtA, i, uint64(types1.SizeOfStdTime(m.Timestamp)))
|
||||
n1, err := types1.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func encodeVarintMetrics(dAtA []byte, offset int, v uint64) int {
|
||||
func (m *Metric) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)
|
||||
l = types1.SizeOfStdTime(m.Timestamp)
|
||||
n += 1 + l + sovMetrics(uint64(l))
|
||||
l = len(m.ID)
|
||||
if l > 0 {
|
||||
@@ -194,7 +194,7 @@ func (m *Metric) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types1.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
Generated
Vendored
+5
-5
@@ -23,7 +23,7 @@ import google_protobuf2 "github.com/gogo/protobuf/types"
|
||||
|
||||
import time "time"
|
||||
|
||||
import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
|
||||
import types "github.com/gogo/protobuf/types"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
@@ -182,8 +182,8 @@ func (m *Process) MarshalTo(dAtA []byte) (int, error) {
|
||||
}
|
||||
dAtA[i] = 0x52
|
||||
i++
|
||||
i = encodeVarintTask(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)))
|
||||
n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
i = encodeVarintTask(dAtA, i, uint64(types.SizeOfStdTime(m.ExitedAt)))
|
||||
n1, err := types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -268,7 +268,7 @@ func (m *Process) Size() (n int) {
|
||||
if m.ExitStatus != 0 {
|
||||
n += 1 + sovTask(uint64(m.ExitStatus))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)
|
||||
l = types.SizeOfStdTime(m.ExitedAt)
|
||||
n += 1 + l + sovTask(uint64(l))
|
||||
return n
|
||||
}
|
||||
@@ -614,7 +614,7 @@ func (m *Process) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dmcgowan/go-tar"
|
||||
"archive/tar"
|
||||
)
|
||||
|
||||
// Forked from https://github.com/golang/go/blob/master/src/archive/tar/strconv.go
|
||||
|
||||
+6
-3
@@ -17,6 +17,7 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -31,7 +32,6 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/dmcgowan/go-tar"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -199,7 +199,7 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
||||
basename := filepath.Base(hdr.Name)
|
||||
aufsHardlinks[basename] = hdr
|
||||
if aufsTempdir == "" {
|
||||
if aufsTempdir, err = ioutil.TempDir("", "dockerplnk"); err != nil {
|
||||
if aufsTempdir, err = ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "dockerplnk"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer os.RemoveAll(aufsTempdir)
|
||||
@@ -465,7 +465,10 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
|
||||
source = filepath.Join(cw.source, p)
|
||||
)
|
||||
|
||||
if f.Mode()&os.ModeSymlink != 0 {
|
||||
switch {
|
||||
case f.Mode()&os.ModeSocket != 0:
|
||||
return nil // ignore sockets
|
||||
case f.Mode()&os.ModeSymlink != 0:
|
||||
if link, err = os.Readlink(source); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+14
-11
@@ -19,13 +19,13 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/dmcgowan/go-tar"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -87,10 +87,6 @@ func mkdir(path string, perm os.FileMode) error {
|
||||
return os.Chmod(path, perm)
|
||||
}
|
||||
|
||||
func skipFile(*tar.Header) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
inUserNS bool
|
||||
nsOnce sync.Once
|
||||
@@ -100,15 +96,22 @@ func setInUserNS() {
|
||||
inUserNS = system.RunningInUserNS()
|
||||
}
|
||||
|
||||
// handleTarTypeBlockCharFifo is an OS-specific helper function used by
|
||||
// createTarFile to handle the following types of header: Block; Char; Fifo
|
||||
func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
|
||||
nsOnce.Do(setInUserNS)
|
||||
if inUserNS {
|
||||
func skipFile(hdr *tar.Header) bool {
|
||||
switch hdr.Typeflag {
|
||||
case tar.TypeBlock, tar.TypeChar:
|
||||
// cannot create a device if running in user namespace
|
||||
return nil
|
||||
nsOnce.Do(setInUserNS)
|
||||
return inUserNS
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// handleTarTypeBlockCharFifo is an OS-specific helper function used by
|
||||
// createTarFile to handle the following types of header: Block; Char; Fifo.
|
||||
// This function must not be called for Block and Char when running in userns.
|
||||
// (skipFile() should return true for them.)
|
||||
func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
|
||||
mode := uint32(hdr.Mode & 07777)
|
||||
switch hdr.Typeflag {
|
||||
case tar.TypeBlock:
|
||||
|
||||
+7
-4
@@ -19,6 +19,7 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
@@ -34,9 +35,7 @@ import (
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/dmcgowan/go-tar"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -180,8 +179,12 @@ func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options
|
||||
return 0, err
|
||||
}
|
||||
defer func() {
|
||||
if err := w.Close(); err != nil {
|
||||
log.G(ctx).Errorf("failed to close layer writer: %v", err)
|
||||
if err2 := w.Close(); err2 != nil {
|
||||
// This error should not be discarded as a failure here
|
||||
// could result in an invalid layer on disk
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
+42
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/defaults"
|
||||
@@ -213,3 +214,44 @@ type DirectIO struct {
|
||||
}
|
||||
|
||||
var _ IO = &DirectIO{}
|
||||
|
||||
// LogFile creates a file on disk that logs the task's STDOUT,STDERR.
|
||||
// If the log file already exists, the logs will be appended to the file.
|
||||
func LogFile(path string) Creator {
|
||||
return func(_ string) (IO, error) {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.Close()
|
||||
return &logIO{
|
||||
config: Config{
|
||||
Stdout: path,
|
||||
Stderr: path,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
type logIO struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
func (l *logIO) Config() Config {
|
||||
return l.config
|
||||
}
|
||||
|
||||
func (l *logIO) Cancel() {
|
||||
|
||||
}
|
||||
|
||||
func (l *logIO) Wait() {
|
||||
|
||||
}
|
||||
|
||||
func (l *logIO) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+10
@@ -141,8 +141,18 @@ func openFifos(ctx context.Context, fifos *FIFOSet) (pipes, error) {
|
||||
// NewDirectIO returns an IO implementation that exposes the IO streams as io.ReadCloser
|
||||
// and io.WriteCloser.
|
||||
func NewDirectIO(ctx context.Context, fifos *FIFOSet) (*DirectIO, error) {
|
||||
return newDirectIO(ctx, fifos, false)
|
||||
}
|
||||
|
||||
// NewDirectIOWithTerminal returns an IO implementation that exposes the streams with terminal enabled
|
||||
func NewDirectIOWithTerminal(ctx context.Context, fifos *FIFOSet) (*DirectIO, error) {
|
||||
return newDirectIO(ctx, fifos, true)
|
||||
}
|
||||
|
||||
func newDirectIO(ctx context.Context, fifos *FIFOSet, terminal bool) (*DirectIO, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
pipes, err := openFifos(ctx, fifos)
|
||||
fifos.Config.Terminal = terminal
|
||||
return &DirectIO{
|
||||
pipes: pipes,
|
||||
cio: cio{
|
||||
|
||||
+162
-202
@@ -19,10 +19,10 @@ package containerd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
containersapi "github.com/containerd/containerd/api/services/containers/v1"
|
||||
@@ -31,22 +31,26 @@ import (
|
||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
||||
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
|
||||
leasesapi "github.com/containerd/containerd/api/services/leases/v1"
|
||||
namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1"
|
||||
snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1"
|
||||
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||
versionservice "github.com/containerd/containerd/api/services/version/v1"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/dialer"
|
||||
contentproxy "github.com/containerd/containerd/content/proxy"
|
||||
"github.com/containerd/containerd/defaults"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/events"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/pkg/dialer"
|
||||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/containerd/containerd/remotes/docker/schema1"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
snproxy "github.com/containerd/containerd/snapshots/proxy"
|
||||
"github.com/containerd/typeurl"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@@ -75,54 +79,79 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
gopts := []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithInsecure(),
|
||||
grpc.WithTimeout(60 * time.Second),
|
||||
grpc.FailOnNonTempDialError(true),
|
||||
grpc.WithBackoffMaxDelay(3 * time.Second),
|
||||
grpc.WithDialer(dialer.Dialer),
|
||||
c := &Client{
|
||||
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
||||
}
|
||||
if len(copts.dialOptions) > 0 {
|
||||
gopts = copts.dialOptions
|
||||
if copts.services != nil {
|
||||
c.services = *copts.services
|
||||
}
|
||||
if copts.defaultns != "" {
|
||||
unary, stream := newNSInterceptors(copts.defaultns)
|
||||
gopts = append(gopts,
|
||||
grpc.WithUnaryInterceptor(unary),
|
||||
grpc.WithStreamInterceptor(stream),
|
||||
)
|
||||
}
|
||||
connector := func() (*grpc.ClientConn, error) {
|
||||
conn, err := grpc.Dial(dialer.DialAddress(address), gopts...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to dial %q", address)
|
||||
if address != "" {
|
||||
gopts := []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithInsecure(),
|
||||
grpc.FailOnNonTempDialError(true),
|
||||
grpc.WithBackoffMaxDelay(3 * time.Second),
|
||||
grpc.WithDialer(dialer.Dialer),
|
||||
|
||||
// TODO(stevvooe): We may need to allow configuration of this on the client.
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
|
||||
}
|
||||
return conn, nil
|
||||
if len(copts.dialOptions) > 0 {
|
||||
gopts = copts.dialOptions
|
||||
}
|
||||
if copts.defaultns != "" {
|
||||
unary, stream := newNSInterceptors(copts.defaultns)
|
||||
gopts = append(gopts,
|
||||
grpc.WithUnaryInterceptor(unary),
|
||||
grpc.WithStreamInterceptor(stream),
|
||||
)
|
||||
}
|
||||
connector := func() (*grpc.ClientConn, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
conn, err := grpc.DialContext(ctx, dialer.DialAddress(address), gopts...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to dial %q", address)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
conn, err := connector()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.conn, c.connector = conn, connector
|
||||
}
|
||||
conn, err := connector()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if copts.services == nil && c.conn == nil {
|
||||
return nil, errors.New("no grpc connection or services is available")
|
||||
}
|
||||
return &Client{
|
||||
conn: conn,
|
||||
connector: connector,
|
||||
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
||||
}, nil
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// NewWithConn returns a new containerd client that is connected to the containerd
|
||||
// instance provided by the connection
|
||||
func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
|
||||
return &Client{
|
||||
var copts clientOpts
|
||||
for _, o := range opts {
|
||||
if err := o(&copts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
c := &Client{
|
||||
conn: conn,
|
||||
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
||||
}, nil
|
||||
}
|
||||
if copts.services != nil {
|
||||
c.services = *copts.services
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Client is the client to interact with containerd and its various services
|
||||
// using a uniform interface
|
||||
type Client struct {
|
||||
services
|
||||
connMu sync.Mutex
|
||||
conn *grpc.ClientConn
|
||||
runtime string
|
||||
connector func() (*grpc.ClientConn, error)
|
||||
@@ -133,6 +162,8 @@ func (c *Client) Reconnect() error {
|
||||
if c.connector == nil {
|
||||
return errors.New("unable to reconnect to containerd, no connector available")
|
||||
}
|
||||
c.connMu.Lock()
|
||||
defer c.connMu.Unlock()
|
||||
c.conn.Close()
|
||||
conn, err := c.connector()
|
||||
if err != nil {
|
||||
@@ -149,6 +180,12 @@ func (c *Client) Reconnect() error {
|
||||
// connection. A timeout can be set in the context to ensure it returns
|
||||
// early.
|
||||
func (c *Client) IsServing(ctx context.Context) (bool, error) {
|
||||
c.connMu.Lock()
|
||||
if c.conn == nil {
|
||||
c.connMu.Unlock()
|
||||
return false, errors.New("no grpc connection available")
|
||||
}
|
||||
c.connMu.Unlock()
|
||||
r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.FailFast(false))
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -176,7 +213,7 @@ func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContain
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer done()
|
||||
defer done(ctx)
|
||||
|
||||
container := containers.Container{
|
||||
ID: id,
|
||||
@@ -212,6 +249,10 @@ type RemoteContext struct {
|
||||
// If no resolver is provided, defaults to Docker registry resolver.
|
||||
Resolver remotes.Resolver
|
||||
|
||||
// Platforms defines which platforms to handle when doing the image operation.
|
||||
// If this field is empty, content for all platforms will be pulled.
|
||||
Platforms []string
|
||||
|
||||
// Unpack is done after an image is pulled to extract into a snapshotter.
|
||||
// If an image is not unpacked on pull, it can be unpacked any time
|
||||
// afterwards. Unpacking is required to run an image.
|
||||
@@ -257,12 +298,13 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer done()
|
||||
defer done(ctx)
|
||||
|
||||
name, desc, err := pullCtx.Resolver.Resolve(ctx, ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to resolve reference %q", ref)
|
||||
}
|
||||
|
||||
fetcher, err := pullCtx.Resolver.Fetcher(ctx, name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get fetcher for %q", name)
|
||||
@@ -280,8 +322,8 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
childrenHandler := images.ChildrenHandler(store)
|
||||
// Set any children labels for that content
|
||||
childrenHandler = images.SetChildrenLabels(store, childrenHandler)
|
||||
// Filter the childen by the platform
|
||||
childrenHandler = images.FilterPlatform(platforms.Default(), childrenHandler)
|
||||
// Filter children by platforms
|
||||
childrenHandler = images.FilterPlatforms(childrenHandler, pullCtx.Platforms...)
|
||||
|
||||
handler = images.Handlers(append(pullCtx.BaseHandlers,
|
||||
remotes.FetchHandler(store, fetcher),
|
||||
@@ -299,38 +341,43 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
}
|
||||
}
|
||||
|
||||
imgrec := images.Image{
|
||||
Name: name,
|
||||
Target: desc,
|
||||
Labels: pullCtx.Labels,
|
||||
img := &image{
|
||||
client: c,
|
||||
i: images.Image{
|
||||
Name: name,
|
||||
Target: desc,
|
||||
Labels: pullCtx.Labels,
|
||||
},
|
||||
}
|
||||
|
||||
if pullCtx.Unpack {
|
||||
if err := img.Unpack(ctx, pullCtx.Snapshotter); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
|
||||
}
|
||||
}
|
||||
|
||||
is := c.ImageService()
|
||||
if created, err := is.Create(ctx, imgrec); err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
if created, err := is.Create(ctx, img.i); err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updated, err := is.Update(ctx, imgrec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
updated, err := is.Update(ctx, img.i)
|
||||
if err != nil {
|
||||
// if image was removed, try create again
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imgrec = updated
|
||||
} else {
|
||||
imgrec = created
|
||||
}
|
||||
|
||||
img := &image{
|
||||
client: c,
|
||||
i: imgrec,
|
||||
}
|
||||
if pullCtx.Unpack {
|
||||
if err := img.Unpack(ctx, pullCtx.Snapshotter); err != nil {
|
||||
errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
|
||||
img.i = updated
|
||||
} else {
|
||||
img.i = created
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// Push uploads the provided content to a remote resource
|
||||
@@ -347,7 +394,7 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
|
||||
return err
|
||||
}
|
||||
|
||||
return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), pushCtx.BaseHandlers...)
|
||||
return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), pushCtx.Platforms, pushCtx.BaseHandlers...)
|
||||
}
|
||||
|
||||
// GetImage returns an existing image
|
||||
@@ -385,82 +432,73 @@ func (c *Client) ListImages(ctx context.Context, filters ...string) ([]Image, er
|
||||
//
|
||||
// The subscriber can stop receiving events by canceling the provided context.
|
||||
// The errs channel will be closed and return a nil error.
|
||||
func (c *Client) Subscribe(ctx context.Context, filters ...string) (ch <-chan *eventsapi.Envelope, errs <-chan error) {
|
||||
var (
|
||||
evq = make(chan *eventsapi.Envelope)
|
||||
errq = make(chan error, 1)
|
||||
)
|
||||
|
||||
errs = errq
|
||||
ch = evq
|
||||
|
||||
session, err := c.EventService().Subscribe(ctx, &eventsapi.SubscribeRequest{
|
||||
Filters: filters,
|
||||
})
|
||||
if err != nil {
|
||||
errq <- err
|
||||
close(errq)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(errq)
|
||||
|
||||
for {
|
||||
ev, err := session.Recv()
|
||||
if err != nil {
|
||||
errq <- err
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case evq <- ev:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ch, errs
|
||||
func (c *Client) Subscribe(ctx context.Context, filters ...string) (ch <-chan *events.Envelope, errs <-chan error) {
|
||||
return c.EventService().Subscribe(ctx, filters...)
|
||||
}
|
||||
|
||||
// Close closes the clients connection to containerd
|
||||
func (c *Client) Close() error {
|
||||
return c.conn.Close()
|
||||
c.connMu.Lock()
|
||||
defer c.connMu.Unlock()
|
||||
if c.conn != nil {
|
||||
return c.conn.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NamespaceService returns the underlying Namespaces Store
|
||||
func (c *Client) NamespaceService() namespaces.Store {
|
||||
if c.namespaceStore != nil {
|
||||
return c.namespaceStore
|
||||
}
|
||||
return NewNamespaceStoreFromClient(namespacesapi.NewNamespacesClient(c.conn))
|
||||
}
|
||||
|
||||
// ContainerService returns the underlying container Store
|
||||
func (c *Client) ContainerService() containers.Store {
|
||||
if c.containerStore != nil {
|
||||
return c.containerStore
|
||||
}
|
||||
return NewRemoteContainerStore(containersapi.NewContainersClient(c.conn))
|
||||
}
|
||||
|
||||
// ContentStore returns the underlying content Store
|
||||
func (c *Client) ContentStore() content.Store {
|
||||
return NewContentStoreFromClient(contentapi.NewContentClient(c.conn))
|
||||
if c.contentStore != nil {
|
||||
return c.contentStore
|
||||
}
|
||||
return contentproxy.NewContentStore(contentapi.NewContentClient(c.conn))
|
||||
}
|
||||
|
||||
// SnapshotService returns the underlying snapshotter for the provided snapshotter name
|
||||
func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter {
|
||||
return NewSnapshotterFromClient(snapshotsapi.NewSnapshotsClient(c.conn), snapshotterName)
|
||||
if c.snapshotters != nil {
|
||||
return c.snapshotters[snapshotterName]
|
||||
}
|
||||
return snproxy.NewSnapshotter(snapshotsapi.NewSnapshotsClient(c.conn), snapshotterName)
|
||||
}
|
||||
|
||||
// TaskService returns the underlying TasksClient
|
||||
func (c *Client) TaskService() tasks.TasksClient {
|
||||
if c.taskService != nil {
|
||||
return c.taskService
|
||||
}
|
||||
return tasks.NewTasksClient(c.conn)
|
||||
}
|
||||
|
||||
// ImageService returns the underlying image Store
|
||||
func (c *Client) ImageService() images.Store {
|
||||
if c.imageStore != nil {
|
||||
return c.imageStore
|
||||
}
|
||||
return NewImageStoreFromClient(imagesapi.NewImagesClient(c.conn))
|
||||
}
|
||||
|
||||
// DiffService returns the underlying Differ
|
||||
func (c *Client) DiffService() DiffService {
|
||||
if c.diffService != nil {
|
||||
return c.diffService
|
||||
}
|
||||
return NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn))
|
||||
}
|
||||
|
||||
@@ -469,14 +507,25 @@ func (c *Client) IntrospectionService() introspectionapi.IntrospectionClient {
|
||||
return introspectionapi.NewIntrospectionClient(c.conn)
|
||||
}
|
||||
|
||||
// LeasesService returns the underlying Leases Client
|
||||
func (c *Client) LeasesService() leasesapi.LeasesClient {
|
||||
if c.leasesService != nil {
|
||||
return c.leasesService
|
||||
}
|
||||
return leasesapi.NewLeasesClient(c.conn)
|
||||
}
|
||||
|
||||
// HealthService returns the underlying GRPC HealthClient
|
||||
func (c *Client) HealthService() grpc_health_v1.HealthClient {
|
||||
return grpc_health_v1.NewHealthClient(c.conn)
|
||||
}
|
||||
|
||||
// EventService returns the underlying EventsClient
|
||||
func (c *Client) EventService() eventsapi.EventsClient {
|
||||
return eventsapi.NewEventsClient(c.conn)
|
||||
// EventService returns the underlying event service
|
||||
func (c *Client) EventService() EventService {
|
||||
if c.eventService != nil {
|
||||
return c.eventService
|
||||
}
|
||||
return NewEventServiceFromClient(eventsapi.NewEventsClient(c.conn))
|
||||
}
|
||||
|
||||
// VersionService returns the underlying VersionClient
|
||||
@@ -494,6 +543,12 @@ type Version struct {
|
||||
|
||||
// Version returns the version of containerd that the client is connected to
|
||||
func (c *Client) Version(ctx context.Context) (Version, error) {
|
||||
c.connMu.Lock()
|
||||
if c.conn == nil {
|
||||
c.connMu.Unlock()
|
||||
return Version{}, errors.New("no grpc connection available")
|
||||
}
|
||||
c.connMu.Unlock()
|
||||
response, err := c.VersionService().Version(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
return Version{}, err
|
||||
@@ -503,98 +558,3 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
|
||||
Revision: response.Revision,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type importOpts struct {
|
||||
}
|
||||
|
||||
// ImportOpt allows the caller to specify import specific options
|
||||
type ImportOpt func(c *importOpts) error
|
||||
|
||||
func resolveImportOpt(opts ...ImportOpt) (importOpts, error) {
|
||||
var iopts importOpts
|
||||
for _, o := range opts {
|
||||
if err := o(&iopts); err != nil {
|
||||
return iopts, err
|
||||
}
|
||||
}
|
||||
return iopts, nil
|
||||
}
|
||||
|
||||
// Import imports an image from a Tar stream using reader.
|
||||
// Caller needs to specify importer. Future version may use oci.v1 as the default.
|
||||
// Note that unreferrenced blobs may be imported to the content store as well.
|
||||
func (c *Client) Import(ctx context.Context, importer images.Importer, reader io.Reader, opts ...ImportOpt) ([]Image, error) {
|
||||
_, err := resolveImportOpt(opts...) // unused now
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, done, err := c.WithLease(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer done()
|
||||
|
||||
imgrecs, err := importer.Import(ctx, c.ContentStore(), reader)
|
||||
if err != nil {
|
||||
// is.Update() is not called on error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
is := c.ImageService()
|
||||
var images []Image
|
||||
for _, imgrec := range imgrecs {
|
||||
if updated, err := is.Update(ctx, imgrec, "target"); err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
created, err := is.Create(ctx, imgrec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imgrec = created
|
||||
} else {
|
||||
imgrec = updated
|
||||
}
|
||||
|
||||
images = append(images, &image{
|
||||
client: c,
|
||||
i: imgrec,
|
||||
})
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
type exportOpts struct {
|
||||
}
|
||||
|
||||
// ExportOpt allows the caller to specify export-specific options
|
||||
type ExportOpt func(c *exportOpts) error
|
||||
|
||||
func resolveExportOpt(opts ...ExportOpt) (exportOpts, error) {
|
||||
var eopts exportOpts
|
||||
for _, o := range opts {
|
||||
if err := o(&eopts); err != nil {
|
||||
return eopts, err
|
||||
}
|
||||
}
|
||||
return eopts, nil
|
||||
}
|
||||
|
||||
// Export exports an image to a Tar stream.
|
||||
// OCI format is used by default.
|
||||
// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
|
||||
// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream.
|
||||
func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocispec.Descriptor, opts ...ExportOpt) (io.ReadCloser, error) {
|
||||
_, err := resolveExportOpt(opts...) // unused now
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pr, pw := io.Pipe()
|
||||
go func() {
|
||||
pw.CloseWithError(exporter.Export(ctx, c.ContentStore(), desc, pw))
|
||||
}()
|
||||
return pr, nil
|
||||
}
|
||||
|
||||
+27
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
type clientOpts struct {
|
||||
defaultns string
|
||||
services *services
|
||||
dialOptions []grpc.DialOption
|
||||
}
|
||||
|
||||
@@ -49,9 +50,35 @@ func WithDialOpts(opts []grpc.DialOption) ClientOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithServices sets services used by the client.
|
||||
func WithServices(opts ...ServicesOpt) ClientOpt {
|
||||
return func(c *clientOpts) error {
|
||||
c.services = &services{}
|
||||
for _, o := range opts {
|
||||
o(c.services)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// RemoteOpt allows the caller to set distribution options for a remote
|
||||
type RemoteOpt func(*Client, *RemoteContext) error
|
||||
|
||||
// WithPlatform allows the caller to specify a platform to retrieve
|
||||
// content for
|
||||
func WithPlatform(platform string) RemoteOpt {
|
||||
return func(_ *Client, c *RemoteContext) error {
|
||||
for _, p := range c.Platforms {
|
||||
if p == platform {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
c.Platforms = append(c.Platforms, platform)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPullUnpack is used to unpack an image after pull. This
|
||||
// uses the snapshotter, content store, and diff service
|
||||
// configured for the client.
|
||||
|
||||
+4
-4
@@ -28,9 +28,9 @@ import (
|
||||
"github.com/containerd/containerd/cio"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/typeurl"
|
||||
prototypes "github.com/gogo/protobuf/types"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -45,7 +45,7 @@ type Container interface {
|
||||
// NewTask creates a new task based on the container metadata
|
||||
NewTask(context.Context, cio.Creator, ...NewTaskOpts) (Task, error)
|
||||
// Spec returns the OCI runtime specification
|
||||
Spec(context.Context) (*specs.Spec, error)
|
||||
Spec(context.Context) (*oci.Spec, error)
|
||||
// Task returns the current task for the container
|
||||
//
|
||||
// If cio.Attach options are passed the client will reattach to the IO for the running
|
||||
@@ -126,12 +126,12 @@ func (c *container) SetLabels(ctx context.Context, labels map[string]string) (ma
|
||||
}
|
||||
|
||||
// Spec returns the current OCI specification for the container
|
||||
func (c *container) Spec(ctx context.Context) (*specs.Spec, error) {
|
||||
func (c *container) Spec(ctx context.Context) (*oci.Spec, error) {
|
||||
r, err := c.get(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var s specs.Spec
|
||||
var s oci.Spec
|
||||
if err := json.Unmarshal(r.Spec.Value, &s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+1
-2
@@ -26,7 +26,6 @@ import (
|
||||
"github.com/containerd/typeurl"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -196,7 +195,7 @@ func WithNewSpec(opts ...oci.SpecOpts) NewContainerOpts {
|
||||
}
|
||||
|
||||
// WithSpec sets the provided spec on the container
|
||||
func WithSpec(s *specs.Spec, opts ...oci.SpecOpts) NewContainerOpts {
|
||||
func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
for _, o := range opts {
|
||||
if err := o(ctx, client, c, s); err != nil {
|
||||
|
||||
+62
-10
@@ -20,7 +20,9 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/opencontainers/go-digest"
|
||||
@@ -64,7 +66,7 @@ func ReadBlob(ctx context.Context, provider Provider, dgst digest.Digest) ([]byt
|
||||
//
|
||||
// Copy is buffered, so no need to wrap reader in buffered io.
|
||||
func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error {
|
||||
cw, err := cs.Writer(ctx, ref, size, expected)
|
||||
cw, err := OpenWriter(ctx, cs, ref, size, expected)
|
||||
if err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return err
|
||||
@@ -77,8 +79,45 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size i
|
||||
return Copy(ctx, cw, r, size, expected, opts...)
|
||||
}
|
||||
|
||||
// OpenWriter opens a new writer for the given reference, retrying if the writer
|
||||
// is locked until the reference is available or returns an error.
|
||||
func OpenWriter(ctx context.Context, cs Ingester, ref string, size int64, expected digest.Digest) (Writer, error) {
|
||||
var (
|
||||
cw Writer
|
||||
err error
|
||||
retry = 16
|
||||
)
|
||||
for {
|
||||
cw, err = cs.Writer(ctx, ref, size, expected)
|
||||
if err != nil {
|
||||
if !errdefs.IsUnavailable(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: Check status to determine if the writer is active,
|
||||
// continue waiting while active, otherwise return lock
|
||||
// error or abort. Requires asserting for an ingest manager
|
||||
|
||||
select {
|
||||
case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))):
|
||||
if retry < 2048 {
|
||||
retry = retry << 1
|
||||
}
|
||||
continue
|
||||
case <-ctx.Done():
|
||||
// Propagate lock error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return cw, err
|
||||
}
|
||||
|
||||
// Copy copies data with the expected digest from the reader into the
|
||||
// provided content store writer.
|
||||
// provided content store writer. This copy commits the writer.
|
||||
//
|
||||
// This is useful when the digest and size are known beforehand. When
|
||||
// the size or digest is unknown, these values may be empty.
|
||||
@@ -97,10 +136,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
|
||||
}
|
||||
}
|
||||
|
||||
buf := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(buf)
|
||||
|
||||
if _, err := io.CopyBuffer(cw, r, *buf); err != nil {
|
||||
if _, err := copyWithBuffer(cw, r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -113,6 +149,18 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyReaderAt copies to a writer from a given reader at for the given
|
||||
// number of bytes. This copy does not commit the writer.
|
||||
func CopyReaderAt(cw Writer, ra ReaderAt, n int64) error {
|
||||
ws, err := cw.Status()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = copyWithBuffer(cw, io.NewSectionReader(ra, ws.Offset, n))
|
||||
return err
|
||||
}
|
||||
|
||||
// seekReader attempts to seek the reader to the given offset, either by
|
||||
// resolving `io.Seeker`, by detecting `io.ReaderAt`, or discarding
|
||||
// up to the given offset.
|
||||
@@ -140,10 +188,7 @@ func seekReader(r io.Reader, offset, size int64) (io.Reader, error) {
|
||||
}
|
||||
|
||||
// well then, let's just discard up to the offset
|
||||
buf := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(buf)
|
||||
|
||||
n, err := io.CopyBuffer(ioutil.Discard, io.LimitReader(r, offset), *buf)
|
||||
n, err := copyWithBuffer(ioutil.Discard, io.LimitReader(r, offset))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to discard to offset")
|
||||
}
|
||||
@@ -153,3 +198,10 @@ func seekReader(r io.Reader, offset, size int64) (io.Reader, error) {
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func copyWithBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||
buf := bufPool.Get().(*[]byte)
|
||||
written, err = io.CopyBuffer(dst, src, *buf)
|
||||
bufPool.Put(buf)
|
||||
return
|
||||
}
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
Generated
Vendored
+27
-26
@@ -14,7 +14,7 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -27,19 +27,20 @@ import (
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
type remoteContent struct {
|
||||
type proxyContentStore struct {
|
||||
client contentapi.ContentClient
|
||||
}
|
||||
|
||||
// NewContentStoreFromClient returns a new content store
|
||||
func NewContentStoreFromClient(client contentapi.ContentClient) content.Store {
|
||||
return &remoteContent{
|
||||
// NewContentStore returns a new content store which communicates over a GRPC
|
||||
// connection using the containerd content GRPC API.
|
||||
func NewContentStore(client contentapi.ContentClient) content.Store {
|
||||
return &proxyContentStore{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *remoteContent) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
|
||||
resp, err := rs.client.Info(ctx, &contentapi.InfoRequest{
|
||||
func (pcs *proxyContentStore) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
|
||||
resp, err := pcs.client.Info(ctx, &contentapi.InfoRequest{
|
||||
Digest: dgst,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -49,8 +50,8 @@ func (rs *remoteContent) Info(ctx context.Context, dgst digest.Digest) (content.
|
||||
return infoFromGRPC(resp.Info), nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error {
|
||||
session, err := rs.client.List(ctx, &contentapi.ListContentRequest{
|
||||
func (pcs *proxyContentStore) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error {
|
||||
session, err := pcs.client.List(ctx, &contentapi.ListContentRequest{
|
||||
Filters: filters,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -77,8 +78,8 @@ func (rs *remoteContent) Walk(ctx context.Context, fn content.WalkFunc, filters
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
if _, err := rs.client.Delete(ctx, &contentapi.DeleteContentRequest{
|
||||
func (pcs *proxyContentStore) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
if _, err := pcs.client.Delete(ctx, &contentapi.DeleteContentRequest{
|
||||
Digest: dgst,
|
||||
}); err != nil {
|
||||
return errdefs.FromGRPC(err)
|
||||
@@ -87,8 +88,8 @@ func (rs *remoteContent) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) ReaderAt(ctx context.Context, dgst digest.Digest) (content.ReaderAt, error) {
|
||||
i, err := rs.Info(ctx, dgst)
|
||||
func (pcs *proxyContentStore) ReaderAt(ctx context.Context, dgst digest.Digest) (content.ReaderAt, error) {
|
||||
i, err := pcs.Info(ctx, dgst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -97,12 +98,12 @@ func (rs *remoteContent) ReaderAt(ctx context.Context, dgst digest.Digest) (cont
|
||||
ctx: ctx,
|
||||
digest: dgst,
|
||||
size: i.Size,
|
||||
client: rs.client,
|
||||
client: pcs.client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) Status(ctx context.Context, ref string) (content.Status, error) {
|
||||
resp, err := rs.client.Status(ctx, &contentapi.StatusRequest{
|
||||
func (pcs *proxyContentStore) Status(ctx context.Context, ref string) (content.Status, error) {
|
||||
resp, err := pcs.client.Status(ctx, &contentapi.StatusRequest{
|
||||
Ref: ref,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -120,8 +121,8 @@ func (rs *remoteContent) Status(ctx context.Context, ref string) (content.Status
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
||||
resp, err := rs.client.Update(ctx, &contentapi.UpdateRequest{
|
||||
func (pcs *proxyContentStore) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
||||
resp, err := pcs.client.Update(ctx, &contentapi.UpdateRequest{
|
||||
Info: infoToGRPC(info),
|
||||
UpdateMask: &protobuftypes.FieldMask{
|
||||
Paths: fieldpaths,
|
||||
@@ -133,8 +134,8 @@ func (rs *remoteContent) Update(ctx context.Context, info content.Info, fieldpat
|
||||
return infoFromGRPC(resp.Info), nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) ListStatuses(ctx context.Context, filters ...string) ([]content.Status, error) {
|
||||
resp, err := rs.client.ListStatuses(ctx, &contentapi.ListStatusesRequest{
|
||||
func (pcs *proxyContentStore) ListStatuses(ctx context.Context, filters ...string) ([]content.Status, error) {
|
||||
resp, err := pcs.client.ListStatuses(ctx, &contentapi.ListStatusesRequest{
|
||||
Filters: filters,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -156,8 +157,8 @@ func (rs *remoteContent) ListStatuses(ctx context.Context, filters ...string) ([
|
||||
return statuses, nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
||||
wrclient, offset, err := rs.negotiate(ctx, ref, size, expected)
|
||||
func (pcs *proxyContentStore) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
||||
wrclient, offset, err := pcs.negotiate(ctx, ref, size, expected)
|
||||
if err != nil {
|
||||
return nil, errdefs.FromGRPC(err)
|
||||
}
|
||||
@@ -170,8 +171,8 @@ func (rs *remoteContent) Writer(ctx context.Context, ref string, size int64, exp
|
||||
}
|
||||
|
||||
// Abort implements asynchronous abort. It starts a new write session on the ref l
|
||||
func (rs *remoteContent) Abort(ctx context.Context, ref string) error {
|
||||
if _, err := rs.client.Abort(ctx, &contentapi.AbortRequest{
|
||||
func (pcs *proxyContentStore) Abort(ctx context.Context, ref string) error {
|
||||
if _, err := pcs.client.Abort(ctx, &contentapi.AbortRequest{
|
||||
Ref: ref,
|
||||
}); err != nil {
|
||||
return errdefs.FromGRPC(err)
|
||||
@@ -180,8 +181,8 @@ func (rs *remoteContent) Abort(ctx context.Context, ref string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rs *remoteContent) negotiate(ctx context.Context, ref string, size int64, expected digest.Digest) (contentapi.Content_WriteClient, int64, error) {
|
||||
wrclient, err := rs.client.Write(ctx)
|
||||
func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size int64, expected digest.Digest) (contentapi.Content_WriteClient, int64, error) {
|
||||
wrclient, err := pcs.client.Write(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user