Skip to content
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
19da635
Initial generation of the aztables module (#14441)
christothes Apr 5, 2021
3e724e2
Update ci.yml
christothes Apr 5, 2021
6ddf807
Introduce internal/testFramework and test aztables with it (#14491)
christothes Apr 21, 2021
1559e92
sanitizer fixes (#14600)
catalinaperalta Apr 28, 2021
fed39eb
Progress on aztables (#14676)
christothes May 21, 2021
b606abd
AsModels
christothes May 28, 2021
8e10930
rename
christothes May 28, 2021
c39e2ca
comments
christothes Jun 1, 2021
c9d0dd3
comment tweaks, options as pointer
christothes Jun 3, 2021
b427598
add EntityMapAsModel
christothes Jun 3, 2021
9747f1d
refactors to AddEntity
christothes Jun 3, 2021
02b61fb
update some code docs
christothes Jun 4, 2021
d21b634
doc fixes
christothes Jun 4, 2021
1b06de5
doc fixes
christothes Jun 4, 2021
09e4fb6
doc improvements
christothes Jun 4, 2021
63e0566
rename testframework to recording
christothes Jun 22, 2021
67fa153
move ci.yml
christothes Jun 28, 2021
e743034
ci path
christothes Jun 28, 2021
f2d1250
ci path
christothes Jun 28, 2021
274d7ac
[Tables] Update from testframework -> recording (#14888)
seankane-msft Jun 30, 2021
ef70309
[Tables] ci fix (#14956)
seankane-msft Jul 1, 2021
31a7267
[Tables] Add post-request validation of entity (#14960)
seankane-msft Jul 2, 2021
6bc983b
[Tables] changing QueryOptions param to be a ptr (#14961)
seankane-msft Jul 8, 2021
3d6b5ce
[Tables] linting Fixes (#15028)
seankane-msft Jul 9, 2021
658d8c5
[Tables] Adding swagger.md (#15016)
seankane-msft Jul 14, 2021
8d1167e
[Tables] Add get/set access policy (#15027)
seankane-msft Jul 20, 2021
88aa7f2
[Tables] Add GetStats, GetProperties, and SetProperties methods (#15112)
seankane-msft Jul 21, 2021
e224444
[Tables] Add support for Entity struct (#15003)
seankane-msft Jul 26, 2021
f905d11
[Tables] change Query to List (#15099)
seankane-msft Jul 26, 2021
6e69790
[Tables] Update transactions method (#15125)
seankane-msft Jul 26, 2021
e165488
Adding Table suffix to Create, Delete, and List methods on service cl…
seankane-msft Jul 28, 2021
4723b6d
[Tables] Architect Feedback (#15196)
seankane-msft Aug 3, 2021
4aa5a96
[EngSys] Test proxy (#15101)
seankane-msft Aug 12, 2021
a8c839f
[Tables] Add authentication via SAS credential (#15256)
seankane-msft Aug 16, 2021
ee892d5
Merge branch 'main' into track2-tables
seankane-msft Aug 18, 2021
ecb0e72
fixing internal (#15315)
seankane-msft Aug 18, 2021
b1fe68c
Fixes2 (#15316)
seankane-msft Aug 18, 2021
088d5b0
[Tables] bump deps (#15350)
seankane-msft Aug 20, 2021
7e6523f
[Tables] connection string parser (#15187)
seankane-msft Aug 24, 2021
c9c467b
[Tables] simplify code space by moving generated to `internal` module…
seankane-msft Sep 1, 2021
e627020
Merge branch 'main' into track2-tables
seankane-msft Sep 1, 2021
ed6e5b6
[Tables] Docs and cleanup (#15428)
seankane-msft Sep 2, 2021
94396e5
[Tables]Rename package (#15448)
seankane-msft Sep 2, 2021
151ce4b
Merge branch 'main' into track2-tables
seankane-msft Sep 2, 2021
71d5aea
[Tables] Merging internal (#15451)
seankane-msft Sep 2, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion eng/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
},
{
"Name": "internal",
"CoverageGoal": 0.90
"CoverageGoal": 0.70
},
{
"Name": "tables",
"CoverageGoal": 0.01
}
]
}
8 changes: 7 additions & 1 deletion eng/pipelines/templates/steps/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ steps:
displayName: "Install Coverage and Junit Dependencies"
workingDirectory: '${{parameters.GoWorkspace}}'

- template: /eng/common/testproxy/test-proxy-docker.yml

- pwsh: |
$testDirs = (./eng/scripts/get_test_dirs.ps1 -serviceDir $(SCOPE))
foreach ($td in $testDirs) {
Expand All @@ -62,11 +64,15 @@ steps:
workingDirectory: '${{parameters.GoWorkspace}}'
env:
GO111MODULE: 'on'
AZURE_RECORD_MODE: 'playback'
PROXY_CERT: $(Build.SourcesDirectory)/eng/common/testproxy/dotnet-devcert.crt
${{ insert }}: ${{ parameters.EnvVars }}

- pwsh: ../eng/scripts/create_coverage.ps1 ${{parameters.ServiceDirectory}}
displayName: 'Generate Coverage XML'
workingDirectory: '${{parameters.GoWorkspace}}sdk'
env:
GO111MODULE: 'off'

- task: PublishTestResults@2
condition: succeededOrFailed()
Expand All @@ -82,4 +88,4 @@ steps:
codeCoverageTool: Cobertura
summaryFileLocation: '${{parameters.GoWorkspace}}sdk/${{parameters.ServiceDirectory}}/coverage.xml'
additionalCodeCoverageFiles: '${{parameters.GoWorkspace}}sdk/${{parameters.ServiceDirectory}}/coverage.html'
failIfCoverageEmpty: true
failIfCoverageEmpty: true
6 changes: 2 additions & 4 deletions sdk/internal/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ module github.com/Azure/azure-sdk-for-go/sdk/internal
go 1.16

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dnaeon/go-vcr v1.2.0
github.com/dnaeon/go-vcr v1.1.0
github.com/stretchr/testify v1.7.0
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
30 changes: 16 additions & 14 deletions sdk/internal/go.sum
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c=
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
268 changes: 268 additions & 0 deletions sdk/internal/recording/recording.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
package recording

import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
Expand All @@ -16,6 +20,7 @@ import (
"path/filepath"
"strconv"
"strings"
"testing"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
Expand Down Expand Up @@ -433,3 +438,266 @@ var modeMap = map[RecordMode]recorder.Mode{
Live: recorder.ModeDisabled,
Playback: recorder.ModeReplaying,
}

var recordMode, _ = os.LookupEnv("AZURE_RECORD_MODE")
var ModeRecording = "record"
var ModePlayback = "playback"

var baseProxyURLSecure = "localhost:5001"
var baseProxyURL = "localhost:5000"

var recordingId string
var IdHeader = "x-recording-id"
var ModeHeader = "x-recording-mode"
var UpstreamUriHeader = "x-recording-upstream-base-uri"

var tr = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
var client = http.Client{
Transport: tr,
}

type RecordingOptions struct {
MaxRetries int32
UseHTTPS bool
Host string
Scheme string
}

func defaultOptions() *RecordingOptions {
return &RecordingOptions{
MaxRetries: 0,
UseHTTPS: true,
Host: "localhost:5001",
Scheme: "https",
}
}

func (r RecordingOptions) HostScheme() string {
if r.UseHTTPS {
return "https://localhost:5001"
}
return "http://localhost:5000"
}

func getTestId(pathToRecordings string, t *testing.T) string {
return pathToRecordings + "/recordings/" + t.Name() + ".json"
}

func StartRecording(t *testing.T, pathToRecordings string, options *RecordingOptions) error {
if options == nil {
options = defaultOptions()
}
if recordMode == "" {
t.Log("AZURE_RECORD_MODE was not set, options are \"record\" or \"playback\". \nDefaulting to playback")
recordMode = "playback"
} else {
t.Log("AZURE_RECORD_MODE: ", recordMode)
}
testId := getTestId(pathToRecordings, t)

url := fmt.Sprintf("%v/%v/start", options.HostScheme(), recordMode)

req, err := http.NewRequest("POST", url, nil)
if err != nil {
return err
}

req.Header.Set("x-recording-file", testId)

resp, err := client.Do(req)
if err != nil {
return err
}
recordingId = resp.Header.Get(IdHeader)
return nil
}

func StopRecording(t *testing.T, options *RecordingOptions) error {
if options == nil {
options = defaultOptions()
}

url := fmt.Sprintf("%v/%v/stop", options.HostScheme(), recordMode)
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return err
}
if recordingId == "" {
return errors.New("Recording ID was never set. Did you call StartRecording?")
}
req.Header.Set("x-recording-id", recordingId)
_, err = client.Do(req)
if err != nil {
t.Errorf(err.Error())
}
return nil
}

func AddUriSanitizer(replacement, regex string, options *RecordingOptions) error {
if options == nil {
options = defaultOptions()
}
url := fmt.Sprintf("%v/Admin/AddSanitizer", options.HostScheme())
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return err
}
req.Header.Set("x-abstraction-identifier", "UriRegexSanitizer")
bodyContent := map[string]string{
"value": replacement,
"regex": regex,
}
marshalled, err := json.Marshal(bodyContent)
if err != nil {
return err
}
req.Body = ioutil.NopCloser(bytes.NewReader(marshalled))
req.ContentLength = int64(len(marshalled))
_, err = client.Do(req)
return err
}

func (o *RecordingOptions) Init() {
if o.MaxRetries != 0 {
o.MaxRetries = 0
}
if o.UseHTTPS {
o.Host = baseProxyURLSecure
o.Scheme = "https"
} else {
o.Host = baseProxyURL
o.Scheme = "http"
}
}

// type recordingPolicy struct {
// options RecordingOptions
// }

// func NewRecordingPolicy(o *RecordingOptions) azcore.Policy {
// if o == nil {
// o = &RecordingOptions{}
// }
// p := &recordingPolicy{options: *o}
// p.options.init()
// return p
// }

// func (p *recordingPolicy) Do(req *azcore.Request) (resp *azcore.Response, err error) {
// originalURLHost := req.URL.Host
// req.URL.Scheme = "https"
// req.URL.Host = p.options.host
// req.Host = p.options.host

// req.Header.Set(UpstreamUriHeader, fmt.Sprintf("%v://%v", p.options.scheme, originalURLHost))
// req.Header.Set(ModeHeader, recordMode)
// req.Header.Set(IdHeader, recordingId)

// return req.Next()
// }

// This looks up an environment variable and if it is not found, returns the recordedValue
func GetEnvVariable(t *testing.T, varName string, recordedValue string) string {
val, ok := os.LookupEnv(varName)
if !ok {
t.Logf("Could not find environment variable: %v", varName)
return recordedValue
}
return val
}

func LiveOnly(t *testing.T) {
if GetRecordMode() != ModeRecording {
t.Skip("Live Test Only")
}
}

// Function for sleeping during a test for `duration` seconds. This method will only execute when
// AZURE_RECORD_MODE = "record", if a test is running in playback this will be a noop.
func Sleep(duration int) {
if GetRecordMode() == ModeRecording {
time.Sleep(time.Duration(duration) * time.Second)
}
}

func GetRecordingId() string {
return recordingId
}

func GetRecordMode() string {
return recordMode
}

func InPlayback() bool {
return GetRecordMode() == ModePlayback
}

func InRecord() bool {
return GetRecordMode() == ModeRecording
}

// type FakeCredential struct {
// accountName string
// accountKey string
// }

// func NewFakeCredential(accountName, accountKey string) *FakeCredential {
// return &FakeCredential{
// accountName: accountName,
// accountKey: accountKey,
// }
// }

// func (f *FakeCredential) AuthenticationPolicy(azcore.AuthenticationPolicyOptions) azcore.Policy {
// return azcore.PolicyFunc(func(req *azcore.Request) (*azcore.Response, error) {
// authHeader := strings.Join([]string{"Authorization ", f.accountName, ":", f.accountKey}, "")
// req.Request.Header.Set(azcore.HeaderAuthorization, authHeader)
// return req.Next()
// })
// }

func getRootCas() (*x509.CertPool, error) {
localFile, ok := os.LookupEnv("PROXY_CERT")

rootCAs, err := x509.SystemCertPool()
if err != nil {
rootCAs = x509.NewCertPool()
}

if !ok {
fmt.Println("Could not find path to proxy certificate, set the environment variable 'PROXY_CERT' to the location of your certificate")
return rootCAs, nil
}

cert, err := ioutil.ReadFile(localFile)
if err != nil {
fmt.Println("error opening cert file")
return nil, err
}

if ok := rootCAs.AppendCertsFromPEM(cert); !ok {
fmt.Println("No certs appended, using system certs only")
}

return rootCAs, nil
}

func GetHTTPClient() (*http.Client, error) {
transport := http.DefaultTransport.(*http.Transport).Clone()

rootCAs, err := getRootCas()
if err != nil {
return nil, err
}

transport.TLSClientConfig.RootCAs = rootCAs
transport.TLSClientConfig.MinVersion = tls.VersionTLS12
transport.TLSClientConfig.InsecureSkipVerify = true

defaultHttpClient := &http.Client{
Transport: transport,
}
return defaultHttpClient, nil
}
Loading