From dfcbf2cb8997d8d87d9e597231f4c96fcae16652 Mon Sep 17 00:00:00 2001 From: Brian Neville <29639579+brianneville@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:50:44 +0000 Subject: [PATCH 1/3] add location label for StartContainer/UpdateContainer Store the location field from the StartContainer/UpdateContainer messages as a label on the started container. if the label is unspecified (L_UNKNOWN) then it is treated as L_PRIMARY as a default. --- client/start_container_test.go | 7 +- server/deploy_test.go | 1 + server/start_container.go | 47 ++++++- server/start_container_test.go | 225 ++++++++++++++++++++++++++++++-- server/update_container.go | 5 +- server/update_container_test.go | 21 +++ 6 files changed, 290 insertions(+), 16 deletions(-) diff --git a/client/start_container_test.go b/client/start_container_test.go index e47817b..bbea66c 100644 --- a/client/start_container_test.go +++ b/client/start_container_test.go @@ -25,6 +25,10 @@ import ( "google.golang.org/grpc/status" ) +const ( + locationLabel = "gnoi.containerz.location" +) + type fakeStartingContainerzServer struct { fakeContainerzServer @@ -405,7 +409,8 @@ func TestStart(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", InstanceName: "some-instance", - Labels: map[string]string{"key1": "value1"}, + Labels: map[string]string{"key1": "value1", + locationLabel: cpb.StartContainerRequest_L_UNKNOWN.String()}, Limits: &cpb.StartContainerRequest_Limits{ MaxCpu: 1.0, SoftMemBytes: 1000, diff --git a/server/deploy_test.go b/server/deploy_test.go index f437229..4c35c8c 100644 --- a/server/deploy_test.go +++ b/server/deploy_test.go @@ -153,6 +153,7 @@ func (f *fakeContainerManager) ContainerUpdate(_ context.Context, instance, imag f.Envs = optionz.EnvMapping f.Volumes = optionz.Volumes f.Devices = optionz.Devices + f.Labels = optionz.Labels f.Network = optionz.Network f.Capabilities = optionz.Capabilities f.RunAs = optionz.RunAs diff --git a/server/start_container.go b/server/start_container.go index e7e3bd3..e4b5c9f 100644 --- a/server/start_container.go +++ b/server/start_container.go @@ -19,6 +19,13 @@ import ( options "github.com/openconfig/containerz/containers" cpb "github.com/openconfig/gnoi/containerz" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const ( + locationLabel = "com.google.containerz.location" ) // StartContainer starts a container. If the image does not exist on the target, @@ -27,7 +34,10 @@ import ( // should provide one. If the instance name already exists, the target should // return an error. func (s *Server) StartContainer(ctx context.Context, request *cpb.StartContainerRequest) (*cpb.StartContainerResponse, error) { - opts := optionsFromStartContainerRequest(request) + opts, err := optionsFromStartContainerRequest(request) + if err != nil { + return nil, err + } resp, err := s.mgr.ContainerStart(ctx, request.GetImageName(), request.GetTag(), request.GetCmd(), opts...) if err != nil { return nil, err @@ -42,7 +52,7 @@ func (s *Server) StartContainer(ctx context.Context, request *cpb.StartContainer }, nil } -func optionsFromStartContainerRequest(request *cpb.StartContainerRequest) []options.Option { +func optionsFromStartContainerRequest(request *cpb.StartContainerRequest) ([]options.Option, error) { var opts []options.Option if len(request.GetPorts()) != 0 { ports := make(map[uint32]uint32, len(request.GetPorts())) @@ -75,6 +85,35 @@ func optionsFromStartContainerRequest(request *cpb.StartContainerRequest) []opti } } - opts = append(opts, options.WithLabels(request.GetLabels()), options.WithEnv(request.GetEnvironment()), options.WithInstanceName(request.GetInstanceName()), options.WithVolumes(request.GetVolumes()), options.WithDevices(request.GetDevices())) - return opts + labels, err := getLabelsWithLocation(request) + if err != nil { + return nil, err + } + + opts = append(opts, options.WithLabels(labels), options.WithEnv(request.GetEnvironment()), options.WithInstanceName(request.GetInstanceName()), options.WithVolumes(request.GetVolumes()), options.WithDevices(request.GetDevices())) + return opts, nil +} + +// buildLabels builds the labels map to include the location, based on the location +// field in the request. L_UNKNOWN is treated as L_PRIMARY +func getLabelsWithLocation(request *cpb.StartContainerRequest) (map[string]string, error) { + location := request.GetLocation() + if location == cpb.StartContainerRequest_L_UNKNOWN { + location = cpb.StartContainerRequest_L_PRIMARY + } + locationStr := cpb.StartContainerRequest_Location_name[int32(location)] + labels := request.GetLabels() + // if the label is already set but has the same value as the location, then ignore it. + if requestedLocation, ok := labels[locationLabel]; ok && requestedLocation != locationStr { + return nil, status.Errorf(codes.InvalidArgument, + "%q label (currently set to %q) should be not be set, or should match"+ + " location field %q. Unspecified location field is treated as L_PRIMARY", + locationLabel, requestedLocation, locationStr) + } else if !ok { + if labels == nil { + labels = make(map[string]string) + } + labels[locationLabel] = locationStr + } + return labels, nil } diff --git a/server/start_container_test.go b/server/start_container_test.go index 1f6580a..458cc92 100644 --- a/server/start_container_test.go +++ b/server/start_container_test.go @@ -16,12 +16,16 @@ package server import ( "context" + "errors" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + cpb "github.com/openconfig/gnoi/containerz" ) @@ -32,6 +36,7 @@ func TestContainerStart(t *testing.T) { inOpts []Option wantResp *cpb.StartContainerResponse wantState *fakeContainerManager + wantErr error }{ { name: "simple", @@ -39,6 +44,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_PRIMARY, }, wantResp: &cpb.StartContainerResponse{ Response: &cpb.StartContainerResponse_StartOk{ @@ -46,6 +52,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -57,6 +65,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_PRIMARY, Ports: []*cpb.StartContainerRequest_Port{ { Internal: 1, @@ -74,6 +83,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -86,6 +97,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_PRIMARY, Ports: []*cpb.StartContainerRequest_Port{ { Internal: 1, @@ -105,6 +117,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -119,6 +133,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, Environment: map[string]string{"1": "2", "3": "4"}, }, wantResp: &cpb.StartContainerResponse{ @@ -127,6 +142,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -139,6 +156,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_BACKUP, Volumes: []*cpb.Volume{ { Name: "vol1", @@ -160,6 +178,8 @@ func TestContainerStart(t *testing.T) { Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_BACKUP.String()}, Volumes: []*cpb.Volume{ { Name: "vol1", @@ -180,6 +200,7 @@ func TestContainerStart(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Network: "some-network", + Location: cpb.StartContainerRequest_L_PRIMARY, }, wantResp: &cpb.StartContainerResponse{ Response: &cpb.StartContainerResponse_StartOk{ @@ -187,6 +208,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -203,6 +226,7 @@ func TestContainerStart(t *testing.T) { Add: []string{"cap1", "cap2"}, Remove: []string{"cap3", "cap4"}, }, + Location: cpb.StartContainerRequest_L_ALL, }, wantResp: &cpb.StartContainerResponse{ Response: &cpb.StartContainerResponse_StartOk{ @@ -210,6 +234,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -225,6 +251,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, Restart: &cpb.StartContainerRequest_Restart{ Policy: cpb.StartContainerRequest_Restart_ON_FAILURE, Attempts: 3, @@ -236,6 +263,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -251,6 +280,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, RunAs: &cpb.StartContainerRequest_RunAs{ User: "some-user", Group: "some-group", @@ -262,6 +292,8 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -278,6 +310,7 @@ func TestContainerStart(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Labels: map[string]string{"key1": "value1"}, + Location: cpb.StartContainerRequest_L_ALL, }, wantResp: &cpb.StartContainerResponse{ Response: &cpb.StartContainerResponse_StartOk{ @@ -285,10 +318,11 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ - Image: "some-image", - Tag: "some-tag", - Cmd: "some-cmd", - Labels: map[string]string{"key1": "value1"}, + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{"key1": "value1", + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, }, }, { @@ -302,6 +336,7 @@ func TestContainerStart(t *testing.T) { SoftMemBytes: 1000, HardMemBytes: 2000, }, + Location: cpb.StartContainerRequest_L_ALL, }, wantResp: &cpb.StartContainerResponse{ Response: &cpb.StartContainerResponse_StartOk{ @@ -309,6 +344,7 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ + Labels: map[string]string{locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", @@ -323,6 +359,7 @@ func TestContainerStart(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Labels: map[string]string{locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Devices: []*cpb.Device{ { SrcPath: "dev1", @@ -340,6 +377,7 @@ func TestContainerStart(t *testing.T) { Permissions: []cpb.Device_Permission{cpb.Device_READ, cpb.Device_WRITE}, }, }, + Location: cpb.StartContainerRequest_L_ALL, }, wantResp: &cpb.StartContainerResponse{ Response: &cpb.StartContainerResponse_StartOk{ @@ -347,9 +385,10 @@ func TestContainerStart(t *testing.T) { }, }, wantState: &fakeContainerManager{ - Image: "some-image", - Tag: "some-tag", - Cmd: "some-cmd", + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Devices: []*cpb.Device{ { SrcPath: "dev1", @@ -369,6 +408,171 @@ func TestContainerStart(t *testing.T) { }, }, }, + { + name: "location-unknown-set-in-map", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_UNKNOWN.String(), + }, + }, + wantErr: status.Errorf(codes.InvalidArgument, + "%q label (currently set to %q) should be not be set, or should match"+ + " location field %q. Unspecified location field is treated as L_PRIMARY", + locationLabel, cpb.StartContainerRequest_L_UNKNOWN.String(), + cpb.StartContainerRequest_L_PRIMARY.String()), + wantState: &fakeContainerManager{}, + }, + { + name: "non-location-label-set", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{"foo": "bar"}, + }, + wantResp: &cpb.StartContainerResponse{ + Response: &cpb.StartContainerResponse_StartOk{ + StartOk: &cpb.StartOK{}, + }, + }, + wantState: &fakeContainerManager{ + Labels: map[string]string{ + "foo": "bar", + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + }, + }, + { + name: "location-unknown-treated-as-primary", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + }, + wantResp: &cpb.StartContainerResponse{ + Response: &cpb.StartContainerResponse_StartOk{ + StartOk: &cpb.StartOK{}, + }, + }, + wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + }, + }, + { + name: "mismatching-location", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String(), + }, + Location: cpb.StartContainerRequest_L_BACKUP, + }, + wantState: &fakeContainerManager{}, + wantErr: status.Errorf(codes.InvalidArgument, + "%q label (currently set to %q) should be not be set, or should match"+ + " location field %q. Unspecified location field is treated as L_PRIMARY", + locationLabel, cpb.StartContainerRequest_L_ALL.String(), + cpb.StartContainerRequest_L_BACKUP.String()), + }, + { + name: "location-label-only", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String(), + }, + }, + wantState: &fakeContainerManager{}, + wantErr: status.Errorf(codes.InvalidArgument, + "%q label (currently set to %q) should be not be set, or should match"+ + " location field %q. Unspecified location field is treated as L_PRIMARY", + locationLabel, cpb.StartContainerRequest_L_ALL.String(), + cpb.StartContainerRequest_L_PRIMARY.String()), + }, + { + name: "matching-location", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String(), + }, + Location: cpb.StartContainerRequest_L_PRIMARY, + }, + wantResp: &cpb.StartContainerResponse{ + Response: &cpb.StartContainerResponse_StartOk{ + StartOk: &cpb.StartOK{}, + }, + }, + wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + }, + }, + { + name: "location-field-only", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_PRIMARY, + }, + wantResp: &cpb.StartContainerResponse{ + Response: &cpb.StartContainerResponse_StartOk{ + StartOk: &cpb.StartOK{}, + }, + }, + wantState: &fakeContainerManager{ + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_PRIMARY.String()}, + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + }, + }, + { + name: "location-label-among-other-labels", + inReq: &cpb.StartContainerRequest{ + ImageName: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + Labels: map[string]string{ + "x": "y", + locationLabel: cpb.StartContainerRequest_L_ALL.String(), + }, + Location: cpb.StartContainerRequest_L_ALL, + }, + wantResp: &cpb.StartContainerResponse{ + Response: &cpb.StartContainerResponse_StartOk{ + StartOk: &cpb.StartOK{}, + }, + }, + wantState: &fakeContainerManager{ + Labels: map[string]string{ + "x": "y", + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, + Image: "some-image", + Tag: "some-tag", + Cmd: "some-cmd", + }, + }, } for _, tc := range tests { @@ -380,12 +584,13 @@ func TestContainerStart(t *testing.T) { defer s.Halt(ctx) resp, err := cli.StartContainer(ctx, tc.inReq) - if err != nil { - t.Errorf("Start(%+v) returned error: %v", tc.inReq, err) + if !errors.Is(err, tc.wantErr) { + t.Errorf("expected Start(%+v) to return error %v, got error: %v", + tc.inReq, tc.wantErr, err) } if diff := cmp.Diff(tc.wantResp, resp, protocmp.Transform()); diff != "" { - t.Errorf("Start(%+v) returned diff (-want +got):\n%s", tc.inReq, diff) + t.Errorf("Start(%+v) returned resp diff (-want +got):\n%s", tc.inReq, diff) } if diff := cmp.Diff(tc.wantState, fake, protocmp.Transform(), cmpopts.IgnoreUnexported(fakeContainerManager{}), cmpopts.SortMaps(func(a, b string) bool { return a < b })); diff != "" { diff --git a/server/update_container.go b/server/update_container.go index c5618c9..33b9e2a 100644 --- a/server/update_container.go +++ b/server/update_container.go @@ -51,7 +51,10 @@ func (s *Server) UpdateContainer(ctx context.Context, request *cpb.UpdateContain return nil, status.Errorf(codes.FailedPrecondition, "expected request to contain populated params, yet was nil") } - opts := optionsFromStartContainerRequest(startReq) + opts, err := optionsFromStartContainerRequest(startReq) + if err != nil { + return nil, err + } instance, err := s.mgr.ContainerUpdate(ctx, request.GetInstanceName(), startReq.GetImageName(), startReq.GetTag(), startReq.GetCmd(), request.GetAsync(), opts...) if err != nil { return nil, err diff --git a/server/update_container_test.go b/server/update_container_test.go index 901f7a0..f004ad8 100644 --- a/server/update_container_test.go +++ b/server/update_container_test.go @@ -46,6 +46,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, }, }, wantResp: &cpb.UpdateContainerResponse{ @@ -62,6 +63,8 @@ func TestContainerUpdate(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Async: false, + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, }, }, { @@ -75,6 +78,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, }, }, wantResp: &cpb.UpdateContainerResponse{ @@ -91,6 +95,8 @@ func TestContainerUpdate(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Async: false, + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, }, }, { @@ -104,6 +110,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, }, }, wantResp: &cpb.UpdateContainerResponse{ @@ -120,6 +127,8 @@ func TestContainerUpdate(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Async: true, + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, }, }, { @@ -133,6 +142,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, Ports: []*cpb.StartContainerRequest_Port{ { Internal: 1, @@ -159,6 +169,8 @@ func TestContainerUpdate(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Ports: map[uint32]uint32{1: 2, 3: 4}, + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, }, }, { @@ -172,6 +184,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, Environment: map[string]string{"1": "2", "3": "4"}, }, }, @@ -189,6 +202,8 @@ func TestContainerUpdate(t *testing.T) { Tag: "some-tag", Cmd: "some-cmd", Envs: map[string]string{"1": "2", "3": "4"}, + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, }, }, { @@ -202,6 +217,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, Volumes: []*cpb.Volume{ { Name: "vol1", @@ -228,6 +244,8 @@ func TestContainerUpdate(t *testing.T) { Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Volumes: []*cpb.Volume{ { Name: "vol1", @@ -252,6 +270,7 @@ func TestContainerUpdate(t *testing.T) { ImageName: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Location: cpb.StartContainerRequest_L_ALL, Devices: []*cpb.Device{ { SrcPath: "dev1", @@ -279,6 +298,8 @@ func TestContainerUpdate(t *testing.T) { Image: "some-image", Tag: "some-tag", Cmd: "some-cmd", + Labels: map[string]string{ + locationLabel: cpb.StartContainerRequest_L_ALL.String()}, Devices: []*cpb.Device{ { SrcPath: "dev1", From b43ea38216112af793b47cd30e978326bdda5cec Mon Sep 17 00:00:00 2001 From: Brian Neville <29639579+brianneville@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:55:19 +0000 Subject: [PATCH 2/3] update location label --- client/start_container_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/start_container_test.go b/client/start_container_test.go index bbea66c..fff209a 100644 --- a/client/start_container_test.go +++ b/client/start_container_test.go @@ -26,7 +26,7 @@ import ( ) const ( - locationLabel = "gnoi.containerz.location" + locationLabel = "com.google.containerz.location" ) type fakeStartingContainerzServer struct { From 317cab1e1af1f762be1d14571fc7aa3b4ca2024e Mon Sep 17 00:00:00 2001 From: Brian Neville <29639579+brianneville@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:26:17 +0000 Subject: [PATCH 3/3] rename getLabelsWithLocation to labelsWithLocation also update comment to have the correct function name, and to note that we're really updating the labels map, and not actually building the entire map from scratch. (i.e. we won't modify any existing labels in the map). --- server/start_container.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/start_container.go b/server/start_container.go index e4b5c9f..92ca152 100644 --- a/server/start_container.go +++ b/server/start_container.go @@ -85,7 +85,7 @@ func optionsFromStartContainerRequest(request *cpb.StartContainerRequest) ([]opt } } - labels, err := getLabelsWithLocation(request) + labels, err := labelsWithLocation(request) if err != nil { return nil, err } @@ -94,9 +94,9 @@ func optionsFromStartContainerRequest(request *cpb.StartContainerRequest) ([]opt return opts, nil } -// buildLabels builds the labels map to include the location, based on the location +// labelsWithLocation updates the labels map to include the location, based on the location // field in the request. L_UNKNOWN is treated as L_PRIMARY -func getLabelsWithLocation(request *cpb.StartContainerRequest) (map[string]string, error) { +func labelsWithLocation(request *cpb.StartContainerRequest) (map[string]string, error) { location := request.GetLocation() if location == cpb.StartContainerRequest_L_UNKNOWN { location = cpb.StartContainerRequest_L_PRIMARY