瀏覽代碼

Merge pull request #414 from docker/restart_policy_single

Restart policy single container
Guillaume Tardif 5 年之前
父節點
當前提交
63fda614b9

+ 3 - 0
aci/convert/container.go

@@ -41,6 +41,9 @@ func ContainerToComposeProject(r containers.ContainerConfig) (types.Project, err
 							MemoryBytes: types.UnitBytes(r.MemLimit.Value()),
 						},
 					},
+					RestartPolicy: &types.RestartPolicy{
+						Condition: r.RestartPolicyCondition,
+					},
 				},
 			},
 		},

+ 12 - 0
aci/convert/container_test.go

@@ -48,6 +48,18 @@ func (suite *ContainerConvertTestSuite) TestConvertContainerEnvironment() {
 	}))
 }
 
+func (suite *ContainerConvertTestSuite) TestConvertRestartPolicy() {
+	container := containers.ContainerConfig{
+		ID:                     "container1",
+		RestartPolicyCondition: "none",
+	}
+	project, err := ContainerToComposeProject(container)
+	Expect(err).To(BeNil())
+	service1 := project.Services[0]
+	Expect(service1.Name).To(Equal(container.ID))
+	Expect(service1.Deploy.RestartPolicy.Condition).To(Equal("none"))
+}
+
 func TestContainerConvertTestSuite(t *testing.T) {
 	RegisterTestingT(t)
 	suite.Run(t, new(ContainerConvertTestSuite))

+ 54 - 14
aci/convert/convert.go

@@ -26,7 +26,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/Azure/azure-sdk-for-go/profiles/latest/containerinstance/mgmt/containerinstance"
+	"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
 	"github.com/Azure/go-autorest/autorest/to"
 	"github.com/compose-spec/compose-go/types"
 
@@ -80,6 +80,7 @@ func ToContainerGroup(aciContext store.AciContext, p types.Project) (containerin
 			Containers:               &containers,
 			Volumes:                  volumes,
 			ImageRegistryCredentials: &registryCreds,
+			RestartPolicy:            project.getRestartPolicy(),
 		},
 	}
 
@@ -215,6 +216,44 @@ func (p projectAciHelper) getAciFileVolumes() (map[string]bool, []containerinsta
 	return azureFileVolumesMap, azureFileVolumesSlice, nil
 }
 
+func (p projectAciHelper) getRestartPolicy() containerinstance.ContainerGroupRestartPolicy {
+	var restartPolicyCondition containerinstance.ContainerGroupRestartPolicy
+	if len(p.Services) == 1 &&
+		p.Services[0].Deploy != nil &&
+		p.Services[0].Deploy.RestartPolicy != nil {
+		restartPolicyCondition = toAciRestartPolicy(p.Services[0].Deploy.RestartPolicy.Condition)
+	} else {
+		restartPolicyCondition = containerinstance.Always
+	}
+	return restartPolicyCondition
+}
+
+func toAciRestartPolicy(restartPolicy string) containerinstance.ContainerGroupRestartPolicy {
+	switch restartPolicy {
+	case containers.RestartPolicyNone:
+		return containerinstance.Never
+	case containers.RestartPolicyAny:
+		return containerinstance.Always
+	case containers.RestartPolicyOnFailure:
+		return containerinstance.OnFailure
+	default:
+		return containerinstance.Always
+	}
+}
+
+func toContainerRestartPolicy(aciRestartPolicy containerinstance.ContainerGroupRestartPolicy) string {
+	switch aciRestartPolicy {
+	case containerinstance.Never:
+		return containers.RestartPolicyNone
+	case containerinstance.Always:
+		return containers.RestartPolicyAny
+	case containerinstance.OnFailure:
+		return containers.RestartPolicyOnFailure
+	default:
+		return containers.RestartPolicyAny
+	}
+}
+
 type serviceConfigAciHelper types.ServiceConfig
 
 func (s serviceConfigAciHelper) getAciFileVolumeMounts(volumesCache map[string]bool) ([]containerinstance.VolumeMount, error) {
@@ -348,19 +387,20 @@ func ContainerGroupToContainer(containerID string, cg containerinstance.Containe
 	platform := string(cg.OsType)
 
 	c := containers.Container{
-		ID:          containerID,
-		Status:      status,
-		Image:       to.String(cc.Image),
-		Command:     command,
-		CPUTime:     0,
-		CPULimit:    cpuLimit,
-		MemoryUsage: 0,
-		MemoryLimit: uint64(memLimits),
-		PidsCurrent: 0,
-		PidsLimit:   0,
-		Labels:      nil,
-		Ports:       ToPorts(cg.IPAddress, *cc.Ports),
-		Platform:    platform,
+		ID:                     containerID,
+		Status:                 status,
+		Image:                  to.String(cc.Image),
+		Command:                command,
+		CPUTime:                0,
+		CPULimit:               cpuLimit,
+		MemoryUsage:            0,
+		MemoryLimit:            uint64(memLimits),
+		PidsCurrent:            0,
+		PidsLimit:              0,
+		Labels:                 nil,
+		Ports:                  ToPorts(cg.IPAddress, *cc.Ports),
+		Platform:               platform,
+		RestartPolicyCondition: toContainerRestartPolicy(cg.RestartPolicy),
 	}
 
 	return c, nil

+ 56 - 0
aci/convert/convert_test.go

@@ -104,6 +104,7 @@ func (suite *ConvertTestSuite) TestContainerGroupToContainer() {
 			Protocol:      "tcp",
 			HostIP:        "42.42.42.42",
 		}},
+		RestartPolicyCondition: "any",
 	}
 
 	container, err := ContainerGroupToContainer("myContainerID", myContainerGroup, myContainer)
