Skip to content

Commit

Permalink
Adding data source subscription(s), new subscription client
Browse files Browse the repository at this point in the history
  • Loading branch information
rkhaled0 committed Mar 14, 2022
1 parent 1950f33 commit b603899
Show file tree
Hide file tree
Showing 23 changed files with 2,129 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .teamcity/components/generated/services.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ var services = mapOf(
"loadbalancer" to "Load Balancer",
"network" to "Network",
"resource" to "Resources",
"storage" to "Storage"
"storage" to "Storage",
"subscription" to "Subscription"
)
3 changes: 3 additions & 0 deletions internal/clients/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
network "github.com/hashicorp/terraform-provider-azurestack/internal/services/network/client"
resource "github.com/hashicorp/terraform-provider-azurestack/internal/services/resource/client"
storage "github.com/hashicorp/terraform-provider-azurestack/internal/services/storage/client"
subscription "github.com/hashicorp/terraform-provider-azurestack/internal/services/subscription/client"
)

type Client struct {
Expand All @@ -28,6 +29,7 @@ type Client struct {
Network *network.Client
Resource *resource.Client
Storage *storage.Client
Subscription *subscription.Client

Features features.UserFeatures
}
Expand All @@ -48,6 +50,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error
client.Network = network.NewClient(o)
client.Resource = resource.NewClient(o)
client.Storage = storage.NewClient(o)
client.Subscription = subscription.NewClient(o)

return nil
}
2 changes: 2 additions & 0 deletions internal/provider/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/hashicorp/terraform-provider-azurestack/internal/services/network"
"github.com/hashicorp/terraform-provider-azurestack/internal/services/resource"
"github.com/hashicorp/terraform-provider-azurestack/internal/services/storage"
"github.com/hashicorp/terraform-provider-azurestack/internal/services/subscription"
"github.com/hashicorp/terraform-provider-azurestack/internal/tf/sdk"
)

Expand All @@ -22,6 +23,7 @@ func SupportedUntypedServices() []sdk.UntypedServiceRegistration {
network.Registration{},
resource.Registration{},
storage.Registration{},
subscription.Registration{},
}
}

Expand Down
19 changes: 19 additions & 0 deletions internal/services/subscription/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-11-01/subscriptions"
"github.com/hashicorp/terraform-provider-azurestack/internal/common"
)

type Client struct {
Client *subscriptions.Client
}

func NewClient(o *common.ClientOptions) *Client {
client := subscriptions.NewClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)

return &Client{
Client: &client,
}
}
82 changes: 82 additions & 0 deletions internal/services/subscription/data_source_subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package subscription

import (
"fmt"
"time"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurestack/internal/az/tags"
"github.com/hashicorp/terraform-provider-azurestack/internal/clients"
"github.com/hashicorp/terraform-provider-azurestack/internal/tf/timeouts"
"github.com/hashicorp/terraform-provider-azurestack/internal/utils"
)

func dataSourceSubscription() *schema.Resource {
return &schema.Resource{
Read: dataSourceSubscriptionRead,
Timeouts: &schema.ResourceTimeout{
Read: schema.DefaultTimeout(5 * time.Minute),
},
Schema: map[string]*schema.Schema{
"subscription_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"tenant_id": {
Type: schema.TypeString,
Computed: true,
},

"display_name": {
Type: schema.TypeString,
Computed: true,
},

"state": {
Type: schema.TypeString,
Computed: true,
},

"location_placement_id": {
Type: schema.TypeString,
Computed: true,
},

"tags": tags.SchemaDataSource(),
},
}
}

func dataSourceSubscriptionRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client)
groupClient := client.Subscription.Client
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

subscriptionId := d.Get("subscription_id").(string)
if subscriptionId == "" {
subscriptionId = client.Account.SubscriptionId
}

resp, err := groupClient.Get(ctx, subscriptionId)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Error: default tags for Subscription %q was not found", subscriptionId)
}

return fmt.Errorf("Error reading default tags for Subscription: %+v", err)
}

d.SetId(*resp.ID)
d.Set("subscription_id", resp.SubscriptionID)
d.Set("display_name", resp.DisplayName)
d.Set("tenant_id", resp.TenantID)
d.Set("state", resp.State)
if resp.SubscriptionPolicies != nil {
d.Set("location_placement_id", resp.SubscriptionPolicies.LocationPlacementID)
}

return tags.FlattenAndSet(d, resp.Tags)
}
67 changes: 67 additions & 0 deletions internal/services/subscription/data_source_subscription_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package subscription_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-azurestack/internal/tf/acceptance"
"github.com/hashicorp/terraform-provider-azurestack/internal/tf/acceptance/check"
)

type SubscriptionDataSource struct{}

