Skip to content

Commit

Permalink
Refactor exported, internal public surface area (Azure#17595)
Browse files Browse the repository at this point in the history
* Refactor exported, internal public surface area

Internal packages are used to break circular dependencies.  Some of this
internal content is actually publicly exported via type aliases.  To
make it clear which internal parts are public, they've been moved into
the internal/exported package along with comments indicating from where
they're exposed.
Moved some shared stuff that was just for pollers into internal/pollers.
Added shared.BytesSetter interface to decouple the payload caching from
the underlying implementation.
Moved some non-shared constants around.
Removed unused x-ms-date constant.

* directly export AccessToken, TokenCredential, TokenRequestOptions
  • Loading branch information
jhendrixMSFT committed Apr 15, 2022
1 parent 78fbcfb commit 4413113
Show file tree
Hide file tree
Showing 52 changed files with 525 additions and 494 deletions.
2 changes: 1 addition & 1 deletion sdk/azcore/arm/internal/pollers/async/async.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func New(resp *http.Response, finalState pollers.FinalStateVia, pollerID string)
}
// check for provisioning state
state, err := armpollers.GetProvisioningState(resp)
if errors.Is(err, shared.ErrNoBody) || state == "" {
if errors.Is(err, pollers.ErrNoBody) || state == "" {
// NOTE: the ARM RPC spec explicitly states that for async PUT the initial response MUST
// contain a provisioning state. to maintain compat with track 1 and other implementations
// we are explicitly relaxing this requirement.
Expand Down
5 changes: 2 additions & 3 deletions sdk/azcore/arm/internal/pollers/body/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (

armpollers "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/pollers"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
)

Expand Down Expand Up @@ -50,7 +49,7 @@ func New(resp *http.Response, pollerID string) (*Poller, error) {
// status code and provisioning state, we might change the value.
curState := pollers.StatusInProgress
provState, err := armpollers.GetProvisioningState(resp)
if err != nil && !errors.Is(err, shared.ErrNoBody) {
if err != nil && !errors.Is(err, pollers.ErrNoBody) {
return nil, err
}
if resp.StatusCode == http.StatusCreated && provState != "" {
Expand Down Expand Up @@ -87,7 +86,7 @@ func (p *Poller) Update(resp *http.Response) error {
return nil
}
state, err := armpollers.GetProvisioningState(resp)
if errors.Is(err, shared.ErrNoBody) {
if errors.Is(err, pollers.ErrNoBody) {
// a missing response body in non-204 case is an error
return err
} else if state == "" {
Expand Down
4 changes: 2 additions & 2 deletions sdk/azcore/arm/internal/pollers/body/body_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"strings"
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
)

const (
Expand Down Expand Up @@ -113,7 +113,7 @@ func TestUpdateNoProvStateFail(t *testing.T) {
if err == nil {
t.Fatal("unexpected nil error")
}
if !errors.Is(err, shared.ErrNoBody) {
if !errors.Is(err, pollers.ErrNoBody) {
t.Fatalf("unexpected error type %T", err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion sdk/azcore/arm/internal/pollers/loc/loc.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (p *Poller) Update(resp *http.Response) error {
if runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) {
// if a 200/201 returns a provisioning state, use that instead
state, err := armpollers.GetProvisioningState(resp)
if err != nil && !errors.Is(err, shared.ErrNoBody) {
if err != nil && !errors.Is(err, pollers.ErrNoBody) {
return err
}
if state != "" {
Expand Down
6 changes: 3 additions & 3 deletions sdk/azcore/arm/internal/pollers/pollers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ package pollers
import (
"net/http"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
)

// provisioningState returns the provisioning state from the response or the empty string.
Expand Down Expand Up @@ -50,7 +50,7 @@ func status(jsonBody map[string]interface{}) string {
// Typically used for Azure-AsyncOperation flows.
// If there is no status in the response body the empty string is returned.
func GetStatus(resp *http.Response) (string, error) {
jsonBody, err := shared.GetJSON(resp)
jsonBody, err := pollers.GetJSON(resp)
if err != nil {
return "", err
}
Expand All @@ -60,7 +60,7 @@ func GetStatus(resp *http.Response) (string, error) {
// GetProvisioningState returns the LRO's state from the response body.
// If there is no state in the response body the empty string is returned.
func GetProvisioningState(resp *http.Response) (string, error) {
jsonBody, err := shared.GetJSON(resp)
jsonBody, err := pollers.GetJSON(resp)
if err != nil {
return "", err
}
Expand Down
6 changes: 3 additions & 3 deletions sdk/azcore/arm/internal/pollers/pollers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"strings"
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
)

func TestGetStatusSuccess(t *testing.T) {
Expand All @@ -35,14 +35,14 @@ func TestGetNoBody(t *testing.T) {
Body: http.NoBody,
}
status, err := GetStatus(resp)
if !errors.Is(err, shared.ErrNoBody) {
if !errors.Is(err, pollers.ErrNoBody) {
t.Fatalf("unexpected error %T", err)
}
if status != "" {
t.Fatal("expected empty status")
}
status, err = GetProvisioningState(resp)
if !errors.Is(err, shared.ErrNoBody) {
if !errors.Is(err, pollers.ErrNoBody) {
t.Fatalf("unexpected error %T", err)
}
if status != "" {
Expand Down
13 changes: 6 additions & 7 deletions sdk/azcore/arm/runtime/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,38 @@ import (
"errors"
"reflect"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pipeline"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)

// NewPipeline creates a pipeline from connection options.
// The telemetry policy, when enabled, will use the specified module and version info.
func NewPipeline(module, version string, cred shared.TokenCredential, plOpts azruntime.PipelineOptions, options *arm.ClientOptions) (pipeline.Pipeline, error) {
func NewPipeline(module, version string, cred azcore.TokenCredential, plOpts azruntime.PipelineOptions, options *arm.ClientOptions) (azruntime.Pipeline, error) {
if options == nil {
options = &arm.ClientOptions{}
}
conf, err := getConfiguration(&options.ClientOptions)
if err != nil {
return pipeline.Pipeline{}, err
return azruntime.Pipeline{}, err
}
authPolicy := NewBearerTokenPolicy(cred, &armpolicy.BearerTokenOptions{
Scopes: []string{conf.Audience + "/.default"},
AuxiliaryTenants: options.AuxiliaryTenants,
})
perRetry := make([]pipeline.Policy, 0, len(plOpts.PerRetry)+1)
perRetry := make([]azpolicy.Policy, 0, len(plOpts.PerRetry)+1)
copy(perRetry, plOpts.PerRetry)
plOpts.PerRetry = append(perRetry, authPolicy)
if !options.DisableRPRegistration {
regRPOpts := armpolicy.RegistrationOptions{ClientOptions: options.ClientOptions}
regPolicy, err := NewRPRegistrationPolicy(cred, &regRPOpts)
if err != nil {
return pipeline.Pipeline{}, err
return azruntime.Pipeline{}, err
}
perCall := make([]pipeline.Policy, 0, len(plOpts.PerCall)+1)
perCall := make([]azpolicy.Policy, 0, len(plOpts.PerCall)+1)
copy(perCall, plOpts.PerCall)
plOpts.PerCall = append(perCall, regPolicy)
}
Expand Down
6 changes: 3 additions & 3 deletions sdk/azcore/arm/runtime/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
"testing"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/log"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
Expand Down Expand Up @@ -179,15 +179,15 @@ func TestPipelineAudience(t *testing.T) {
t.Fatal("unexpected audience " + audience)
}
getTokenCalled := false
cred := mockCredential{getTokenImpl: func(ctx context.Context, options shared.TokenRequestOptions) (*shared.AccessToken, error) {
cred := mockCredential{getTokenImpl: func(ctx context.Context, options policy.TokenRequestOptions) (*azcore.AccessToken, error) {
getTokenCalled = true
if n := len(options.Scopes); n != 1 {
t.Fatalf("expected 1 scope, got %d", n)
}
if options.Scopes[0] != audience+"/.default" {
t.Fatalf(`unexpected scope "%s"`, options.Scopes[0])
}
return &shared.AccessToken{Token: "...", ExpiresOn: time.Now().Add(time.Hour)}, nil
return &azcore.AccessToken{Token: "...", ExpiresOn: time.Now().Add(time.Hour)}, nil
}}
req, err := azruntime.NewRequest(context.Background(), http.MethodGet, srv.URL())
if err != nil {
Expand Down
15 changes: 8 additions & 7 deletions sdk/azcore/arm/runtime/policy_bearer_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
Expand All @@ -23,8 +24,8 @@ type acquiringResourceState struct {

// acquire acquires or updates the resource; only one
// thread/goroutine at a time ever calls this function
func acquire(state acquiringResourceState) (newResource *shared.AccessToken, newExpiration time.Time, err error) {
tk, err := state.p.cred.GetToken(state.ctx, shared.TokenRequestOptions{
func acquire(state acquiringResourceState) (newResource *azcore.AccessToken, newExpiration time.Time, err error) {
tk, err := state.p.cred.GetToken(state.ctx, azpolicy.TokenRequestOptions{
Scopes: state.p.options.Scopes,
TenantID: state.tenant,
})
Expand All @@ -37,18 +38,18 @@ func acquire(state acquiringResourceState) (newResource *shared.AccessToken, new
// BearerTokenPolicy authorizes requests with bearer tokens acquired from a TokenCredential.
type BearerTokenPolicy struct {
// mainResource is the resource to be retreived using the tenant specified in the credential
mainResource *shared.ExpiringResource[*shared.AccessToken, acquiringResourceState]
mainResource *shared.ExpiringResource[*azcore.AccessToken, acquiringResourceState]
// auxResources are additional resources that are required for cross-tenant applications
auxResources map[string]*shared.ExpiringResource[*shared.AccessToken, acquiringResourceState]
auxResources map[string]*shared.ExpiringResource[*azcore.AccessToken, acquiringResourceState]
// the following fields are read-only
cred shared.TokenCredential
cred azcore.TokenCredential
options armpolicy.BearerTokenOptions
}

// NewBearerTokenPolicy creates a policy object that authorizes requests with bearer tokens.
// cred: an azcore.TokenCredential implementation such as a credential object from azidentity
// opts: optional settings. Pass nil to accept default values; this is the same as passing a zero-value options.
func NewBearerTokenPolicy(cred shared.TokenCredential, opts *armpolicy.BearerTokenOptions) *BearerTokenPolicy {
func NewBearerTokenPolicy(cred azcore.TokenCredential, opts *armpolicy.BearerTokenOptions) *BearerTokenPolicy {
if opts == nil {
opts = &armpolicy.BearerTokenOptions{}
}
Expand All @@ -58,7 +59,7 @@ func NewBearerTokenPolicy(cred shared.TokenCredential, opts *armpolicy.BearerTok
mainResource: shared.NewExpiringResource(acquire),
}
if len(opts.AuxiliaryTenants) > 0 {
p.auxResources = map[string]*shared.ExpiringResource[*shared.AccessToken, acquiringResourceState]{}
p.auxResources = map[string]*shared.ExpiringResource[*azcore.AccessToken, acquiringResourceState]{}
}
for _, t := range opts.AuxiliaryTenants {
p.auxResources[t] = shared.NewExpiringResource(acquire)
Expand Down
19 changes: 10 additions & 9 deletions sdk/azcore/arm/runtime/policy_bearer_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import (
"testing"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pipeline"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
azpolicy "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/mock"
Expand All @@ -29,14 +30,14 @@ const (
)

type mockCredential struct {
getTokenImpl func(ctx context.Context, options shared.TokenRequestOptions) (*shared.AccessToken, error)
getTokenImpl func(ctx context.Context, options policy.TokenRequestOptions) (*azcore.AccessToken, error)
}

func (mc mockCredential) GetToken(ctx context.Context, options shared.TokenRequestOptions) (*shared.AccessToken, error) {
func (mc mockCredential) GetToken(ctx context.Context, options policy.TokenRequestOptions) (*azcore.AccessToken, error) {
if mc.getTokenImpl != nil {
return mc.getTokenImpl(ctx, options)
}
return &shared.AccessToken{Token: "***", ExpiresOn: time.Now().Add(time.Hour)}, nil
return &azcore.AccessToken{Token: "***", ExpiresOn: time.Now().Add(time.Hour)}, nil
}

func (mc mockCredential) NewAuthenticationPolicy() azpolicy.Policy {
Expand All @@ -47,11 +48,11 @@ func (mc mockCredential) Do(req *azpolicy.Request) (*http.Response, error) {
return nil, nil
}

func newTestPipeline(opts *azpolicy.ClientOptions) pipeline.Pipeline {
func newTestPipeline(opts *azpolicy.ClientOptions) runtime.Pipeline {
return runtime.NewPipeline("testmodule", "v0.1.0", runtime.PipelineOptions{}, opts)
}

func defaultTestPipeline(srv azpolicy.Transporter, scope string) (pipeline.Pipeline, error) {
func defaultTestPipeline(srv azpolicy.Transporter, scope string) (runtime.Pipeline, error) {
retryOpts := azpolicy.RetryOptions{
MaxRetryDelay: 500 * time.Millisecond,
RetryDelay: time.Millisecond,
Expand Down Expand Up @@ -97,7 +98,7 @@ func TestBearerPolicy_CredentialFailGetToken(t *testing.T) {
defer close()
expectedErr := errors.New("oops")
failCredential := mockCredential{}
failCredential.getTokenImpl = func(ctx context.Context, options shared.TokenRequestOptions) (*shared.AccessToken, error) {
failCredential.getTokenImpl = func(ctx context.Context, options policy.TokenRequestOptions) (*azcore.AccessToken, error) {
return nil, expectedErr
}
b := NewBearerTokenPolicy(failCredential, nil)
Expand Down Expand Up @@ -156,7 +157,7 @@ func TestBearerPolicy_GetTokenFailsNoDeadlock(t *testing.T) {
MaxRetries: 3,
}
b := NewBearerTokenPolicy(mockCredential{}, nil)
pipeline := newTestPipeline(&azpolicy.ClientOptions{Transport: srv, Retry: retryOpts, PerRetryPolicies: []pipeline.Policy{b}})
pipeline := newTestPipeline(&azpolicy.ClientOptions{Transport: srv, Retry: retryOpts, PerRetryPolicies: []azpolicy.Policy{b}})
req, err := runtime.NewRequest(context.Background(), http.MethodGet, srv.URL())
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -189,7 +190,7 @@ func TestBearerTokenWithAuxiliaryTenants(t *testing.T) {
AuxiliaryTenants: []string{"tenant1", "tenant2", "tenant3"},
},
)
pipeline := newTestPipeline(&azpolicy.ClientOptions{Transport: srv, Retry: retryOpts, PerRetryPolicies: []pipeline.Policy{b}})
pipeline := newTestPipeline(&azpolicy.ClientOptions{Transport: srv, Retry: retryOpts, PerRetryPolicies: []azpolicy.Policy{b}})
req, err := runtime.NewRequest(context.Background(), http.MethodGet, srv.URL())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
Expand Down
15 changes: 8 additions & 7 deletions sdk/azcore/arm/runtime/policy_register_rp.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import (
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pipeline"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
Expand Down Expand Up @@ -49,7 +50,7 @@ func setDefaults(r *armpolicy.RegistrationOptions) {
// NewRPRegistrationPolicy creates a policy object configured using the specified options.
// The policy controls whether an unregistered resource provider should automatically be
// registered. See https://aka.ms/rps-not-found for more information.
func NewRPRegistrationPolicy(cred shared.TokenCredential, o *armpolicy.RegistrationOptions) (azpolicy.Policy, error) {
func NewRPRegistrationPolicy(cred azcore.TokenCredential, o *armpolicy.RegistrationOptions) (azpolicy.Policy, error) {
if o == nil {
o = &armpolicy.RegistrationOptions{}
}
Expand All @@ -60,7 +61,7 @@ func NewRPRegistrationPolicy(cred shared.TokenCredential, o *armpolicy.Registrat
authPolicy := NewBearerTokenPolicy(cred, &armpolicy.BearerTokenOptions{Scopes: []string{conf.Audience + "/.default"}})
p := &rpRegistrationPolicy{
endpoint: conf.Endpoint,
pipeline: runtime.NewPipeline(shared.Module, shared.Version, runtime.PipelineOptions{PerRetry: []pipeline.Policy{authPolicy}}, &o.ClientOptions),
pipeline: runtime.NewPipeline(shared.Module, shared.Version, runtime.PipelineOptions{PerRetry: []azpolicy.Policy{authPolicy}}, &o.ClientOptions),
options: *o,
}
// init the copy
Expand All @@ -70,7 +71,7 @@ func NewRPRegistrationPolicy(cred shared.TokenCredential, o *armpolicy.Registrat

type rpRegistrationPolicy struct {
endpoint string
pipeline pipeline.Pipeline
pipeline runtime.Pipeline
options armpolicy.RegistrationOptions
}

Expand Down Expand Up @@ -207,7 +208,7 @@ type serviceErrorDetails struct {
///////////////////////////////////////////////////////////////////////////////////////////////

type providersOperations struct {
p pipeline.Pipeline
p runtime.Pipeline
u string
subID string
}
Expand Down Expand Up @@ -247,7 +248,7 @@ func (client *providersOperations) getCreateRequest(ctx context.Context, resourc
// getHandleResponse handles the Get response.
func (client *providersOperations) getHandleResponse(resp *http.Response) (*ProviderResponse, error) {
if !runtime.HasStatusCode(resp, http.StatusOK) {
return nil, shared.NewResponseError(resp)
return nil, exported.NewResponseError(resp)
}
result := ProviderResponse{RawResponse: resp}
err := runtime.UnmarshalAsJSON(resp, &result.Provider)
Expand Down Expand Up @@ -292,7 +293,7 @@ func (client *providersOperations) registerCreateRequest(ctx context.Context, re
// registerHandleResponse handles the Register response.
func (client *providersOperations) registerHandleResponse(resp *http.Response) (*ProviderResponse, error) {
if !runtime.HasStatusCode(resp, http.StatusOK) {
return nil, shared.NewResponseError(resp)
return nil, exported.NewResponseError(resp)
}
result := ProviderResponse{RawResponse: resp}
err := runtime.UnmarshalAsJSON(resp, &result.Provider)
Expand Down

0 comments on commit 4413113

Please sign in to comment.