diff --git a/sdk/resourcemanager/internal/CHANGELOG.md b/sdk/resourcemanager/internal/CHANGELOG.md index 1f595293dd48..6e168aa46b7b 100644 --- a/sdk/resourcemanager/internal/CHANGELOG.md +++ b/sdk/resourcemanager/internal/CHANGELOG.md @@ -1,12 +1,12 @@ # Release History -## 2.0.1 (Unreleased) +## 3.0.0 (2024-05-31) ### Features Added +* Add `StartProxy` to help start and stop build-in test proxy for each module's test. ### Breaking Changes - -### Bugs Fixed +* Remove `NewRecordingPolicy`, use `GetCredAndClientOptions` directly. ### Other Changes * Updated dependencies. @@ -14,7 +14,7 @@ ## 2.0.0 (2023-11-16) ### Breaking Changes -* Removed `testutil.GetEnv`, use `github.com/Azure/azure-sdk-for-go/sdk/internal/recording.GetEnvVariable` instead. +* Remove `testutil.GetEnv`, use `github.com/Azure/azure-sdk-for-go/sdk/internal/recording.GetEnvVariable` instead. * Remove `testutil.GenerateAlphaNumericID`, use `github.com/Azure/azure-sdk-for-go/sdk/internal/recording.GenerateAlphaNumericID` instead. ### Other Changes diff --git a/sdk/resourcemanager/internal/assets.json b/sdk/resourcemanager/internal/assets.json index 7ae429e7fb60..f352199c5401 100644 --- a/sdk/resourcemanager/internal/assets.json +++ b/sdk/resourcemanager/internal/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/resourcemanager/internal", - "Tag": "go/resourcemanager/internal_227105d301" + "Tag": "go/resourcemanager/internal_94fa3b908d" } diff --git a/sdk/resourcemanager/internal/ci.resourcemanager.yml b/sdk/resourcemanager/internal/ci.resourcemanager.yml index 397b6cfe86ed..f1f625343066 100644 --- a/sdk/resourcemanager/internal/ci.resourcemanager.yml +++ b/sdk/resourcemanager/internal/ci.resourcemanager.yml @@ -27,3 +27,4 @@ extends: parameters: IncludeRelease: true ServiceDirectory: resourcemanager/internal + UsePipelineProxy: false diff --git a/sdk/resourcemanager/internal/go.mod b/sdk/resourcemanager/internal/go.mod index 43ae188b6527..eef7d2b23445 100644 --- a/sdk/resourcemanager/internal/go.mod +++ b/sdk/resourcemanager/internal/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/stretchr/testify v1.9.0 ) diff --git a/sdk/resourcemanager/internal/go.sum b/sdk/resourcemanager/internal/go.sum index 768b5b91d903..a6522835ce2c 100644 --- a/sdk/resourcemanager/internal/go.sum +++ b/sdk/resourcemanager/internal/go.sum @@ -2,8 +2,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqb github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.7.0 h1:rTfKOCZGy5ViVrlA74ZPE99a+SgoEE2K/yg3RyW9dFA= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.7.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= diff --git a/sdk/resourcemanager/internal/testutil/credential.go b/sdk/resourcemanager/internal/testutil/credential.go index ab944e3702fd..5fc1a25ff836 100644 --- a/sdk/resourcemanager/internal/testutil/credential.go +++ b/sdk/resourcemanager/internal/testutil/credential.go @@ -33,16 +33,14 @@ func (c *FakeCredential) GetToken(ctx context.Context, opts policy.TokenRequestO // In the record mode, the credential will be a DefaultAzureCredential which combines several common credentials. // In the playback mode, the credential will be a fake credential which will bypass truly authorization. func GetCredAndClientOptions(t *testing.T) (azcore.TokenCredential, *arm.ClientOptions) { - p := NewRecordingPolicy(t, &recording.RecordingOptions{UseHTTPS: true}) - client, err := recording.GetHTTPClient(t) + transport, err := recording.NewRecordingHTTPClient(t, nil) if err != nil { - t.Fatalf("Failed to create recording client: %v", err) + t.Fatalf("Failed to create recording transport: %v", err) } options := &arm.ClientOptions{ ClientOptions: policy.ClientOptions{ - PerCallPolicies: []policy.Policy{p}, - Transport: client, + Transport: transport, }, } diff --git a/sdk/resourcemanager/internal/testutil/credential_test.go b/sdk/resourcemanager/internal/testutil/credential_test.go index 96cdbc434d87..0c8b952f9a42 100644 --- a/sdk/resourcemanager/internal/testutil/credential_test.go +++ b/sdk/resourcemanager/internal/testutil/credential_test.go @@ -35,7 +35,7 @@ func (r *testBody) Seek(offset int64, whence int) (int64, error) { } func TestGetCredAndClientOptions(t *testing.T) { - testEndpoint := "http://test" + testEndpoint := "https://test" cred, options := GetCredAndClientOptions(t) pl, err := armruntime.NewPipeline("testmodule", "v0.1.0", cred, runtime.PipelineOptions{}, options) require.NoError(t, err) @@ -50,4 +50,5 @@ func TestGetCredAndClientOptions(t *testing.T) { require.Equal(t, "Bearer FakeToken", resp.Request.Header.Get("Authorization")) } require.Equal(t, testEndpoint, resp.Request.URL.String()) + } diff --git a/sdk/resourcemanager/internal/testutil/helper_test.go b/sdk/resourcemanager/internal/testutil/helper_test.go index e593c7ef2e8a..5dcf9ceb7259 100644 --- a/sdk/resourcemanager/internal/testutil/helper_test.go +++ b/sdk/resourcemanager/internal/testutil/helper_test.go @@ -8,7 +8,6 @@ package testutil import ( "context" - "strings" "testing" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" @@ -18,14 +17,7 @@ import ( "github.com/stretchr/testify/require" ) -const ( - pathToPackage = "sdk/resourcemanager/internal/testdata" -) - func TestCreateDeleteResourceGroup(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode { - t.Skip("https://github.com/Azure/azure-sdk-for-go/issues/22869") - } ctx := context.Background() cred, options := GetCredAndClientOptions(t) subscriptionID := recording.GetEnvVariable("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") @@ -33,15 +25,11 @@ func TestCreateDeleteResourceGroup(t *testing.T) { defer stop() resourceGroup, _, err := CreateResourceGroup(ctx, subscriptionID, cred, options, "eastus") require.NoError(t, err) - require.True(t, strings.HasPrefix(*resourceGroup.Name, "go-sdk-test-")) _, err = DeleteResourceGroup(ctx, subscriptionID, cred, options, *resourceGroup.Name) require.NoError(t, err) } func TestCreateDeployment(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode { - t.Skip("https://github.com/Azure/azure-sdk-for-go/issues/22869") - } ctx := context.Background() cred, options := GetCredAndClientOptions(t) subscriptionID := recording.GetEnvVariable("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") diff --git a/sdk/resourcemanager/internal/testutil/recording.go b/sdk/resourcemanager/internal/testutil/recording.go index dc50275c9167..798de282c767 100644 --- a/sdk/resourcemanager/internal/testutil/recording.go +++ b/sdk/resourcemanager/internal/testutil/recording.go @@ -8,95 +8,51 @@ package testutil import ( "fmt" - "net/http" - "strconv" "testing" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" ) -const recordingRandomSeedVariableName = "recordingRandomSeed" - -var ( - recordingSeed int64 -) - -type recordingPolicy struct { - options recording.RecordingOptions - t *testing.T -} - -// Host of the test proxy. -func (r *recordingPolicy) Host() string { - if r.options.UseHTTPS { - return "localhost:5001" - } - return "localhost:5000" -} - -// Scheme of the test proxy. -func (r *recordingPolicy) Scheme() string { - if r.options.UseHTTPS { - return "https" - } - return "http" -} - -// NewRecordingPolicy will create a recording policy which can be used in pipeline. -// The policy will change the destination of the request to the proxy server and add required header for the recording test. -func NewRecordingPolicy(t *testing.T, o *recording.RecordingOptions) policy.Policy { - if o == nil { - o = &recording.RecordingOptions{UseHTTPS: true} - } - p := &recordingPolicy{options: *o, t: t} - return p -} - -// Do with recording mode. -// When handling live request, the policy will do nothing. -// Otherwise, the policy will replace the URL of the request with the test proxy endpoint. -// After request, the policy will change back to the original URL for the request to prevent wrong polling URL for LRO. -func (r *recordingPolicy) Do(req *policy.Request) (resp *http.Response, err error) { - if recording.GetRecordMode() != "live" && !recording.IsLiveOnly(r.t) { - oriSchema := req.Raw().URL.Scheme - oriHost := req.Raw().URL.Host - req.Raw().URL.Scheme = r.Scheme() - req.Raw().URL.Host = r.Host() - req.Raw().Host = r.Host() +// StartProxy starts the test proxy with the path to store test recording file. +// It should be used in the module test preparation stage only once. +// It will return a delegate function to stop test proxy. +func StartProxy(pathToPackage string) func() { + if recording.GetRecordMode() == recording.PlaybackMode || recording.GetRecordMode() == recording.RecordingMode { + proxy, err := recording.StartTestProxy(pathToPackage, nil) + if err != nil { + panic(fmt.Sprintf("Failed to start recording proxy: %v", err)) + } - // replace request target to use test proxy - req.Raw().Header.Set(recording.UpstreamURIHeader, fmt.Sprintf("%v://%v", oriSchema, oriHost)) - req.Raw().Header.Set(recording.ModeHeader, recording.GetRecordMode()) - req.Raw().Header.Set(recording.IDHeader, recording.GetRecordingId(r.t)) + // sanitizer for any uuid string, e.g., subscriptionID + err = recording.AddGeneralRegexSanitizer("00000000-0000-0000-0000-000000000000", `[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}`, proxy.Options) + if err != nil { + panic(fmt.Sprintf("Failed to add uuid sanitizer: %v", err)) + } + // consolidate resource group name for recording and playback + err = recording.AddGeneralRegexSanitizer(recording.SanitizedValue, `go-sdk-test-\d+`, proxy.Options) + if err != nil { + panic(fmt.Sprintf("Failed to add resource group name sanitizer: %v", err)) + } + // disable location header sanitizer + err = recording.RemoveRegisteredSanitizers([]string{"AZSDK2003", "AZSDK2030"}, proxy.Options) + if err != nil { + panic(fmt.Sprintf("Failed to remove location header sanitizer: %v", err)) + } - resp, err = req.Next() - // for any lro operation, need to change back to the original target to prevent - if resp != nil { - resp.Request.URL.Scheme = oriSchema - resp.Request.URL.Host = oriHost + return func() { + err := recording.StopTestProxy(proxy) + if err != nil { + panic(fmt.Sprintf("Failed to stop recording proxy: %v", err)) + } } - return resp, err - } else { - return req.Next() } + return func() {} } // StartRecording starts the recording with the path to store recording file. // It will return a delegate function to stop recording. func StartRecording(t *testing.T, pathToPackage string) func() { - option := &recording.RecordingOptions{UseHTTPS: true} - // sanitizer for any uuid string, e.g., subscriptionID - err := recording.AddGeneralRegexSanitizer("00000000-0000-0000-0000-000000000000", `[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}`, option) - if err != nil { - t.Fatalf("Failed to add uuid sanitizer: %v", err) - } - // consolidate resource group name for recording and playback - err = recording.AddGeneralRegexSanitizer("go-sdk-test-rg", `go-sdk-test-\d+`, option) - if err != nil { - t.Fatalf("Failed to add resource group name sanitizer: %v", err) - } - err = recording.Start(t, pathToPackage, option) + err := recording.Start(t, pathToPackage, nil) if err != nil { t.Fatalf("Failed to start recording: %v", err) } @@ -105,7 +61,7 @@ func StartRecording(t *testing.T, pathToPackage string) func() { // StopRecording stops the recording. func StopRecording(t *testing.T) { - err := recording.Stop(t, &recording.RecordingOptions{Variables: map[string]interface{}{recordingRandomSeedVariableName: strconv.FormatInt(recordingSeed, 10)}}) + err := recording.Stop(t, nil) if err != nil { t.Fatalf("Failed to stop recording: %v", err) } diff --git a/sdk/resourcemanager/internal/testutil/recording_test.go b/sdk/resourcemanager/internal/testutil/recording_test.go index e490946dd7ef..cddfdec15224 100644 --- a/sdk/resourcemanager/internal/testutil/recording_test.go +++ b/sdk/resourcemanager/internal/testutil/recording_test.go @@ -7,30 +7,9 @@ package testutil import ( - "context" - "net/http" - "strings" "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" - "github.com/stretchr/testify/require" ) -func TestRecordingPolicy(t *testing.T) { - testEndpoint := "http://test" - pl := runtime.NewPipeline("testmodule", "v0.1.0", runtime.PipelineOptions{}, &policy.ClientOptions{PerCallPolicies: []policy.Policy{NewRecordingPolicy(t, &recording.RecordingOptions{UseHTTPS: false})}}) - req, err := runtime.NewRequest(context.Background(), http.MethodGet, testEndpoint) - require.NoError(t, err) - err = req.SetBody(&testBody{body: strings.NewReader("test")}, "text/plain") - require.NoError(t, err) - resp, err := pl.Do(req) - require.NoError(t, err) - require.Equal(t, http.StatusBadRequest, resp.StatusCode) - require.Equal(t, testEndpoint, resp.Request.URL.String()) -} - func TestStartStopRecording(t *testing.T) { stop := StartRecording(t, pathToPackage) defer stop() diff --git a/sdk/resourcemanager/internal/testutil/testsuite_test.go b/sdk/resourcemanager/internal/testutil/testsuite_test.go index 82e7de89a81c..be48f3065e0f 100644 --- a/sdk/resourcemanager/internal/testutil/testsuite_test.go +++ b/sdk/resourcemanager/internal/testutil/testsuite_test.go @@ -46,9 +46,6 @@ func (testsuite *ExampleTestSuite) TearDownSuite() { } func TestExampleTestSuite(t *testing.T) { - if recording.GetRecordMode() == recording.PlaybackMode { - t.Skip("https://github.com/Azure/azure-sdk-for-go/issues/22869") - } suite.Run(t, new(ExampleTestSuite)) } diff --git a/sdk/resourcemanager/internal/testutil/utils_test.go b/sdk/resourcemanager/internal/testutil/utils_test.go new file mode 100644 index 000000000000..c18d6ab0f112 --- /dev/null +++ b/sdk/resourcemanager/internal/testutil/utils_test.go @@ -0,0 +1,27 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package testutil + +import ( + "os" + "testing" +) + +const ( + pathToPackage = "sdk/resourcemanager/internal/testdata" +) + +func TestMain(m *testing.M) { + code := run(m) + os.Exit(code) +} + +func run(m *testing.M) int { + f := StartProxy(pathToPackage) + defer f() + return m.Run() +} diff --git a/sdk/resourcemanager/internal/version.go b/sdk/resourcemanager/internal/version.go index b9d2d458a17a..0009f1bda4ae 100644 --- a/sdk/resourcemanager/internal/version.go +++ b/sdk/resourcemanager/internal/version.go @@ -11,5 +11,5 @@ const ( Module = "internal" // Version is the semantic version (see http://semver.org) of this module. - Version = "v2.0.1" + Version = "v3.0.0" )