github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/rkt/enter.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 //+build linux 16 17 package main 18 19 import ( 20 "errors" 21 "fmt" 22 23 "github.com/appc/spec/schema/types" 24 "github.com/hashicorp/errwrap" 25 pkgPod "github.com/rkt/rkt/pkg/pod" 26 "github.com/rkt/rkt/stage0" 27 "github.com/rkt/rkt/store/imagestore" 28 "github.com/rkt/rkt/store/treestore" 29 "github.com/spf13/cobra" 30 ) 31 32 var ( 33 cmdEnter = &cobra.Command{ 34 Use: "enter [--app=APPNAME] UUID [CMD [ARGS ...]]", 35 Short: "Enter the namespaces of an app within a rkt pod", 36 37 Long: `UUID should be the UUID of a running pod. 38 39 By default the CMD that is run is /bin/bash, providing the user with shell 40 access to the running pod.`, 41 Run: ensureSuperuser(runWrapper(runEnter)), 42 } 43 flagAppName string 44 ) 45 46 const ( 47 defaultCmd = "/bin/bash" 48 ) 49 50 func init() { 51 cmdRkt.AddCommand(cmdEnter) 52 cmdEnter.Flags().StringVar(&flagAppName, "app", "", "name of the app to enter within the specified pod") 53 54 // Disable interspersed flags to stop parsing after the first non flag 55 // argument. This is need to permit to correctly handle 56 // multiple "IMAGE -- imageargs ---" options 57 cmdEnter.Flags().SetInterspersed(false) 58 } 59 60 func runEnter(cmd *cobra.Command, args []string) (exit int) { 61 if len(args) < 1 { 62 cmd.Usage() 63 return 254 64 } 65 66 p, err := pkgPod.PodFromUUIDString(getDataDir(), args[0]) 67 if err != nil { 68 stderr.PrintE("problem retrieving pod", err) 69 return 254 70 } 71 defer p.Close() 72 73 if p.State() != pkgPod.Running { 74 stderr.Printf("pod %q isn't currently running", p.UUID) 75 return 254 76 } 77 78 podPID, err := p.ContainerPid1() 79 if err != nil { 80 stderr.PrintE(fmt.Sprintf("unable to determine the pid for pod %q", p.UUID), err) 81 return 254 82 } 83 84 appName, err := getAppName(p) 85 if err != nil { 86 stderr.PrintE("unable to determine app name", err) 87 return 254 88 } 89 90 argv, err := getEnterArgv(p, args) 91 if err != nil { 92 stderr.PrintE("enter failed", err) 93 return 254 94 } 95 96 s, err := imagestore.NewStore(storeDir()) 97 if err != nil { 98 stderr.PrintE("cannot open store", err) 99 return 254 100 } 101 102 ts, err := treestore.NewStore(treeStoreDir(), s) 103 if err != nil { 104 stderr.PrintE("cannot open store", err) 105 return 254 106 } 107 108 stage1TreeStoreID, err := p.GetStage1TreeStoreID() 109 if err != nil { 110 stderr.PrintE("error getting stage1 treeStoreID", err) 111 return 254 112 } 113 114 stage1RootFS := ts.GetRootFS(stage1TreeStoreID) 115 116 if err = stage0.Enter(p.Path(), podPID, *appName, stage1RootFS, argv); err != nil { 117 stderr.PrintE("enter failed", err) 118 return 254 119 } 120 // not reached when stage0.Enter execs /enter 121 return 0 122 } 123 124 // getAppName returns the app name to enter 125 // If one was supplied in the flags then it's simply returned 126 // If the PM contains a single app, that app's name is returned 127 // If the PM has multiple apps, the names are printed and an error is returned 128 func getAppName(p *pkgPod.Pod) (*types.ACName, error) { 129 if flagAppName != "" { 130 return types.NewACName(flagAppName) 131 } 132 133 // figure out the app name, or show a list if multiple are present 134 _, m, err := p.PodManifest() 135 if err != nil { 136 return nil, errwrap.Wrap(errors.New("error reading pod manifest"), err) 137 } 138 139 switch len(m.Apps) { 140 case 0: 141 return nil, fmt.Errorf("pod contains zero apps") 142 case 1: 143 return &m.Apps[0].Name, nil 144 default: 145 } 146 147 stderr.Print("pod contains multiple apps:") 148 for _, ra := range m.Apps { 149 stderr.Printf("\t%v", ra.Name) 150 } 151 152 return nil, fmt.Errorf("specify app using \"rkt enter --app= ...\"") 153 } 154 155 // getEnterArgv returns the argv to use for entering the pod 156 func getEnterArgv(p *pkgPod.Pod, cmdArgs []string) ([]string, error) { 157 var argv []string 158 if len(cmdArgs) < 2 { 159 stderr.Printf("no command specified, assuming %q", defaultCmd) 160 argv = []string{defaultCmd} 161 } else { 162 argv = cmdArgs[1:] 163 } 164 165 return argv, nil 166 }