From dff7a03ccff6db55abe16b81b276b885b7b2d966 Mon Sep 17 00:00:00 2001 From: Shubhranshu153 Date: Mon, 28 Oct 2024 08:51:15 +0000 Subject: [PATCH] feat: Add Support for idmapping in finch-daemon Signed-off-by: Shubhranshu153 --- Makefile | 7 ++- internal/service/container/create.go | 14 ++++++ internal/service/container/create_test.go | 56 +++++++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 3b59445..aa33e68 100644 --- a/Makefile +++ b/Makefile @@ -48,9 +48,6 @@ restore-mod: mv build/go.mod.bak go.mod mv build/go.sum.bak go.sum -clean-build-dir: - rm -rf build - clean: @rm -f $(BINARIES) @rm -rf $(BIN) @@ -108,8 +105,10 @@ $(GOLINT): linux curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(BIN) v1.60.3 .PHONY: lint -lint: linux $(GOLINT) +lint: linux $(GOLINT) patch-nerdctl + go mod edit -replace=github.com/containerd/nerdctl@v1.7.7=./build/nerdctl && go mod tidy $(GOLINT) run ./... + $(MAKE) restore-mod .PHONY: test-unit test-unit: linux diff --git a/internal/service/container/create.go b/internal/service/container/create.go index 8ca6b39..49d61ec 100644 --- a/internal/service/container/create.go +++ b/internal/service/container/create.go @@ -6,6 +6,7 @@ package container import ( "context" "fmt" + "strings" "github.com/containerd/containerd" "github.com/containerd/containerd/cio" @@ -20,6 +21,17 @@ import ( "github.com/runfinch/finch-daemon/pkg/errdefs" ) +// ExtractUsernsFromLabels searches for a label with the prefix +// "runfinch.com/internal/userns=" and sets the Userns field. +func extractUsernsFromLabels(createOpt *types.ContainerCreateOptions) { + for _, label := range createOpt.Label { + if strings.HasPrefix(label, "runfinch.com/internal/userns=") { + createOpt.Userns = strings.TrimPrefix(label, "runfinch.com/internal/userns=") + return // Exit after the first match + } + } +} + func (s *service) Create(ctx context.Context, image string, cmd []string, createOpt types.ContainerCreateOptions, netOpt types.NetworkOptions) (cid string, err error) { // Set path to nerdctl binary required for OCI hooks and logging if createOpt.NerdctlCmd == "" { @@ -31,6 +43,8 @@ func (s *service) Create(ctx context.Context, image string, cmd []string, create createOpt.NerdctlArgs = []string{} } + extractUsernsFromLabels(&createOpt) + // translate network IDs to names because nerdctl currently does not recognize networks by their IDs during create. // TODO: remove this when the issue is fixed upstream. if err := s.translateNetworkIds(&netOpt); err != nil { diff --git a/internal/service/container/create_test.go b/internal/service/container/create_test.go index b8cd495..cc0d1f0 100644 --- a/internal/service/container/create_test.go +++ b/internal/service/container/create_test.go @@ -287,3 +287,59 @@ var _ = Describe("Container Create API ", func() { }) }) }) + +var _ = Describe("Extracting Userns from Labels", func() { + var ( + createOpt *types.ContainerCreateOptions + ) + + BeforeEach(func() { + createOpt = &types.ContainerCreateOptions{} + }) + + Describe("when there are labels", func() { + Context("with a matching userns label", func() { + BeforeEach(func() { + createOpt.Label = []string{"runfinch.com/internal/userns=test-namespace", "other.label=value"} + }) + + It("should extract the userns correctly", func() { + extractUsernsFromLabels(createOpt) + Expect(createOpt.Userns).To(Equal("test-namespace")) + }) + }) + + Context("without a matching userns label", func() { + BeforeEach(func() { + createOpt.Label = []string{"other.label=value"} + }) + + It("should not set userns", func() { + extractUsernsFromLabels(createOpt) + Expect(createOpt.Userns).To(BeEmpty()) + }) + }) + + Context("with multiple matching userns labels", func() { + BeforeEach(func() { + createOpt.Label = []string{"runfinch.com/internal/userns=test-namespace", "runfinch.com/internal/userns=another-namespace"} + }) + + It("should extract only the first userns label", func() { + extractUsernsFromLabels(createOpt) + Expect(createOpt.Userns).To(Equal("test-namespace")) + }) + }) + + Context("when the label list is empty", func() { + BeforeEach(func() { + createOpt.Label = []string{} + }) + + It("should not set userns", func() { + extractUsernsFromLabels(createOpt) + Expect(createOpt.Userns).To(BeEmpty()) + }) + }) + }) +})