Repository: Azure/azure-service-bus-go
Pull request #192 (2020-09-28 19:15:41)

Add AzureEnvironment namespace option and use its definition
The namespace connection settings are currently harcoded.
when deployed in different azure environment, Suffix and authentidation resourceURI endpoint need to be configured.
For most cases the autorest environment configuration should work, and should be the default source of truth.
For some special cases, we need to configure it manually.

This allows to use the values set in autorest azure environments, and to override it alltogether if needed by exposing the ResourceURI properties on the Namespace struct.

I think that the autorest environment value for service bus is outdated, and I have opened an issue for it :
https://github.com/Azure/go-autorest/issues/565





Patch:
diff --git a/go.mod b/go.mod
index 0b33260..62f15df 100644
--- a/go.mod
+++ b/go.mod
@@ -6,8 +6,8 @@ require (
 	github.com/Azure/azure-amqp-common-go/v3 v3.0.1
 	github.com/Azure/azure-sdk-for-go v37.1.0+incompatible
 	github.com/Azure/go-amqp v0.13.1
-	github.com/Azure/go-autorest/autorest v0.11.3
-	github.com/Azure/go-autorest/autorest/adal v0.9.1
+	github.com/Azure/go-autorest/autorest v0.11.7
+	github.com/Azure/go-autorest/autorest/adal v0.9.4
 	github.com/Azure/go-autorest/autorest/date v0.3.0
 	github.com/Azure/go-autorest/autorest/to v0.4.0
 	github.com/Azure/go-autorest/autorest/validation v0.3.0 // indirect
diff --git a/go.sum b/go.sum
index c566751..7acc75a 100644
--- a/go.sum
+++ b/go.sum
@@ -9,13 +9,18 @@ github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.11.3 h1:fyYnmYujkIXUgv88D9/Wo2ybE4Zwd/TmQd5sSI5u2Ws=
 github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
+github.com/Azure/go-autorest/autorest v0.11.7 h1:lHnVA0bNUzUw2tYgGiwmOrlBi/VgmaTYfMbsww/7o2A=
+github.com/Azure/go-autorest/autorest v0.11.7/go.mod h1:V6p3pKZx1KKkJubbxnDWrzNhEIfOy/pTGasLqzHIPHs=
 github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
 github.com/Azure/go-autorest/autorest/adal v0.9.1 h1:xjPqigMQe2+0DAJ5A6MLUPp5D2r2Io8qHCuCMMI/yJU=
 github.com/Azure/go-autorest/autorest/adal v0.9.1/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
+github.com/Azure/go-autorest/autorest/adal v0.9.4 h1:1/DtH4Szusk4psLBrJn/gocMRIf1ji30WAz3GfyULRQ=
+github.com/Azure/go-autorest/autorest/adal v0.9.4/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
 github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
 github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
 github.com/Azure/go-autorest/autorest/mocks v0.4.0 h1:z20OWOSG5aCye0HEkDp6TPmP17ZcfeMxPi6HnSALa8c=
 github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
 github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
 github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
 github.com/Azure/go-autorest/autorest/validation v0.3.0 h1:3I9AAI63HfcLtphd9g39ruUwRI+Ca+z/f36KHPFRUss=
diff --git a/namespace.go b/namespace.go
index 619b515..d0dd29a 100644
--- a/namespace.go
+++ b/namespace.go
@@ -52,6 +52,9 @@ const (
 	Version = "0.10.3"
 
 	rootUserAgent = "/golang-service-bus"
+
+	// default ServiceBus resource uri to authenticate with
+	serviceBusResourceURI = "https://servicebus.azure.net/"
 )
 
 type (
@@ -71,10 +74,6 @@ type (
 	NamespaceOption func(h *Namespace) error
 )
 
-const (
-	serviceBusResourceURI = "https://servicebus.azure.net/"
-)
-
 // NamespaceWithConnectionString configures a namespace with the information provided in a Service Bus connection string
 func NamespaceWithConnectionString(connStr string) NamespaceOption {
 	return func(ns *Namespace) error {
@@ -141,7 +140,8 @@ func NamespaceWithEnvironmentBinding(name string) NamespaceOption {
 	return func(ns *Namespace) error {
 		provider, err := aad.NewJWTProvider(
 			aad.JWTProviderWithEnvironmentVars(),
-			aad.JWTProviderWithResourceURI(serviceBusResourceURI),
+			// TODO: fix bug upstream to use environment resourceURI
+			aad.JWTProviderWithResourceURI(ns.getResourceURI()),
 		)
 		if err != nil {
 			return err
@@ -153,6 +153,31 @@ func NamespaceWithEnvironmentBinding(name string) NamespaceOption {
 	}
 }
 
+// NamespaceWithAzureEnvironment sets the namespace's Environment, Suffix and ResourceURI parameters according
+// to the Azure Environment defined in "github.com/Azure/go-autorest/autorest/azure" package.
+// This allows to configure the library to be used in the different Azure clouds.
+// environmentName is the name of the cloud as defined in autorest : https://github.com/Azure/go-autorest/blob/b076c1437d051bf4c328db428b70f4fe22ad38b0/autorest/azure/environments.go#L34-L39
+func NamespaceWithAzureEnvironment(namespaceName, environmentName string) NamespaceOption {
+	return func(ns *Namespace) error {
+		azureEnv, err := azure.EnvironmentFromName(environmentName)
+		if err != nil {
+			return err
+		}
+		ns.Environment = azureEnv
+		ns.Suffix = azureEnv.ServiceBusEndpointSuffix
+		ns.Name = namespaceName
+		return nil
+	}
+}
+
+// NamespaceWithTokenProvider sets the token provider on the namespace
+func NamespaceWithTokenProvider(provider auth.TokenProvider) NamespaceOption {
+	return func(ns *Namespace) error {
+		ns.TokenProvider = provider
+		return nil
+	}
+}
+
 // NewNamespace creates a new namespace configured through NamespaceOption(s)
 func NewNamespace(opts ...NamespaceOption) (*Namespace, error) {
 	ns := &Namespace{
@@ -246,13 +271,16 @@ func (ns *Namespace) getUserAgent() string {
 	return userAgent
 }
 
+func (ns *Namespace) getResourceURI() string {
+	if ns.Environment.ResourceIdentifiers.ServiceBus == "" {
+		return serviceBusResourceURI
+	}
+	return ns.Environment.ResourceIdentifiers.ServiceBus
+}
+
 func (ns *Namespace) resolveSuffix() string {
-	var suffix string
 	if ns.Suffix != "" {
-		suffix = ns.Suffix
-	} else {
-		suffix = azure.PublicCloud.ServiceBusEndpointSuffix
+		return ns.Suffix
 	}
-
-	return suffix
+	return azure.PublicCloud.ServiceBusEndpointSuffix
 }


Test patch:
diff --git a/namespace_test.go b/namespace_test.go
index 3fc5822..178328d 100644
--- a/namespace_test.go
+++ b/namespace_test.go
@@ -30,6 +30,7 @@ import (
 	"time"
 
 	"github.com/Azure/azure-service-bus-go/internal/test"
+	"github.com/Azure/go-autorest/autorest/azure"
 	"github.com/joho/godotenv"
 	"github.com/stretchr/testify/suite"
 )
@@ -58,6 +59,22 @@ func (suite *serviceBusSuite) TestCreateNamespaceFromConnectionString() {
 	}
 }
 
+func TestNewNamespaceWithAzureEnvironment(t *testing.T) {
+	ns, err := NewNamespace(NamespaceWithAzureEnvironment("namespaceName", "AzureGermanCloud"))
+	if err != nil {
+		t.Fatalf("unexpected error creating namespace: %s", err)
+	}
+	if ns.Environment != azure.GermanCloud {
+		t.Fatalf("expected namespace environment to be %q but was %q", azure.GermanCloud, ns.Environment)
+	}
+	if !strings.EqualFold(ns.Suffix, azure.GermanCloud.ServiceBusEndpointSuffix) {
+		t.Fatalf("expected suffix to be %q but was %q", azure.GermanCloud.ServiceBusEndpointSuffix, ns.Suffix)
+	}
+	if ns.Name != "namespaceName" {
+		t.Fatalf("expected namespace name to be %q but was %q", "namespaceName", ns.Name)
+	}
+}
+
 // TearDownSuite destroys created resources during the run of the suite
 func (suite *serviceBusSuite) TearDownSuite() {
 	suite.BaseSuite.TearDownSuite()