@@ -19,11 +19,19 @@ import (
1919 "context"
2020 "fmt"
2121 "log"
22+ "path"
2223 "regexp"
2324 "strings"
2425 "sync"
2526 "time"
2627
28+ "github.com/GoogleCloudPlatform/osconfig/e2e_tests/compute"
29+ "github.com/GoogleCloudPlatform/osconfig/e2e_tests/config"
30+ gcpclients "github.com/GoogleCloudPlatform/osconfig/e2e_tests/gcp_clients"
31+ testconfig "github.com/GoogleCloudPlatform/osconfig/e2e_tests/test_config"
32+ utils "github.com/GoogleCloudPlatform/osconfig/e2e_tests/utils"
33+ computeApi "google.golang.org/api/compute/v1"
34+
2735 "github.com/GoogleCloudPlatform/compute-image-tools/go/e2e_test_utils/junitxml"
2836)
2937
@@ -36,46 +44,91 @@ type TestRunner struct { // TODO: Unify test suites implementation to use this r
3644 TestSuiteName string
3745}
3846
47+ type ComputeInstanceMetadata struct {
48+ Metadata []* computeApi.MetadataItems
49+ MachineType string
50+ Image string
51+ InstanceNamePrefix string
52+ }
53+
3954// RunTestCase wraps execution of a test case with timeout and retry logic as well as creating a JUnit XML record.
40- func (tr * TestRunner ) RunTestCase (ctx context.Context , tc * junitxml.TestCase , f func (tc * junitxml.TestCase ), tests chan * junitxml.TestCase , wg * sync.WaitGroup , logger * log.Logger , regex * regexp.Regexp ) {
55+ func (tr * TestRunner ) RunTestCase (ctx context.Context , tc * junitxml.TestCase , f func (tc * junitxml.TestCase , inst * compute. Instance , testProjectConfig * testconfig. Project , instName string ), tests chan * junitxml.TestCase , wg * sync.WaitGroup , logger * log.Logger , regex * regexp.Regexp , computeInstanceMetadata * ComputeInstanceMetadata ) {
4156 defer wg .Done ()
4257
4358 if tc .FilterTestCase (regex ) {
4459 tc .Finish (tests )
4560 } else {
4661 logger .Printf ("Running TestCase %q" , tc .Name )
4762
48- runTestCase (ctx , tc , f , tests , wg , logger , regex )
63+ tr . runTestCase (ctx , tc , f , tests , logger , computeInstanceMetadata )
4964
5065 // Retry test if failure
5166 if tc .Failure != nil {
5267 rerunTC := junitxml .NewTestCase (tr .TestSuiteName , strings .TrimPrefix (tc .Name , fmt .Sprintf ("[%s] " , tr .TestSuiteName )))
5368 logger .Printf ("Rerunning TestCase %q" , rerunTC .Name )
54- runTestCase (ctx , rerunTC , f , tests , wg , logger , regex )
69+ tr . runTestCase (ctx , rerunTC , f , tests , logger , computeInstanceMetadata )
5570 }
5671 }
5772}
5873
59- func runTestCase (ctx context.Context , tc * junitxml.TestCase , f func (tc * junitxml.TestCase ), tests chan * junitxml.TestCase , wg * sync. WaitGroup , logger * log.Logger , regex * regexp. Regexp ) {
74+ func ( tr * TestRunner ) runTestCase (ctx context.Context , tc * junitxml.TestCase , f func (tc * junitxml.TestCase , inst * compute. Instance , testProjectConfig * testconfig. Project , instName string ), tests chan * junitxml.TestCase , logger * log.Logger , computeInstanceMetadata * ComputeInstanceMetadata ) {
6075 ctx , cancel := context .WithTimeout (ctx , timeout ) // Timeout applied on single test execution
6176 defer cancel ()
6277
78+ testProjectConfig := testconfig .GetProject ()
79+ zone := testProjectConfig .AcquireZone ()
80+ defer testProjectConfig .ReleaseZone (zone )
81+
82+ instanceName := fmt .Sprintf ("%s-%s" , computeInstanceMetadata .InstanceNamePrefix , utils .RandString (5 ))
83+ inst , err := createComputeInstance (tc , instanceName , computeInstanceMetadata .Image , computeInstanceMetadata .MachineType , zone , computeInstanceMetadata .Metadata , testProjectConfig , logger )
84+ defer inst .Cleanup ()
85+ defer inst .RecordSerialOutput (ctx , path .Join (* config .OutDir , tr .TestSuiteName ), 1 )
86+
87+ if err != nil {
88+ return
89+ }
90+
6391 select {
6492 case <- ctx .Done ():
6593 logger .Printf ("TestCase %q timed out after %v." , tc .Name , timeout )
6694 tc .WriteFailure ("Test timed out." )
6795 tc .Finish (tests )
68- case <- runAsync (tc , f ):
96+ case <- runAsync (tc , inst , testProjectConfig , instanceName , f ):
6997 tc .Finish (tests )
7098 logger .Printf ("TestCase %q finished in %fs" , tc .Name , tc .Time )
7199 }
72100}
73101
74- func runAsync (tc * junitxml.TestCase , f func (tc * junitxml.TestCase )) <- chan int {
102+ func runAsync (tc * junitxml.TestCase , inst * compute. Instance , testProjectConfig * testconfig. Project , instName string , f func (tc * junitxml.TestCase , inst * compute. Instance , testProjectConfig * testconfig. Project , instName string )) <- chan int {
75103 resultChan := make (chan int , 1 )
76104 go func () {
77- f (tc )
105+ f (tc , inst , testProjectConfig , instName )
78106 resultChan <- 1
79107 }()
80108 return resultChan
81109}
110+
111+ func createComputeInstance (tc * junitxml.TestCase , instanceName , image , machineType , zone string , metadata []* computeApi.MetadataItems , testProjectConfig * testconfig.Project , logger * log.Logger ) (* compute.Instance , error ) {
112+ computeClient , err := gcpclients .GetComputeClient ()
113+ if err != nil {
114+ tc .WriteFailure ("Error getting compute client: %v" , err )
115+ return nil , err
116+ }
117+
118+ tc .Logf ("Creating instance %q with image %q" , instanceName , image )
119+ inst , err := utils .CreateComputeInstance (metadata , computeClient , machineType , image , instanceName , testProjectConfig .TestProjectID , zone , testProjectConfig .ServiceAccountEmail , testProjectConfig .ServiceAccountScopes )
120+
121+ if err != nil {
122+ tc .WriteFailure ("Error creating instance: %v" , utils .GetStatusFromError (err ))
123+ return nil , err
124+ }
125+
126+ tc .Logf ("Waiting for agent install to complete" )
127+ if _ , err := inst .WaitForGuestAttributes ("osconfig_tests/install_done" , 5 * time .Second , 25 * time .Minute ); err != nil {
128+ tc .WriteFailure ("Error waiting for osconfig agent install: %v" , err )
129+ return nil , err
130+ }
131+ tc .Logf ("Agent installed successfully" )
132+
133+ return inst , nil
134+ }
0 commit comments