func TestAccDataSourceSubscription_current(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurestack_subscription", "current")

data.DataSourceTest(t, []resource.TestStep{
{
Config: SubscriptionDataSource{}.currentConfig(),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("subscription_id").HasValue(data.Client().SubscriptionID),
check.That(data.ResourceName).Key("display_name").Exists(),
check.That(data.ResourceName).Key("tenant_id").Exists(),
check.That(data.ResourceName).Key("state").HasValue("Enabled"),
),
},
})
}

func TestAccDataSourceSubscription_specific(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurestack_subscription", "specific")

data.DataSourceTest(t, []resource.TestStep{
{
Config: SubscriptionDataSource{}.specificConfig(data.Client().SubscriptionID),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("subscription_id").HasValue(data.Client().SubscriptionID),
check.That(data.ResourceName).Key("display_name").Exists(),
check.That(data.ResourceName).Key("tenant_id").Exists(),
check.That(data.ResourceName).Key("location_placement_id").Exists(),
),
},
})
}

func (d SubscriptionDataSource) currentConfig() string {
return `
provider "azurestack" {
features {}
}
data "azurestack_subscription" "current" {}
`
}

func (d SubscriptionDataSource) specificConfig(subscriptionId string) string {
return fmt.Sprintf(`
provider "azurestack" {
features {}
subscription_id = "%s"
}
data "azurestack_subscription" "specific" {
subscription_id = "%s"
}
`, subscriptionId, subscriptionId)
}
148 changes: 148 additions & 0 deletions internal/services/subscription/data_source_subscriptions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package subscription

import (
"fmt"
"strings"
"time"

"github.com/hashicorp/terraform-provider-azurestack/internal/az/tags"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurestack/internal/clients"
"github.com/hashicorp/terraform-provider-azurestack/internal/tf/timeouts"
)

func dataSourceSubscriptions() *schema.Resource {
return &schema.Resource{
Read: dataSourceSubscriptionsRead,

Timeouts: &schema.ResourceTimeout{
Read: schema.DefaultTimeout(5 * time.Minute),
},

Schema: map[string]*schema.Schema{
"display_name_prefix": {
Type: schema.TypeString,
Optional: true,
},
"display_name_contains": {
Type: schema.TypeString,
Optional: true,
},
"subscriptions": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},

"subscription_id": {
Type: schema.TypeString,
Computed: true,
},

"tenant_id": {
Type: schema.TypeString,
Computed: true,
},

"display_name": {
Type: schema.TypeString,
Computed: true,
},

"state": {
Type: schema.TypeString,
Computed: true,
},

"location_placement_id": {
Type: schema.TypeString,
Computed: true,
},

"tags": tags.SchemaDataSource(),
},
},
},
},
}
}

func dataSourceSubscriptionsRead(d *schema.ResourceData, meta interface{}) error {
armClient := meta.(*clients.Client)
subClient := armClient.Subscription.Client
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

displayNamePrefix := strings.ToLower(d.Get("display_name_prefix").(string))
displayNameContains := strings.ToLower(d.Get("display_name_contains").(string))

// ListComplete returns an iterator struct
results, err := subClient.ListComplete(ctx)
if err != nil {
return fmt.Errorf("Error listing subscriptions: %+v", err)
}

// iterate across each subscriptions and append them to slice
subscriptions := make([]map[string]interface{}, 0)
for results.NotDone() {
val := results.Value()

s := make(map[string]interface{})

if v := val.ID; v != nil {
s["id"] = *v
}
if v := val.SubscriptionID; v != nil {
s["subscription_id"] = *v
}
if v := val.TenantID; v != nil {
s["tenant_id"] = *v
}
if v := val.DisplayName; v != nil {
s["display_name"] = *v
}
s["state"] = string(val.State)

if policies := val.SubscriptionPolicies; policies != nil {
if v := policies.LocationPlacementID; v != nil {
s["location_placement_id"] = *v
}
}

if err = results.Next(); err != nil {
return fmt.Errorf("Error going to next subscriptions value: %+v", err)
}

// check if the display name prefix matches the given input
if displayNamePrefix != "" {
if !strings.HasPrefix(strings.ToLower(s["display_name"].(string)), displayNamePrefix) {
// the display name does not match the given prefix
continue
}
}

// check if the display name matches the 'contains' comparison
if displayNameContains != "" {
if !strings.Contains(strings.ToLower(s["display_name"].(string)), displayNameContains) {
// the display name does not match the contains check
continue
}
}

s["tags"] = tags.Flatten(val.Tags)

subscriptions = append(subscriptions, s)
}

d.SetId("subscriptions-" + armClient.Account.TenantId)
if err = d.Set("subscriptions", subscriptions); err != nil {
return fmt.Errorf("Error setting `subscriptions`: %+v", err)
}

return nil
}
Loading

0 comments on commit b603899

Please sign in to comment.