diff --git a/azurerm/internal/services/resource/client/client.go b/azurerm/internal/services/resource/client/client.go index 93b6411c88361..79d75c88bb6c1 100644 --- a/azurerm/internal/services/resource/client/client.go +++ b/azurerm/internal/services/resource/client/client.go @@ -3,6 +3,7 @@ package client import ( providers "github.com/Azure/azure-sdk-for-go/profiles/2017-03-09/resources/mgmt/resources" "github.com/Azure/azure-sdk-for-go/services/preview/resources/mgmt/2019-06-01-preview/templatespecs" + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-09-01/locks" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-06-01/resources" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common" @@ -10,6 +11,7 @@ import ( type Client struct { DeploymentsClient *resources.DeploymentsClient + FeaturesClient *features.Client GroupsClient *resources.GroupsClient LocksClient *locks.ManagementLocksClient ProvidersClient *providers.ProvidersClient @@ -22,6 +24,9 @@ func NewClient(o *common.ClientOptions) *Client { deploymentsClient := resources.NewDeploymentsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&deploymentsClient.Client, o.ResourceManagerAuthorizer) + featuresClient := features.NewClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&featuresClient.Client, o.ResourceManagerAuthorizer) + groupsClient := resources.NewGroupsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&groupsClient.Client, o.ResourceManagerAuthorizer) @@ -45,6 +50,7 @@ func NewClient(o *common.ClientOptions) *Client { return &Client{ GroupsClient: &groupsClient, DeploymentsClient: &deploymentsClient, + FeaturesClient: &featuresClient, LocksClient: &locksClient, ProvidersClient: &providersClient, ResourceProvidersClient: &resourceProvidersClient, diff --git a/azurerm/internal/services/resource/feature_resource.go b/azurerm/internal/services/resource/feature_resource.go new file mode 100644 index 0000000000000..f32aade90ecbd --- /dev/null +++ b/azurerm/internal/services/resource/feature_resource.go @@ -0,0 +1,198 @@ +package resource + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" +) + +const ( + Pending = "Pending" + Registering = "Registering" + Unregistering = "Unregistering" + Registered = "Registered" + NotRegistered = "NotRegistered" + Unregistered = "Unregistered" +) + +func resourceFeature() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceFeatureCreate, + Read: resourceFeatureRead, + Delete: resourceFeatureDelete, + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.FeatureID(id) + return err + }), + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(30 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "provider_namespace": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + } +} + +func resourceFeatureCreate(d *pluginsdk.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + client := meta.(*clients.Client).Resource.FeaturesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + providerNamespace := d.Get("provider_namespace").(string) + id := parse.NewFeatureID(subscriptionId, providerNamespace, name) + + existing, err := client.Get(ctx, id.ProviderNamespace, id.Name) + if err != nil { + return fmt.Errorf("error checking for existing feature %q: %+v", id, err) + } + + if existing.Properties != nil && existing.Properties.State != nil { + if strings.EqualFold(*existing.Properties.State, Pending) { + return fmt.Errorf("feature (%q) which requires manual approval should not be managed by terraform", id) + } + if !strings.EqualFold(*existing.Properties.State, NotRegistered) && !strings.EqualFold(*existing.Properties.State, Unregistered) { + return tf.ImportAsExistsError("azurerm_feature", id.ID()) + } + } + + resp, err := client.Register(ctx, id.ProviderNamespace, id.Name) + if err != nil { + return fmt.Errorf("error registering feature %q: %+v", id, err) + } + + if resp.Properties != nil && resp.Properties.State != nil { + if strings.EqualFold(*resp.Properties.State, Pending) { + return fmt.Errorf("feature (%q) which requires manual approval can not be managed by terraform", id) + } + } + + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("context had no deadline") + } + stateConf := &pluginsdk.StateChangeConf{ + Pending: []string{Registering}, + Target: []string{Registered}, + Refresh: featureRegisteringStateRefreshFunc(ctx, client, id), + MinTimeout: 3 * time.Minute, + Timeout: time.Until(deadline), + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for BackupInstance(%q) policy protection to be completed: %+v", id, err) + } + + d.SetId(id.ID()) + + return resourceFeatureRead(d, meta) +} + +func resourceFeatureRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Resource.FeaturesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.FeatureID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ProviderNamespace, id.Name) + if err != nil { + return fmt.Errorf("error retrieving feature %q: %+v", id, err) + } + if resp.Properties != nil && resp.Properties.State != nil { + if strings.EqualFold(*resp.Properties.State, Pending) { + return fmt.Errorf("feature (%q) which requires manual approval can not be managed by terraform", id) + } + if !strings.EqualFold(*resp.Properties.State, Registered) { + return fmt.Errorf("feature (%q) is not registered", id) + } + } + + d.Set("name", id.Name) + d.Set("provider_namespace", id.ProviderNamespace) + return nil +} + +func resourceFeatureDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Resource.FeaturesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.FeatureID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Unregister(ctx, id.ProviderNamespace, id.Name) + if err != nil { + return fmt.Errorf("error unregistering feature %q: %+v", id, err) + } + + if resp.Properties != nil && resp.Properties.State != nil { + if strings.EqualFold(*resp.Properties.State, Pending) { + return fmt.Errorf("feature (%q) which requires manual approval can not be managed by terraform", id) + } + } + + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("context had no deadline") + } + stateConf := &pluginsdk.StateChangeConf{ + Pending: []string{Unregistering}, + Target: []string{NotRegistered, Unregistered}, + Refresh: featureRegisteringStateRefreshFunc(ctx, client, *id), + MinTimeout: 3 * time.Minute, + Timeout: time.Until(deadline), + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for BackupInstance(%q) policy protection to be completed: %+v", id, err) + } + + return nil +} + +func featureRegisteringStateRefreshFunc(ctx context.Context, client *features.Client, id parse.FeatureId) pluginsdk.StateRefreshFunc { + return func() (interface{}, string, error) { + res, err := client.Get(ctx, id.ProviderNamespace, id.Name) + if err != nil { + return nil, "", fmt.Errorf("retrieving feature (%q): %+v", id, err) + } + if res.Properties == nil || res.Properties.State == nil { + return nil, "", fmt.Errorf("error reading feature (%q) registering status: %+v", id, err) + } + + return res, *res.Properties.State, nil + } +} diff --git a/azurerm/internal/services/resource/feature_resource_test.go b/azurerm/internal/services/resource/feature_resource_test.go new file mode 100644 index 0000000000000..6e1555ca0b178 --- /dev/null +++ b/azurerm/internal/services/resource/feature_resource_test.go @@ -0,0 +1,104 @@ +package resource_test + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance/check" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +type FeatureResource struct { +} + +func TestAccFeatureResource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_feature", "test") + r := FeatureResource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.basic(), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + }) +} + +func TestAccDataProtectionBackupVault_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_feature", "test") + r := FeatureResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.requiresImportBasic(), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func (r FeatureResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.FeatureID(state.ID) + if err != nil { + return nil, err + } + resp, err := client.Resource.FeaturesClient.Get(ctx, id.ProviderNamespace, id.Name) + if err != nil { + return nil, fmt.Errorf("error retrieving feature %q: %+v", id, err) + } + if resp.Properties != nil && resp.Properties.State != nil { + if strings.EqualFold(*resp.Properties.State, "Pending") { + return nil, fmt.Errorf("feature (%q) which requires manual approval can not be managed by terraform", id) + } + if !strings.EqualFold(*resp.Properties.State, "Registered") { + return utils.Bool(false), nil + } + } + return utils.Bool(true), nil +} + +func (r FeatureResource) basic() string { + return ` +provider "azurerm" { + features {} +} + +resource "azurerm_feature" "test" { + name = "AutoApproveFeature" + provider_namespace = "Microsoft.CognitiveServices" +} +` +} + +func (r FeatureResource) requiresImportBasic() string { + return ` +provider "azurerm" { + features {} +} + +resource "azurerm_feature" "test" { + name = "AllowManagedDisksReplaceOSDisk" + provider_namespace = "Microsoft.Compute" +} +` +} + +func (r FeatureResource) requiresImport(data acceptance.TestData) string { + config := r.requiresImportBasic() + return fmt.Sprintf(` +%s + +resource "azurerm_feature" "import" { + name = azurerm_feature.test.name + provider_namespace = azurerm_feature.test.provider_namespace +} +`, config) +} diff --git a/azurerm/internal/services/resource/parse/feature.go b/azurerm/internal/services/resource/parse/feature.go new file mode 100644 index 0000000000000..118fea50daef8 --- /dev/null +++ b/azurerm/internal/services/resource/parse/feature.go @@ -0,0 +1,66 @@ +package parse + +import ( + "fmt" + "strings" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type FeatureId struct { + SubscriptionId string + ProviderNamespace string + Name string +} + +func NewFeatureID(subscriptionId, resourceProvider, name string) FeatureId { + return FeatureId{ + SubscriptionId: subscriptionId, + ProviderNamespace: resourceProvider, + Name: name, + } +} + +func (id FeatureId) String() string { + segments := []string{ + fmt.Sprintf("Name %q", id.Name), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Feature", segmentsStr) +} + +func (id FeatureId) ID() string { + fmtString := "/subscriptions/%s/providers/Microsoft.Features/providers/%s/features/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ProviderNamespace, id.Name) +} + +// FeatureID parses a Feature ID into an FeatureId struct +func FeatureID(input string) (*FeatureId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := FeatureId{ + SubscriptionId: id.SubscriptionID, + ProviderNamespace: id.SecondaryProvider, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ProviderNamespace == "" { + return nil, fmt.Errorf("ID was missing the 'providers' element") + } + + if resourceId.Name, err = id.PopSegment("features"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/azurerm/internal/services/resource/parse/feature_test.go b/azurerm/internal/services/resource/parse/feature_test.go new file mode 100644 index 0000000000000..4d33d7e1e9add --- /dev/null +++ b/azurerm/internal/services/resource/parse/feature_test.go @@ -0,0 +1,95 @@ +package parse + +import ( + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid" +) + +var _ resourceid.Formatter = FeatureId{} + +func TestFeatureIDFormatter(t *testing.T) { + actual := NewFeatureID("12345678-1234-9876-4563-123456789012", "Microsoft.Test", "Feature1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/Microsoft.Test/features/Feature1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestFeatureID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *FeatureId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/provider1/", + Error: true, + }, + + { + // missing value for Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/provider1/features/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/provider1/features/Feature1", + Expected: &FeatureId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ProviderNamespace: "provider1", + Name: "Feature1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/PROVIDERS/MICROSOFT.FEATURES/PROVIDERS/PROVIDER1/FEATURES/FEATURE1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := FeatureID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + } +} diff --git a/azurerm/internal/services/resource/registration.go b/azurerm/internal/services/resource/registration.go index 0af28a060f633..4143a075076ea 100644 --- a/azurerm/internal/services/resource/registration.go +++ b/azurerm/internal/services/resource/registration.go @@ -36,6 +36,7 @@ func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ + "azurerm_feature": resourceFeature(), "azurerm_management_lock": resourceManagementLock(), "azurerm_management_group_template_deployment": managementGroupTemplateDeploymentResource(), "azurerm_resource_group": resourceResourceGroup(), diff --git a/azurerm/internal/services/resource/validate/feature_id.go b/azurerm/internal/services/resource/validate/feature_id.go new file mode 100644 index 0000000000000..54919f8e12d4e --- /dev/null +++ b/azurerm/internal/services/resource/validate/feature_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/resource/parse" +) + +func FeatureID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := parse.FeatureID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/azurerm/internal/services/resource/validate/feature_id_test.go b/azurerm/internal/services/resource/validate/feature_id_test.go new file mode 100644 index 0000000000000..b283aef598103 --- /dev/null +++ b/azurerm/internal/services/resource/validate/feature_id_test.go @@ -0,0 +1,64 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestFeatureID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/provider1/", + Valid: false, + }, + + { + // missing value for Name + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/provider1/features/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/providers/Microsoft.Features/providers/provider1/features/Feature1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/PROVIDERS/MICROSOFT.FEATURES/PROVIDERS/PROVIDER1/FEATURES/FEATURE1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := FeatureID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/CHANGELOG.md new file mode 100644 index 0000000000000..52911e4cc5e4c --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/CHANGELOG.md @@ -0,0 +1,2 @@ +# Change History + diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/_meta.json b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/_meta.json new file mode 100644 index 0000000000000..eeb401a2e66fc --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/_meta.json @@ -0,0 +1,11 @@ +{ + "commit": "3c764635e7d442b3e74caf593029fcd440b3ef82", + "readme": "/_/azure-rest-api-specs/specification/resources/resource-manager/readme.md", + "tag": "package-features-2015-12", + "use": "@microsoft.azure/autorest.go@2.1.183", + "repository_url": "https://github.com/Azure/azure-rest-api-specs.git", + "autorest_command": "autorest --use=@microsoft.azure/autorest.go@2.1.183 --tag=package-features-2015-12 --go-sdk-folder=/_/azure-sdk-for-go --go --verbose --use-onever --version=V2 --go.license-header=MICROSOFT_MIT_NO_VERSION /_/azure-rest-api-specs/specification/resources/resource-manager/readme.md", + "additional_properties": { + "additional_options": "--go --verbose --use-onever --version=V2 --go.license-header=MICROSOFT_MIT_NO_VERSION" + } +} \ No newline at end of file diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/client.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/client.go new file mode 100644 index 0000000000000..511547962d331 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/client.go @@ -0,0 +1,157 @@ +// Package features implements the Azure ARM Features service API version 2015-12-01. +// +// Azure Feature Exposure Control (AFEC) provides a mechanism for the resource providers to control feature exposure to +// users. Resource providers typically use this mechanism to provide public/private preview for new features prior to +// making them generally available. Users need to explicitly register for AFEC features to get access to such +// functionality. +package features + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +const ( + // DefaultBaseURI is the default URI used for the service Features + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Features. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client using a custom endpoint. Use this when interacting with +// an Azure cloud that uses a non-standard base URI (sovereign clouds, Azure stack). +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} + +// ListOperations lists all of the available Microsoft.Features REST API operations. +func (client BaseClient) ListOperations(ctx context.Context) (result OperationListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/BaseClient.ListOperations") + defer func() { + sc := -1 + if result.olr.Response.Response != nil { + sc = result.olr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listOperationsNextResults + req, err := client.ListOperationsPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "features.BaseClient", "ListOperations", nil, "Failure preparing request") + return + } + + resp, err := client.ListOperationsSender(req) + if err != nil { + result.olr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "features.BaseClient", "ListOperations", resp, "Failure sending request") + return + } + + result.olr, err = client.ListOperationsResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.BaseClient", "ListOperations", resp, "Failure responding to request") + return + } + if result.olr.hasNextLink() && result.olr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListOperationsPreparer prepares the ListOperations request. +func (client BaseClient) ListOperationsPreparer(ctx context.Context) (*http.Request, error) { + const APIVersion = "2015-12-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/providers/Microsoft.Features/operations"), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListOperationsSender sends the ListOperations request. The method will close the +// http.Response Body if it receives an error. +func (client BaseClient) ListOperationsSender(req *http.Request) (*http.Response, error) { + return client.Send(req, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) +} + +// ListOperationsResponder handles the response to the ListOperations request. The method always +// closes the http.Response Body. +func (client BaseClient) ListOperationsResponder(resp *http.Response) (result OperationListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listOperationsNextResults retrieves the next set of results, if any. +func (client BaseClient) listOperationsNextResults(ctx context.Context, lastResults OperationListResult) (result OperationListResult, err error) { + req, err := lastResults.operationListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "features.BaseClient", "listOperationsNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListOperationsSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "features.BaseClient", "listOperationsNextResults", resp, "Failure sending next results request") + } + result, err = client.ListOperationsResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.BaseClient", "listOperationsNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListOperationsComplete enumerates all values, automatically crossing page boundaries as required. +func (client BaseClient) ListOperationsComplete(ctx context.Context) (result OperationListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/BaseClient.ListOperations") + defer func() { + sc := -1 + if result.Response().Response.Response != nil { + sc = result.page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.page, err = client.ListOperations(ctx) + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/features.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/features.go new file mode 100644 index 0000000000000..42088f87ad9a1 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/features.go @@ -0,0 +1,491 @@ +package features + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// Client is the azure Feature Exposure Control (AFEC) provides a mechanism for the resource providers to control +// feature exposure to users. Resource providers typically use this mechanism to provide public/private preview for new +// features prior to making them generally available. Users need to explicitly register for AFEC features to get access +// to such functionality. +type Client struct { + BaseClient +} + +// NewClient creates an instance of the Client client. +func NewClient(subscriptionID string) Client { + return NewClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewClientWithBaseURI creates an instance of the Client client using a custom endpoint. Use this when interacting +// with an Azure cloud that uses a non-standard base URI (sovereign clouds, Azure stack). +func NewClientWithBaseURI(baseURI string, subscriptionID string) Client { + return Client{NewWithBaseURI(baseURI, subscriptionID)} +} + +// Get gets the preview feature with the specified name. +// Parameters: +// resourceProviderNamespace - the resource provider namespace for the feature. +// featureName - the name of the feature to get. +func (client Client) Get(ctx context.Context, resourceProviderNamespace string, featureName string) (result Result, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.Get") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + req, err := client.GetPreparer(ctx, resourceProviderNamespace, featureName) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "Get", nil, "Failure preparing request") + return + } + + resp, err := client.GetSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "features.Client", "Get", resp, "Failure sending request") + return + } + + result, err = client.GetResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "Get", resp, "Failure responding to request") + return + } + + return +} + +// GetPreparer prepares the Get request. +func (client Client) GetPreparer(ctx context.Context, resourceProviderNamespace string, featureName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "featureName": autorest.Encode("path", featureName), + "resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-12-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Features/providers/{resourceProviderNamespace}/features/{featureName}", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// GetSender sends the Get request. The method will close the +// http.Response Body if it receives an error. +func (client Client) GetSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// GetResponder handles the response to the Get request. The method always +// closes the http.Response Body. +func (client Client) GetResponder(resp *http.Response) (result Result, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// List gets all the preview features in a provider namespace that are available through AFEC for the subscription. +// Parameters: +// resourceProviderNamespace - the namespace of the resource provider for getting features. +func (client Client) List(ctx context.Context, resourceProviderNamespace string) (result OperationsListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.List") + defer func() { + sc := -1 + if result.olr.Response.Response != nil { + sc = result.olr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx, resourceProviderNamespace) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.olr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "features.Client", "List", resp, "Failure sending request") + return + } + + result.olr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "List", resp, "Failure responding to request") + return + } + if result.olr.hasNextLink() && result.olr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client Client) ListPreparer(ctx context.Context, resourceProviderNamespace string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-12-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Features/providers/{resourceProviderNamespace}/features", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListSender sends the List request. The method will close the +// http.Response Body if it receives an error. +func (client Client) ListSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client Client) ListResponder(resp *http.Response) (result OperationsListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listNextResults retrieves the next set of results, if any. +func (client Client) listNextResults(ctx context.Context, lastResults OperationsListResult) (result OperationsListResult, err error) { + req, err := lastResults.operationsListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "features.Client", "listNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "features.Client", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client Client) ListComplete(ctx context.Context, resourceProviderNamespace string) (result OperationsListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.List") + defer func() { + sc := -1 + if result.Response().Response.Response != nil { + sc = result.page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.page, err = client.List(ctx, resourceProviderNamespace) + return +} + +// ListAll gets all the preview features that are available through AFEC for the subscription. +func (client Client) ListAll(ctx context.Context) (result OperationsListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.ListAll") + defer func() { + sc := -1 + if result.olr.Response.Response != nil { + sc = result.olr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listAllNextResults + req, err := client.ListAllPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "ListAll", nil, "Failure preparing request") + return + } + + resp, err := client.ListAllSender(req) + if err != nil { + result.olr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "features.Client", "ListAll", resp, "Failure sending request") + return + } + + result.olr, err = client.ListAllResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "ListAll", resp, "Failure responding to request") + return + } + if result.olr.hasNextLink() && result.olr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListAllPreparer prepares the ListAll request. +func (client Client) ListAllPreparer(ctx context.Context) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-12-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Features/features", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListAllSender sends the ListAll request. The method will close the +// http.Response Body if it receives an error. +func (client Client) ListAllSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// ListAllResponder handles the response to the ListAll request. The method always +// closes the http.Response Body. +func (client Client) ListAllResponder(resp *http.Response) (result OperationsListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listAllNextResults retrieves the next set of results, if any. +func (client Client) listAllNextResults(ctx context.Context, lastResults OperationsListResult) (result OperationsListResult, err error) { + req, err := lastResults.operationsListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "features.Client", "listAllNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListAllSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "features.Client", "listAllNextResults", resp, "Failure sending next results request") + } + result, err = client.ListAllResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "listAllNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListAllComplete enumerates all values, automatically crossing page boundaries as required. +func (client Client) ListAllComplete(ctx context.Context) (result OperationsListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.ListAll") + defer func() { + sc := -1 + if result.Response().Response.Response != nil { + sc = result.page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.page, err = client.ListAll(ctx) + return +} + +// Register registers the preview feature for the subscription. +// Parameters: +// resourceProviderNamespace - the namespace of the resource provider. +// featureName - the name of the feature to register. +func (client Client) Register(ctx context.Context, resourceProviderNamespace string, featureName string) (result Result, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.Register") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + req, err := client.RegisterPreparer(ctx, resourceProviderNamespace, featureName) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "Register", nil, "Failure preparing request") + return + } + + resp, err := client.RegisterSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "features.Client", "Register", resp, "Failure sending request") + return + } + + result, err = client.RegisterResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "Register", resp, "Failure responding to request") + return + } + + return +} + +// RegisterPreparer prepares the Register request. +func (client Client) RegisterPreparer(ctx context.Context, resourceProviderNamespace string, featureName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "featureName": autorest.Encode("path", featureName), + "resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-12-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsPost(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Features/providers/{resourceProviderNamespace}/features/{featureName}/register", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// RegisterSender sends the Register request. The method will close the +// http.Response Body if it receives an error. +func (client Client) RegisterSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// RegisterResponder handles the response to the Register request. The method always +// closes the http.Response Body. +func (client Client) RegisterResponder(resp *http.Response) (result Result, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// Unregister unregisters the preview feature for the subscription. +// Parameters: +// resourceProviderNamespace - the namespace of the resource provider. +// featureName - the name of the feature to unregister. +func (client Client) Unregister(ctx context.Context, resourceProviderNamespace string, featureName string) (result Result, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/Client.Unregister") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + req, err := client.UnregisterPreparer(ctx, resourceProviderNamespace, featureName) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "Unregister", nil, "Failure preparing request") + return + } + + resp, err := client.UnregisterSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "features.Client", "Unregister", resp, "Failure sending request") + return + } + + result, err = client.UnregisterResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "features.Client", "Unregister", resp, "Failure responding to request") + return + } + + return +} + +// UnregisterPreparer prepares the Unregister request. +func (client Client) UnregisterPreparer(ctx context.Context, resourceProviderNamespace string, featureName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "featureName": autorest.Encode("path", featureName), + "resourceProviderNamespace": autorest.Encode("path", resourceProviderNamespace), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-12-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsPost(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Features/providers/{resourceProviderNamespace}/features/{featureName}/unregister", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// UnregisterSender sends the Unregister request. The method will close the +// http.Response Body if it receives an error. +func (client Client) UnregisterSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// UnregisterResponder handles the response to the Unregister request. The method always +// closes the http.Response Body. +func (client Client) UnregisterResponder(resp *http.Response) (result Result, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/models.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/models.go new file mode 100644 index 0000000000000..d5b01ec005309 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/models.go @@ -0,0 +1,374 @@ +package features + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/to" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// The package's fully qualified name. +const fqdn = "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features" + +// Operation microsoft.Features operation +type Operation struct { + // Name - Operation name: {provider}/{resource}/{operation} + Name *string `json:"name,omitempty"` + // Display - The object that represents the operation. + Display *OperationDisplay `json:"display,omitempty"` +} + +// OperationDisplay the object that represents the operation. +type OperationDisplay struct { + // Provider - Service provider: Microsoft.Features + Provider *string `json:"provider,omitempty"` + // Resource - Resource on which the operation is performed: Profile, endpoint, etc. + Resource *string `json:"resource,omitempty"` + // Operation - Operation type: Read, write, delete, etc. + Operation *string `json:"operation,omitempty"` +} + +// OperationListResult result of the request to list Microsoft.Features operations. It contains a list of +// operations and a URL link to get the next set of results. +type OperationListResult struct { + autorest.Response `json:"-"` + // Value - List of Microsoft.Features operations. + Value *[]Operation `json:"value,omitempty"` + // NextLink - URL to get the next set of operation list results if there are any. + NextLink *string `json:"nextLink,omitempty"` +} + +// OperationListResultIterator provides access to a complete listing of Operation values. +type OperationListResultIterator struct { + i int + page OperationListResultPage +} + +// NextWithContext advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +func (iter *OperationListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationListResultIterator.NextWithContext") + defer func() { + sc := -1 + if iter.Response().Response.Response != nil { + sc = iter.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + iter.i++ + if iter.i < len(iter.page.Values()) { + return nil + } + err = iter.page.NextWithContext(ctx) + if err != nil { + iter.i-- + return err + } + iter.i = 0 + return nil +} + +// Next advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (iter *OperationListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter OperationListResultIterator) NotDone() bool { + return iter.page.NotDone() && iter.i < len(iter.page.Values()) +} + +// Response returns the raw server response from the last page request. +func (iter OperationListResultIterator) Response() OperationListResult { + return iter.page.Response() +} + +// Value returns the current value or a zero-initialized value if the +// iterator has advanced beyond the end of the collection. +func (iter OperationListResultIterator) Value() Operation { + if !iter.page.NotDone() { + return Operation{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the OperationListResultIterator type. +func NewOperationListResultIterator(page OperationListResultPage) OperationListResultIterator { + return OperationListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (olr OperationListResult) IsEmpty() bool { + return olr.Value == nil || len(*olr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (olr OperationListResult) hasNextLink() bool { + return olr.NextLink != nil && len(*olr.NextLink) != 0 +} + +// operationListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (olr OperationListResult) operationListResultPreparer(ctx context.Context) (*http.Request, error) { + if !olr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(olr.NextLink))) +} + +// OperationListResultPage contains a page of Operation values. +type OperationListResultPage struct { + fn func(context.Context, OperationListResult) (OperationListResult, error) + olr OperationListResult +} + +// NextWithContext advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +func (page *OperationListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationListResultPage.NextWithContext") + defer func() { + sc := -1 + if page.Response().Response.Response != nil { + sc = page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + for { + next, err := page.fn(ctx, page.olr) + if err != nil { + return err + } + page.olr = next + if !next.hasNextLink() || !next.IsEmpty() { + break + } + } + return nil +} + +// Next advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (page *OperationListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page OperationListResultPage) NotDone() bool { + return !page.olr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page OperationListResultPage) Response() OperationListResult { + return page.olr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page OperationListResultPage) Values() []Operation { + if page.olr.IsEmpty() { + return nil + } + return *page.olr.Value +} + +// Creates a new instance of the OperationListResultPage type. +func NewOperationListResultPage(cur OperationListResult, getNextPage func(context.Context, OperationListResult) (OperationListResult, error)) OperationListResultPage { + return OperationListResultPage{ + fn: getNextPage, + olr: cur, + } +} + +// OperationsListResult list of previewed features. +type OperationsListResult struct { + autorest.Response `json:"-"` + // Value - The array of features. + Value *[]Result `json:"value,omitempty"` + // NextLink - The URL to use for getting the next set of results. + NextLink *string `json:"nextLink,omitempty"` +} + +// OperationsListResultIterator provides access to a complete listing of Result values. +type OperationsListResultIterator struct { + i int + page OperationsListResultPage +} + +// NextWithContext advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +func (iter *OperationsListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationsListResultIterator.NextWithContext") + defer func() { + sc := -1 + if iter.Response().Response.Response != nil { + sc = iter.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + iter.i++ + if iter.i < len(iter.page.Values()) { + return nil + } + err = iter.page.NextWithContext(ctx) + if err != nil { + iter.i-- + return err + } + iter.i = 0 + return nil +} + +// Next advances to the next value. If there was an error making +// the request the iterator does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (iter *OperationsListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter OperationsListResultIterator) NotDone() bool { + return iter.page.NotDone() && iter.i < len(iter.page.Values()) +} + +// Response returns the raw server response from the last page request. +func (iter OperationsListResultIterator) Response() OperationsListResult { + return iter.page.Response() +} + +// Value returns the current value or a zero-initialized value if the +// iterator has advanced beyond the end of the collection. +func (iter OperationsListResultIterator) Value() Result { + if !iter.page.NotDone() { + return Result{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the OperationsListResultIterator type. +func NewOperationsListResultIterator(page OperationsListResultPage) OperationsListResultIterator { + return OperationsListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (olr OperationsListResult) IsEmpty() bool { + return olr.Value == nil || len(*olr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (olr OperationsListResult) hasNextLink() bool { + return olr.NextLink != nil && len(*olr.NextLink) != 0 +} + +// operationsListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (olr OperationsListResult) operationsListResultPreparer(ctx context.Context) (*http.Request, error) { + if !olr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(olr.NextLink))) +} + +// OperationsListResultPage contains a page of Result values. +type OperationsListResultPage struct { + fn func(context.Context, OperationsListResult) (OperationsListResult, error) + olr OperationsListResult +} + +// NextWithContext advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +func (page *OperationsListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationsListResultPage.NextWithContext") + defer func() { + sc := -1 + if page.Response().Response.Response != nil { + sc = page.Response().Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + for { + next, err := page.fn(ctx, page.olr) + if err != nil { + return err + } + page.olr = next + if !next.hasNextLink() || !next.IsEmpty() { + break + } + } + return nil +} + +// Next advances to the next page of values. If there was an error making +// the request the page does not advance and the error is returned. +// Deprecated: Use NextWithContext() instead. +func (page *OperationsListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page OperationsListResultPage) NotDone() bool { + return !page.olr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page OperationsListResultPage) Response() OperationsListResult { + return page.olr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page OperationsListResultPage) Values() []Result { + if page.olr.IsEmpty() { + return nil + } + return *page.olr.Value +} + +// Creates a new instance of the OperationsListResultPage type. +func NewOperationsListResultPage(cur OperationsListResult, getNextPage func(context.Context, OperationsListResult) (OperationsListResult, error)) OperationsListResultPage { + return OperationsListResultPage{ + fn: getNextPage, + olr: cur, + } +} + +// Properties information about feature. +type Properties struct { + // State - The registration state of the feature for the subscription. + State *string `json:"state,omitempty"` +} + +// Result previewed feature information. +type Result struct { + autorest.Response `json:"-"` + // Name - The name of the feature. + Name *string `json:"name,omitempty"` + // Properties - Properties of the previewed feature. + Properties *Properties `json:"properties,omitempty"` + // ID - The resource ID of the feature. + ID *string `json:"id,omitempty"` + // Type - The resource type of the feature. + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/version.go b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/version.go new file mode 100644 index 0000000000000..382caa0ee9670 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features/version.go @@ -0,0 +1,19 @@ +package features + +import "github.com/Azure/azure-sdk-for-go/version" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/" + Version() + " features/2015-12-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return version.Number +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 378f237736324..f187f73f6f3f2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -111,6 +111,7 @@ github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2019-05-13/back github.com/Azure/azure-sdk-for-go/services/redis/mgmt/2020-06-01/redis github.com/Azure/azure-sdk-for-go/services/redisenterprise/mgmt/2021-03-01/redisenterprise github.com/Azure/azure-sdk-for-go/services/relay/mgmt/2017-04-01/relay +github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2015-12-01/features github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-02-01/resources github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-09-01/locks github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/managedapplications diff --git a/website/docs/r/feature.html.markdown b/website/docs/r/feature.html.markdown new file mode 100644 index 0000000000000..f193ac9ac158f --- /dev/null +++ b/website/docs/r/feature.html.markdown @@ -0,0 +1,51 @@ +--- +subcategory: "Base" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_feature" +description: |- + Manages a Feature. +--- + +# azurerm_feature + +Register and unregister a preview feature for the subscription. Features which `approvalType` is `AutoApproval` can be managed by terraform. + +## Example Usage + +```hcl +resource "azurerm_feature" "example" { + name = "AutoApproveFeature" + provider_namespace = "Microsoft.CognitiveServices" +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name of the feature to register. Changing this forces a new Feature to be created. + +* `provider_namespace` - (Required) The namespace of the resource provider. Changing this forces a new Feature to be created. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Feature. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Feature. +* `read` - (Defaults to 5 minutes) Used when retrieving the Feature. +* `update` - (Defaults to 30 minutes) Used when updating the Feature. +* `delete` - (Defaults to 30 minutes) Used when deleting the Feature. + +## Import + +Features can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_feature.example /subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Features/providers/provider1/features/Feature1 +```