@@ -158,6 +159,47 @@ func (suite *ConvertTestSuite) TestComposeSingleContainerGroupToContainerNoDnsSi
 	Expect(*(*group.Containers)[0].Image).To(Equal("image1"))
 }
 
+func (suite *ConvertTestSuite) TestComposeSingleContainerGroupToContainerSpecificRestartPolicy() {
+	project := types.Project{
+		Services: []types.ServiceConfig{
+			{
+				Name:  "service1",
+				Image: "image1",
+				Deploy: &types.DeployConfig{
+					RestartPolicy: &types.RestartPolicy{
+						Condition: "on-failure",
+					},
+				},
+			},
+		},
+	}
+
+	group, err := ToContainerGroup(suite.ctx, project)
+	Expect(err).To(BeNil())
+
+	Expect(len(*group.Containers)).To(Equal(1))
+	Expect(*(*group.Containers)[0].Name).To(Equal("service1"))
+	Expect(group.RestartPolicy).To(Equal(containerinstance.OnFailure))
+}
+
+func (suite *ConvertTestSuite) TestComposeSingleContainerGroupToContainerDefaultRestartPolicy() {
+	project := types.Project{
+		Services: []types.ServiceConfig{
+			{
+				Name:  "service1",
+				Image: "image1",
+			},
+		},
+	}
+
+	group, err := ToContainerGroup(suite.ctx, project)
+	Expect(err).To(BeNil())
+
+	Expect(len(*group.Containers)).To(Equal(1))
+	Expect(*(*group.Containers)[0].Name).To(Equal("service1"))
+	Expect(group.RestartPolicy).To(Equal(containerinstance.Always))
+}
+
 func (suite *ConvertTestSuite) TestComposeContainerGroupToContainerMultiplePorts() {
 	project := types.Project{
 		Services: []types.ServiceConfig{
@@ -287,6 +329,20 @@ func (suite *ConvertTestSuite) TestComposeContainerGroupToContainerenvVar() {
 	Expect(envVars).To(ContainElement(containerinstance.EnvironmentVariable{Name: to.StringPtr("key2"), Value: to.StringPtr("value2")}))
 }
 
+func (suite *ConvertTestSuite) TestConvertToAciRestartPolicyCondition() {
+	Expect(toAciRestartPolicy("none")).To(Equal(containerinstance.Never))
+	Expect(toAciRestartPolicy("always")).To(Equal(containerinstance.Always))
+	Expect(toAciRestartPolicy("on-failure")).To(Equal(containerinstance.OnFailure))
+	Expect(toAciRestartPolicy("on-failure:5")).To(Equal(containerinstance.Always))
+}
+
+func (suite *ConvertTestSuite) TestConvertToDockerRestartPolicyCondition() {
+	Expect(toContainerRestartPolicy(containerinstance.Never)).To(Equal("none"))
+	Expect(toContainerRestartPolicy(containerinstance.Always)).To(Equal("any"))
+	Expect(toContainerRestartPolicy(containerinstance.OnFailure)).To(Equal("on-failure"))
+	Expect(toContainerRestartPolicy("")).To(Equal("any"))
+}
+
 func TestConvertTestSuite(t *testing.T) {
 	RegisterTestingT(t)
 	suite.Run(t, new(ConvertTestSuite))

+ 1 - 0
cli/cmd/run/run.go

@@ -52,6 +52,7 @@ func Command() *cobra.Command {
 	cmd.Flags().Float64Var(&opts.Cpus, "cpus", 1., "Number of CPUs")
 	cmd.Flags().VarP(&opts.Memory, "memory", "m", "Memory limit")
 	cmd.Flags().StringArrayVarP(&opts.Environment, "env", "e", []string{}, "Set environment variables")
+	cmd.Flags().StringVarP(&opts.RestartPolicyCondition, "restart", "", containers.RestartPolicyNone, "Restart policy to apply when a container exits")
 
 	return cmd
 }

+ 1 - 0
cli/cmd/run/testdata/run-help.golden

@@ -11,4 +11,5 @@ Flags:
   -m, --memory bytes          Memory limit
       --name string           Assign a name to the container
   -p, --publish stringArray   Publish a container's port(s). [HOST_PORT:]CONTAINER_PORT
+      --restart string        Restart policy to apply when a container exits (default "none")
   -v, --volume stringArray    Volume. Ex: user:key@my_share:/absolute/path/to/target

+ 2 - 1
cli/cmd/testdata/inspect-out-id.golden

@@ -11,5 +11,6 @@
     "PidsLimit": 0,
     "Labels": null,
     "Ports": null,
-    "Platform": "Linux"
+    "Platform": "Linux",
+    "RestartPolicyCondition": "none"
 }

+ 36 - 16
cli/options/run/opts.go

@@ -21,6 +21,8 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/docker/api/utils"
+
 	"github.com/docker/docker/pkg/namesgenerator"
 	"github.com/docker/go-connections/nat"
 
@@ -30,14 +32,15 @@ import (
 
 // Opts contain run command options
 type Opts struct {
-	Name        string
-	Publish     []string
-	Labels      []string
-	Volumes     []string
-	Cpus        float64
-	Memory      formatter.MemBytes
-	Detach      bool
-	Environment []string
+	Name                   string
+	Publish                []string
+	Labels                 []string
+	Volumes                []string
+	Cpus                   float64
+	Memory                 formatter.MemBytes
+	Detach                 bool
+	Environment            []string
+	RestartPolicyCondition string
 }
 
 // ToContainerConfig convert run options to a container configuration
@@ -56,18 +59,35 @@ func (r *Opts) ToContainerConfig(image string) (containers.ContainerConfig, erro
 		return containers.ContainerConfig{}, err
 	}
 
+	restartPolicy, err := toRestartPolicy(r.RestartPolicyCondition)
+	if err != nil {
+		return containers.ContainerConfig{}, err
+	}
+
 	return containers.ContainerConfig{
-		ID:          r.Name,
-		Image:       image,
-		Ports:       publish,
-		Labels:      labels,
-		Volumes:     r.Volumes,
-		MemLimit:    r.Memory,
-		CPULimit:    r.Cpus,
-		Environment: r.Environment,
+		ID:                     r.Name,
+		Image:                  image,
+		Ports:                  publish,
+		Labels:                 labels,
+		Volumes:                r.Volumes,
+		MemLimit:               r.Memory,
+		CPULimit:               r.Cpus,
+		Environment:            r.Environment,
+		RestartPolicyCondition: restartPolicy,
 	}, nil
 }
 
+func toRestartPolicy(value string) (string, error) {
+	if value == "" {
+		return containers.RestartPolicyNone, nil
+	}
+	if utils.StringContains(containers.RestartPolicyList, value) {
+		return value, nil
+	}
+
+	return "", fmt.Errorf("invalid restart value, must be one of %s", strings.Join(containers.RestartPolicyList, ", "))
+}
+
 func (r *Opts) toPorts() ([]containers.Port, error) {
 	_, bindings, err := nat.ParsePortSpecs(r.Publish)
 	if err != nil {

+ 43 - 0
cli/options/run/opts_test.go

@@ -173,3 +173,46 @@ func TestLabels(t *testing.T) {
 		assert.DeepEqual(t, result, testCase.expected)
 	}
 }
+
+func TestValidateRestartPolicy(t *testing.T) {
+	testCases := []struct {
+		in            string
+		expected      string
+		expectedError error
+	}{
+		{
+			in:            "none",
+			expected:      "none",
+			expectedError: nil,
+		},
+		{
+			in:            "any",
+			expected:      "any",
+			expectedError: nil,
+		},
+		{
+			in:            "on-failure",
+			expected:      "on-failure",
+			expectedError: nil,
+		},
+		{
+			in:            "",
+			expected:      "none",
+			expectedError: nil,
+		},
+		{
+			in:            "toto",
+			expected:      "",
+			expectedError: errors.New("invalid restart value, must be one of none, any, on-failure"),
+		},
+	}
+	for _, testCase := range testCases {
+		result, err := toRestartPolicy(testCase.in)
+		if testCase.expectedError == nil {
+			assert.NilError(t, err)
+		} else {
+			assert.Error(t, err, testCase.expectedError.Error())
+		}
+		assert.Equal(t, testCase.expected, result)
+	}
+}

+ 28 - 13
containers/api.go

@@ -23,21 +23,34 @@ import (
 	"github.com/docker/api/formatter"
 )
 
+const (
+	// RestartPolicyAny Always restarts
+	RestartPolicyAny = "any"
+	// RestartPolicyNone Never restarts
+	RestartPolicyNone = "none"
+	// RestartPolicyOnFailure Restarts only on failure
+	RestartPolicyOnFailure = "on-failure"
+)
+
+// RestartPolicyList all available restart policy values
+var RestartPolicyList = []string{RestartPolicyNone, RestartPolicyAny, RestartPolicyOnFailure}
+
 // Container represents a created container
 type Container struct {
-	ID          string
-	Status      string
-	Image       string
-	Command     string
-	CPUTime     uint64
-	CPULimit    float64
-	MemoryUsage uint64
-	MemoryLimit uint64
-	PidsCurrent uint64
-	PidsLimit   uint64
-	Labels      []string
-	Ports       []Port
-	Platform    string
+	ID                     string
+	Status                 string
+	Image                  string
+	Command                string
+	CPUTime                uint64
+	CPULimit               float64
+	MemoryUsage            uint64
+	MemoryLimit            uint64
+	PidsCurrent            uint64
+	PidsLimit              uint64
+	Labels                 []string
+	Ports                  []Port
+	Platform               string
+	RestartPolicyCondition string
 }
 
 // Port represents a published port of a container
@@ -70,6 +83,8 @@ type ContainerConfig struct {
 	CPULimit float64
 	// Environment variables
 	Environment []string
+	// Restart policy condition
+	RestartPolicyCondition string
 }
 
 // ExecRequest contaiens configuration about an exec request

+ 1 - 1
docs/cli/run.md

@@ -31,7 +31,7 @@ docker run [OPTIONS] _image_ [COMMAND] [ARG...]
       --cpus                           Number of CPUs to allocate, approximately
   -p, --publish list                   Publish a container's port(s) to the host
   -P, --publish-all                    Publish all exposed ports to random ports
-      --restart string                 Restart policy to apply when a container exits (default "no")
+      --restart string                 Restart policy to apply when a container exits (default "none")
       --entrypoint string              Overwrite the default ENTRYPOINT of the image
 
       --mount mount                    Attach a filesystem mount to the container

+ 2 - 1
ecs/backend.go

@@ -18,6 +18,8 @@ package ecs
 import (
 	"context"
 
+	ecsplugin "github.com/docker/ecs-plugin/pkg/amazon/backend"
+
 	"github.com/docker/api/backend"
 	"github.com/docker/api/compose"
 	"github.com/docker/api/containers"
@@ -25,7 +27,6 @@ import (
 	"github.com/docker/api/context/cloud"
 	"github.com/docker/api/context/store"
 	"github.com/docker/api/errdefs"
-	ecsplugin "github.com/docker/ecs-plugin/pkg/amazon/backend"
 )
 
 const backendType = store.EcsContextType

+ 4 - 3
example/backend.go

@@ -57,9 +57,10 @@ type containerService struct{}
 
 func (cs *containerService) Inspect(ctx context.Context, id string) (containers.Container, error) {
 	return containers.Container{
-		ID:       "id",
-		Image:    "nginx",
-		Platform: "Linux",
+		ID:                     "id",
+		Image:                  "nginx",
+		Platform:               "Linux",
+		RestartPolicyCondition: "none",
 	}, nil
 }
 

+ 6 - 13
metrics/metrics.go

@@ -20,6 +20,8 @@ import (
 	"strings"
 
 	flag "github.com/spf13/pflag"
+
+	"github.com/docker/api/utils"
 )
 
 var managementCommands = []string{
@@ -111,7 +113,7 @@ func getCommand(args []string, flags *flag.FlagSet) string {
 		}
 
 		for {
-			if contains(managementCommands, command) {
+			if utils.StringContains(managementCommands, command) {
 				if sub := getSubCommand(command, strippedArgs[1:]); sub != "" {
 					command += " " + sub
 					strippedArgs = strippedArgs[1:]
@@ -128,11 +130,11 @@ func getCommand(args []string, flags *flag.FlagSet) string {
 func getScanCommand(args []string) string {
 	command := args[0]
 
-	if contains(args, "--auth") {
+	if utils.StringContains(args, "--auth") {
 		return command + " auth"
 	}
 
-	if contains(args, "--version") {
+	if utils.StringContains(args, "--version") {
 		return command + " version"
 	}
 
@@ -145,7 +147,7 @@ func getSubCommand(command string, args []string) string {
 	}
 
 	if val, ok := managementSubCommands[command]; ok {
-		if contains(val, args[0]) {
+		if utils.StringContains(val, args[0]) {
 			return args[0]
 		}
 		return ""
@@ -158,15 +160,6 @@ func getSubCommand(command string, args []string) string {
 	return ""
 }
 
-func contains(array []string, needle string) bool {
-	for _, val := range array {
-		if val == needle {
-			return true
-		}
-	}
-	return false
-}
-
 func stripFlags(args []string, flags *flag.FlagSet) []string {
 	commands := []string{}
 

+ 3 - 10
progress/tty.go

@@ -25,6 +25,8 @@ import (
 	"sync"
 	"time"
 
+	"github.com/docker/api/utils"
+
 	"github.com/buger/goterm"
 	"github.com/morikuni/aec"
 )
@@ -63,7 +65,7 @@ func (w *ttyWriter) Stop() {
 func (w *ttyWriter) Event(e Event) {
 	w.mtx.Lock()
 	defer w.mtx.Unlock()
-	if !contains(w.eventIDs, e.ID) {
+	if !utils.StringContains(w.eventIDs, e.ID) {
 		w.eventIDs = append(w.eventIDs, e.ID)
 	}
 	if _, ok := w.events[e.ID]; ok {
@@ -181,12 +183,3 @@ func numDone(events map[string]Event) int {
 func align(l, r string, w int) string {
 	return fmt.Sprintf("%-[2]*[1]s %[3]s", l, w-len(r)-1, r)
 }
-
-func contains(ar []string, needle string) bool {
-	for _, v := range ar {
-		if needle == v {
-			return true
-		}
-	}
-	return false
-}

+ 3 - 2
protos/compose/v1/compose.pb.go

@@ -23,14 +23,15 @@ package v1
 
 import (
 	context "context"
+	reflect "reflect"
+	sync "sync"
+
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
 )
 
 const (

+ 154 - 130
protos/containers/v1/containers.pb.go

@@ -23,14 +23,15 @@ package v1
 
 import (
 	context "context"
+	reflect "reflect"
+	sync "sync"
+
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
 )
 
 const (
@@ -120,19 +121,20 @@ type Container struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Id          string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Image       string   `protobuf:"bytes,2,opt,name=image,proto3" json:"image,omitempty"`
-	Status      string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
-	Command     string   `protobuf:"bytes,4,opt,name=command,proto3" json:"command,omitempty"`
-	CpuTime     uint64   `protobuf:"varint,5,opt,name=cpu_time,json=cpuTime,proto3" json:"cpu_time,omitempty"`
-	MemoryUsage uint64   `protobuf:"varint,6,opt,name=memory_usage,json=memoryUsage,proto3" json:"memory_usage,omitempty"`
-	MemoryLimit uint64   `protobuf:"varint,7,opt,name=memory_limit,json=memoryLimit,proto3" json:"memory_limit,omitempty"`
-	PidsCurrent uint64   `protobuf:"varint,8,opt,name=pids_current,json=pidsCurrent,proto3" json:"pids_current,omitempty"`
-	PidsLimit   uint64   `protobuf:"varint,9,opt,name=pids_limit,json=pidsLimit,proto3" json:"pids_limit,omitempty"`
-	Labels      []string `protobuf:"bytes,10,rep,name=labels,proto3" json:"labels,omitempty"`
-	Ports       []*Port  `protobuf:"bytes,11,rep,name=ports,proto3" json:"ports,omitempty"`
-	CpuLimit    uint64   `protobuf:"varint,12,opt,name=cpu_limit,json=cpuLimit,proto3" json:"cpu_limit,omitempty"`
-	Platform    string   `protobuf:"bytes,13,opt,name=platform,proto3" json:"platform,omitempty"`
+	Id                     string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Image                  string   `protobuf:"bytes,2,opt,name=image,proto3" json:"image,omitempty"`
+	Status                 string   `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+	Command                string   `protobuf:"bytes,4,opt,name=command,proto3" json:"command,omitempty"`
+	CpuTime                uint64   `protobuf:"varint,5,opt,name=cpu_time,json=cpuTime,proto3" json:"cpu_time,omitempty"`
+	MemoryUsage            uint64   `protobuf:"varint,6,opt,name=memory_usage,json=memoryUsage,proto3" json:"memory_usage,omitempty"`
+	MemoryLimit            uint64   `protobuf:"varint,7,opt,name=memory_limit,json=memoryLimit,proto3" json:"memory_limit,omitempty"`
+	PidsCurrent            uint64   `protobuf:"varint,8,opt,name=pids_current,json=pidsCurrent,proto3" json:"pids_current,omitempty"`
+	PidsLimit              uint64   `protobuf:"varint,9,opt,name=pids_limit,json=pidsLimit,proto3" json:"pids_limit,omitempty"`
+	Labels                 []string `protobuf:"bytes,10,rep,name=labels,proto3" json:"labels,omitempty"`
+	Ports                  []*Port  `protobuf:"bytes,11,rep,name=ports,proto3" json:"ports,omitempty"`
+	CpuLimit               uint64   `protobuf:"varint,12,opt,name=cpu_limit,json=cpuLimit,proto3" json:"cpu_limit,omitempty"`
+	Platform               string   `protobuf:"bytes,13,opt,name=platform,proto3" json:"platform,omitempty"`
+	RestartPolicyCondition string   `protobuf:"bytes,14,opt,name=restart_policy_condition,json=restartPolicyCondition,proto3" json:"restart_policy_condition,omitempty"`
 }
 
 func (x *Container) Reset() {
@@ -258,6 +260,13 @@ func (x *Container) GetPlatform() string {
 	return ""
 }
 
+func (x *Container) GetRestartPolicyCondition() string {
+	if x != nil {
+		return x.RestartPolicyCondition
+	}
+	return ""
+}
+
 type InspectRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -543,13 +552,14 @@ type RunRequest struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Id          string            `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Image       string            `protobuf:"bytes,2,opt,name=image,proto3" json:"image,omitempty"`
-	Ports       []*Port           `protobuf:"bytes,3,rep,name=ports,proto3" json:"ports,omitempty"`
-	Labels      map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	Volumes     []string          `protobuf:"bytes,5,rep,name=volumes,proto3" json:"volumes,omitempty"`
-	MemoryLimit uint64            `protobuf:"varint,6,opt,name=memory_limit,json=memoryLimit,proto3" json:"memory_limit,omitempty"`
-	CpuLimit    uint64            `protobuf:"varint,7,opt,name=cpu_limit,json=cpuLimit,proto3" json:"cpu_limit,omitempty"`
+	Id                     string            `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Image                  string            `protobuf:"bytes,2,opt,name=image,proto3" json:"image,omitempty"`
+	Ports                  []*Port           `protobuf:"bytes,3,rep,name=ports,proto3" json:"ports,omitempty"`
+	Labels                 map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Volumes                []string          `protobuf:"bytes,5,rep,name=volumes,proto3" json:"volumes,omitempty"`
+	MemoryLimit            uint64            `protobuf:"varint,6,opt,name=memory_limit,json=memoryLimit,proto3" json:"memory_limit,omitempty"`
+	CpuLimit               uint64            `protobuf:"varint,7,opt,name=cpu_limit,json=cpuLimit,proto3" json:"cpu_limit,omitempty"`
+	RestartPolicyCondition string            `protobuf:"bytes,8,opt,name=restart_policy_condition,json=restartPolicyCondition,proto3" json:"restart_policy_condition,omitempty"`
 }
 
 func (x *RunRequest) Reset() {
@@ -633,6 +643,13 @@ func (x *RunRequest) GetCpuLimit() uint64 {
 	return 0
 }
 
+func (x *RunRequest) GetRestartPolicyCondition() string {
+	if x != nil {
+		return x.RestartPolicyCondition
+	}
+	return ""
+}
+
 type RunResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1016,7 +1033,7 @@ var file_protos_containers_v1_containers_proto_rawDesc = []byte{
 	0x69, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74,
 	0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74,
 	0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x70, 0x18,
-	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x70, 0x22, 0x98, 0x03,
+	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x70, 0x22, 0xd2, 0x03,
 	0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69,
 	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69,
 	0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67,
@@ -1042,127 +1059,134 @@ var file_protos_containers_v1_containers_proto_rawDesc = []byte{
 	0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01,
 	0x28, 0x04, 0x52, 0x08, 0x63, 0x70, 0x75, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1a, 0x0a, 0x08,
 	0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
-	0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x20, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70,
-	0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5f, 0x0a, 0x0f, 0x49, 0x6e,
-	0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a,
-	0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70,
-	0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
-	0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
-	0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x35, 0x0a, 0x0d, 0x44,
-	0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05,
-	0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72,
-	0x63, 0x65, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x0e, 0x0a,
-	0x0c, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xdd, 0x02,
-	0x0a, 0x0a, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05,
-	0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61,
-	0x67, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
-	0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x70, 0x6f,
-	0x72, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20,
-	0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72,
-	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
-	0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
-	0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75,
-	0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d,
-	0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6c, 0x69, 0x6d,
-	0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
-	0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x6c, 0x69, 0x6d,
-	0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x63, 0x70, 0x75, 0x4c, 0x69, 0x6d,
-	0x69, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x0d, 0x0a,
-	0x0b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8c, 0x01, 0x0a,
-	0x0b, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
-	0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61,
-	0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28,
-	0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x05,
-	0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x74, 0x79,
-	0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x74, 0x74, 0x79, 0x22, 0x26, 0x0a, 0x0c, 0x45,
-	0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f,
-	0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74,
-	0x70, 0x75, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
-	0x03, 0x61, 0x6c, 0x6c, 0x22, 0x5e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
-	0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64,
-	0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-	0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43,
-	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x22, 0x48, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
-	0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61,
-	0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x22, 0x24,
-	0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76,
-	0x61, 0x6c, 0x75, 0x65, 0x32, 0x95, 0x06, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
-	0x65, 0x72, 0x73, 0x12, 0x6b, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f,
+	0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x74,
+	0x61, 0x72, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69,
+	0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x73, 0x74,
+	0x61, 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69,
+	0x6f, 0x6e, 0x22, 0x20, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x02, 0x69, 0x64, 0x22, 0x5f, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61,
+	0x69, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74,
+	0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x35, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x22, 0x10, 0x0a, 0x0e,
+	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37,
+	0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
+	0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a,
+	0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
+	0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x70, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x97, 0x03, 0x0a, 0x0a, 0x52, 0x75, 0x6e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x3f, 0x0a, 0x05,
+	0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f,
 	0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f,
 	0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e,
+	0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x53, 0x0a,
+	0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e,
 	0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70,
 	0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x6b, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64,
-	0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-	0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53,
-	0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a,
-	0x03, 0x52, 0x75, 0x6e, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65,
-	0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e,
-	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
-	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
-	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04, 0x45, 0x78, 0x65, 0x63, 0x12,
+	0x2e, 0x76, 0x31, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c,
+	0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65,
+	0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20,
+	0x03, 0x28, 0x09, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c,
+	0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12,
+	0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x08, 0x63, 0x70, 0x75, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x18,
+	0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x63,
+	0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16,
+	0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x6e,
+	0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
+	0x01, 0x22, 0x0d, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x22, 0x8c, 0x01, 0x0a, 0x0b, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
+	0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74,
+	0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
+	0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18,
+	0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65,
+	0x6e, 0x76, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x10, 0x0a,
+	0x03, 0x74, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x74, 0x74, 0x79, 0x22,
+	0x26, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
+	0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x1f, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x5e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74,
+	0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x48, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x73,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61,
+	0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63,
+	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f,
+	0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x6c,
+	0x6f, 0x77, 0x22, 0x24, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x95, 0x06, 0x0a, 0x0a, 0x43, 0x6f, 0x6e,
+	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x6b, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12,
 	0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
-	0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
 	0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
 	0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x30, 0x2e, 0x63,
+	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x30, 0x2e, 0x63,
 	0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31,
+	0x76, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31,
 	0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x32, 0x2e,
-	0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x68, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64,
+	0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+	0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
+	0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e,
+	0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x04, 0x45,
+	0x78, 0x65, 0x63, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72,
+	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
+	0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
+	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73,
+	0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70,
+	0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
+	0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e,
+	0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
+	0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74,
+	0x65, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
 	0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
 	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
-	0x74, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61,
-	0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
-	0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63,
-	0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63,
-	0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73,
-	0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d,
-	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x65,
-	0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x6e,
-	0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0x62, 0x06, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
+	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
+	0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x07, 0x49, 0x6e,
+	0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x6f, 0x63, 0x6b,
+	0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x63, 0x6f,
+	0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70,
+	0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64,
+	0x6f, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+	0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76,
+	0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (

+ 2 - 0
protos/containers/v1/containers.proto

@@ -50,6 +50,7 @@ message Container {
 	repeated Port ports = 11;
 	uint64 cpu_limit = 12;
 	string platform = 13;
+	string restart_policy_condition = 14;
 }
 
 message InspectRequest {
@@ -84,6 +85,7 @@ message RunRequest {
 	repeated string volumes = 5;
 	uint64 memory_limit = 6;
 	uint64 cpu_limit = 7;
+	string restart_policy_condition= 8;
 }
 
 message RunResponse {

+ 3 - 2
protos/contexts/v1/contexts.pb.go

@@ -23,14 +23,15 @@ package v1
 
 import (
 	context "context"
+	reflect "reflect"
+	sync "sync"
+
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
 )
 
 const (

+ 3 - 2
protos/streams/v1/streams.pb.go

@@ -23,6 +23,9 @@ package v1
 
 import (
 	context "context"
+	reflect "reflect"
+	sync "sync"
+
 	proto "github.com/golang/protobuf/proto"
 	any "github.com/golang/protobuf/ptypes/any"
 	grpc "google.golang.org/grpc"
@@ -30,8 +33,6 @@ import (
 	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
 )
 
 const (

+ 22 - 20
server/proxy/containers.go

@@ -111,19 +111,20 @@ func (p *proxy) Logs(request *containersv1.LogsRequest, stream containersv1.Cont
 
 func toGrpcContainer(c containers.Container) *containersv1.Container {
 	return &containersv1.Container{
-		Id:          c.ID,
-		Image:       c.Image,
-		Status:      c.Status,
-		Command:     c.Command,
-		CpuTime:     c.CPUTime,
-		MemoryUsage: c.MemoryUsage,
-		MemoryLimit: c.MemoryLimit,
-		Platform:    c.Platform,
-		PidsCurrent: c.PidsCurrent,
-		PidsLimit:   c.PidsLimit,
-		Labels:      c.Labels,
-		Ports:       portsToGrpc(c.Ports),
-		CpuLimit:    uint64(c.CPULimit),
+		Id:                     c.ID,
+		Image:                  c.Image,
+		Status:                 c.Status,
+		Command:                c.Command,
+		CpuTime:                c.CPUTime,
+		MemoryUsage:            c.MemoryUsage,
+		MemoryLimit:            c.MemoryLimit,
+		Platform:               c.Platform,
+		PidsCurrent:            c.PidsCurrent,
+		PidsLimit:              c.PidsLimit,
+		Labels:                 c.Labels,
+		Ports:                  portsToGrpc(c.Ports),
+		CpuLimit:               uint64(c.CPULimit),
+		RestartPolicyCondition: c.RestartPolicyCondition,
 	}
 }
 
@@ -139,12 +140,13 @@ func grpcContainerToContainerConfig(request *containersv1.RunRequest) containers
 	}
 
 	return containers.ContainerConfig{
-		ID:       request.GetId(),
-		Image:    request.GetImage(),
-		Ports:    ports,
-		Labels:   request.GetLabels(),
-		Volumes:  request.GetVolumes(),
-		MemLimit: formatter.MemBytes(request.GetMemoryLimit()),
-		CPULimit: float64(request.GetCpuLimit()),
+		ID:                     request.GetId(),
+		Image:                  request.GetImage(),
+		Ports:                  ports,
+		Labels:                 request.GetLabels(),
+		Volumes:                request.GetVolumes(),
+		MemLimit:               formatter.MemBytes(request.GetMemoryLimit()),
+		CPULimit:               float64(request.GetCpuLimit()),
+		RestartPolicyCondition: request.RestartPolicyCondition,
 	}
 }

+ 11 - 3
tests/aci-e2e/e2e-aci_test.go

@@ -86,6 +86,7 @@ func (s *E2eACISuite) TestACIRunSingleContainer() {
 	defer deleteResourceGroup(resourceGroupName)
 
 	var nginxExposedURL string
+	var containerID string
 	s.Step("runs nginx on port 80", func() {
 		aciContext := store.AciContext{
 			SubscriptionID: subscriptionID,
@@ -118,7 +119,7 @@ func (s *E2eACISuite) TestACIRunSingleContainer() {
 		Expect(containerFields[1]).To(Equal("nginx"))
 		Expect(containerFields[2]).To(Equal("Running"))
 		exposedIP := containerFields[3]
-		containerID := containerFields[0]
+		containerID = containerFields[0]
 		Expect(exposedIP).To(ContainSubstring(":80->80/tcp"))
 
 		nginxExposedURL = strings.ReplaceAll(exposedIP, "->80/tcp", "")
@@ -129,6 +130,13 @@ func (s *E2eACISuite) TestACIRunSingleContainer() {
 		Expect(output).To(ContainSubstring("GET"))
 	})
 
+	s.Step("inspect command", func() {
+		inspect := s.NewDockerCommand("inspect", containerID).ExecOrDie()
+		Expect(inspect).To(ContainSubstring("\"Platform\": \"Linux\""))
+		Expect(inspect).To(ContainSubstring("\"CPULimit\": 1"))
+		Expect(inspect).To(ContainSubstring("\"RestartPolicyCondition\": \"none\""))
+	})
+
 	s.Step("exec command", func() {
 		output := s.NewDockerCommand("exec", containerName, "pwd").ExecOrDie()
 		Expect(output).To(ContainSubstring("/"))
@@ -174,13 +182,12 @@ func (s *E2eACISuite) TestACIRunSingleContainer() {
 		shutdown := make(chan time.Time)
 		errs := make(chan error)
 		outChan := make(chan string)
-		cmd := s.NewDockerCommand("run", "nginx", "--memory", "0.1G", "--cpus", "0.1", "-p", "80:80", "--name", testContainerName).WithTimeout(shutdown)
+		cmd := s.NewDockerCommand("run", "nginx", "--restart", "on-failure", "--memory", "0.1G", "--cpus", "0.1", "-p", "80:80", "--name", testContainerName).WithTimeout(shutdown)
 		go func() {
 			output, err := cmd.Exec()
 			outChan <- output
 			errs <- err
 		}()
-		var containerID string
 		err := WaitFor(time.Second, 100*time.Second, errs, func() bool {
 			output := s.NewDockerCommand("ps").ExecOrDie()
 			lines := Lines(output)
@@ -201,6 +208,7 @@ func (s *E2eACISuite) TestACIRunSingleContainer() {
 		inspect := s.NewDockerCommand("inspect", containerID).ExecOrDie()
 		Expect(inspect).To(ContainSubstring("\"CPULimit\": 0.1"))
 		Expect(inspect).To(ContainSubstring("\"MemoryLimit\": 107374182"))
+		Expect(inspect).To(ContainSubstring("\"RestartPolicyCondition\": \"on-failure\""))
 
 		// Give a little time to get logs of the curl call
 		time.Sleep(5 * time.Second)

+ 2 - 1
tests/e2e/testdata/inspect-id.golden

@@ -11,5 +11,6 @@
     "PidsLimit": 0,
     "Labels": null,
     "Ports": null,
-    "Platform": "Linux"
+    "Platform": "Linux",
+    "RestartPolicyCondition": "none"
 }

+ 11 - 0
utils/stringutils.go

@@ -0,0 +1,11 @@
+package utils
+
+// StringContains check if an array contains a specific value
+func StringContains(array []string, needle string) bool {
+	for _, val := range array {
+		if val == needle {
+			return true
+		}
+	}
+	return false
+}