github.com/containerd/Containerd@v1.4.13/runtime/v2/bundle_linux_test.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package v2
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  	"strconv"
    27  	"syscall"
    28  	"testing"
    29  
    30  	"github.com/containerd/containerd/namespaces"
    31  	"github.com/containerd/containerd/oci"
    32  	"github.com/containerd/containerd/pkg/testutil"
    33  	"github.com/opencontainers/runtime-spec/specs-go"
    34  )
    35  
    36  func TestNewBundle(t *testing.T) {
    37  	testutil.RequiresRoot(t)
    38  	tests := []struct {
    39  		userns bool
    40  	}{{
    41  		userns: false,
    42  	}, {
    43  		userns: true,
    44  	}}
    45  	const usernsGID = 4200
    46  
    47  	for i, tc := range tests {
    48  		t.Run(strconv.Itoa(i), func(t *testing.T) {
    49  			dir, err := ioutil.TempDir("", "test-new-bundle")
    50  			if err != nil {
    51  				t.Fatal("failed to create test directory", err)
    52  			}
    53  			defer os.RemoveAll(dir)
    54  			work := filepath.Join(dir, "work")
    55  			state := filepath.Join(dir, "state")
    56  			id := fmt.Sprintf("new-bundle-%d", i)
    57  			spec := oci.Spec{}
    58  			if tc.userns {
    59  				spec.Linux = &specs.Linux{
    60  					GIDMappings: []specs.LinuxIDMapping{{ContainerID: 0, HostID: usernsGID}},
    61  				}
    62  			}
    63  			specBytes, err := json.Marshal(&spec)
    64  			if err != nil {
    65  				t.Fatal("failed to marshal spec", err)
    66  			}
    67  
    68  			ctx := namespaces.WithNamespace(context.TODO(), namespaces.Default)
    69  			b, err := NewBundle(ctx, work, state, id, specBytes)
    70  			if err != nil {
    71  				t.Fatal("NewBundle should succeed", err)
    72  			}
    73  			if b == nil {
    74  				t.Fatal("bundle should not be nil")
    75  			}
    76  
    77  			fi, err := os.Stat(b.Path)
    78  			if err != nil {
    79  				t.Error("should be able to stat bundle path", err)
    80  			}
    81  			if tc.userns {
    82  				if fi.Mode() != os.ModeDir|0710 {
    83  					t.Error("bundle path should be a directory with perm 0710")
    84  				}
    85  			} else {
    86  				if fi.Mode() != os.ModeDir|0700 {
    87  					t.Error("bundle path should be a directory with perm 0700")
    88  				}
    89  			}
    90  			stat, ok := fi.Sys().(*syscall.Stat_t)
    91  			if !ok {
    92  				t.Fatal("should assert to *syscall.Stat_t")
    93  			}
    94  			expectedGID := uint32(0)
    95  			if tc.userns {
    96  				expectedGID = usernsGID
    97  			}
    98  			if expectedGID != stat.Gid {
    99  				t.Error("gid should match", expectedGID, stat.Gid)
   100  			}
   101  		})
   102  	}
   103  }
   104  
   105  func TestRemappedGID(t *testing.T) {
   106  	tests := []struct {
   107  		spec oci.Spec
   108  		gid  uint32
   109  	}{{
   110  		// empty spec
   111  		spec: oci.Spec{},
   112  		gid:  0,
   113  	}, {
   114  		// empty Linux section
   115  		spec: oci.Spec{
   116  			Linux: &specs.Linux{},
   117  		},
   118  		gid: 0,
   119  	}, {
   120  		// empty ID mappings
   121  		spec: oci.Spec{
   122  			Linux: &specs.Linux{
   123  				GIDMappings: make([]specs.LinuxIDMapping, 0),
   124  			},
   125  		},
   126  		gid: 0,
   127  	}, {
   128  		// valid ID mapping
   129  		spec: oci.Spec{
   130  			Linux: &specs.Linux{
   131  				GIDMappings: []specs.LinuxIDMapping{{
   132  					ContainerID: 0,
   133  					HostID:      1000,
   134  				}},
   135  			},
   136  		},
   137  		gid: 1000,
   138  	}, {
   139  		// missing ID mapping
   140  		spec: oci.Spec{
   141  			Linux: &specs.Linux{
   142  				GIDMappings: []specs.LinuxIDMapping{{
   143  					ContainerID: 100,
   144  					HostID:      1000,
   145  				}},
   146  			},
   147  		},
   148  		gid: 0,
   149  	}}
   150  
   151  	for i, tc := range tests {
   152  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   153  			s, err := json.Marshal(tc.spec)
   154  			if err != nil {
   155  				t.Fatal("failed to marshal spec", err)
   156  			}
   157  			gid, err := remappedGID(s)
   158  			if err != nil {
   159  				t.Error("should unmarshal successfully", err)
   160  			}
   161  			if tc.gid != gid {
   162  				t.Error("expected GID to match", tc.gid, gid)
   163  			}
   164  		})
   165  	}
   166  }