@@ -16,183 +16,188 @@ limitations under the License.
1616package  server
1717
1818import  (
19- 	 "context" 
20- 	 "errors" 
21- 	 "fmt" 
22- 	 "io" 
23- 	 "net/http" 
24- 	 "os" 
25- 	 "path/filepath" 
26- 	 "strings" 
27- 	 sync "sync" 
28- 	 "syscall" 
29- 	 "time" 
30- 
31- 	 "github.com/linuxsuren/api-testing/pkg/util/home" 
32- 
33- 	 "github.com/linuxsuren/api-testing/pkg/downloader" 
34- 	 "github.com/linuxsuren/api-testing/pkg/logging" 
35- 
36- 	 fakeruntime "github.com/linuxsuren/go-fake-runtime" 
19+      "context" 
20+      "errors" 
21+      "fmt" 
22+      "io" 
23+      "net/http" 
24+      "os" 
25+      "path/filepath" 
26+      "strings" 
27+      sync "sync" 
28+      "syscall" 
29+      "time" 
30+ 
31+      "github.com/linuxsuren/api-testing/pkg/util/home" 
32+ 
33+      "github.com/linuxsuren/api-testing/pkg/downloader" 
34+      "github.com/linuxsuren/api-testing/pkg/logging" 
35+ 
36+      fakeruntime "github.com/linuxsuren/go-fake-runtime" 
3737)
3838
3939var  (
40- 	 serverLogger  =  logging .DefaultLogger (logging .LogLevelInfo ).WithName ("server" )
40+      serverLogger  =  logging .DefaultLogger (logging .LogLevelInfo ).WithName ("server" )
4141)
4242
4343type  ExtManager  interface  {
44- 	 Start (name , socket  string ) (err  error )
45- 	 StopAll () (err  error )
46- 	 WithDownloader (downloader.PlatformAwareOCIDownloader )
44+      Start (name , socket  string ) (err  error )
45+      StopAll () (err  error )
46+      WithDownloader (downloader.PlatformAwareOCIDownloader )
4747}
4848
4949type  storeExtManager  struct  {
50- 	 execer                fakeruntime.Execer 
51- 	 ociDownloader         downloader.PlatformAwareOCIDownloader 
52- 	 socketPrefix          string 
53- 	 filesNeedToBeRemoved  []string 
54- 	 extStatusMap          map [string ]bool 
55- 	 processs              []fakeruntime.Process 
56- 	 processChan           chan  fakeruntime.Process 
57- 	 stopSingal            chan  struct {}
58- 	 lock                  * sync.RWMutex 
50+      execer                fakeruntime.Execer 
51+      ociDownloader         downloader.PlatformAwareOCIDownloader 
52+      socketPrefix          string 
53+      filesNeedToBeRemoved  []string 
54+      extStatusMap          map [string ]bool 
55+      processs              []fakeruntime.Process 
56+      processChan           chan  fakeruntime.Process 
57+      stopSingal            chan  struct {}
58+      lock                  * sync.RWMutex 
5959}
6060
6161var  ss  * storeExtManager 
6262
6363func  NewStoreExtManager (execer  fakeruntime.Execer ) ExtManager  {
64- 	 if  ss  ==  nil  {
65- 		 ss  =  & storeExtManager {
66- 			 processChan : make (chan  fakeruntime.Process ),
67- 			 stopSingal :  make (chan  struct {}, 1 ),
68- 			 lock :        & sync.RWMutex {},
69- 		 }
70- 		 ss .execer  =  execer 
71- 		 ss .socketPrefix  =  "unix://" 
72- 		 ss .extStatusMap  =  map [string ]bool {}
73- 		 ss .processCollect ()
74- 		 ss .WithDownloader (& nonDownloader {})
75- 	 }
76- 	 return  ss 
64+      if  ss  ==  nil  {
65+          ss  =  & storeExtManager {
66+              processChan : make (chan  fakeruntime.Process ),
67+              stopSingal :  make (chan  struct {}, 1 ),
68+              lock :        & sync.RWMutex {},
69+          }
70+          ss .execer  =  execer 
71+          ss .socketPrefix  =  "unix://" 
72+          ss .extStatusMap  =  map [string ]bool {}
73+          ss .processCollect ()
74+          ss .WithDownloader (& nonDownloader {})
75+      }
76+      return  ss 
7777}
7878
7979func  NewStoreExtManagerInstance (execer  fakeruntime.Execer ) ExtManager  {
80- 	 ss  =  & storeExtManager {
81- 		 processChan : make (chan  fakeruntime.Process ),
82- 		 stopSingal :  make (chan  struct {}, 1 ),
83- 		 lock :        & sync.RWMutex {},
84- 	 }
85- 	 ss .execer  =  execer 
86- 	 ss .socketPrefix  =  "unix://" 
87- 	 ss .extStatusMap  =  map [string ]bool {}
88- 	 ss .processCollect ()
89- 	 ss .WithDownloader (& nonDownloader {})
90- 	 return  ss 
80+      ss  =  & storeExtManager {
81+          processChan : make (chan  fakeruntime.Process ),
82+          stopSingal :  make (chan  struct {}, 1 ),
83+          lock :        & sync.RWMutex {},
84+      }
85+      ss .execer  =  execer 
86+      ss .socketPrefix  =  "unix://" 
87+      ss .extStatusMap  =  map [string ]bool {}
88+      ss .processCollect ()
89+      ss .WithDownloader (& nonDownloader {})
90+      return  ss 
9191}
9292
9393func  (s  * storeExtManager ) Start (name , socket  string ) (err  error ) {
94- 	if  v , ok  :=  s .extStatusMap [name ]; ok  &&  v  {
95- 		return 
96- 	}
97- 	targetDir  :=  home .GetUserBinDir ()
98- 	targetBinaryFile  :=  filepath .Join (targetDir , name )
99- 
100- 	var  binaryPath  string 
101- 	if  _ , err  =  os .Stat (targetBinaryFile ); err  ==  nil  {
102- 		binaryPath  =  targetBinaryFile 
103- 	} else  {
104- 		binaryPath , err  =  s .execer .LookPath (name )
105- 		if  err  !=  nil  {
106- 			err  =  fmt .Errorf ("not found extension, try to download it, error: %v" , err )
107- 			go  func () {
108- 				reader , dErr  :=  s .ociDownloader .Download (name , "" , "" )
109- 				if  dErr  !=  nil  {
110- 					serverLogger .Error (dErr , "failed to download extension" , "name" , name )
111- 				} else  {
112- 					extFile  :=  s .ociDownloader .GetTargetFile ()
113- 
114- 					targetFile  :=  filepath .Base (extFile )
115- 					if  dErr  =  downloader .WriteTo (reader , targetDir , targetFile ); dErr  ==  nil  {
116- 						binaryPath  =  filepath .Join (targetDir , targetFile )
117- 						s .startPlugin (socket , binaryPath , name )
118- 					} else  {
119- 						serverLogger .Error (dErr , "failed to save extension" , "targetFile" , targetFile )
120- 					}
121- 				}
122- 			}()
123- 		}
124- 	}
125- 
126- 	if  err  ==  nil  {
127- 		go  s .startPlugin (socket , binaryPath , name )
128- 	}
129- 	return 
94+     if  v , ok  :=  s .extStatusMap [name ]; ok  &&  v  {
95+         return 
96+     }
97+     if  s .execer .OS () ==  "windows"  {
98+         name  =  name  +  ".exe" 
99+     }
100+     targetDir  :=  home .GetUserBinDir ()
101+     targetBinaryFile  :=  filepath .Join (targetDir , name )
102+ 
103+     var  binaryPath  string 
104+     if  _ , err  =  os .Stat (targetBinaryFile ); err  ==  nil  {
105+         binaryPath  =  targetBinaryFile 
106+     } else  {
107+         serverLogger .Info ("failed to find extension" , "error" , err .Error ())
108+ 
109+         binaryPath , err  =  s .execer .LookPath (name )
110+         if  err  !=  nil  {
111+             err  =  fmt .Errorf ("not found extension, try to download it, error: %v" , err )
112+             go  func () {
113+                 reader , dErr  :=  s .ociDownloader .Download (name , "" , "" )
114+                 if  dErr  !=  nil  {
115+                     serverLogger .Error (dErr , "failed to download extension" , "name" , name )
116+                 } else  {
117+                     extFile  :=  s .ociDownloader .GetTargetFile ()
118+ 
119+                     targetFile  :=  filepath .Base (extFile )
120+                     if  dErr  =  downloader .WriteTo (reader , targetDir , targetFile ); dErr  ==  nil  {
121+                         binaryPath  =  filepath .Join (targetDir , targetFile )
122+                         s .startPlugin (socket , binaryPath , name )
123+                     } else  {
124+                         serverLogger .Error (dErr , "failed to save extension" , "targetFile" , targetFile )
125+                     }
126+                 }
127+             }()
128+         }
129+     }
130+ 
131+     if  err  ==  nil  {
132+         go  s .startPlugin (socket , binaryPath , name )
133+     }
134+     return 
130135}
131136
132137func  (s  * storeExtManager ) startPlugin (socketURL , plugin , pluginName  string ) (err  error ) {
133- 	 if  strings .Contains (socketURL , ":" ) &&  ! strings .HasPrefix (socketURL , s .socketPrefix ) {
134- 		 err  =  s .startPluginViaHTTP (socketURL , plugin , pluginName )
135- 		 return 
136- 	 }
137- 	 socketFile  :=  strings .TrimPrefix (socketURL , s .socketPrefix )
138- 	 _  =  os .RemoveAll (socketFile ) // always deleting the socket file to avoid start failing 
138+      if  strings .Contains (socketURL , ":" ) &&  ! strings .HasPrefix (socketURL , s .socketPrefix ) {
139+          err  =  s .startPluginViaHTTP (socketURL , plugin , pluginName )
140+          return 
141+      }
142+      socketFile  :=  strings .TrimPrefix (socketURL , s .socketPrefix )
143+      _  =  os .RemoveAll (socketFile ) // always deleting the socket file to avoid start failing 
139144
140- 	 s .lock .Lock ()
141- 	 s .filesNeedToBeRemoved  =  append (s .filesNeedToBeRemoved , socketFile )
142- 	 s .extStatusMap [pluginName ] =  true 
143- 	 s .lock .Unlock ()
145+      s .lock .Lock ()
146+      s .filesNeedToBeRemoved  =  append (s .filesNeedToBeRemoved , socketFile )
147+      s .extStatusMap [pluginName ] =  true 
148+      s .lock .Unlock ()
144149
145- 	 if  err  =  s .execer .RunCommandWithIO (plugin , "" , os .Stdout , os .Stderr , s .processChan , "--socket" , socketFile ); err  !=  nil  {
146- 		 serverLogger .Info ("failed to start ext manager" , "socket" , socketURL , "error: " , err .Error ())
147- 	 }
148- 	 return 
150+      if  err  =  s .execer .RunCommandWithIO (plugin , "" , os .Stdout , os .Stderr , s .processChan , "--socket" , socketFile ); err  !=  nil  {
151+          serverLogger .Info ("failed to start ext manager" , "socket" , socketURL , "error: " , err .Error ())
152+      }
153+      return 
149154}
150155
151156func  (s  * storeExtManager ) startPluginViaHTTP (httpURL , plugin , pluginName  string ) (err  error ) {
152- 	 port  :=  strings .Split (httpURL , ":" )[1 ]
153- 	 if  err  =  s .execer .RunCommandWithIO (plugin , "" , os .Stdout , os .Stderr , s .processChan , "--port" , port ); err  !=  nil  {
154- 		 serverLogger .Info ("failed to start ext manager" , "port" , port , "error: " , err .Error ())
155- 	 }
156- 	 return 
157+      port  :=  strings .Split (httpURL , ":" )[1 ]
158+      if  err  =  s .execer .RunCommandWithIO (plugin , "" , os .Stdout , os .Stderr , s .processChan , "--port" , port ); err  !=  nil  {
159+          serverLogger .Info ("failed to start ext manager" , "port" , port , "error: " , err .Error ())
160+      }
161+      return 
157162}
158163
159164func  (s  * storeExtManager ) StopAll () error  {
160- 	 serverLogger .Info ("stop" , "extensions" , len (s .processs ))
161- 	 for  _ , p  :=  range  s .processs  {
162- 		 if  p  !=  nil  {
163- 			 // Use Kill on Windows, Signal on other platforms 
164- 			 if  isWindows () {
165- 				 p .Kill ()
166- 			 } else  {
167- 				 p .Signal (syscall .SIGTERM )
168- 			 }
169- 		 }
170- 	 }
171- 	 s .stopSingal  <-  struct {}{}
172- 	 return  nil 
165+      serverLogger .Info ("stop" , "extensions" , len (s .processs ))
166+      for  _ , p  :=  range  s .processs  {
167+          if  p  !=  nil  {
168+              // Use Kill on Windows, Signal on other platforms 
169+              if  isWindows () {
170+                  p .Kill ()
171+              } else  {
172+                  p .Signal (syscall .SIGTERM )
173+              }
174+          }
175+      }
176+      s .stopSingal  <-  struct {}{}
177+      return  nil 
173178}
174179
175180// isWindows returns true if the program is running on Windows OS. 
176181func  isWindows () bool  {
177- 	 return  strings .Contains (strings .ToLower (os .Getenv ("OS" )), "windows" ) || 
178- 		 (strings .Contains (strings .ToLower (os .Getenv ("GOOS" )), "windows" ))
182+      return  strings .Contains (strings .ToLower (os .Getenv ("OS" )), "windows" ) || 
183+          (strings .Contains (strings .ToLower (os .Getenv ("GOOS" )), "windows" ))
179184}
180185
181186func  (s  * storeExtManager ) WithDownloader (ociDownloader  downloader.PlatformAwareOCIDownloader ) {
182- 	 s .ociDownloader  =  ociDownloader 
187+      s .ociDownloader  =  ociDownloader 
183188}
184189
185190func  (s  * storeExtManager ) processCollect () {
186- 	 go  func () {
187- 		 for  {
188- 			 select  {
189- 			 case  p  :=  <- s .processChan :
190- 				 s .processs  =  append (s .processs , p )
191- 			 case  <- s .stopSingal :
192- 				 return 
193- 			 }
194- 		 }
195- 	 }()
191+      go  func () {
192+          for  {
193+              select  {
194+              case  p  :=  <- s .processChan :
195+                  s .processs  =  append (s .processs , p )
196+              case  <- s .stopSingal :
197+                  return 
198+              }
199+          }
200+      }()
196201}
197202
198203var  ErrDownloadNotSupport  =  errors .New ("no support" )
@@ -202,44 +207,44 @@ type nonDownloader struct{}
202207var  _  downloader.PlatformAwareOCIDownloader  =  & nonDownloader {}
203208
204209func  (n  * nonDownloader ) WithBasicAuth (username  string , password  string ) {
205- 	 // Do nothing because this is an empty implementation 
210+      // Do nothing because this is an empty implementation 
206211}
207212
208213func  (n  * nonDownloader ) Download (image , tag , file  string ) (reader  io.Reader , err  error ) {
209- 	 err  =  ErrDownloadNotSupport 
210- 	 return 
214+      err  =  ErrDownloadNotSupport 
215+      return 
211216}
212217
213218func  (n  * nonDownloader ) WithOS (string ) {
214- 	 // Do nothing because this is an empty implementation 
219+      // Do nothing because this is an empty implementation 
215220}
216221
217222func  (n  * nonDownloader ) WithArch (string ) {
218- 	 // Do nothing because this is an empty implementation 
223+      // Do nothing because this is an empty implementation 
219224}
220225
221226func  (n  * nonDownloader ) WithRegistry (string ) {
222- 	 // Do nothing because this is an empty implementation 
227+      // Do nothing because this is an empty implementation 
223228}
224229
225230func  (n  * nonDownloader ) WithKind (string ) {
226- 	 // Do nothing because this is an empty implementation 
231+      // Do nothing because this is an empty implementation 
227232}
228233
229234func  (n  * nonDownloader ) WithImagePrefix (imagePrefix  string ) {
230- 	 // Do nothing because this is an empty implementation 
235+      // Do nothing because this is an empty implementation 
231236}
232237func  (d  * nonDownloader ) WithRoundTripper (rt  http.RoundTripper ) {
233- 	 // Do nothing because this is an empty implementation 
238+      // Do nothing because this is an empty implementation 
234239}
235240
236241func  (d  * nonDownloader ) WithInsecure (bool ) {
237- 	 // Do nothing because this is an empty implementation 
242+      // Do nothing because this is an empty implementation 
238243}
239244
240245func  (d  * nonDownloader ) WithTimeout (time.Duration )   {}
241246func  (d  * nonDownloader ) WithContext (context.Context ) {}
242247
243248func  (n  * nonDownloader ) GetTargetFile () string  {
244- 	 return  "" 
249+      return  "" 
245250}
0 commit comments