github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/tests/inspect/inspect.go (about) 1 // Copyright 2015 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 main 16 17 import ( 18 "bufio" 19 "bytes" 20 "crypto/sha1" 21 "flag" 22 "fmt" 23 "io/ioutil" 24 "os" 25 "os/signal" 26 "path/filepath" 27 "sort" 28 "strconv" 29 "strings" 30 "syscall" 31 "time" 32 "unsafe" 33 34 "golang.org/x/sys/unix" 35 36 "github.com/appc/spec/pkg/device" 37 "github.com/rkt/rkt/common/cgroup" 38 "github.com/rkt/rkt/common/cgroup/v1" 39 "github.com/rkt/rkt/common/cgroup/v2" 40 "github.com/rkt/rkt/tests/testutils" 41 "github.com/syndtr/gocapability/capability" 42 ) 43 44 var ( 45 globalFlagset = flag.NewFlagSet("inspect", flag.ExitOnError) 46 globalFlags = struct { 47 ReadStdin bool 48 CheckTty bool 49 CheckPath bool 50 PrintExec bool 51 PrintMsg string 52 SuffixMsg string 53 PrintEnv string 54 PrintCapsPid int 55 PrintUser bool 56 PrintGroups bool 57 PrintCwd bool 58 ExitCode int 59 ReadFile bool 60 WriteFile bool 61 StatFile bool 62 HashFile bool 63 FileSymlinkTarget bool 64 Sleep int 65 PreSleep int 66 PrintMemoryLimit bool 67 PrintCPUQuota bool 68 PrintCPUShares bool 69 FileName string 70 Content string 71 CheckCgroupMounts bool 72 PrintNetNS bool 73 PrintIpcNS bool 74 PrintIPv4 string 75 PrintIPv6 string 76 PrintDefaultGWv4 bool 77 PrintDefaultGWv6 bool 78 PrintGWv4 string 79 PrintGWv6 string 80 PrintHostname bool 81 GetHTTP string 82 ServeHTTP string 83 ServeHTTPTimeout int 84 PrintIfaceCount bool 85 PrintAppAnnotation string 86 SilentSigterm bool 87 CheckMountNS bool 88 PrintNoNewPrivs bool 89 CheckMknod string 90 }{} 91 ) 92 93 func init() { 94 globalFlagset.BoolVar(&globalFlags.ReadStdin, "read-stdin", false, "Read a line from stdin") 95 globalFlagset.BoolVar(&globalFlags.CheckTty, "check-tty", false, "Check if stdin is a terminal") 96 globalFlagset.BoolVar(&globalFlags.CheckPath, "check-path", false, "Check if environment variable PATH does not contain \\n") 97 globalFlagset.BoolVar(&globalFlags.PrintExec, "print-exec", false, "Print the command we were exceed as (i.e. argv[0])") 98 globalFlagset.StringVar(&globalFlags.PrintMsg, "print-msg", "", "Print the message given as parameter") 99 globalFlagset.StringVar(&globalFlags.SuffixMsg, "suffix-msg", "", "Print this suffix after some commands") 100 globalFlagset.BoolVar(&globalFlags.PrintCwd, "print-cwd", false, "Print the current working directory") 101 globalFlagset.StringVar(&globalFlags.PrintEnv, "print-env", "", "Print the specified environment variable") 102 globalFlagset.IntVar(&globalFlags.PrintCapsPid, "print-caps-pid", -1, "Print capabilities of the specified pid (or current process if pid=0)") 103 globalFlagset.BoolVar(&globalFlags.PrintUser, "print-user", false, "Print uid and gid") 104 globalFlagset.BoolVar(&globalFlags.PrintGroups, "print-groups", false, "Print all gids") 105 globalFlagset.IntVar(&globalFlags.ExitCode, "exit-code", 0, "Return this exit code") 106 globalFlagset.BoolVar(&globalFlags.ReadFile, "read-file", false, "Print the content of the file $FILE") 107 globalFlagset.BoolVar(&globalFlags.WriteFile, "write-file", false, "Write $CONTENT in the file $FILE") 108 globalFlagset.BoolVar(&globalFlags.StatFile, "stat-file", false, "Print the ownership and mode of the file $FILE") 109 globalFlagset.BoolVar(&globalFlags.HashFile, "hash-file", false, "Print the SHA1SUM of the file $FILE") 110 globalFlagset.BoolVar(&globalFlags.FileSymlinkTarget, "file-symlink-target", false, "Print the symlink target of $FILE") 111 globalFlagset.IntVar(&globalFlags.Sleep, "sleep", -1, "Sleep before exiting (in seconds)") 112 globalFlagset.IntVar(&globalFlags.PreSleep, "pre-sleep", -1, "Sleep before executing (in seconds)") 113 globalFlagset.BoolVar(&globalFlags.PrintMemoryLimit, "print-memorylimit", false, "Print cgroup memory limit") 114 globalFlagset.BoolVar(&globalFlags.PrintCPUQuota, "print-cpuquota", false, "Print cgroup cpu quota in milli-cores") 115 globalFlagset.BoolVar(&globalFlags.PrintCPUShares, "print-cpushares", false, "Print cgroup cpu shares") 116 globalFlagset.StringVar(&globalFlags.FileName, "file-name", "", "The file to read/write, $FILE will be ignored if this is specified") 117 globalFlagset.StringVar(&globalFlags.Content, "content", "", "The content to write, $CONTENT will be ignored if this is specified") 118 globalFlagset.BoolVar(&globalFlags.CheckCgroupMounts, "check-cgroups", false, "Try to write to the cgroup filesystem. Everything should be RO except some well-known files") 119 globalFlagset.BoolVar(&globalFlags.PrintNetNS, "print-netns", false, "Print the network namespace") 120 globalFlagset.BoolVar(&globalFlags.PrintIpcNS, "print-ipcns", false, "Print the IPC namespace") 121 globalFlagset.StringVar(&globalFlags.PrintIPv4, "print-ipv4", "", "Takes an interface name and prints its IPv4") 122 globalFlagset.StringVar(&globalFlags.PrintIPv6, "print-ipv6", "", "Takes an interface name and prints its IPv6") 123 globalFlagset.BoolVar(&globalFlags.PrintDefaultGWv4, "print-defaultgwv4", false, "Print the default IPv4 gateway") 124 globalFlagset.BoolVar(&globalFlags.PrintDefaultGWv6, "print-defaultgwv6", false, "Print the default IPv6 gateway") 125 globalFlagset.StringVar(&globalFlags.PrintGWv4, "print-gwv4", "", "Takes an interface name and prints its gateway's IPv4") 126 globalFlagset.StringVar(&globalFlags.PrintGWv6, "print-gwv6", "", "Takes an interface name and prints its gateway's IPv6") 127 globalFlagset.BoolVar(&globalFlags.PrintHostname, "print-hostname", false, "Prints the pod hostname") 128 globalFlagset.StringVar(&globalFlags.GetHTTP, "get-http", "", "HTTP-Get from the given address") 129 globalFlagset.StringVar(&globalFlags.ServeHTTP, "serve-http", "", "Serve the hostname via HTTP on the given address:port") 130 globalFlagset.IntVar(&globalFlags.ServeHTTPTimeout, "serve-http-timeout", 30, "HTTP Timeout to wait for a client connection") 131 globalFlagset.BoolVar(&globalFlags.PrintIfaceCount, "print-iface-count", false, "Print the interface count") 132 globalFlagset.StringVar(&globalFlags.PrintAppAnnotation, "print-app-annotation", "", "Take an annotation name of the app, and prints its value") 133 globalFlagset.BoolVar(&globalFlags.SilentSigterm, "silent-sigterm", false, "Exit with a success exit status if we receive SIGTERM") 134 globalFlagset.BoolVar(&globalFlags.CheckMountNS, "check-mountns", false, "Check if app's mount ns is different than stage1's. Requires CAP_SYS_PTRACE") 135 globalFlagset.BoolVar(&globalFlags.PrintNoNewPrivs, "print-no-new-privs", false, "print the prctl PR_GET_NO_NEW_PRIVS value") 136 globalFlagset.StringVar(&globalFlags.CheckMknod, "check-mknod", "", "check whether mknod on restricted devices is allowed") 137 } 138 139 func in(list []int, el int) bool { 140 for _, x := range list { 141 if el == x { 142 return true 143 } 144 } 145 return false 146 } 147 148 func main() { 149 globalFlagset.Parse(os.Args[1:]) 150 args := globalFlagset.Args() 151 if len(args) > 0 { 152 fmt.Fprintln(os.Stderr, "Wrong parameters") 153 os.Exit(254) 154 } 155 156 if globalFlags.SilentSigterm { 157 terminateCh := make(chan os.Signal, 1) 158 signal.Notify(terminateCh, syscall.SIGTERM) 159 go func() { 160 <-terminateCh 161 os.Exit(0) 162 }() 163 } 164 165 if globalFlags.PreSleep >= 0 { 166 time.Sleep(time.Duration(globalFlags.PreSleep) * time.Second) 167 } 168 169 if globalFlags.ReadStdin { 170 reader := bufio.NewReader(os.Stdin) 171 fmt.Printf("Enter text:\n") 172 text, _ := reader.ReadString('\n') 173 fmt.Printf("Received text: %s\n", text) 174 } 175 176 if globalFlags.PrintNoNewPrivs { 177 r1, _, err := syscall.Syscall( 178 syscall.SYS_PRCTL, 179 uintptr(unix.PR_GET_NO_NEW_PRIVS), 180 uintptr(0), uintptr(0), 181 ) 182 183 fmt.Printf("no_new_privs: %v err: %v\n", r1, err) 184 } 185 186 if globalFlags.CheckMknod != "" { 187 /* format: c:5:2:name */ 188 dev := strings.SplitN(globalFlags.CheckMknod, ":", 4) 189 if len(dev) < 4 { 190 fmt.Fprintln(os.Stderr, "Not enough parameters for mknod") 191 os.Exit(254) 192 } 193 typ := dev[0] 194 major, err := strconv.Atoi(dev[1]) 195 if err != nil { 196 fmt.Fprintln(os.Stderr, "Wrong major") 197 os.Exit(254) 198 } 199 minor, err := strconv.Atoi(dev[2]) 200 if err != nil { 201 fmt.Fprintln(os.Stderr, "Wrong minor") 202 os.Exit(254) 203 } 204 nodeName := dev[3] 205 206 majorMinor := device.Makedev(uint(major), uint(minor)) 207 mode := uint32(0777) 208 switch typ { 209 case "c": 210 mode |= syscall.S_IFCHR 211 case "b": 212 mode |= syscall.S_IFBLK 213 default: 214 fmt.Fprintln(os.Stderr, "Wrong device node type") 215 os.Exit(254) 216 } 217 218 if err := syscall.Mknod(nodeName, mode, int(majorMinor)); err != nil { 219 fmt.Fprintf(os.Stderr, "mknod %s: fail: %v\n", nodeName, err) 220 os.Exit(254) 221 } else { 222 fmt.Printf("mknod %s: succeed\n", nodeName) 223 os.Exit(0) 224 } 225 } 226 227 if globalFlags.CheckTty { 228 fd := int(os.Stdin.Fd()) 229 var termios syscall.Termios 230 _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 231 if err == 0 { 232 fmt.Printf("stdin is a terminal\n") 233 } else { 234 fmt.Printf("stdin is not a terminal\n") 235 } 236 } 237 238 if globalFlags.CheckPath { 239 envBytes, err := ioutil.ReadFile("/proc/self/environ") 240 if err != nil { 241 fmt.Fprintf(os.Stderr, "Error reading environment from \"/proc/self/environ\": %v\n", err) 242 os.Exit(254) 243 } 244 for _, v := range bytes.Split(envBytes, []byte{0}) { 245 if len(v) == 0 { 246 continue 247 } 248 if strings.HasPrefix(string(v), "PATH=") { 249 if strings.Contains(string(v), "\n") { 250 fmt.Fprintf(os.Stderr, "Malformed PATH: found new line") 251 os.Exit(254) 252 } else { 253 fmt.Printf("PATH is good\n") 254 os.Exit(0) 255 } 256 } else { 257 continue 258 } 259 } 260 fmt.Fprintf(os.Stderr, "PATH not found") 261 os.Exit(254) 262 } 263 264 if globalFlags.PrintExec { 265 fmt.Fprintf(os.Stdout, "inspect exceed as: %s\n", os.Args[0]) 266 } 267 268 if globalFlags.PrintMsg != "" { 269 fmt.Fprintf(os.Stdout, "%s\n", globalFlags.PrintMsg) 270 messageLoopStr := os.Getenv("MESSAGE_LOOP") 271 messageLoop, err := strconv.Atoi(messageLoopStr) 272 if err == nil { 273 for i := 0; i < messageLoop; i++ { 274 time.Sleep(time.Second) 275 fmt.Fprintf(os.Stdout, "%s\n", globalFlags.PrintMsg) 276 } 277 } 278 } 279 280 if globalFlags.PrintEnv != "" { 281 fmt.Fprintf(os.Stdout, "%s=%s\n", globalFlags.PrintEnv, os.Getenv(globalFlags.PrintEnv)) 282 } 283 284 if globalFlags.PrintCapsPid >= 0 { 285 caps, err := capability.NewPid(globalFlags.PrintCapsPid) 286 if err != nil { 287 fmt.Fprintf(os.Stderr, "Cannot get caps: %v\n", err) 288 os.Exit(254) 289 } 290 fmt.Printf("Capability set: effective: %s (%s)\n", caps.StringCap(capability.EFFECTIVE), globalFlags.SuffixMsg) 291 fmt.Printf("Capability set: permitted: %s (%s)\n", caps.StringCap(capability.PERMITTED), globalFlags.SuffixMsg) 292 fmt.Printf("Capability set: inheritable: %s (%s)\n", caps.StringCap(capability.INHERITABLE), globalFlags.SuffixMsg) 293 fmt.Printf("Capability set: bounding: %s (%s)\n", caps.StringCap(capability.BOUNDING), globalFlags.SuffixMsg) 294 295 if capStr := os.Getenv("CAPABILITY"); capStr != "" { 296 capInt, err := strconv.Atoi(capStr) 297 if err != nil { 298 fmt.Fprintf(os.Stderr, "Environment variable $CAPABILITY is not a valid capability number: %v\n", err) 299 os.Exit(254) 300 } 301 c := capability.Cap(capInt) 302 if caps.Get(capability.BOUNDING, c) { 303 fmt.Printf("%v=enabled (%s)\n", c.String(), globalFlags.SuffixMsg) 304 } else { 305 fmt.Printf("%v=disabled (%s)\n", c.String(), globalFlags.SuffixMsg) 306 } 307 } 308 } 309 310 if globalFlags.PrintUser { 311 fmt.Printf("User: uid=%d euid=%d gid=%d egid=%d\n", os.Getuid(), os.Geteuid(), os.Getgid(), os.Getegid()) 312 } 313 314 if globalFlags.PrintGroups { 315 gids, err := os.Getgroups() 316 if err != nil { 317 fmt.Fprintf(os.Stderr, "Error getting groups: %v\n", err) 318 os.Exit(254) 319 } 320 // getgroups(2): It is unspecified whether the effective group ID of 321 // the calling process is included in the returned list. (Thus, an 322 // application should also call getegid(2) and add or remove the 323 // resulting value.) 324 egid := os.Getegid() 325 if !in(gids, egid) { 326 gids = append(gids, egid) 327 sort.Ints(gids) 328 } 329 var b bytes.Buffer 330 for _, gid := range gids { 331 b.WriteString(fmt.Sprintf("%d ", gid)) 332 } 333 fmt.Printf("Groups: %s\n", b.String()) 334 } 335 336 if globalFlags.WriteFile { 337 fileName := os.Getenv("FILE") 338 if globalFlags.FileName != "" { 339 fileName = globalFlags.FileName 340 } 341 content := os.Getenv("CONTENT") 342 if globalFlags.Content != "" { 343 content = globalFlags.Content 344 } 345 346 err := ioutil.WriteFile(fileName, []byte(content), 0600) 347 if err != nil { 348 fmt.Fprintf(os.Stderr, "Cannot write to file %q: %v\n", fileName, err) 349 os.Exit(254) 350 } 351 } 352 353 if globalFlags.ReadFile { 354 fileName := os.Getenv("FILE") 355 if globalFlags.FileName != "" { 356 fileName = globalFlags.FileName 357 } 358 359 dat, err := ioutil.ReadFile(fileName) 360 if err != nil { 361 fmt.Fprintf(os.Stderr, "Cannot read file %q: %v\n", fileName, err) 362 os.Exit(254) 363 } 364 fmt.Print("<<<") 365 fmt.Print(string(dat)) 366 fmt.Print(">>>\n") 367 } 368 369 if globalFlags.StatFile { 370 fileName := os.Getenv("FILE") 371 if globalFlags.FileName != "" { 372 fileName = globalFlags.FileName 373 } 374 375 fi, err := os.Stat(fileName) 376 if err != nil { 377 fmt.Fprintf(os.Stderr, "Cannot stat file %q: %v\n", fileName, err) 378 os.Exit(254) 379 } 380 fmt.Printf("%s: mode: %s\n", fileName, fi.Mode().String()) 381 fmt.Printf("%s: user: %v\n", fileName, fi.Sys().(*syscall.Stat_t).Uid) 382 fmt.Printf("%s: group: %v\n", fileName, fi.Sys().(*syscall.Stat_t).Gid) 383 } 384 385 if globalFlags.HashFile { 386 fileName := os.Getenv("FILE") 387 if globalFlags.FileName != "" { 388 fileName = globalFlags.FileName 389 } 390 391 dat, err := ioutil.ReadFile(fileName) 392 if err != nil { 393 fmt.Fprintf(os.Stderr, "Cannot read file %q: %v\n", fileName, err) 394 os.Exit(254) 395 } 396 397 fmt.Printf("sha1sum: %x\n", sha1.Sum(dat)) 398 } 399 400 if globalFlags.FileSymlinkTarget { 401 fileName := os.Getenv("FILE") 402 if globalFlags.FileName != "" { 403 fileName = globalFlags.FileName 404 } 405 406 dst, err := os.Readlink(fileName) 407 if err != nil { 408 fmt.Fprintf(os.Stderr, "Cannot read file target %q: %v\n", fileName, err) 409 os.Exit(1) 410 } 411 412 fmt.Printf("symlink: %q -> %q\n", fileName, dst) 413 } 414 415 if globalFlags.PrintCwd { 416 wd, err := os.Getwd() 417 if err != nil { 418 fmt.Fprintf(os.Stderr, "Cannot get working directory: %v\n", err) 419 os.Exit(254) 420 } 421 fmt.Printf("cwd: %s\n", wd) 422 } 423 424 if globalFlags.PrintMemoryLimit { 425 // we use /proc/1/root to escape the chroot we're in and read the file 426 isUnified, err := cgroup.IsCgroupUnified("/proc/1/root/") 427 if err != nil { 428 fmt.Fprintf(os.Stderr, "Error getting cgroup type: %v\n", err) 429 os.Exit(254) 430 } 431 432 var limitPath string 433 if isUnified { 434 cgroupPath, err := v2.GetOwnCgroupPath() 435 if err != nil { 436 fmt.Fprintf(os.Stderr, "Error getting own memory cgroup path: %v\n", err) 437 os.Exit(254) 438 } 439 limitPath = filepath.Join("/proc/1/root/sys/fs/cgroup/", cgroupPath, "memory.max") 440 fmt.Fprintln(os.Stderr, "limitPath:", limitPath) 441 } else { 442 memCgroupPath, err := v1.GetOwnCgroupPath("memory") 443 if err != nil { 444 fmt.Fprintf(os.Stderr, "Error getting own memory cgroup path: %v\n", err) 445 os.Exit(254) 446 } 447 limitPath = filepath.Join("/proc/1/root/sys/fs/cgroup/memory", memCgroupPath, "memory.limit_in_bytes") 448 fmt.Fprintln(os.Stderr, limitPath) 449 } 450 limit, err := ioutil.ReadFile(limitPath) 451 if err != nil { 452 fmt.Fprintf(os.Stderr, "Can't read %s\n", limitPath) 453 os.Exit(254) 454 } 455 456 fmt.Printf("Memory Limit: %s\n", string(limit)) 457 } 458 459 if globalFlags.PrintCPUQuota { 460 cpuCgroupPath, err := v1.GetOwnCgroupPath("cpu") 461 if err != nil { 462 fmt.Fprintf(os.Stderr, "Error getting own cpu cgroup path: %v\n", err) 463 os.Exit(254) 464 } 465 // we use /proc/1/root to escape the chroot we're in and read our 466 // cpu quota 467 periodPath := filepath.Join("/proc/1/root/sys/fs/cgroup/cpu", cpuCgroupPath, "cpu.cfs_period_us") 468 periodBytes, err := ioutil.ReadFile(periodPath) 469 if err != nil { 470 fmt.Fprintf(os.Stderr, "Can't read cpu.cpu_period_us\n") 471 os.Exit(254) 472 } 473 quotaPath := filepath.Join("/proc/1/root/sys/fs/cgroup/cpu", cpuCgroupPath, "cpu.cfs_quota_us") 474 quotaBytes, err := ioutil.ReadFile(quotaPath) 475 if err != nil { 476 fmt.Fprintf(os.Stderr, "Can't read cpu.cpu_quota_us\n") 477 os.Exit(254) 478 } 479 480 period, err := strconv.Atoi(strings.Trim(string(periodBytes), "\n")) 481 if err != nil { 482 fmt.Fprintf(os.Stderr, "%v\n", err) 483 os.Exit(254) 484 } 485 quota, err := strconv.Atoi(strings.Trim(string(quotaBytes), "\n")) 486 if err != nil { 487 fmt.Fprintf(os.Stderr, "%v\n", err) 488 os.Exit(254) 489 } 490 491 quotaMilliCores := quota * 1000 / period 492 fmt.Printf("CPU Quota: %s\n", strconv.Itoa(quotaMilliCores)) 493 } 494 495 if globalFlags.PrintCPUShares { 496 cpuCgroupPath, err := v1.GetOwnCgroupPath("cpu") 497 if err != nil { 498 fmt.Fprintf(os.Stderr, "Error getting own cpu cgroup path: %v\n", err) 499 os.Exit(1) 500 } 501 // we use /proc/1/root to escape the chroot we're in and read our 502 // cpu quota 503 sharesPath := filepath.Join("/proc/1/root/sys/fs/cgroup/cpu", cpuCgroupPath, "cpu.shares") 504 sharesBytes, err := ioutil.ReadFile(sharesPath) 505 if err != nil { 506 fmt.Fprintf(os.Stderr, "Can't read cpu.shares\n") 507 os.Exit(1) 508 } 509 510 fmt.Printf("CPU Shares: %s", string(sharesBytes)) 511 } 512 513 if globalFlags.CheckCgroupMounts { 514 rootCgroupPath := "/proc/1/root/sys/fs/cgroup" 515 testPaths := []string{rootCgroupPath} 516 517 // test a couple of controllers if they're available 518 if _, err := os.Stat(filepath.Join(rootCgroupPath, "memory")); err == nil { 519 testPaths = append(testPaths, filepath.Join(rootCgroupPath, "memory")) 520 } 521 if _, err := os.Stat(filepath.Join(rootCgroupPath, "cpu")); err == nil { 522 testPaths = append(testPaths, filepath.Join(rootCgroupPath, "cpu")) 523 } 524 525 for _, p := range testPaths { 526 if err := syscall.Mkdir(filepath.Join(p, "test"), 0600); err == nil || err != syscall.EROFS { 527 fmt.Fprintf(os.Stderr, "check-cgroups: FAIL (%v)", err) 528 os.Exit(254) 529 } 530 } 531 532 fmt.Println("check-cgroups: SUCCESS") 533 } 534 535 if globalFlags.PrintNetNS { 536 ns, err := os.Readlink("/proc/self/ns/net") 537 if err != nil { 538 fmt.Fprintf(os.Stderr, "%v\n", err) 539 os.Exit(1) 540 } 541 fmt.Printf("NetNS: %s\n", ns) 542 } 543 544 if globalFlags.PrintIpcNS { 545 ns, err := os.Readlink("/proc/self/ns/ipc") 546 if err != nil { 547 fmt.Fprintf(os.Stderr, "%v\n", err) 548 os.Exit(1) 549 } 550 fmt.Printf("IPCNS: %s\n", ns) 551 } 552 553 if globalFlags.PrintIPv4 != "" { 554 iface := globalFlags.PrintIPv4 555 ips, err := testutils.GetIPsv4(iface) 556 if err != nil { 557 fmt.Fprintf(os.Stderr, "%v\n", err) 558 os.Exit(254) 559 } 560 if len(ips) == 0 { 561 fmt.Fprintf(os.Stderr, "No IPv4 found for interface %+v:\n", iface) 562 os.Exit(254) 563 } 564 fmt.Printf("%v IPv4: %s\n", iface, ips[0]) 565 } 566 567 if globalFlags.PrintDefaultGWv4 { 568 gw, err := testutils.GetDefaultGWv4() 569 if err != nil { 570 fmt.Fprintf(os.Stderr, "%v\n", err) 571 os.Exit(254) 572 } 573 fmt.Printf("DefaultGWv4: %s\n", gw) 574 } 575 576 if globalFlags.PrintDefaultGWv6 { 577 gw, err := testutils.GetDefaultGWv6() 578 if err != nil { 579 fmt.Fprintf(os.Stderr, "%v\n", err) 580 os.Exit(254) 581 } 582 fmt.Printf("DefaultGWv6: %s\n", gw) 583 } 584 585 if globalFlags.PrintGWv4 != "" { 586 // TODO: GetGW not implemented yet 587 iface := globalFlags.PrintGWv4 588 gw, err := testutils.GetGWv4(iface) 589 if err != nil { 590 fmt.Fprintf(os.Stderr, "%v\n", err) 591 os.Exit(254) 592 } 593 fmt.Printf("%v GWv4: %s\n", iface, gw) 594 } 595 596 if globalFlags.PrintIPv6 != "" { 597 // TODO 598 } 599 600 if globalFlags.PrintGWv6 != "" { 601 // TODO 602 } 603 604 if globalFlags.PrintHostname { 605 hostname, err := os.Hostname() 606 if err != nil { 607 fmt.Fprintf(os.Stderr, "%v\n", err) 608 os.Exit(254) 609 } 610 fmt.Printf("Hostname: %s\n", hostname) 611 } 612 613 if globalFlags.ServeHTTP != "" { 614 err := testutils.HTTPServe(globalFlags.ServeHTTP, globalFlags.ServeHTTPTimeout) 615 if err != nil { 616 fmt.Fprintf(os.Stderr, "%v\n", err) 617 os.Exit(254) 618 } 619 } 620 621 if globalFlags.GetHTTP != "" { 622 body, err := testutils.HTTPGet(globalFlags.GetHTTP) 623 if err != nil { 624 fmt.Fprintf(os.Stderr, "%v\n", err) 625 os.Exit(254) 626 } 627 fmt.Printf("HTTP-Get received: %s\n", body) 628 } 629 630 if globalFlags.PrintIfaceCount { 631 ifaceCount, err := testutils.GetIfaceCount() 632 if err != nil { 633 fmt.Fprintf(os.Stderr, "%v\n", err) 634 os.Exit(254) 635 } 636 fmt.Printf("Interface count: %d\n", ifaceCount) 637 } 638 639 if globalFlags.PrintAppAnnotation != "" { 640 mdsUrl, appName := os.Getenv("AC_METADATA_URL"), os.Getenv("AC_APP_NAME") 641 body, err := testutils.HTTPGet(fmt.Sprintf("%s/acMetadata/v1/apps/%s/annotations/%s", mdsUrl, appName, globalFlags.PrintAppAnnotation)) 642 if err != nil { 643 fmt.Fprintf(os.Stderr, "%v\n", err) 644 os.Exit(254) 645 } 646 fmt.Printf("Annotation %s=%s\n", globalFlags.PrintAppAnnotation, body) 647 } 648 649 if globalFlags.CheckMountNS { 650 appMountNS, err := os.Readlink("/proc/self/ns/mnt") 651 if err != nil { 652 fmt.Fprintf(os.Stderr, "%v\n", err) 653 os.Exit(254) 654 } 655 s1MountNS, err := os.Readlink("/proc/1/ns/mnt") 656 if err != nil { 657 fmt.Fprintf(os.Stderr, "%v\n", err) 658 os.Exit(254) 659 } 660 if appMountNS != s1MountNS { 661 fmt.Println("check-mountns: DIFFERENT") 662 } else { 663 fmt.Println("check-mountns: IDENTICAL") 664 os.Exit(254) 665 } 666 } 667 668 if globalFlags.Sleep >= 0 { 669 time.Sleep(time.Duration(globalFlags.Sleep) * time.Second) 670 } 671 672 os.Exit(globalFlags.ExitCode) 673 }