github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/pkg/mock/mock.go (about) 1 // Copyright (c) 2017 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package mock 7 8 import ( 9 "flag" 10 "fmt" 11 "io/ioutil" 12 "net" 13 "net/url" 14 "os" 15 "path/filepath" 16 17 "google.golang.org/grpc" 18 ) 19 20 // DefaultMockKataShimBinPath is populated at link time. 21 var DefaultMockKataShimBinPath string 22 23 // DefaultMockHookBinPath is populated at link time. 24 var DefaultMockHookBinPath string 25 26 // ShimStdoutOutput is the expected output sent by the mock shim on stdout. 27 const ShimStdoutOutput = "Some output on stdout" 28 29 // ShimStderrOutput is the expected output sent by the mock shim on stderr. 30 const ShimStderrOutput = "Some output on stderr" 31 32 // ShimMockConfig is the configuration structure for all virtcontainers shim mock implementations. 33 type ShimMockConfig struct { 34 Name string 35 URLParamName string 36 ContainerParamName string 37 TokenParamName string 38 } 39 40 // StartShim is a common routine for starting a shim mock. 41 func StartShim(config ShimMockConfig) error { 42 logDirPath, err := ioutil.TempDir("", config.Name+"-") 43 if err != nil { 44 return err 45 } 46 47 logFilePath := filepath.Join(logDirPath, "mock_"+config.Name+".log") 48 49 f, err := os.Create(logFilePath) 50 if err != nil { 51 return err 52 } 53 defer f.Close() 54 55 tokenFlag := flag.String(config.TokenParamName, "", "Container token") 56 urlFlag := flag.String(config.URLParamName, "", "Agent URL") 57 containerFlag := flag.String(config.ContainerParamName, "", "Container ID") 58 59 flag.Parse() 60 61 fmt.Fprintf(f, "INFO: Token = %s\n", *tokenFlag) 62 fmt.Fprintf(f, "INFO: URL = %s\n", *urlFlag) 63 fmt.Fprintf(f, "INFO: Container = %s\n", *containerFlag) 64 65 if *tokenFlag == "" { 66 err := fmt.Errorf("token should not be empty") 67 fmt.Fprintf(f, "%s\n", err) 68 return err 69 } 70 71 if *urlFlag == "" { 72 err := fmt.Errorf("url should not be empty") 73 fmt.Fprintf(f, "%s\n", err) 74 return err 75 } 76 77 if _, err := url.Parse(*urlFlag); err != nil { 78 err2 := fmt.Errorf("could not parse the URL %q: %s", *urlFlag, err) 79 fmt.Fprintf(f, "%s\n", err2) 80 return err2 81 } 82 83 if *containerFlag == "" { 84 err := fmt.Errorf("container should not be empty") 85 fmt.Fprintf(f, "%s\n", err) 86 return err 87 } 88 89 // Print some traces to stdout 90 fmt.Fprint(os.Stdout, ShimStdoutOutput) 91 os.Stdout.Close() 92 93 // Print some traces to stderr 94 fmt.Fprint(os.Stderr, ShimStderrOutput) 95 os.Stderr.Close() 96 97 fmt.Fprint(f, "INFO: Shim exited properly\n") 98 99 return nil 100 } 101 102 // ProxyMock is the proxy mock interface. 103 // It allows for implementing different kind 104 // of containers proxies front end. 105 type ProxyMock interface { 106 Start(URL string) error 107 Stop() error 108 } 109 110 // ProxyUnixMock is the UNIX proxy mock 111 type ProxyUnixMock struct { 112 ClientHandler func(c net.Conn) 113 114 listener net.Listener 115 } 116 117 // ProxyGRPCMock is the gRPC proxy mock 118 type ProxyGRPCMock struct { 119 // GRPCImplementer is the structure implementing 120 // the GRPC interface we want the proxy to serve. 121 GRPCImplementer interface{} 122 123 // GRPCRegister is the registration routine for 124 // the GRPC service. 125 GRPCRegister func(s *grpc.Server, srv interface{}) 126 127 listener net.Listener 128 } 129 130 // Start starts the UNIX proxy mock 131 func (p *ProxyUnixMock) Start(URL string) error { 132 if p.ClientHandler == nil { 133 return fmt.Errorf("Missing client handler") 134 } 135 136 url, err := url.Parse(URL) 137 if err != nil { 138 return err 139 } 140 141 l, err := net.Listen(url.Scheme, url.Path) 142 if err != nil { 143 return err 144 } 145 146 p.listener = l 147 148 go func() { 149 defer func() { 150 l.Close() 151 }() 152 153 for { 154 conn, err := l.Accept() 155 if err != nil { 156 return 157 } 158 159 go p.ClientHandler(conn) 160 } 161 }() 162 163 return nil 164 } 165 166 // Stop stops the UNIX proxy mock 167 func (p *ProxyUnixMock) Stop() error { 168 if p.listener == nil { 169 return fmt.Errorf("Missing proxy listener") 170 } 171 172 return p.listener.Close() 173 } 174 175 // Start starts the gRPC proxy mock 176 func (p *ProxyGRPCMock) Start(URL string) error { 177 if p.GRPCImplementer == nil { 178 return fmt.Errorf("Missing gRPC handler") 179 } 180 181 if p.GRPCRegister == nil { 182 return fmt.Errorf("Missing gRPC registration routine") 183 } 184 185 url, err := url.Parse(URL) 186 if err != nil { 187 return err 188 } 189 190 l, err := net.Listen(url.Scheme, url.Path) 191 if err != nil { 192 return err 193 } 194 195 p.listener = l 196 197 grpcServer := grpc.NewServer() 198 p.GRPCRegister(grpcServer, p.GRPCImplementer) 199 200 go func() { 201 grpcServer.Serve(l) 202 }() 203 204 return nil 205 } 206 207 // Stop stops the gRPC proxy mock 208 func (p *ProxyGRPCMock) Stop() error { 209 if p.listener == nil { 210 return fmt.Errorf("Missing proxy listener") 211 } 212 213 return p.listener.Close() 214 }