@@ -23,6 +23,7 @@ import (
2323 "io"
2424 "os"
2525 "path"
26+ "path/filepath"
2627 "runtime"
2728 "strings"
2829 "syscall"
@@ -2352,3 +2353,112 @@ func TestTaskSpec(t *testing.T) {
23522353 }
23532354 <- statusC
23542355}
2356+
2357+ func TestContainerAccessMount (t * testing.T ) {
2358+ // The Linux busybox image has a www-data user.
2359+ username := "www-data"
2360+ isWindows := runtime .GOOS == "windows"
2361+ if isWindows {
2362+ username = "ContainerUser"
2363+ }
2364+
2365+ // FIXME(claudiub): Currently, this won't be able to pass on Windows. This should be removed once
2366+ // the issue is fixed.
2367+ checkContainerAccessMount (t , username , ! isWindows )
2368+ }
2369+
2370+ func TestContainerAccessMountRoot (t * testing.T ) {
2371+ username := "root"
2372+ if runtime .GOOS == "windows" {
2373+ username = "ContainerAdministrator"
2374+ }
2375+ checkContainerAccessMount (t , username , true )
2376+ }
2377+
2378+ func checkContainerAccessMount (t * testing.T , username string , shouldPass bool ) {
2379+ t .Parallel ()
2380+
2381+ client , err := newClient (t , address )
2382+ if err != nil {
2383+ t .Fatal (err )
2384+ }
2385+ defer client .Close ()
2386+
2387+ var (
2388+ image Image
2389+ ctx , cancel = testContext (t )
2390+ id = t .Name ()
2391+ )
2392+ defer cancel ()
2393+
2394+ tempDir , err := os .MkdirTemp ("" , id )
2395+ if err != nil {
2396+ t .Fatal (err )
2397+ }
2398+ defer func () {
2399+ os .RemoveAll (tempDir )
2400+ }()
2401+
2402+ const expectedStr = "Hello there."
2403+ tempFile := filepath .Join (tempDir , "hello.txt" )
2404+ os .WriteFile (tempFile , []byte (expectedStr ), 0644 )
2405+
2406+ command := []string {"cat" , "/greetings/hello.txt" }
2407+ destination := "/greetings"
2408+ if runtime .GOOS == "windows" {
2409+ command = []string {"type" , `C:\greetings\hello.txt` }
2410+ destination = `C:\greetings`
2411+ }
2412+ mounts := []specs.Mount {
2413+ {
2414+ Destination : destination ,
2415+ Source : tempDir ,
2416+ Options : []string {"rbind" , "ro" },
2417+ },
2418+ }
2419+
2420+ image , err = client .GetImage (ctx , testImage )
2421+ if err != nil {
2422+ t .Fatal (err )
2423+ }
2424+
2425+ container , err := client .NewContainer (ctx , id , WithNewSnapshot (id , image ), WithNewSpec (oci .WithImageConfig (image ), oci .WithMounts (mounts ), oci .WithUsername (username ), withProcessArgs (command ... )))
2426+ if err != nil {
2427+ t .Fatal (err )
2428+ }
2429+ defer container .Delete (ctx , WithSnapshotCleanup )
2430+
2431+ stdout := bytes .NewBuffer (nil )
2432+ task , err := container .NewTask (ctx , cio .NewCreator (withByteBuffers (stdout )))
2433+ if err != nil {
2434+ t .Fatal (err )
2435+ }
2436+ defer task .Delete (ctx )
2437+
2438+ statusC , err := task .Wait (ctx )
2439+ if err != nil {
2440+ t .Fatal (err )
2441+ }
2442+
2443+ if err := task .Start (ctx ); err != nil {
2444+ t .Fatal (err )
2445+ }
2446+
2447+ status := <- statusC
2448+ code , _ , err := status .Result ()
2449+ if err != nil {
2450+ t .Fatal (err )
2451+ }
2452+
2453+ if shouldPass && code != 0 {
2454+ t .Errorf ("expected exec exit code 0 but received %d" , code )
2455+ }
2456+ if _ , err := task .Delete (ctx ); err != nil {
2457+ t .Fatal (err )
2458+ }
2459+
2460+ stdoutStr := stdout .String ()
2461+ if (shouldPass && ! strings .Contains (stdoutStr , expectedStr )) || (! shouldPass && strings .Contains (stdoutStr , expectedStr )) {
2462+ t .Fatalf ("process output does not match expectation: expected to pass: %t, ideal output: %q, actual output:\n \n %q" , shouldPass , expectedStr , stdoutStr )
2463+ }
2464+ }
0 commit comments