github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/stage1/init/common/pod_test.go (about) 1 // Copyright 2014 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package common 16 17 import ( 18 "io/ioutil" 19 "os" 20 "path/filepath" 21 "regexp" 22 "testing" 23 24 stage1commontypes "github.com/rkt/rkt/stage1/common/types" 25 26 "github.com/appc/spec/schema" 27 "github.com/appc/spec/schema/types" 28 ) 29 30 const tstprefix = "pod-test" 31 32 func TestQuoteExec(t *testing.T) { 33 tests := []struct { 34 input []string 35 output string 36 }{ 37 { 38 input: []string{`path`, `"arg1"`, `"'arg2'"`, `'arg3'`}, 39 output: `"path" "\"arg1\"" "\"\'arg2\'\"" "\'arg3\'"`, 40 }, { 41 input: []string{`path`}, 42 output: `"path"`, 43 }, { 44 input: []string{`path`, ``, `arg2`}, 45 output: `"path" "" "arg2"`, 46 }, { 47 input: []string{`path`, `"foo\bar"`, `\`}, 48 output: `"path" "\"foo\\bar\"" "\\"`, 49 }, { 50 input: []string{`path with spaces`, `"foo\bar"`, `\`}, 51 output: `"path with spaces" "\"foo\\bar\"" "\\"`, 52 }, { 53 input: []string{`path with "quo't'es" and \slashes`, `"arg"`, `\`}, 54 output: `"path with \"quo\'t\'es\" and \\slashes" "\"arg\"" "\\"`, 55 }, { 56 input: []string{`$path$`, `$argument`}, 57 output: `"$path$" "$$argument"`, 58 }, { 59 input: []string{`%path%`, `%argument`}, 60 output: `"%path%" "%%argument"`, 61 }, { 62 input: []string{`path`, `Args\nwith\nnewlines`}, 63 output: `"path" "Args\\nwith\\nnewlines"`, 64 }, { 65 input: []string{`path`, "Args\nwith\nnewlines"}, 66 output: `"path" "Args\nwith\nnewlines"`, 67 }, 68 } 69 70 for i, tt := range tests { 71 o := quoteExec(tt.input) 72 if o != tt.output { 73 t.Errorf("#%d: expected `%v` got `%v`", i, tt.output, o) 74 } 75 } 76 } 77 78 var ( 79 falseVar = false 80 trueVar = true 81 ) 82 83 // TestAppToNspawnArgsOverridesImageManifestReadOnly tests 84 // that the ImageManifest's `readOnly` volume setting will be 85 // overrided by PodManifest. 86 func Disabled_TestAppToNspawnArgsOverridesImageManifestReadOnly(t *testing.T) { 87 tests := []struct { 88 imageManifestVolumeReadOnly bool 89 podManifestVolumeReadOnly *bool 90 expectReadOnly bool 91 }{ 92 { 93 false, 94 nil, 95 false, 96 }, 97 { 98 false, 99 &falseVar, 100 false, 101 }, 102 { 103 false, 104 &trueVar, 105 true, 106 }, 107 { 108 true, 109 nil, 110 true, 111 }, 112 { 113 true, 114 &falseVar, 115 false, 116 }, 117 { 118 true, 119 &trueVar, 120 true, 121 }, 122 } 123 124 for i, tt := range tests { 125 podManifest := &schema.PodManifest{ 126 Volumes: []types.Volume{ 127 { 128 Name: *types.MustACName("foo-mount"), 129 Kind: "host", 130 Source: "/host/foo", 131 ReadOnly: tt.podManifestVolumeReadOnly, 132 }, 133 }, 134 } 135 appManifest := &schema.RuntimeApp{ 136 Mounts: []schema.Mount{ 137 { 138 Volume: *types.MustACName("foo-mount"), 139 Path: "/app/foo", 140 }, 141 }, 142 App: &types.App{ 143 Exec: []string{"/bin/foo"}, 144 User: "0", 145 Group: "0", 146 MountPoints: []types.MountPoint{ 147 { 148 Name: *types.MustACName("foo-mount"), 149 Path: "/app/foo", 150 ReadOnly: tt.imageManifestVolumeReadOnly, 151 }, 152 }, 153 }, 154 } 155 156 tmpDir, err := ioutil.TempDir("", tstprefix) 157 if err != nil { 158 t.Errorf("error creating tempdir: %v", err) 159 continue 160 } 161 defer os.RemoveAll(tmpDir) 162 163 if err := os.MkdirAll(filepath.Join(tmpDir, "/stage1/rootfs/opt/stage2/rootfs"), 0755); err != nil { 164 t.Errorf("error stage2 rootfs in tmpdir: %v", err) 165 continue 166 } 167 168 p := &stage1commontypes.Pod{Manifest: podManifest, Root: tmpDir} 169 output, err := appToNspawnArgs(p, appManifest) 170 if err != nil { 171 t.Errorf("#%d: unexpected error: `%v`", i, err) 172 } 173 174 if ro := hasBindROArg(output); ro != tt.expectReadOnly { 175 t.Errorf("#%d: expected: readOnly: %v, saw: %v \nOutput:\n%v", i, tt.expectReadOnly, ro, output) 176 } 177 } 178 } 179 180 func hasBindROArg(output []string) bool { 181 roRegexp := regexp.MustCompile("^--bind-ro=/host/foo:.*/app/foo(:rbind)?$") 182 for i := len(output) - 1; i >= 0; i-- { 183 if roRegexp.MatchString(output[i]) { 184 return true 185 } 186 } 187 return false 188 } 189 190 func Disabled_TestAppToNspawnArgsRecursive(t *testing.T) { 191 tests := []struct { 192 podManifestVolumeRecursive *bool 193 expectRecursive bool 194 }{ 195 { 196 nil, 197 true, 198 }, 199 { 200 &trueVar, 201 true, 202 }, 203 { 204 &falseVar, 205 false, 206 }, 207 } 208 209 for i, tt := range tests { 210 podManifest := &schema.PodManifest{ 211 Volumes: []types.Volume{ 212 { 213 Name: *types.MustACName("foo-mount"), 214 Kind: "host", 215 Source: "/host/foo", 216 Recursive: tt.podManifestVolumeRecursive, 217 }, 218 }, 219 } 220 appManifest := &schema.RuntimeApp{ 221 Mounts: []schema.Mount{ 222 { 223 Volume: *types.MustACName("foo-mount"), 224 Path: "/app/foo", 225 }, 226 }, 227 App: &types.App{ 228 Exec: []string{"/bin/foo"}, 229 User: "0", 230 Group: "0", 231 MountPoints: []types.MountPoint{ 232 { 233 Name: *types.MustACName("foo-mount"), 234 Path: "/app/foo", 235 }, 236 }, 237 }, 238 } 239 240 tmpDir, err := ioutil.TempDir("", tstprefix) 241 if err != nil { 242 t.Errorf("error creating tempdir: %v", err) 243 continue 244 } 245 defer os.RemoveAll(tmpDir) 246 247 if err := os.MkdirAll(filepath.Join(tmpDir, "/stage1/rootfs/opt/stage2/rootfs"), 0755); err != nil { 248 t.Errorf("error stage2 rootfs in tmpdir: %v", err) 249 continue 250 } 251 252 p := &stage1commontypes.Pod{Manifest: podManifest, Root: tmpDir} 253 output, err := appToNspawnArgs(p, appManifest) 254 if err != nil { 255 t.Errorf("#%d: unexpected error: `%v`", i, err) 256 } 257 if rbind := hasRbindArg(output); rbind != tt.expectRecursive { 258 t.Errorf("#%d: expected: recursive: %v, saw: %v \nOutput:\n%v", i, tt.expectRecursive, rbind, output) 259 } 260 } 261 } 262 263 func hasRbindArg(output []string) bool { 264 rbindRegexp := regexp.MustCompile("^--bind(-ro)?=/host/foo:.*/app/foo:rbind$") 265 for i := len(output) - 1; i >= 0; i-- { 266 if rbindRegexp.MatchString(output[i]) { 267 return true 268 } 269 } 270 return false 271 }