@@ -27,6 +27,8 @@ import (
2727const (
2828 tmpHelloService = "/tmp/hello.service"
2929 fxtHelloService = "fixtures/units/hello.service"
30+ tmpFixtures = "/tmp/fixtures"
31+ numUnitsReplace = 9
3032)
3133
3234// TestUnitRunnable is the simplest test possible, deplying a single-node
@@ -181,6 +183,10 @@ func TestUnitSubmitReplace(t *testing.T) {
181183 if err := replaceUnitCommon ("submit" ); err != nil {
182184 t .Fatal (err )
183185 }
186+
187+ if err := replaceUnitMultiple ("submit" , numUnitsReplace ); err != nil {
188+ t .Fatal (err )
189+ }
184190}
185191
186192// TestUnitLoadReplace() tests whether a command "fleetctl load --replace
@@ -189,6 +195,10 @@ func TestUnitLoadReplace(t *testing.T) {
189195 if err := replaceUnitCommon ("load" ); err != nil {
190196 t .Fatal (err )
191197 }
198+
199+ if err := replaceUnitMultiple ("load" , numUnitsReplace ); err != nil {
200+ t .Fatal (err )
201+ }
192202}
193203
194204// TestUnitStartReplace() tests whether a command "fleetctl start --replace
@@ -197,6 +207,10 @@ func TestUnitStartReplace(t *testing.T) {
197207 if err := replaceUnitCommon ("start" ); err != nil {
198208 t .Fatal (err )
199209 }
210+
211+ if err := replaceUnitMultiple ("start" , numUnitsReplace ); err != nil {
212+ t .Fatal (err )
213+ }
200214}
201215
202216func TestUnitSSHActions (t * testing.T ) {
@@ -325,6 +339,123 @@ func replaceUnitCommon(cmd string) error {
325339 return nil
326340}
327341
342+ // replaceUnitMultiple() tests whether a command "fleetctl {submit,load,start}
343+ // --replace hello.service" works or not.
344+ func replaceUnitMultiple (cmd string , n int ) error {
345+ // check if cmd is one of the supported commands.
346+ listCmds := []string {"submit" , "load" , "start" }
347+ found := false
348+ for _ , ccmd := range listCmds {
349+ if ccmd == cmd {
350+ found = true
351+ }
352+ }
353+ if ! found {
354+ return fmt .Errorf ("invalid command %s" , cmd )
355+ }
356+
357+ var listUnitCmd string
358+ if cmd == "submit" {
359+ listUnitCmd = "list-unit-files"
360+ } else {
361+ listUnitCmd = "list-units"
362+ }
363+
364+ cluster , err := platform .NewNspawnCluster ("smoke" )
365+ if err != nil {
366+ return fmt .Errorf ("%v" , err )
367+ }
368+ defer cluster .Destroy ()
369+
370+ m , err := cluster .CreateMember ()
371+ if err != nil {
372+ return fmt .Errorf ("%v" , err )
373+ }
374+ _ , err = cluster .WaitForNMachines (m , 1 )
375+ if err != nil {
376+ return fmt .Errorf ("%v" , err )
377+ }
378+
379+ if _ , err := os .Stat (tmpFixtures ); os .IsNotExist (err ) {
380+ os .Mkdir (tmpFixtures , 0755 )
381+ }
382+
383+ var stdout string
384+ for i := 1 ; i <= n ; i ++ {
385+ curHelloService := fmt .Sprintf ("/tmp/hello%d.service" , i )
386+ tmpHelloFixture := fmt .Sprintf ("/tmp/fixtures/hello%d.service" , i )
387+
388+ // generate a new service derived by fixtures, and store it under /tmp
389+ err = copyFile (tmpHelloFixture , fxtHelloService )
390+ if err != nil {
391+ return fmt .Errorf ("Failed to copy a temp fleet service: %v" , err )
392+ }
393+
394+ // run a command for a unit and assert it shows up
395+ if _ , _ , err := cluster .Fleetctl (m , cmd , tmpHelloFixture ); err != nil {
396+ return fmt .Errorf ("Unable to %s fleet unit: %v" , cmd , err )
397+ }
398+
399+ stdout , _ , err = cluster .Fleetctl (m , listUnitCmd , "--no-legend" )
400+ if err != nil {
401+ return fmt .Errorf ("Failed to run %s: %v" , listUnitCmd , err )
402+ }
403+ units := strings .Split (strings .TrimSpace (stdout ), "\n " )
404+ if len (units ) != i {
405+ return fmt .Errorf ("Did not find %d units in cluster: \n %s" , i , stdout )
406+ }
407+
408+ // generate a new service derived by fixtures, and store it under /tmp
409+ err = genNewFleetService (curHelloService , fxtHelloService , "sleep 2" , "sleep 1" )
410+ if err != nil {
411+ return fmt .Errorf ("Failed to generate a temp fleet service: %v" , err )
412+ }
413+ }
414+
415+ for i := 1 ; i <= n ; i ++ {
416+ curHelloService := fmt .Sprintf ("/tmp/hello%d.service" , i )
417+
418+ // replace the unit and assert it shows up
419+ if _ , _ , err = cluster .Fleetctl (m , cmd , "--replace" , curHelloService ); err != nil {
420+ return fmt .Errorf ("Unable to replace fleet unit: %v" , err )
421+ }
422+ stdout , _ , err = cluster .Fleetctl (m , listUnitCmd , "--no-legend" )
423+ if err != nil {
424+ return fmt .Errorf ("Failed to run %s: %v" , listUnitCmd , err )
425+ }
426+ units := strings .Split (strings .TrimSpace (stdout ), "\n " )
427+ if len (units ) != n {
428+ return fmt .Errorf ("Did not find %d units in cluster: \n %s" , n , stdout )
429+ }
430+ }
431+
432+ // clean up temp services under /tmp
433+ for i := 1 ; i <= n ; i ++ {
434+ curHelloService := fmt .Sprintf ("/tmp/hello%d.service" , i )
435+ os .Remove (curHelloService )
436+
437+ if err := destroyUnitRetrying (cluster , m , fxtHelloService ); err != nil {
438+ return fmt .Errorf ("Cannot destroy unit %v" , fxtHelloService )
439+ }
440+ }
441+ os .Remove (tmpFixtures )
442+
443+ return nil
444+ }
445+
446+ // copyFile()
447+ func copyFile (newFile , oldFile string ) error {
448+ input , err := ioutil .ReadFile (oldFile )
449+ if err != nil {
450+ return err
451+ }
452+ err = ioutil .WriteFile (newFile , []byte (input ), 0644 )
453+ if err != nil {
454+ return err
455+ }
456+ return nil
457+ }
458+
328459// genNewFleetService() is a helper for generating a temporary fleet service
329460// that reads from oldFile, replaces oldVal with newVal, and stores the result
330461// to newFile.
0 commit comments