diff --git a/.teamcity/components/generated/services.kt b/.teamcity/components/generated/services.kt index d2f58ff50534..72e26cb37bce 100644 --- a/.teamcity/components/generated/services.kt +++ b/.teamcity/components/generated/services.kt @@ -34,6 +34,7 @@ var services = mapOf( "desktopvirtualization" to "Desktop Virtualization", "devtestlabs" to "Dev Test", "digitaltwins" to "Digital Twins", + "domainservices" to "DomainServices", "eventgrid" to "EventGrid", "eventhub" to "EventHub", "firewall" to "Firewall", diff --git a/azurerm/helpers/validate/strings.go b/azurerm/helpers/validate/strings.go index d40a05d89ddc..59de1d3f6fc8 100644 --- a/azurerm/helpers/validate/strings.go +++ b/azurerm/helpers/validate/strings.go @@ -1,10 +1,29 @@ package validate import ( + "encoding/base64" "fmt" "strings" ) +// Base64EncodedString validates that the string is base64 encoded +func Base64EncodedString(i interface{}, k string) ([]string, []error) { + v, ok := i.(string) + if !ok { + return nil, []error{fmt.Errorf("expected type of %q to be string", k)} + } + + if strings.TrimSpace(v) == "" { + return nil, []error{fmt.Errorf("%q must not be empty", k)} + } + + if _, err := base64.StdEncoding.DecodeString(v); err != nil { + return nil, []error{fmt.Errorf("%q must be a valid base64 encoded string", k)} + } + + return nil, nil +} + // LowerCasedString validates that the string is lower-cased func LowerCasedString(i interface{}, k string) ([]string, []error) { v, ok := i.(string) diff --git a/azurerm/helpers/validate/strings_test.go b/azurerm/helpers/validate/strings_test.go index 4d476653f586..8813a69d122f 100644 --- a/azurerm/helpers/validate/strings_test.go +++ b/azurerm/helpers/validate/strings_test.go @@ -4,6 +4,34 @@ import ( "testing" ) +func TestBase64EncodedString(t *testing.T) { + cases := []struct { + Input string + Errors int + }{ + { + Input: "", + Errors: 1, + }, + { + Input: "aGVsbG8td29ybGQ=", + Errors: 0, + }, + { + Input: "hello-world", + Errors: 1, + }, + } + + for _, tc := range cases { + t.Run(tc.Input, func(t *testing.T) { + if _, errors := Base64EncodedString(tc.Input, "base64"); len(errors) != tc.Errors { + t.Fatalf("Expected Base64 string to have %d not %d errors for %q: %v", tc.Errors, len(errors), tc.Input, errors) + } + }) + } +} + func TestLowerCasedStrings(t *testing.T) { cases := []struct { Value string diff --git a/azurerm/internal/clients/client.go b/azurerm/internal/clients/client.go index 5bcb90baeccc..0c4f87f34517 100644 --- a/azurerm/internal/clients/client.go +++ b/azurerm/internal/clients/client.go @@ -40,6 +40,7 @@ import ( devtestlabs "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/devtestlabs/client" digitaltwins "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/digitaltwins/client" dns "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/dns/client" + domainservices "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices/client" eventgrid "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventgrid/client" eventhub "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/client" firewall "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/firewall/client" @@ -142,6 +143,7 @@ type Client struct { DevTestLabs *devtestlabs.Client DigitalTwins *digitaltwins.Client Dns *dns.Client + DomainServices *domainservices.Client EventGrid *eventgrid.Client Eventhub *eventhub.Client Firewall *firewall.Client @@ -246,6 +248,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error client.DevTestLabs = devtestlabs.NewClient(o) client.DigitalTwins = digitaltwins.NewClient(o) client.Dns = dns.NewClient(o) + client.DomainServices = domainservices.NewClient(o) client.EventGrid = eventgrid.NewClient(o) client.Eventhub = eventhub.NewClient(o) client.Firewall = firewall.NewClient(o) diff --git a/azurerm/internal/provider/services.go b/azurerm/internal/provider/services.go index cf5d31aebe01..7f81dace1b2c 100644 --- a/azurerm/internal/provider/services.go +++ b/azurerm/internal/provider/services.go @@ -36,6 +36,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/devtestlabs" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/digitaltwins" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/dns" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventgrid" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/firewall" @@ -147,6 +148,7 @@ func SupportedUntypedServices() []sdk.UntypedServiceRegistration { devtestlabs.Registration{}, digitaltwins.Registration{}, dns.Registration{}, + domainservices.Registration{}, eventgrid.Registration{}, eventhub.Registration{}, firewall.Registration{}, diff --git a/azurerm/internal/services/domainservices/active_directory_domain_service_data_source.go b/azurerm/internal/services/domainservices/active_directory_domain_service_data_source.go new file mode 100644 index 000000000000..b7e977f27287 --- /dev/null +++ b/azurerm/internal/services/domainservices/active_directory_domain_service_data_source.go @@ -0,0 +1,285 @@ +package domainservices + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "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" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceActiveDirectoryDomainService() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceActiveDirectoryDomainServiceRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotWhiteSpace, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "deployment_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "domain_configuration_type": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "domain_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "filtered_sync_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "location": azure.SchemaLocationForDataSource(), + + "notifications": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "additional_recipients": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + "notify_dc_admins": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + "notify_global_admins": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + }, + }, + }, + + "replica_sets": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: dataSourceActiveDirectoryDomainServiceReplicaSetSchema(), + }, + }, + + "secure_ldap": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "external_access_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "certificate_expiry": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "certificate_thumbprint": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "public_certificate": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "security": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ntlm_v1_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "sync_kerberos_passwords": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "sync_ntlm_passwords": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "sync_on_prem_passwords": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "tls_v1_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + }, + }, + }, + + "sku": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "sync_owner": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "tags": tags.SchemaDataSource(), + + "tenant_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "version": { + Type: pluginsdk.TypeInt, + Computed: true, + }, + }, + } +} + +func dataSourceActiveDirectoryDomainServiceReplicaSetSchema() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + // TODO: add health-related attributes + + "domain_controller_ip_addresses": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "external_access_ip_address": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "location": azure.SchemaLocationForDataSource(), + + "service_status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + } +} + +func dataSourceActiveDirectoryDomainServiceRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + return err + } + + if resp.ID == nil { + return fmt.Errorf("reading Domain Service: ID was returned nil") + } + d.SetId(*resp.ID) + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + + if resp.Location == nil { + return fmt.Errorf("reading Domain Service %q: location was returned nil", d.Id()) + } + d.Set("location", azure.NormalizeLocation(*resp.Location)) + + if props := resp.DomainServiceProperties; props != nil { + d.Set("deployment_id", props.DeploymentID) + + domainConfigType := "" + if v := props.DomainConfigurationType; v != nil { + domainConfigType = *v + } + d.Set("domain_configuration_type", domainConfigType) + + d.Set("domain_name", props.DomainName) + + d.Set("filtered_sync_enabled", false) + if props.FilteredSync == aad.FilteredSyncEnabled { + d.Set("filtered_sync_enabled", true) + } + + d.Set("sku", props.Sku) + d.Set("sync_owner", props.SyncOwner) + d.Set("tenant_id", props.TenantID) + d.Set("version", props.Version) + + if err := d.Set("notifications", flattenDomainServiceNotifications(props.NotificationSettings)); err != nil { + return fmt.Errorf("setting `notifications`: %+v", err) + } + + if err := d.Set("secure_ldap", flattenDomainServiceLdaps(d, props.LdapsSettings, true)); err != nil { + return fmt.Errorf("setting `secure_ldap`: %+v", err) + } + + if err := d.Set("security", flattenDomainServiceSecurity(props.DomainSecuritySettings)); err != nil { + return fmt.Errorf("setting `security`: %+v", err) + } + + replicaSets := flattenDomainServiceReplicaSets(props.ReplicaSets) + if err := d.Set("replica_sets", replicaSets); err != nil { + return fmt.Errorf("setting `replica_sets`: %+v", err) + } + } + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/domainservices/active_directory_domain_service_replica_set_resource.go b/azurerm/internal/services/domainservices/active_directory_domain_service_replica_set_resource.go new file mode 100644 index 000000000000..219115a0f8cc --- /dev/null +++ b/azurerm/internal/services/domainservices/active_directory_domain_service_replica_set_resource.go @@ -0,0 +1,332 @@ +package domainservices + +import ( + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad" + + networkValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "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/location" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceActiveDirectoryDomainServiceReplicaSet() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceActiveDirectoryDomainServiceReplicaSetCreate, + Read: resourceActiveDirectoryDomainServiceReplicaSetRead, + Delete: resourceActiveDirectoryDomainServiceReplicaSetDelete, + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(3 * time.Hour), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(2 * time.Hour), + Delete: pluginsdk.DefaultTimeout(1 * time.Hour), + }, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.DomainServiceReplicaSetID(id) + return err + }), + + Schema: map[string]*pluginsdk.Schema{ + "domain_service_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DomainServiceID, + }, + + "location": azure.SchemaLocation(), + + "subnet_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, + + "domain_controller_ip_addresses": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "external_access_ip_address": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "service_status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + } +} + +func resourceActiveDirectoryDomainServiceReplicaSetCreate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + domainServiceId, err := parse.DomainServiceID(d.Get("domain_service_id").(string)) + if err != nil { + return err + } + if domainServiceId == nil { + return fmt.Errorf("parsing ID for Domain Service Replica Set") + } + + locks.ByName(domainServiceId.Name, DomainServiceResourceName) + defer locks.UnlockByName(domainServiceId.Name, DomainServiceResourceName) + + domainService, err := client.Get(ctx, domainServiceId.ResourceGroup, domainServiceId.Name) + if err != nil { + if utils.ResponseWasNotFound(domainService.Response) { + return fmt.Errorf("could not find %s: %s", domainServiceId, err) + } + return fmt.Errorf("reading %s: %s", domainServiceId, err) + } + + if domainService.DomainServiceProperties.ReplicaSets == nil || len(*domainService.DomainServiceProperties.ReplicaSets) == 0 { + return fmt.Errorf("reading %s: returned with missing replica set information, expected at least 1 replica set: %s", domainServiceId, err) + } + + subnetId := d.Get("subnet_id").(string) + replicaSets := *domainService.DomainServiceProperties.ReplicaSets + + for _, r := range replicaSets { + if r.ReplicaSetID == nil { + return fmt.Errorf("reading %s: a replica set was returned with a missing ReplicaSetID", domainServiceId) + } + if r.SubnetID == nil { + return fmt.Errorf("reading %s: a replica set was returned with a missing SubnetID", domainServiceId) + } + + // We assume that two replica sets cannot coexist in the same subnet + if strings.EqualFold(subnetId, *r.SubnetID) { + // Generate an ID here since we only know it once we know the ReplicaSetID + id := parse.NewDomainServiceReplicaSetID(domainServiceId.SubscriptionId, domainServiceId.ResourceGroup, domainServiceId.Name, *r.ReplicaSetID) + return tf.ImportAsExistsError("azurerm_active_directory_domain_service_replica_set", id.ID()) + } + } + + loc := location.Normalize(d.Get("location").(string)) + replicaSets = append(replicaSets, aad.ReplicaSet{ + Location: utils.String(loc), + SubnetID: utils.String(subnetId), + }) + + domainService.DomainServiceProperties.ReplicaSets = &replicaSets + + future, err := client.CreateOrUpdate(ctx, domainServiceId.ResourceGroup, domainServiceId.Name, domainService) + if err != nil { + return fmt.Errorf("creating/updating Replica Sets for %s: %+v", domainServiceId, err) + } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for Replica Sets for %s: %+v", domainServiceId, err) + } + + // We need to retrieve the domain service again to find out the new replica set ID + domainService, err = client.Get(ctx, domainServiceId.ResourceGroup, domainServiceId.Name) + if err != nil { + if utils.ResponseWasNotFound(domainService.Response) { + return fmt.Errorf("could not find %s: %s", domainServiceId, err) + } + return fmt.Errorf("reading %s: %s", domainServiceId, err) + } + + if domainService.DomainServiceProperties.ReplicaSets == nil || len(*domainService.DomainServiceProperties.ReplicaSets) == 0 { + return fmt.Errorf("reading %s: returned with missing replica set information, expected at least 1 replica set: %s", domainServiceId, err) + } + + var id parse.DomainServiceReplicaSetId + // Assuming that two replica sets cannot coexist in the same subnet, we identify our new replica set by its SubnetID + for _, r := range *domainService.DomainServiceProperties.ReplicaSets { + if r.ReplicaSetID == nil { + return fmt.Errorf("reading %s: a replica set was returned with a missing ReplicaSetID", domainServiceId) + } + if r.SubnetID == nil { + return fmt.Errorf("reading %s: a replica set was returned with a missing SubnetID", domainServiceId) + } + + if strings.EqualFold(subnetId, *r.SubnetID) { + // We found it! + id = parse.NewDomainServiceReplicaSetID(domainServiceId.SubscriptionId, domainServiceId.ResourceGroup, domainServiceId.Name, *r.ReplicaSetID) + } + } + + if id.ReplicaSetName == "" { + return fmt.Errorf("reading %s: the new replica set was not returned", domainServiceId) + } + + // Wait for all replica sets to become available with two domain controllers each before proceeding + timeout, _ := ctx.Deadline() + stateConf := &pluginsdk.StateChangeConf{ + Pending: []string{"pending"}, + Target: []string{"available"}, + Refresh: domainServiceControllerRefreshFunc(ctx, client, *domainServiceId, false), + Delay: 1 * time.Minute, + PollInterval: 1 * time.Minute, + Timeout: time.Until(timeout), + } + + if _, err := stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for both domain controllers to become available in all replica sets for %s: %+v", domainServiceId, err) + } + + d.SetId(id.ID()) + + return resourceActiveDirectoryDomainServiceReplicaSetRead(d, meta) +} + +func resourceActiveDirectoryDomainServiceReplicaSetRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DomainServiceReplicaSetID(d.Id()) + if err != nil { + return err + } + + domainService, err := client.Get(ctx, id.ResourceGroup, id.DomainServiceName) + if err != nil { + if utils.ResponseWasNotFound(domainService.Response) { + d.SetId("") + return nil + } + return err + } + + if domainService.DomainServiceProperties.ReplicaSets == nil || len(*domainService.DomainServiceProperties.ReplicaSets) == 0 { + return fmt.Errorf("reading %s: domain service returned with missing replica set information, expected at least 1 replica set: %s", id, err) + } + + var ( + domainControllerIpAddresses []string + externalAccessIpAddress string + loc string + serviceStatus string + subnetId string + ) + + replicaSets := *domainService.DomainServiceProperties.ReplicaSets + + for _, r := range replicaSets { + if r.ReplicaSetID == nil { + return fmt.Errorf("reading %s: a replica set was returned with a missing ReplicaSetID", id) + } + + // ReplicaSetName in the ID struct is really the replica set ID + if *r.ReplicaSetID == id.ReplicaSetName { + if r.DomainControllerIPAddress != nil { + domainControllerIpAddresses = *r.DomainControllerIPAddress + } + if r.ExternalAccessIPAddress != nil { + externalAccessIpAddress = *r.ExternalAccessIPAddress + } + if r.Location != nil { + loc = location.NormalizeNilable(r.Location) + } + if r.ServiceStatus != nil { + serviceStatus = *r.ServiceStatus + } + if r.SubnetID != nil { + subnetId = *r.SubnetID + } + } + } + + d.Set("domain_controller_ip_addresses", domainControllerIpAddresses) + d.Set("external_access_ip_address", externalAccessIpAddress) + d.Set("location", loc) + d.Set("service_status", serviceStatus) + d.Set("subnet_id", subnetId) + + return nil +} + +func resourceActiveDirectoryDomainServiceReplicaSetDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DomainServiceReplicaSetID(d.Id()) + if err != nil { + return err + } + + domainService, err := client.Get(ctx, id.ResourceGroup, id.DomainServiceName) + if err != nil { + if utils.ResponseWasNotFound(domainService.Response) { + return fmt.Errorf("deleting %s: domain service was not found: %s", id, err) + } + return err + } + + if domainService.DomainServiceProperties.ReplicaSets == nil || len(*domainService.DomainServiceProperties.ReplicaSets) == 0 { + return fmt.Errorf("deleting %s: domain service returned with missing replica set information, expected at least 1 replica set: %s", id, err) + } + + replicaSets := *domainService.DomainServiceProperties.ReplicaSets + + newReplicaSets := make([]aad.ReplicaSet, 0) + for _, r := range replicaSets { + if r.ReplicaSetID == nil { + return fmt.Errorf("deleting %s: a replica set was returned with a missing ReplicaSetID", id) + } + + if *r.ReplicaSetID == id.ReplicaSetName { + continue + } + + newReplicaSets = append(newReplicaSets, r) + } + + if len(replicaSets) == len(newReplicaSets) { + return fmt.Errorf("deleting %s: could not determine which replica set to remove", id) + } + + domainService.DomainServiceProperties.ReplicaSets = &newReplicaSets + + future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.DomainServiceName, domainService) + if err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) + } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for deletion of %s: %+v", id, err) + } + + // Wait for all replica sets to become available with two domain controllers each before proceeding + // Generate a partial DomainServiceId since we don't need to know the initial replica set ID here + domainServiceId := parse.NewDomainServiceID(id.SubscriptionId, id.ResourceGroup, id.DomainServiceName, "") + timeout, _ := ctx.Deadline() + stateConf := &pluginsdk.StateChangeConf{ + Pending: []string{"pending"}, + Target: []string{"available"}, + Refresh: domainServiceControllerRefreshFunc(ctx, client, domainServiceId, true), + Delay: 1 * time.Minute, + PollInterval: 1 * time.Minute, + Timeout: time.Until(timeout), + } + + if _, err := stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for replica sets to finish updating for %s: %+v", domainServiceId, err) + } + + return nil +} diff --git a/azurerm/internal/services/domainservices/active_directory_domain_service_resource.go b/azurerm/internal/services/domainservices/active_directory_domain_service_resource.go new file mode 100644 index 000000000000..7420adc457d6 --- /dev/null +++ b/azurerm/internal/services/domainservices/active_directory_domain_service_resource.go @@ -0,0 +1,771 @@ +package domainservices + +import ( + "context" + "fmt" + "log" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad" + "github.com/hashicorp/go-azure-helpers/response" + + azValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + networkValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network/validate" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "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/location" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/domainservices/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "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" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +const DomainServiceResourceName = "azurerm_active_directory_domain_service" + +func resourceActiveDirectoryDomainService() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceActiveDirectoryDomainServiceCreateUpdate, + Read: resourceActiveDirectoryDomainServiceRead, + Update: resourceActiveDirectoryDomainServiceCreateUpdate, + Delete: resourceActiveDirectoryDomainServiceDelete, + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(3 * time.Hour), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(2 * time.Hour), + Delete: pluginsdk.DefaultTimeout(1 * time.Hour), + }, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.DomainServiceID(id) + return err + }), + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, // TODO: proper validation + }, + + "location": azure.SchemaLocation(), + + "resource_group_name": azure.SchemaResourceGroupName(), + + "domain_name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, // TODO: proper validation, first prefix must be 15 chars or less + }, + + "initial_replica_set": { + Type: pluginsdk.TypeList, + Required: true, + MinItems: 1, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "domain_controller_ip_addresses": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "external_access_ip_address": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + // location is computed here + "location": azure.SchemaLocationForDataSource(), + + "service_status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, + }, + }, + }, + + "sku": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Standard", + "Enterprise", + "Premium", + }, false), + }, + + "filtered_sync_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "notifications": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "additional_recipients": { + Type: pluginsdk.TypeSet, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotWhiteSpace, + }, + }, + + "notify_dc_admins": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "notify_global_admins": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, + + "secure_ldap": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "enabled": { + Type: pluginsdk.TypeBool, + Required: true, + }, + + "external_access_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "pfx_certificate": { + Type: pluginsdk.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: azValidate.Base64EncodedString, + }, + + "pfx_certificate_password": { + Type: pluginsdk.TypeString, + Required: true, + Sensitive: true, + }, + + "certificate_expiry": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "certificate_thumbprint": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "public_certificate": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "security": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ntlm_v1_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "sync_kerberos_passwords": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "sync_ntlm_passwords": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "sync_on_prem_passwords": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "tls_v1_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, + + "tags": tags.Schema(), + + "deployment_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "sync_owner": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "version": { + Type: pluginsdk.TypeInt, + Computed: true, + }, + }, + } +} + +func resourceActiveDirectoryDomainServiceCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + resourceErrorName := fmt.Sprintf("Domain Service (Name: %q, Resource Group: %q)", name, resourceGroup) + + locks.ByName(name, DomainServiceResourceName) + defer locks.UnlockByName(name, DomainServiceResourceName) + + // If this is a new resource, we cannot determine the resource ID until after it has been created since we need to + // know the ID of the first replica set. + var id *parse.DomainServiceId + + if d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing %s: %s", resourceErrorName, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + // Parse the replica sets and assume the first one returned to be the initial replica set + // This is a best effort and the user can choose any replica set if they structure their config accordingly + props := existing.DomainServiceProperties + if props == nil { + return fmt.Errorf("checking for presence of existing %s: API response contained nil or missing properties", resourceErrorName) + } + replicaSets := flattenDomainServiceReplicaSets(props.ReplicaSets) + if len(replicaSets) == 0 { + return fmt.Errorf("checking for presence of existing %s: API response contained nil or missing replica set details", resourceErrorName) + } + initialReplicaSetId := replicaSets[0].(map[string]interface{})["id"].(string) + id := parse.NewDomainServiceID(client.SubscriptionID, resourceGroup, name, initialReplicaSetId) + + return tf.ImportAsExistsError(DomainServiceResourceName, id.ID()) + } + } else { + var err error + id, err = parse.DomainServiceID(d.Id()) + if err != nil { + return fmt.Errorf("preparing update for %s: %+v", resourceErrorName, err) + } + if id == nil { + return fmt.Errorf("preparing update for %s: resource ID could not be parsed", resourceErrorName) + } + } + + loc := location.Normalize(d.Get("location").(string)) + filteredSync := aad.FilteredSyncDisabled + if d.Get("filtered_sync_enabled").(bool) { + filteredSync = aad.FilteredSyncDisabled + } + + domainService := aad.DomainService{ + DomainServiceProperties: &aad.DomainServiceProperties{ + DomainName: utils.String(d.Get("domain_name").(string)), + DomainSecuritySettings: expandDomainServiceSecurity(d.Get("security").([]interface{})), + FilteredSync: filteredSync, + LdapsSettings: expandDomainServiceLdaps(d.Get("secure_ldap").([]interface{})), + NotificationSettings: expandDomainServiceNotifications(d.Get("notifications").([]interface{})), + Sku: utils.String(d.Get("sku").(string)), + }, + Location: utils.String(loc), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } + + if d.IsNewResource() { + // On resource creation, specify the initial replica set. + // No provision is made for changing the initial replica set, it should remain intact for the resource to function properly + replicaSets := []aad.ReplicaSet{ + { + Location: utils.String(loc), + SubnetID: utils.String(d.Get("initial_replica_set.0.subnet_id").(string)), + }, + } + domainService.DomainServiceProperties.ReplicaSets = &replicaSets + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, domainService) + if err != nil { + return fmt.Errorf("creating/updating %s: %+v", resourceErrorName, err) + } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for %s: %+v", resourceErrorName, err) + } + + // Retrieve the domain service to discover the unique ID for the initial replica set, which should not subsequently change + if d.IsNewResource() { + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("retrieving %s after creating: %+v", resourceErrorName, err) + } + props := resp.DomainServiceProperties + if props == nil { + return fmt.Errorf("%s returned with no properties", resourceErrorName) + } + if props.ReplicaSets == nil { + return fmt.Errorf("%s returned with no replica set details", resourceErrorName) + } + + replicaSets := flattenDomainServiceReplicaSets(props.ReplicaSets) + if replicaSetCount := len(replicaSets); replicaSetCount != 1 { + return fmt.Errorf("unexpected number of replica sets for %s: expected 1, saw %d", resourceErrorName, replicaSetCount) + } + + // Once we know the initial replica set ID, we can build a resource ID + initialReplicaSetId := replicaSets[0].(map[string]interface{})["id"].(string) + newId := parse.NewDomainServiceID(client.SubscriptionID, resourceGroup, name, initialReplicaSetId) + id = &newId + d.SetId(id.ID()) + + if err := d.Set("initial_replica_set", []interface{}{replicaSets[0]}); err != nil { + return fmt.Errorf("setting `initial_replica_set` after creating resource: %+v", err) + } + } + + if id == nil { + return fmt.Errorf("after creating/updating %s: id was unexpectedly nil", resourceErrorName) + } + + // A fully deployed domain service has 2 domain controllers per replica set, but the create operation completes early before the DCs are online. + // The domain service is still provisioning and further operations are blocked until both DCs are up and ready. + timeout, _ := ctx.Deadline() + stateConf := &pluginsdk.StateChangeConf{ + Pending: []string{"pending"}, + Target: []string{"available"}, + Refresh: domainServiceControllerRefreshFunc(ctx, client, *id, false), + Delay: 1 * time.Minute, + PollInterval: 1 * time.Minute, + Timeout: time.Until(timeout), + } + + if _, err := stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for both domain controllers to become available in initial replica set for %s: %+v", id, err) + } + + return resourceActiveDirectoryDomainServiceRead(d, meta) +} + +func resourceActiveDirectoryDomainServiceRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DomainServiceID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return err + } + + d.Set("name", id.Name) + d.Set("resource_group_name", id.ResourceGroup) + + loc := location.NormalizeNilable(resp.Location) + d.Set("location", loc) + + if props := resp.DomainServiceProperties; props != nil { + d.Set("deployment_id", props.DeploymentID) + d.Set("domain_name", props.DomainName) + d.Set("sync_owner", props.SyncOwner) + d.Set("tenant_id", props.TenantID) + d.Set("version", props.Version) + + d.Set("filtered_sync_enabled", false) + if props.FilteredSync == aad.FilteredSyncEnabled { + d.Set("filtered_sync_enabled", true) + } + + d.Set("sku", props.Sku) + + if err := d.Set("notifications", flattenDomainServiceNotifications(props.NotificationSettings)); err != nil { + return fmt.Errorf("setting `notifications`: %+v", err) + } + + var initialReplicaSet interface{} + replicaSets := flattenDomainServiceReplicaSets(props.ReplicaSets) + + // Determine the initial replica set. This is why we need to include InitialReplicaSetId in the resource ID, + // without it we would not be able to reliably support importing. + for _, replicaSetRaw := range replicaSets { + replicaSet := replicaSetRaw.(map[string]interface{}) + if replicaSet["id"].(string) == id.InitialReplicaSetIdName { + initialReplicaSet = replicaSetRaw + break + } + } + if initialReplicaSet == nil { + // It's safest to error out here, since we don't want to wipe the initial replica set from state if it was deleted manually + return fmt.Errorf("reading %s: could not determine initial replica set from API response", id) + } + if err := d.Set("initial_replica_set", []interface{}{initialReplicaSet}); err != nil { + return fmt.Errorf("setting `initial_replica_set`: %+v", err) + } + + if err := d.Set("secure_ldap", flattenDomainServiceLdaps(d, props.LdapsSettings, false)); err != nil { + return fmt.Errorf("setting `secure_ldap`: %+v", err) + } + + if err := d.Set("security", flattenDomainServiceSecurity(props.DomainSecuritySettings)); err != nil { + return fmt.Errorf("setting `security`: %+v", err) + } + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceActiveDirectoryDomainServiceDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).DomainServices.DomainServicesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.DomainServiceID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ResourceGroup, id.Name) + if err != nil { + if response.WasNotFound(future.Response()) { + return nil + } + return fmt.Errorf("deleting %s: %+v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + if !response.WasNotFound(future.Response()) { + return fmt.Errorf("waiting for deletion of %s: %+v", id, err) + } + } + + return nil +} + +func domainServiceControllerRefreshFunc(ctx context.Context, client *aad.DomainServicesClient, id parse.DomainServiceId, deleting bool) pluginsdk.StateRefreshFunc { + return func() (interface{}, string, error) { + log.Printf("[DEBUG] Waiting for domain controllers to deploy...") + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + if err != nil { + return nil, "error", err + } + if resp.DomainServiceProperties == nil || resp.DomainServiceProperties.ReplicaSets == nil || len(*resp.DomainServiceProperties.ReplicaSets) == 0 { + return nil, "error", fmt.Errorf("API error: `replicaSets` was not returned") + } + // Loop through all replica sets and ensure they are running and each have two available domain controllers + for _, repl := range *resp.DomainServiceProperties.ReplicaSets { + if repl.ServiceStatus == nil { + return resp, "pending", nil + } + switch { + case !deleting && strings.EqualFold(*repl.ServiceStatus, "TearingDown"): + // Sometimes a service error will cause the replica set, or resource, to self destruct + return resp, "error", fmt.Errorf("service error: a replica set is unexpectedly tearing down") + case strings.EqualFold(*repl.ServiceStatus, "Failed"): + // If a replica set enters a failed state, it needs manual intervention + return resp, "error", fmt.Errorf("service error: a replica set has entered a Failed state and must be recovered or deleted manually") + case !strings.EqualFold(*repl.ServiceStatus, "Running"): + // If it's not yet running, it isn't ready + return resp, "pending", nil + case repl.DomainControllerIPAddress == nil || len(*repl.DomainControllerIPAddress) < 2: + // When a domain controller is online, its IP address will be returned. We're looking for 2 active domain controllers. + return resp, "pending", nil + } + } + return resp, "available", nil + } +} + +func expandDomainServiceLdaps(input []interface{}) (ldaps *aad.LdapsSettings) { + ldaps = &aad.LdapsSettings{ + Ldaps: aad.LdapsDisabled, + } + + if len(input) > 0 { + v := input[0].(map[string]interface{}) + if v["enabled"].(bool) { + ldaps.Ldaps = aad.LdapsEnabled + } + ldaps.PfxCertificate = utils.String(v["pfx_certificate"].(string)) + ldaps.PfxCertificatePassword = utils.String(v["pfx_certificate_password"].(string)) + if v["external_access_enabled"].(bool) { + ldaps.ExternalAccess = aad.Enabled + } else { + ldaps.ExternalAccess = aad.Disabled + } + } + + return +} + +func expandDomainServiceNotifications(input []interface{}) *aad.NotificationSettings { + if len(input) == 0 { + return nil + } + + v := input[0].(map[string]interface{}) + + additionalRecipients := make([]string, 0) + if ar, ok := v["additional_recipients"]; ok { + for _, r := range ar.(*pluginsdk.Set).List() { + additionalRecipients = append(additionalRecipients, r.(string)) + } + } + + notifyDcAdmins := aad.NotifyDcAdminsDisabled + if n, ok := v["notify_dc_admins"]; ok && n.(bool) { + notifyDcAdmins = aad.NotifyDcAdminsEnabled + } + + notifyGlobalAdmins := aad.NotifyGlobalAdminsDisabled + if n, ok := v["notify_global_admins"]; ok && n.(bool) { + notifyGlobalAdmins = aad.NotifyGlobalAdminsEnabled + } + + return &aad.NotificationSettings{ + AdditionalRecipients: &additionalRecipients, + NotifyDcAdmins: notifyDcAdmins, + NotifyGlobalAdmins: notifyGlobalAdmins, + } +} + +func expandDomainServiceSecurity(input []interface{}) *aad.DomainSecuritySettings { + if len(input) == 0 { + return nil + } + v := input[0].(map[string]interface{}) + + ntlmV1 := aad.NtlmV1Disabled + syncKerberosPasswords := aad.SyncKerberosPasswordsDisabled + syncNtlmPasswords := aad.SyncNtlmPasswordsDisabled + syncOnPremPasswords := aad.SyncOnPremPasswordsDisabled + tlsV1 := aad.TLSV1Disabled + + if v["ntlm_v1_enabled"].(bool) { + ntlmV1 = aad.NtlmV1Enabled + } + if v["sync_kerberos_passwords"].(bool) { + syncKerberosPasswords = aad.SyncKerberosPasswordsEnabled + } + if v["sync_ntlm_passwords"].(bool) { + syncNtlmPasswords = aad.SyncNtlmPasswordsEnabled + } + if v["sync_on_prem_passwords"].(bool) { + syncOnPremPasswords = aad.SyncOnPremPasswordsEnabled + } + if v["tls_v1_enabled"].(bool) { + tlsV1 = aad.TLSV1Enabled + } + + return &aad.DomainSecuritySettings{ + NtlmV1: ntlmV1, + SyncKerberosPasswords: syncKerberosPasswords, + SyncNtlmPasswords: syncNtlmPasswords, + SyncOnPremPasswords: syncOnPremPasswords, + TLSV1: tlsV1, + } +} + +func flattenDomainServiceLdaps(d *pluginsdk.ResourceData, input *aad.LdapsSettings, dataSource bool) []interface{} { + result := map[string]interface{}{ + "enabled": false, + "external_access_enabled": false, + "certificate_expiry": "", + "certificate_thumbprint": "", + "public_certificate": "", + } + + if !dataSource { + // Read pfx_certificate and pfx_certificate_password from existing state since it's not returned + result["pfx_certificate"] = "" + if v, ok := d.GetOk("secure_ldap.0.pfx_certificate"); ok { + result["pfx_certificate"] = v.(string) + } + result["pfx_certificate_password"] = "" + if v, ok := d.GetOk("secure_ldap.0.pfx_certificate_password"); ok { + result["pfx_certificate_password"] = v.(string) + } + } + + if input != nil { + if input.ExternalAccess == aad.Enabled { + result["external_access_enabled"] = true + } + if input.Ldaps == aad.LdapsEnabled { + result["enabled"] = true + } + if v := input.CertificateNotAfter; v != nil { + result["certificate_expiry"] = v.Format(time.RFC3339) + } + if v := input.CertificateThumbprint; v != nil { + result["certificate_thumbprint"] = *v + } + if v := input.PublicCertificate; v != nil { + result["public_certificate"] = *v + } + } + + return []interface{}{result} +} + +func flattenDomainServiceNotifications(input *aad.NotificationSettings) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + result := map[string]interface{}{ + "additional_recipients": make([]string, 0), + "notify_dc_admins": false, + "notify_global_admins": false, + } + if input.AdditionalRecipients != nil { + result["additional_recipients"] = *input.AdditionalRecipients + } + if input.NotifyDcAdmins == aad.NotifyDcAdminsEnabled { + result["notify_dc_admins"] = true + } + if input.NotifyGlobalAdmins == aad.NotifyGlobalAdminsEnabled { + result["notify_global_admins"] = true + } + + return []interface{}{result} +} + +func flattenDomainServiceReplicaSets(input *[]aad.ReplicaSet) (ret []interface{}) { + if input == nil { + return + } + + for _, in := range *input { + repl := map[string]interface{}{ + "domain_controller_ip_addresses": make([]string, 0), + "external_access_ip_address": "", + "location": location.NormalizeNilable(in.Location), + "id": "", + "service_status": "", + "subnet_id": "", + } + if in.DomainControllerIPAddress != nil { + repl["domain_controller_ip_addresses"] = *in.DomainControllerIPAddress + } + if in.ExternalAccessIPAddress != nil { + repl["external_access_ip_address"] = *in.ExternalAccessIPAddress + } + if in.ReplicaSetID != nil { + repl["id"] = *in.ReplicaSetID + } + if in.ServiceStatus != nil { + repl["service_status"] = *in.ServiceStatus + } + if in.SubnetID != nil { + repl["subnet_id"] = *in.SubnetID + } + ret = append(ret, repl) + } + + return +} + +func flattenDomainServiceSecurity(input *aad.DomainSecuritySettings) []interface{} { + if input == nil { + return make([]interface{}, 0) + } + + result := map[string]bool{ + "ntlm_v1_enabled": false, + "sync_kerberos_passwords": false, + "sync_ntlm_passwords": false, + "sync_on_prem_passwords": false, + "tls_v1_enabled": false, + } + if input.NtlmV1 == aad.NtlmV1Enabled { + result["ntlm_v1_enabled"] = true + } + if input.SyncKerberosPasswords == aad.SyncKerberosPasswordsEnabled { + result["sync_kerberos_passwords"] = true + } + if input.SyncNtlmPasswords == aad.SyncNtlmPasswordsEnabled { + result["sync_ntlm_passwords"] = true + } + if input.SyncOnPremPasswords == aad.SyncOnPremPasswordsEnabled { + result["sync_on_prem_passwords"] = true + } + if input.TLSV1 == aad.TLSV1Enabled { + result["tls_v1_enabled"] = true + } + + return []interface{}{result} +} diff --git a/azurerm/internal/services/domainservices/active_directory_domain_service_test.go b/azurerm/internal/services/domainservices/active_directory_domain_service_test.go new file mode 100644 index 000000000000..747546c35b6a --- /dev/null +++ b/azurerm/internal/services/domainservices/active_directory_domain_service_test.go @@ -0,0 +1,527 @@ +package domainservices_test + +import ( + "context" + "fmt" + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/pluginsdk" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "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/domainservices/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +// To generate a suitable cert for AADDS: +// +// openssl req -subj '/CN=*.never.gonna.shut.you.down/O=HashiCorp, Inc./ST=CA/C=US' \ +// -addext "subjectAltName=DNS:never.gonna.shut.you.down,DNS:*.never.gonna.shut.you.down" \ +// -addext "keyUsage=critical,nonRepudiation,digitalSignature,keyEncipherment" \ +// -addext "extendedKeyUsage=1.3.6.1.5.5.7.3.1" \ +// -new -newkey rsa:2048 -sha256 -days 36500 -nodes -x509 -keyout aadds.key -out aadds.crt +// +// Then package as a pfx bundle: +// +// openssl pkcs12 -export -out "aadds.pfx" -inkey "aadds.key" -in "aadds.crt" \ +// -password pass:qwer5678 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES +// +// The configuration value is the base64 encoded representation of the resulting pkcs12 bundle: +// +// base64 0 + + return utils.Bool(exists), nil +} + +func (VirtualNetworkDnsServersResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + subnet { + name = "subnet1" + address_prefix = "10.0.1.0/24" + } +} + +resource "azurerm_virtual_network_dns_servers" "test" { + virtual_network_id = azurerm_virtual_network.test.id + dns_servers = ["10.7.7.2", "10.7.7.7", "10.7.7.1"] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/azurerm/internal/services/network/virtual_network_resource.go b/azurerm/internal/services/network/virtual_network_resource.go index dcfcf00a9de8..55c459e14d12 100644 --- a/azurerm/internal/services/network/virtual_network_resource.go +++ b/azurerm/internal/services/network/virtual_network_resource.go @@ -91,6 +91,7 @@ func resourceVirtualNetwork() *pluginsdk.Resource { "dns_servers": { Type: pluginsdk.TypeList, Optional: true, + Computed: true, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringIsNotEmpty, diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/CHANGELOG.md new file mode 100644 index 000000000000..b2f3714508b7 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/CHANGELOG.md @@ -0,0 +1,8 @@ +# Change History + +## Additive Changes + +### New Funcs + +1. HealthAlert.MarshalJSON() ([]byte, error) +1. HealthMonitor.MarshalJSON() ([]byte, error) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/_meta.json b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/_meta.json new file mode 100644 index 000000000000..abf829d9cd13 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/_meta.json @@ -0,0 +1,11 @@ +{ + "commit": "3c764635e7d442b3e74caf593029fcd440b3ef82", + "readme": "/_/azure-rest-api-specs/specification/domainservices/resource-manager/readme.md", + "tag": "package-2020-01", + "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-2020-01 --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/domainservices/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/domainservices/mgmt/2020-01-01/aad/client.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/client.go new file mode 100644 index 000000000000..910b84b2297b --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/client.go @@ -0,0 +1,41 @@ +// Package aad implements the Azure ARM Aad service API version 2020-01-01. +// +// The AAD Domain Services API. +package aad + +// 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 ( + "github.com/Azure/go-autorest/autorest" +) + +const ( + // DefaultBaseURI is the default URI used for the service Aad + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Aad. +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, + } +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/domainserviceoperations.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/domainserviceoperations.go new file mode 100644 index 000000000000..d64ff6d3d9e5 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/domainserviceoperations.go @@ -0,0 +1,141 @@ +package aad + +// 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" +) + +// DomainServiceOperationsClient is the the AAD Domain Services API. +type DomainServiceOperationsClient struct { + BaseClient +} + +// NewDomainServiceOperationsClient creates an instance of the DomainServiceOperationsClient client. +func NewDomainServiceOperationsClient(subscriptionID string) DomainServiceOperationsClient { + return NewDomainServiceOperationsClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewDomainServiceOperationsClientWithBaseURI creates an instance of the DomainServiceOperationsClient 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 NewDomainServiceOperationsClientWithBaseURI(baseURI string, subscriptionID string) DomainServiceOperationsClient { + return DomainServiceOperationsClient{NewWithBaseURI(baseURI, subscriptionID)} +} + +// List lists all the available Domain Services operations. +func (client DomainServiceOperationsClient) List(ctx context.Context) (result OperationEntityListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServiceOperationsClient.List") + defer func() { + sc := -1 + if result.oelr.Response.Response != nil { + sc = result.oelr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServiceOperationsClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.oelr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.DomainServiceOperationsClient", "List", resp, "Failure sending request") + return + } + + result.oelr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServiceOperationsClient", "List", resp, "Failure responding to request") + return + } + if result.oelr.hasNextLink() && result.oelr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client DomainServiceOperationsClient) ListPreparer(ctx context.Context) (*http.Request, error) { + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/providers/Microsoft.AAD/operations"), + 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 DomainServiceOperationsClient) ListSender(req *http.Request) (*http.Response, error) { + return client.Send(req, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client DomainServiceOperationsClient) ListResponder(resp *http.Response) (result OperationEntityListResult, 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 DomainServiceOperationsClient) listNextResults(ctx context.Context, lastResults OperationEntityListResult) (result OperationEntityListResult, err error) { + req, err := lastResults.operationEntityListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "aad.DomainServiceOperationsClient", "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, "aad.DomainServiceOperationsClient", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServiceOperationsClient", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client DomainServiceOperationsClient) ListComplete(ctx context.Context) (result OperationEntityListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServiceOperationsClient.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) + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/domainservices.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/domainservices.go new file mode 100644 index 000000000000..b795ee180417 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/domainservices.go @@ -0,0 +1,626 @@ +package aad + +// 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/autorest/validation" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// DomainServicesClient is the the AAD Domain Services API. +type DomainServicesClient struct { + BaseClient +} + +// NewDomainServicesClient creates an instance of the DomainServicesClient client. +func NewDomainServicesClient(subscriptionID string) DomainServicesClient { + return NewDomainServicesClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewDomainServicesClientWithBaseURI creates an instance of the DomainServicesClient 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 NewDomainServicesClientWithBaseURI(baseURI string, subscriptionID string) DomainServicesClient { + return DomainServicesClient{NewWithBaseURI(baseURI, subscriptionID)} +} + +// CreateOrUpdate the Create Domain Service operation creates a new domain service with the specified parameters. If +// the specific service already exists, then any patchable properties will be updated and any immutable properties will +// remain unchanged. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +// domainService - properties supplied to the Create or Update a Domain Service operation. +func (client DomainServicesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, domainServiceName string, domainService DomainService) (result DomainServicesCreateOrUpdateFuture, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.CreateOrUpdate") + defer func() { + sc := -1 + if result.FutureAPI != nil && result.FutureAPI.Response() != nil { + sc = result.FutureAPI.Response().StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.DomainServicesClient", "CreateOrUpdate", err.Error()) + } + + req, err := client.CreateOrUpdatePreparer(ctx, resourceGroupName, domainServiceName, domainService) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "CreateOrUpdate", nil, "Failure preparing request") + return + } + + result, err = client.CreateOrUpdateSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "CreateOrUpdate", nil, "Failure sending request") + return + } + + return +} + +// CreateOrUpdatePreparer prepares the CreateOrUpdate request. +func (client DomainServicesClient) CreateOrUpdatePreparer(ctx context.Context, resourceGroupName string, domainServiceName string, domainService DomainService) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AAD/domainServices/{domainServiceName}", pathParameters), + autorest.WithJSON(domainService), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the +// http.Response Body if it receives an error. +func (client DomainServicesClient) CreateOrUpdateSender(req *http.Request) (future DomainServicesCreateOrUpdateFuture, err error) { + var resp *http.Response + resp, err = client.Send(req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + var azf azure.Future + azf, err = azure.NewFutureFromResponse(resp) + future.FutureAPI = &azf + future.Result = future.result + return +} + +// CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always +// closes the http.Response Body. +func (client DomainServicesClient) CreateOrUpdateResponder(resp *http.Response) (result DomainService, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated, http.StatusAccepted), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// Delete the Delete Domain Service operation deletes an existing Domain Service. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +func (client DomainServicesClient) Delete(ctx context.Context, resourceGroupName string, domainServiceName string) (result DomainServicesDeleteFuture, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.Delete") + defer func() { + sc := -1 + if result.FutureAPI != nil && result.FutureAPI.Response() != nil { + sc = result.FutureAPI.Response().StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.DomainServicesClient", "Delete", err.Error()) + } + + req, err := client.DeletePreparer(ctx, resourceGroupName, domainServiceName) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Delete", nil, "Failure preparing request") + return + } + + result, err = client.DeleteSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Delete", nil, "Failure sending request") + return + } + + return +} + +// DeletePreparer prepares the Delete request. +func (client DomainServicesClient) DeletePreparer(ctx context.Context, resourceGroupName string, domainServiceName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsDelete(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AAD/domainServices/{domainServiceName}", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// DeleteSender sends the Delete request. The method will close the +// http.Response Body if it receives an error. +func (client DomainServicesClient) DeleteSender(req *http.Request) (future DomainServicesDeleteFuture, err error) { + var resp *http.Response + resp, err = client.Send(req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + var azf azure.Future + azf, err = azure.NewFutureFromResponse(resp) + future.FutureAPI = &azf + future.Result = future.result + return +} + +// DeleteResponder handles the response to the Delete request. The method always +// closes the http.Response Body. +func (client DomainServicesClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted, http.StatusNoContent), + autorest.ByClosing()) + result.Response = resp + return +} + +// Get the Get Domain Service operation retrieves a json representation of the Domain Service. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +func (client DomainServicesClient) Get(ctx context.Context, resourceGroupName string, domainServiceName string) (result DomainService, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.Get") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.DomainServicesClient", "Get", err.Error()) + } + + req, err := client.GetPreparer(ctx, resourceGroupName, domainServiceName) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Get", nil, "Failure preparing request") + return + } + + resp, err := client.GetSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Get", resp, "Failure sending request") + return + } + + result, err = client.GetResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Get", resp, "Failure responding to request") + return + } + + return +} + +// GetPreparer prepares the Get request. +func (client DomainServicesClient) GetPreparer(ctx context.Context, resourceGroupName string, domainServiceName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AAD/domainServices/{domainServiceName}", 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 DomainServicesClient) 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 DomainServicesClient) GetResponder(resp *http.Response) (result DomainService, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// List the List Domain Services in Subscription operation lists all the domain services available under the given +// subscription (and across all resource groups within that subscription). +func (client DomainServicesClient) List(ctx context.Context) (result DomainServiceListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.List") + defer func() { + sc := -1 + if result.dslr.Response.Response != nil { + sc = result.dslr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.dslr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "List", resp, "Failure sending request") + return + } + + result.dslr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "List", resp, "Failure responding to request") + return + } + if result.dslr.hasNextLink() && result.dslr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client DomainServicesClient) ListPreparer(ctx context.Context) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.AAD/domainServices", 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 DomainServicesClient) 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 DomainServicesClient) ListResponder(resp *http.Response) (result DomainServiceListResult, 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 DomainServicesClient) listNextResults(ctx context.Context, lastResults DomainServiceListResult) (result DomainServiceListResult, err error) { + req, err := lastResults.domainServiceListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "aad.DomainServicesClient", "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, "aad.DomainServicesClient", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client DomainServicesClient) ListComplete(ctx context.Context) (result DomainServiceListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.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) + return +} + +// ListByResourceGroup the List Domain Services in Resource Group operation lists all the domain services available +// under the given resource group. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +func (client DomainServicesClient) ListByResourceGroup(ctx context.Context, resourceGroupName string) (result DomainServiceListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.ListByResourceGroup") + defer func() { + sc := -1 + if result.dslr.Response.Response != nil { + sc = result.dslr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.DomainServicesClient", "ListByResourceGroup", err.Error()) + } + + result.fn = client.listByResourceGroupNextResults + req, err := client.ListByResourceGroupPreparer(ctx, resourceGroupName) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "ListByResourceGroup", nil, "Failure preparing request") + return + } + + resp, err := client.ListByResourceGroupSender(req) + if err != nil { + result.dslr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "ListByResourceGroup", resp, "Failure sending request") + return + } + + result.dslr, err = client.ListByResourceGroupResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "ListByResourceGroup", resp, "Failure responding to request") + return + } + if result.dslr.hasNextLink() && result.dslr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListByResourceGroupPreparer prepares the ListByResourceGroup request. +func (client DomainServicesClient) ListByResourceGroupPreparer(ctx context.Context, resourceGroupName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AAD/domainServices", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListByResourceGroupSender sends the ListByResourceGroup request. The method will close the +// http.Response Body if it receives an error. +func (client DomainServicesClient) ListByResourceGroupSender(req *http.Request) (*http.Response, error) { + return client.Send(req, azure.DoRetryWithRegistration(client.Client)) +} + +// ListByResourceGroupResponder handles the response to the ListByResourceGroup request. The method always +// closes the http.Response Body. +func (client DomainServicesClient) ListByResourceGroupResponder(resp *http.Response) (result DomainServiceListResult, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// listByResourceGroupNextResults retrieves the next set of results, if any. +func (client DomainServicesClient) listByResourceGroupNextResults(ctx context.Context, lastResults DomainServiceListResult) (result DomainServiceListResult, err error) { + req, err := lastResults.domainServiceListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "aad.DomainServicesClient", "listByResourceGroupNextResults", nil, "Failure preparing next results request") + } + if req == nil { + return + } + resp, err := client.ListByResourceGroupSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + return result, autorest.NewErrorWithError(err, "aad.DomainServicesClient", "listByResourceGroupNextResults", resp, "Failure sending next results request") + } + result, err = client.ListByResourceGroupResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "listByResourceGroupNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListByResourceGroupComplete enumerates all values, automatically crossing page boundaries as required. +func (client DomainServicesClient) ListByResourceGroupComplete(ctx context.Context, resourceGroupName string) (result DomainServiceListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.ListByResourceGroup") + 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.ListByResourceGroup(ctx, resourceGroupName) + return +} + +// Update the Update Domain Service operation can be used to update the existing deployment. The update call only +// supports the properties listed in the PATCH body. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +// domainService - properties supplied to the Update a Domain Service operation. +func (client DomainServicesClient) Update(ctx context.Context, resourceGroupName string, domainServiceName string, domainService DomainService) (result DomainServicesUpdateFuture, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServicesClient.Update") + defer func() { + sc := -1 + if result.FutureAPI != nil && result.FutureAPI.Response() != nil { + sc = result.FutureAPI.Response().StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.DomainServicesClient", "Update", err.Error()) + } + + req, err := client.UpdatePreparer(ctx, resourceGroupName, domainServiceName, domainService) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Update", nil, "Failure preparing request") + return + } + + result, err = client.UpdateSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesClient", "Update", nil, "Failure sending request") + return + } + + return +} + +// UpdatePreparer prepares the Update request. +func (client DomainServicesClient) UpdatePreparer(ctx context.Context, resourceGroupName string, domainServiceName string, domainService DomainService) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPatch(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.AAD/domainServices/{domainServiceName}", pathParameters), + autorest.WithJSON(domainService), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// UpdateSender sends the Update request. The method will close the +// http.Response Body if it receives an error. +func (client DomainServicesClient) UpdateSender(req *http.Request) (future DomainServicesUpdateFuture, err error) { + var resp *http.Response + resp, err = client.Send(req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + var azf azure.Future + azf, err = azure.NewFutureFromResponse(resp) + future.FutureAPI = &azf + future.Result = future.result + return +} + +// UpdateResponder handles the response to the Update request. The method always +// closes the http.Response Body. +func (client DomainServicesClient) UpdateResponder(resp *http.Response) (result DomainService, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/enums.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/enums.go new file mode 100644 index 000000000000..3c0900cccb82 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/enums.go @@ -0,0 +1,157 @@ +package aad + +// 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. + +// ExternalAccess enumerates the values for external access. +type ExternalAccess string + +const ( + // Disabled ... + Disabled ExternalAccess = "Disabled" + // Enabled ... + Enabled ExternalAccess = "Enabled" +) + +// PossibleExternalAccessValues returns an array of possible values for the ExternalAccess const type. +func PossibleExternalAccessValues() []ExternalAccess { + return []ExternalAccess{Disabled, Enabled} +} + +// FilteredSync enumerates the values for filtered sync. +type FilteredSync string + +const ( + // FilteredSyncDisabled ... + FilteredSyncDisabled FilteredSync = "Disabled" + // FilteredSyncEnabled ... + FilteredSyncEnabled FilteredSync = "Enabled" +) + +// PossibleFilteredSyncValues returns an array of possible values for the FilteredSync const type. +func PossibleFilteredSyncValues() []FilteredSync { + return []FilteredSync{FilteredSyncDisabled, FilteredSyncEnabled} +} + +// Ldaps enumerates the values for ldaps. +type Ldaps string + +const ( + // LdapsDisabled ... + LdapsDisabled Ldaps = "Disabled" + // LdapsEnabled ... + LdapsEnabled Ldaps = "Enabled" +) + +// PossibleLdapsValues returns an array of possible values for the Ldaps const type. +func PossibleLdapsValues() []Ldaps { + return []Ldaps{LdapsDisabled, LdapsEnabled} +} + +// NotifyDcAdmins enumerates the values for notify dc admins. +type NotifyDcAdmins string + +const ( + // NotifyDcAdminsDisabled ... + NotifyDcAdminsDisabled NotifyDcAdmins = "Disabled" + // NotifyDcAdminsEnabled ... + NotifyDcAdminsEnabled NotifyDcAdmins = "Enabled" +) + +// PossibleNotifyDcAdminsValues returns an array of possible values for the NotifyDcAdmins const type. +func PossibleNotifyDcAdminsValues() []NotifyDcAdmins { + return []NotifyDcAdmins{NotifyDcAdminsDisabled, NotifyDcAdminsEnabled} +} + +// NotifyGlobalAdmins enumerates the values for notify global admins. +type NotifyGlobalAdmins string + +const ( + // NotifyGlobalAdminsDisabled ... + NotifyGlobalAdminsDisabled NotifyGlobalAdmins = "Disabled" + // NotifyGlobalAdminsEnabled ... + NotifyGlobalAdminsEnabled NotifyGlobalAdmins = "Enabled" +) + +// PossibleNotifyGlobalAdminsValues returns an array of possible values for the NotifyGlobalAdmins const type. +func PossibleNotifyGlobalAdminsValues() []NotifyGlobalAdmins { + return []NotifyGlobalAdmins{NotifyGlobalAdminsDisabled, NotifyGlobalAdminsEnabled} +} + +// NtlmV1 enumerates the values for ntlm v1. +type NtlmV1 string + +const ( + // NtlmV1Disabled ... + NtlmV1Disabled NtlmV1 = "Disabled" + // NtlmV1Enabled ... + NtlmV1Enabled NtlmV1 = "Enabled" +) + +// PossibleNtlmV1Values returns an array of possible values for the NtlmV1 const type. +func PossibleNtlmV1Values() []NtlmV1 { + return []NtlmV1{NtlmV1Disabled, NtlmV1Enabled} +} + +// SyncKerberosPasswords enumerates the values for sync kerberos passwords. +type SyncKerberosPasswords string + +const ( + // SyncKerberosPasswordsDisabled ... + SyncKerberosPasswordsDisabled SyncKerberosPasswords = "Disabled" + // SyncKerberosPasswordsEnabled ... + SyncKerberosPasswordsEnabled SyncKerberosPasswords = "Enabled" +) + +// PossibleSyncKerberosPasswordsValues returns an array of possible values for the SyncKerberosPasswords const type. +func PossibleSyncKerberosPasswordsValues() []SyncKerberosPasswords { + return []SyncKerberosPasswords{SyncKerberosPasswordsDisabled, SyncKerberosPasswordsEnabled} +} + +// SyncNtlmPasswords enumerates the values for sync ntlm passwords. +type SyncNtlmPasswords string + +const ( + // SyncNtlmPasswordsDisabled ... + SyncNtlmPasswordsDisabled SyncNtlmPasswords = "Disabled" + // SyncNtlmPasswordsEnabled ... + SyncNtlmPasswordsEnabled SyncNtlmPasswords = "Enabled" +) + +// PossibleSyncNtlmPasswordsValues returns an array of possible values for the SyncNtlmPasswords const type. +func PossibleSyncNtlmPasswordsValues() []SyncNtlmPasswords { + return []SyncNtlmPasswords{SyncNtlmPasswordsDisabled, SyncNtlmPasswordsEnabled} +} + +// SyncOnPremPasswords enumerates the values for sync on prem passwords. +type SyncOnPremPasswords string + +const ( + // SyncOnPremPasswordsDisabled ... + SyncOnPremPasswordsDisabled SyncOnPremPasswords = "Disabled" + // SyncOnPremPasswordsEnabled ... + SyncOnPremPasswordsEnabled SyncOnPremPasswords = "Enabled" +) + +// PossibleSyncOnPremPasswordsValues returns an array of possible values for the SyncOnPremPasswords const type. +func PossibleSyncOnPremPasswordsValues() []SyncOnPremPasswords { + return []SyncOnPremPasswords{SyncOnPremPasswordsDisabled, SyncOnPremPasswordsEnabled} +} + +// TLSV1 enumerates the values for tlsv1. +type TLSV1 string + +const ( + // TLSV1Disabled ... + TLSV1Disabled TLSV1 = "Disabled" + // TLSV1Enabled ... + TLSV1Enabled TLSV1 = "Enabled" +) + +// PossibleTLSV1Values returns an array of possible values for the TLSV1 const type. +func PossibleTLSV1Values() []TLSV1 { + return []TLSV1{TLSV1Disabled, TLSV1Enabled} +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/models.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/models.go new file mode 100644 index 000000000000..fe31df5f8136 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/models.go @@ -0,0 +1,1334 @@ +package aad + +// 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" + "encoding/json" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/autorest/date" + "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/domainservices/mgmt/2020-01-01/aad" + +// CloudError an error response from the Domain Services. +type CloudError struct { + // Error - An error response from the Domain Services. + Error *CloudErrorBody `json:"error,omitempty"` +} + +// CloudErrorBody an error response from the Domain Services. +type CloudErrorBody struct { + // Code - An identifier for the error. Codes are invariant and are intended to be consumed programmatically. + Code *string `json:"code,omitempty"` + // Message - A message describing the error, intended to be suitable for display in a user interface. + Message *string `json:"message,omitempty"` + // Target - The target of the particular error. For example, the name of the property in error. + Target *string `json:"target,omitempty"` + // Details - A list of additional details about the error. + Details *[]CloudErrorBody `json:"details,omitempty"` +} + +// ContainerAccount container Account Description +type ContainerAccount struct { + // AccountName - The account name + AccountName *string `json:"accountName,omitempty"` + // Spn - The account spn + Spn *string `json:"spn,omitempty"` + // Password - The account password + Password *string `json:"password,omitempty"` +} + +// DomainSecuritySettings domain Security Settings +type DomainSecuritySettings struct { + // NtlmV1 - A flag to determine whether or not NtlmV1 is enabled or disabled. Possible values include: 'NtlmV1Enabled', 'NtlmV1Disabled' + NtlmV1 NtlmV1 `json:"ntlmV1,omitempty"` + // TLSV1 - A flag to determine whether or not TlsV1 is enabled or disabled. Possible values include: 'TLSV1Enabled', 'TLSV1Disabled' + TLSV1 TLSV1 `json:"tlsV1,omitempty"` + // SyncNtlmPasswords - A flag to determine whether or not SyncNtlmPasswords is enabled or disabled. Possible values include: 'SyncNtlmPasswordsEnabled', 'SyncNtlmPasswordsDisabled' + SyncNtlmPasswords SyncNtlmPasswords `json:"syncNtlmPasswords,omitempty"` + // SyncKerberosPasswords - A flag to determine whether or not SyncKerberosPasswords is enabled or disabled. Possible values include: 'SyncKerberosPasswordsEnabled', 'SyncKerberosPasswordsDisabled' + SyncKerberosPasswords SyncKerberosPasswords `json:"syncKerberosPasswords,omitempty"` + // SyncOnPremPasswords - A flag to determine whether or not SyncOnPremPasswords is enabled or disabled. Possible values include: 'SyncOnPremPasswordsEnabled', 'SyncOnPremPasswordsDisabled' + SyncOnPremPasswords SyncOnPremPasswords `json:"syncOnPremPasswords,omitempty"` +} + +// DomainService domain service. +type DomainService struct { + autorest.Response `json:"-"` + // DomainServiceProperties - Domain service properties + *DomainServiceProperties `json:"properties,omitempty"` + // ID - READ-ONLY; Resource Id + ID *string `json:"id,omitempty"` + // Name - READ-ONLY; Resource name + Name *string `json:"name,omitempty"` + // Type - READ-ONLY; Resource type + Type *string `json:"type,omitempty"` + // Location - Resource location + Location *string `json:"location,omitempty"` + // Tags - Resource tags + Tags map[string]*string `json:"tags"` + // Etag - Resource etag + Etag *string `json:"etag,omitempty"` +} + +// MarshalJSON is the custom marshaler for DomainService. +func (ds DomainService) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if ds.DomainServiceProperties != nil { + objectMap["properties"] = ds.DomainServiceProperties + } + if ds.Location != nil { + objectMap["location"] = ds.Location + } + if ds.Tags != nil { + objectMap["tags"] = ds.Tags + } + if ds.Etag != nil { + objectMap["etag"] = ds.Etag + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for DomainService struct. +func (ds *DomainService) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var domainServiceProperties DomainServiceProperties + err = json.Unmarshal(*v, &domainServiceProperties) + if err != nil { + return err + } + ds.DomainServiceProperties = &domainServiceProperties + } + case "id": + if v != nil { + var ID string + err = json.Unmarshal(*v, &ID) + if err != nil { + return err + } + ds.ID = &ID + } + case "name": + if v != nil { + var name string + err = json.Unmarshal(*v, &name) + if err != nil { + return err + } + ds.Name = &name + } + case "type": + if v != nil { + var typeVar string + err = json.Unmarshal(*v, &typeVar) + if err != nil { + return err + } + ds.Type = &typeVar + } + case "location": + if v != nil { + var location string + err = json.Unmarshal(*v, &location) + if err != nil { + return err + } + ds.Location = &location + } + case "tags": + if v != nil { + var tags map[string]*string + err = json.Unmarshal(*v, &tags) + if err != nil { + return err + } + ds.Tags = tags + } + case "etag": + if v != nil { + var etag string + err = json.Unmarshal(*v, &etag) + if err != nil { + return err + } + ds.Etag = &etag + } + } + } + + return nil +} + +// DomainServiceListResult the response from the List Domain Services operation. +type DomainServiceListResult struct { + autorest.Response `json:"-"` + // Value - the list of domain services. + Value *[]DomainService `json:"value,omitempty"` + // NextLink - READ-ONLY; The continuation token for the next page of results. + NextLink *string `json:"nextLink,omitempty"` +} + +// MarshalJSON is the custom marshaler for DomainServiceListResult. +func (dslr DomainServiceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if dslr.Value != nil { + objectMap["value"] = dslr.Value + } + return json.Marshal(objectMap) +} + +// DomainServiceListResultIterator provides access to a complete listing of DomainService values. +type DomainServiceListResultIterator struct { + i int + page DomainServiceListResultPage +} + +// 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 *DomainServiceListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServiceListResultIterator.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 *DomainServiceListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter DomainServiceListResultIterator) 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 DomainServiceListResultIterator) Response() DomainServiceListResult { + 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 DomainServiceListResultIterator) Value() DomainService { + if !iter.page.NotDone() { + return DomainService{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the DomainServiceListResultIterator type. +func NewDomainServiceListResultIterator(page DomainServiceListResultPage) DomainServiceListResultIterator { + return DomainServiceListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (dslr DomainServiceListResult) IsEmpty() bool { + return dslr.Value == nil || len(*dslr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (dslr DomainServiceListResult) hasNextLink() bool { + return dslr.NextLink != nil && len(*dslr.NextLink) != 0 +} + +// domainServiceListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (dslr DomainServiceListResult) domainServiceListResultPreparer(ctx context.Context) (*http.Request, error) { + if !dslr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(dslr.NextLink))) +} + +// DomainServiceListResultPage contains a page of DomainService values. +type DomainServiceListResultPage struct { + fn func(context.Context, DomainServiceListResult) (DomainServiceListResult, error) + dslr DomainServiceListResult +} + +// 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 *DomainServiceListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/DomainServiceListResultPage.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.dslr) + if err != nil { + return err + } + page.dslr = 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 *DomainServiceListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page DomainServiceListResultPage) NotDone() bool { + return !page.dslr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page DomainServiceListResultPage) Response() DomainServiceListResult { + return page.dslr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page DomainServiceListResultPage) Values() []DomainService { + if page.dslr.IsEmpty() { + return nil + } + return *page.dslr.Value +} + +// Creates a new instance of the DomainServiceListResultPage type. +func NewDomainServiceListResultPage(cur DomainServiceListResult, getNextPage func(context.Context, DomainServiceListResult) (DomainServiceListResult, error)) DomainServiceListResultPage { + return DomainServiceListResultPage{ + fn: getNextPage, + dslr: cur, + } +} + +// DomainServiceProperties properties of the Domain Service. +type DomainServiceProperties struct { + // Version - READ-ONLY; Data Model Version + Version *int32 `json:"version,omitempty"` + // TenantID - READ-ONLY; Azure Active Directory Tenant Id + TenantID *string `json:"tenantId,omitempty"` + // DomainName - The name of the Azure domain that the user would like to deploy Domain Services to. + DomainName *string `json:"domainName,omitempty"` + // DeploymentID - READ-ONLY; Deployment Id + DeploymentID *string `json:"deploymentId,omitempty"` + // SyncOwner - READ-ONLY; SyncOwner ReplicaSet Id + SyncOwner *string `json:"syncOwner,omitempty"` + // ReplicaSets - List of ReplicaSets + ReplicaSets *[]ReplicaSet `json:"replicaSets,omitempty"` + // LdapsSettings - Secure LDAP Settings + LdapsSettings *LdapsSettings `json:"ldapsSettings,omitempty"` + // ResourceForestSettings - Resource Forest Settings + ResourceForestSettings *ResourceForestSettings `json:"resourceForestSettings,omitempty"` + // DomainSecuritySettings - DomainSecurity Settings + DomainSecuritySettings *DomainSecuritySettings `json:"domainSecuritySettings,omitempty"` + // DomainConfigurationType - Domain Configuration Type + DomainConfigurationType *string `json:"domainConfigurationType,omitempty"` + // Sku - Sku Type + Sku *string `json:"sku,omitempty"` + // FilteredSync - Enabled or Disabled flag to turn on Group-based filtered sync. Possible values include: 'FilteredSyncEnabled', 'FilteredSyncDisabled' + FilteredSync FilteredSync `json:"filteredSync,omitempty"` + // NotificationSettings - Notification Settings + NotificationSettings *NotificationSettings `json:"notificationSettings,omitempty"` + // ProvisioningState - READ-ONLY; the current deployment or provisioning state, which only appears in the response. + ProvisioningState *string `json:"provisioningState,omitempty"` +} + +// MarshalJSON is the custom marshaler for DomainServiceProperties. +func (dsp DomainServiceProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if dsp.DomainName != nil { + objectMap["domainName"] = dsp.DomainName + } + if dsp.ReplicaSets != nil { + objectMap["replicaSets"] = dsp.ReplicaSets + } + if dsp.LdapsSettings != nil { + objectMap["ldapsSettings"] = dsp.LdapsSettings + } + if dsp.ResourceForestSettings != nil { + objectMap["resourceForestSettings"] = dsp.ResourceForestSettings + } + if dsp.DomainSecuritySettings != nil { + objectMap["domainSecuritySettings"] = dsp.DomainSecuritySettings + } + if dsp.DomainConfigurationType != nil { + objectMap["domainConfigurationType"] = dsp.DomainConfigurationType + } + if dsp.Sku != nil { + objectMap["sku"] = dsp.Sku + } + if dsp.FilteredSync != "" { + objectMap["filteredSync"] = dsp.FilteredSync + } + if dsp.NotificationSettings != nil { + objectMap["notificationSettings"] = dsp.NotificationSettings + } + return json.Marshal(objectMap) +} + +// DomainServicesCreateOrUpdateFuture an abstraction for monitoring and retrieving the results of a +// long-running operation. +type DomainServicesCreateOrUpdateFuture struct { + azure.FutureAPI + // Result returns the result of the asynchronous operation. + // If the operation has not completed it will return an error. + Result func(DomainServicesClient) (DomainService, error) +} + +// UnmarshalJSON is the custom unmarshaller for CreateFuture. +func (future *DomainServicesCreateOrUpdateFuture) UnmarshalJSON(body []byte) error { + var azFuture azure.Future + if err := json.Unmarshal(body, &azFuture); err != nil { + return err + } + future.FutureAPI = &azFuture + future.Result = future.result + return nil +} + +// result is the default implementation for DomainServicesCreateOrUpdateFuture.Result. +func (future *DomainServicesCreateOrUpdateFuture) result(client DomainServicesClient) (ds DomainService, err error) { + var done bool + done, err = future.DoneWithContext(context.Background(), client) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesCreateOrUpdateFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + ds.Response.Response = future.Response() + err = azure.NewAsyncOpIncompleteError("aad.DomainServicesCreateOrUpdateFuture") + return + } + sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) + if ds.Response.Response, err = future.GetResult(sender); err == nil && ds.Response.Response.StatusCode != http.StatusNoContent { + ds, err = client.CreateOrUpdateResponder(ds.Response.Response) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesCreateOrUpdateFuture", "Result", ds.Response.Response, "Failure responding to request") + } + } + return +} + +// DomainServicesDeleteFuture an abstraction for monitoring and retrieving the results of a long-running +// operation. +type DomainServicesDeleteFuture struct { + azure.FutureAPI + // Result returns the result of the asynchronous operation. + // If the operation has not completed it will return an error. + Result func(DomainServicesClient) (autorest.Response, error) +} + +// UnmarshalJSON is the custom unmarshaller for CreateFuture. +func (future *DomainServicesDeleteFuture) UnmarshalJSON(body []byte) error { + var azFuture azure.Future + if err := json.Unmarshal(body, &azFuture); err != nil { + return err + } + future.FutureAPI = &azFuture + future.Result = future.result + return nil +} + +// result is the default implementation for DomainServicesDeleteFuture.Result. +func (future *DomainServicesDeleteFuture) result(client DomainServicesClient) (ar autorest.Response, err error) { + var done bool + done, err = future.DoneWithContext(context.Background(), client) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesDeleteFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + ar.Response = future.Response() + err = azure.NewAsyncOpIncompleteError("aad.DomainServicesDeleteFuture") + return + } + ar.Response = future.Response() + return +} + +// DomainServicesUpdateFuture an abstraction for monitoring and retrieving the results of a long-running +// operation. +type DomainServicesUpdateFuture struct { + azure.FutureAPI + // Result returns the result of the asynchronous operation. + // If the operation has not completed it will return an error. + Result func(DomainServicesClient) (DomainService, error) +} + +// UnmarshalJSON is the custom unmarshaller for CreateFuture. +func (future *DomainServicesUpdateFuture) UnmarshalJSON(body []byte) error { + var azFuture azure.Future + if err := json.Unmarshal(body, &azFuture); err != nil { + return err + } + future.FutureAPI = &azFuture + future.Result = future.result + return nil +} + +// result is the default implementation for DomainServicesUpdateFuture.Result. +func (future *DomainServicesUpdateFuture) result(client DomainServicesClient) (ds DomainService, err error) { + var done bool + done, err = future.DoneWithContext(context.Background(), client) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesUpdateFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + ds.Response.Response = future.Response() + err = azure.NewAsyncOpIncompleteError("aad.DomainServicesUpdateFuture") + return + } + sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) + if ds.Response.Response, err = future.GetResult(sender); err == nil && ds.Response.Response.StatusCode != http.StatusNoContent { + ds, err = client.UpdateResponder(ds.Response.Response) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.DomainServicesUpdateFuture", "Result", ds.Response.Response, "Failure responding to request") + } + } + return +} + +// ForestTrust forest Trust Setting +type ForestTrust struct { + // TrustedDomainFqdn - Trusted Domain FQDN + TrustedDomainFqdn *string `json:"trustedDomainFqdn,omitempty"` + // TrustDirection - Trust Direction + TrustDirection *string `json:"trustDirection,omitempty"` + // FriendlyName - Friendly Name + FriendlyName *string `json:"friendlyName,omitempty"` + // RemoteDNSIps - Remote Dns ips + RemoteDNSIps *string `json:"remoteDnsIps,omitempty"` + // TrustPassword - Trust Password + TrustPassword *string `json:"trustPassword,omitempty"` +} + +// HealthAlert health Alert Description +type HealthAlert struct { + // ID - READ-ONLY; Health Alert Id + ID *string `json:"id,omitempty"` + // Name - READ-ONLY; Health Alert Name + Name *string `json:"name,omitempty"` + // Issue - READ-ONLY; Health Alert Issue + Issue *string `json:"issue,omitempty"` + // Severity - READ-ONLY; Health Alert Severity + Severity *string `json:"severity,omitempty"` + // Raised - READ-ONLY; Health Alert Raised DateTime + Raised *date.Time `json:"raised,omitempty"` + // LastDetected - READ-ONLY; Health Alert Last Detected DateTime + LastDetected *date.Time `json:"lastDetected,omitempty"` + // ResolutionURI - READ-ONLY; Health Alert TSG Link + ResolutionURI *string `json:"resolutionUri,omitempty"` +} + +// MarshalJSON is the custom marshaler for HealthAlert. +func (ha HealthAlert) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// HealthMonitor health Monitor Description +type HealthMonitor struct { + // ID - READ-ONLY; Health Monitor Id + ID *string `json:"id,omitempty"` + // Name - READ-ONLY; Health Monitor Name + Name *string `json:"name,omitempty"` + // Details - READ-ONLY; Health Monitor Details + Details *string `json:"details,omitempty"` +} + +// MarshalJSON is the custom marshaler for HealthMonitor. +func (hm HealthMonitor) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + return json.Marshal(objectMap) +} + +// LdapsSettings secure LDAP Settings +type LdapsSettings struct { + // Ldaps - A flag to determine whether or not Secure LDAP is enabled or disabled. Possible values include: 'LdapsEnabled', 'LdapsDisabled' + Ldaps Ldaps `json:"ldaps,omitempty"` + // PfxCertificate - The certificate required to configure Secure LDAP. The parameter passed here should be a base64encoded representation of the certificate pfx file. + PfxCertificate *string `json:"pfxCertificate,omitempty"` + // PfxCertificatePassword - The password to decrypt the provided Secure LDAP certificate pfx file. + PfxCertificatePassword *string `json:"pfxCertificatePassword,omitempty"` + // PublicCertificate - READ-ONLY; Public certificate used to configure secure ldap. + PublicCertificate *string `json:"publicCertificate,omitempty"` + // CertificateThumbprint - READ-ONLY; Thumbprint of configure ldaps certificate. + CertificateThumbprint *string `json:"certificateThumbprint,omitempty"` + // CertificateNotAfter - READ-ONLY; NotAfter DateTime of configure ldaps certificate. + CertificateNotAfter *date.Time `json:"certificateNotAfter,omitempty"` + // ExternalAccess - A flag to determine whether or not Secure LDAP access over the internet is enabled or disabled. Possible values include: 'Enabled', 'Disabled' + ExternalAccess ExternalAccess `json:"externalAccess,omitempty"` +} + +// MarshalJSON is the custom marshaler for LdapsSettings. +func (ls LdapsSettings) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if ls.Ldaps != "" { + objectMap["ldaps"] = ls.Ldaps + } + if ls.PfxCertificate != nil { + objectMap["pfxCertificate"] = ls.PfxCertificate + } + if ls.PfxCertificatePassword != nil { + objectMap["pfxCertificatePassword"] = ls.PfxCertificatePassword + } + if ls.ExternalAccess != "" { + objectMap["externalAccess"] = ls.ExternalAccess + } + return json.Marshal(objectMap) +} + +// NotificationSettings settings for notification +type NotificationSettings struct { + // NotifyGlobalAdmins - Should global admins be notified. Possible values include: 'NotifyGlobalAdminsEnabled', 'NotifyGlobalAdminsDisabled' + NotifyGlobalAdmins NotifyGlobalAdmins `json:"notifyGlobalAdmins,omitempty"` + // NotifyDcAdmins - Should domain controller admins be notified. Possible values include: 'NotifyDcAdminsEnabled', 'NotifyDcAdminsDisabled' + NotifyDcAdmins NotifyDcAdmins `json:"notifyDcAdmins,omitempty"` + // AdditionalRecipients - The list of additional recipients + AdditionalRecipients *[]string `json:"additionalRecipients,omitempty"` +} + +// OperationDisplayInfo the operation supported by Domain Services. +type OperationDisplayInfo struct { + // Description - The description of the operation. + Description *string `json:"description,omitempty"` + // Operation - The action that users can perform, based on their permission level. + Operation *string `json:"operation,omitempty"` + // Provider - Service provider: Domain Services. + Provider *string `json:"provider,omitempty"` + // Resource - Resource on which the operation is performed. + Resource *string `json:"resource,omitempty"` +} + +// OperationEntity the operation supported by Domain Services. +type OperationEntity struct { + // Name - Operation name: {provider}/{resource}/{operation}. + Name *string `json:"name,omitempty"` + // Display - The operation supported by Domain Services. + Display *OperationDisplayInfo `json:"display,omitempty"` + // Origin - The origin of the operation. + Origin *string `json:"origin,omitempty"` +} + +// OperationEntityListResult the list of domain service operation response. +type OperationEntityListResult struct { + autorest.Response `json:"-"` + // Value - The list of operations. + Value *[]OperationEntity `json:"value,omitempty"` + // NextLink - READ-ONLY; The continuation token for the next page of results. + NextLink *string `json:"nextLink,omitempty"` +} + +// MarshalJSON is the custom marshaler for OperationEntityListResult. +func (oelr OperationEntityListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if oelr.Value != nil { + objectMap["value"] = oelr.Value + } + return json.Marshal(objectMap) +} + +// OperationEntityListResultIterator provides access to a complete listing of OperationEntity values. +type OperationEntityListResultIterator struct { + i int + page OperationEntityListResultPage +} + +// 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 *OperationEntityListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationEntityListResultIterator.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 *OperationEntityListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter OperationEntityListResultIterator) 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 OperationEntityListResultIterator) Response() OperationEntityListResult { + 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 OperationEntityListResultIterator) Value() OperationEntity { + if !iter.page.NotDone() { + return OperationEntity{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the OperationEntityListResultIterator type. +func NewOperationEntityListResultIterator(page OperationEntityListResultPage) OperationEntityListResultIterator { + return OperationEntityListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (oelr OperationEntityListResult) IsEmpty() bool { + return oelr.Value == nil || len(*oelr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (oelr OperationEntityListResult) hasNextLink() bool { + return oelr.NextLink != nil && len(*oelr.NextLink) != 0 +} + +// operationEntityListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (oelr OperationEntityListResult) operationEntityListResultPreparer(ctx context.Context) (*http.Request, error) { + if !oelr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(oelr.NextLink))) +} + +// OperationEntityListResultPage contains a page of OperationEntity values. +type OperationEntityListResultPage struct { + fn func(context.Context, OperationEntityListResult) (OperationEntityListResult, error) + oelr OperationEntityListResult +} + +// 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 *OperationEntityListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OperationEntityListResultPage.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.oelr) + if err != nil { + return err + } + page.oelr = 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 *OperationEntityListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page OperationEntityListResultPage) NotDone() bool { + return !page.oelr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page OperationEntityListResultPage) Response() OperationEntityListResult { + return page.oelr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page OperationEntityListResultPage) Values() []OperationEntity { + if page.oelr.IsEmpty() { + return nil + } + return *page.oelr.Value +} + +// Creates a new instance of the OperationEntityListResultPage type. +func NewOperationEntityListResultPage(cur OperationEntityListResult, getNextPage func(context.Context, OperationEntityListResult) (OperationEntityListResult, error)) OperationEntityListResultPage { + return OperationEntityListResultPage{ + fn: getNextPage, + oelr: cur, + } +} + +// OuContainer resource for OuContainer. +type OuContainer struct { + autorest.Response `json:"-"` + // OuContainerProperties - OuContainer properties + *OuContainerProperties `json:"properties,omitempty"` + // ID - READ-ONLY; Resource Id + ID *string `json:"id,omitempty"` + // Name - READ-ONLY; Resource name + Name *string `json:"name,omitempty"` + // Type - READ-ONLY; Resource type + Type *string `json:"type,omitempty"` + // Location - Resource location + Location *string `json:"location,omitempty"` + // Tags - Resource tags + Tags map[string]*string `json:"tags"` + // Etag - Resource etag + Etag *string `json:"etag,omitempty"` +} + +// MarshalJSON is the custom marshaler for OuContainer. +func (oc OuContainer) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if oc.OuContainerProperties != nil { + objectMap["properties"] = oc.OuContainerProperties + } + if oc.Location != nil { + objectMap["location"] = oc.Location + } + if oc.Tags != nil { + objectMap["tags"] = oc.Tags + } + if oc.Etag != nil { + objectMap["etag"] = oc.Etag + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for OuContainer struct. +func (oc *OuContainer) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var ouContainerProperties OuContainerProperties + err = json.Unmarshal(*v, &ouContainerProperties) + if err != nil { + return err + } + oc.OuContainerProperties = &ouContainerProperties + } + case "id": + if v != nil { + var ID string + err = json.Unmarshal(*v, &ID) + if err != nil { + return err + } + oc.ID = &ID + } + case "name": + if v != nil { + var name string + err = json.Unmarshal(*v, &name) + if err != nil { + return err + } + oc.Name = &name + } + case "type": + if v != nil { + var typeVar string + err = json.Unmarshal(*v, &typeVar) + if err != nil { + return err + } + oc.Type = &typeVar + } + case "location": + if v != nil { + var location string + err = json.Unmarshal(*v, &location) + if err != nil { + return err + } + oc.Location = &location + } + case "tags": + if v != nil { + var tags map[string]*string + err = json.Unmarshal(*v, &tags) + if err != nil { + return err + } + oc.Tags = tags + } + case "etag": + if v != nil { + var etag string + err = json.Unmarshal(*v, &etag) + if err != nil { + return err + } + oc.Etag = &etag + } + } + } + + return nil +} + +// OuContainerCreateFuture an abstraction for monitoring and retrieving the results of a long-running +// operation. +type OuContainerCreateFuture struct { + azure.FutureAPI + // Result returns the result of the asynchronous operation. + // If the operation has not completed it will return an error. + Result func(OuContainerClient) (OuContainer, error) +} + +// UnmarshalJSON is the custom unmarshaller for CreateFuture. +func (future *OuContainerCreateFuture) UnmarshalJSON(body []byte) error { + var azFuture azure.Future + if err := json.Unmarshal(body, &azFuture); err != nil { + return err + } + future.FutureAPI = &azFuture + future.Result = future.result + return nil +} + +// result is the default implementation for OuContainerCreateFuture.Result. +func (future *OuContainerCreateFuture) result(client OuContainerClient) (oc OuContainer, err error) { + var done bool + done, err = future.DoneWithContext(context.Background(), client) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerCreateFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + oc.Response.Response = future.Response() + err = azure.NewAsyncOpIncompleteError("aad.OuContainerCreateFuture") + return + } + sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) + if oc.Response.Response, err = future.GetResult(sender); err == nil && oc.Response.Response.StatusCode != http.StatusNoContent { + oc, err = client.CreateResponder(oc.Response.Response) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerCreateFuture", "Result", oc.Response.Response, "Failure responding to request") + } + } + return +} + +// OuContainerDeleteFuture an abstraction for monitoring and retrieving the results of a long-running +// operation. +type OuContainerDeleteFuture struct { + azure.FutureAPI + // Result returns the result of the asynchronous operation. + // If the operation has not completed it will return an error. + Result func(OuContainerClient) (autorest.Response, error) +} + +// UnmarshalJSON is the custom unmarshaller for CreateFuture. +func (future *OuContainerDeleteFuture) UnmarshalJSON(body []byte) error { + var azFuture azure.Future + if err := json.Unmarshal(body, &azFuture); err != nil { + return err + } + future.FutureAPI = &azFuture + future.Result = future.result + return nil +} + +// result is the default implementation for OuContainerDeleteFuture.Result. +func (future *OuContainerDeleteFuture) result(client OuContainerClient) (ar autorest.Response, err error) { + var done bool + done, err = future.DoneWithContext(context.Background(), client) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerDeleteFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + ar.Response = future.Response() + err = azure.NewAsyncOpIncompleteError("aad.OuContainerDeleteFuture") + return + } + ar.Response = future.Response() + return +} + +// OuContainerListResult the response from the List OuContainer operation. +type OuContainerListResult struct { + autorest.Response `json:"-"` + // Value - The list of OuContainer. + Value *[]OuContainer `json:"value,omitempty"` + // NextLink - READ-ONLY; The continuation token for the next page of results. + NextLink *string `json:"nextLink,omitempty"` +} + +// MarshalJSON is the custom marshaler for OuContainerListResult. +func (oclr OuContainerListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if oclr.Value != nil { + objectMap["value"] = oclr.Value + } + return json.Marshal(objectMap) +} + +// OuContainerListResultIterator provides access to a complete listing of OuContainer values. +type OuContainerListResultIterator struct { + i int + page OuContainerListResultPage +} + +// 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 *OuContainerListResultIterator) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerListResultIterator.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 *OuContainerListResultIterator) Next() error { + return iter.NextWithContext(context.Background()) +} + +// NotDone returns true if the enumeration should be started or is not yet complete. +func (iter OuContainerListResultIterator) 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 OuContainerListResultIterator) Response() OuContainerListResult { + 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 OuContainerListResultIterator) Value() OuContainer { + if !iter.page.NotDone() { + return OuContainer{} + } + return iter.page.Values()[iter.i] +} + +// Creates a new instance of the OuContainerListResultIterator type. +func NewOuContainerListResultIterator(page OuContainerListResultPage) OuContainerListResultIterator { + return OuContainerListResultIterator{page: page} +} + +// IsEmpty returns true if the ListResult contains no values. +func (oclr OuContainerListResult) IsEmpty() bool { + return oclr.Value == nil || len(*oclr.Value) == 0 +} + +// hasNextLink returns true if the NextLink is not empty. +func (oclr OuContainerListResult) hasNextLink() bool { + return oclr.NextLink != nil && len(*oclr.NextLink) != 0 +} + +// ouContainerListResultPreparer prepares a request to retrieve the next set of results. +// It returns nil if no more results exist. +func (oclr OuContainerListResult) ouContainerListResultPreparer(ctx context.Context) (*http.Request, error) { + if !oclr.hasNextLink() { + return nil, nil + } + return autorest.Prepare((&http.Request{}).WithContext(ctx), + autorest.AsJSON(), + autorest.AsGet(), + autorest.WithBaseURL(to.String(oclr.NextLink))) +} + +// OuContainerListResultPage contains a page of OuContainer values. +type OuContainerListResultPage struct { + fn func(context.Context, OuContainerListResult) (OuContainerListResult, error) + oclr OuContainerListResult +} + +// 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 *OuContainerListResultPage) NextWithContext(ctx context.Context) (err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerListResultPage.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.oclr) + if err != nil { + return err + } + page.oclr = 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 *OuContainerListResultPage) Next() error { + return page.NextWithContext(context.Background()) +} + +// NotDone returns true if the page enumeration should be started or is not yet complete. +func (page OuContainerListResultPage) NotDone() bool { + return !page.oclr.IsEmpty() +} + +// Response returns the raw server response from the last page request. +func (page OuContainerListResultPage) Response() OuContainerListResult { + return page.oclr +} + +// Values returns the slice of values for the current page or nil if there are no values. +func (page OuContainerListResultPage) Values() []OuContainer { + if page.oclr.IsEmpty() { + return nil + } + return *page.oclr.Value +} + +// Creates a new instance of the OuContainerListResultPage type. +func NewOuContainerListResultPage(cur OuContainerListResult, getNextPage func(context.Context, OuContainerListResult) (OuContainerListResult, error)) OuContainerListResultPage { + return OuContainerListResultPage{ + fn: getNextPage, + oclr: cur, + } +} + +// OuContainerProperties properties of the OuContainer. +type OuContainerProperties struct { + // TenantID - READ-ONLY; Azure Active Directory tenant id + TenantID *string `json:"tenantId,omitempty"` + // DomainName - READ-ONLY; The domain name of Domain Services. + DomainName *string `json:"domainName,omitempty"` + // DeploymentID - READ-ONLY; The Deployment id + DeploymentID *string `json:"deploymentId,omitempty"` + // ContainerID - READ-ONLY; The OuContainer name + ContainerID *string `json:"containerId,omitempty"` + // Accounts - The list of container accounts + Accounts *[]ContainerAccount `json:"accounts,omitempty"` + // ServiceStatus - READ-ONLY; Status of OuContainer instance + ServiceStatus *string `json:"serviceStatus,omitempty"` + // DistinguishedName - READ-ONLY; Distinguished Name of OuContainer instance + DistinguishedName *string `json:"distinguishedName,omitempty"` + // ProvisioningState - READ-ONLY; The current deployment or provisioning state, which only appears in the response. + ProvisioningState *string `json:"provisioningState,omitempty"` +} + +// MarshalJSON is the custom marshaler for OuContainerProperties. +func (ocp OuContainerProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if ocp.Accounts != nil { + objectMap["accounts"] = ocp.Accounts + } + return json.Marshal(objectMap) +} + +// OuContainerUpdateFuture an abstraction for monitoring and retrieving the results of a long-running +// operation. +type OuContainerUpdateFuture struct { + azure.FutureAPI + // Result returns the result of the asynchronous operation. + // If the operation has not completed it will return an error. + Result func(OuContainerClient) (OuContainer, error) +} + +// UnmarshalJSON is the custom unmarshaller for CreateFuture. +func (future *OuContainerUpdateFuture) UnmarshalJSON(body []byte) error { + var azFuture azure.Future + if err := json.Unmarshal(body, &azFuture); err != nil { + return err + } + future.FutureAPI = &azFuture + future.Result = future.result + return nil +} + +// result is the default implementation for OuContainerUpdateFuture.Result. +func (future *OuContainerUpdateFuture) result(client OuContainerClient) (oc OuContainer, err error) { + var done bool + done, err = future.DoneWithContext(context.Background(), client) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerUpdateFuture", "Result", future.Response(), "Polling failure") + return + } + if !done { + oc.Response.Response = future.Response() + err = azure.NewAsyncOpIncompleteError("aad.OuContainerUpdateFuture") + return + } + sender := autorest.DecorateSender(client, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) + if oc.Response.Response, err = future.GetResult(sender); err == nil && oc.Response.Response.StatusCode != http.StatusNoContent { + oc, err = client.UpdateResponder(oc.Response.Response) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerUpdateFuture", "Result", oc.Response.Response, "Failure responding to request") + } + } + return +} + +// ReplicaSet replica Set Definition +type ReplicaSet struct { + // ReplicaSetID - READ-ONLY; ReplicaSet Id + ReplicaSetID *string `json:"replicaSetId,omitempty"` + // Location - Virtual network location + Location *string `json:"location,omitempty"` + // VnetSiteID - READ-ONLY; Virtual network site id + VnetSiteID *string `json:"vnetSiteId,omitempty"` + // SubnetID - The name of the virtual network that Domain Services will be deployed on. The id of the subnet that Domain Services will be deployed on. /virtualNetwork/vnetName/subnets/subnetName. + SubnetID *string `json:"subnetId,omitempty"` + // DomainControllerIPAddress - READ-ONLY; List of Domain Controller IP Address + DomainControllerIPAddress *[]string `json:"domainControllerIpAddress,omitempty"` + // ExternalAccessIPAddress - READ-ONLY; External access ip address. + ExternalAccessIPAddress *string `json:"externalAccessIpAddress,omitempty"` + // ServiceStatus - READ-ONLY; Status of Domain Service instance + ServiceStatus *string `json:"serviceStatus,omitempty"` + // HealthLastEvaluated - READ-ONLY; Last domain evaluation run DateTime + HealthLastEvaluated *date.TimeRFC1123 `json:"healthLastEvaluated,omitempty"` + // HealthMonitors - READ-ONLY; List of Domain Health Monitors + HealthMonitors *[]HealthMonitor `json:"healthMonitors,omitempty"` + // HealthAlerts - READ-ONLY; List of Domain Health Alerts + HealthAlerts *[]HealthAlert `json:"healthAlerts,omitempty"` +} + +// MarshalJSON is the custom marshaler for ReplicaSet. +func (rs ReplicaSet) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if rs.Location != nil { + objectMap["location"] = rs.Location + } + if rs.SubnetID != nil { + objectMap["subnetId"] = rs.SubnetID + } + return json.Marshal(objectMap) +} + +// Resource the Resource model definition. +type Resource struct { + // ID - READ-ONLY; Resource Id + ID *string `json:"id,omitempty"` + // Name - READ-ONLY; Resource name + Name *string `json:"name,omitempty"` + // Type - READ-ONLY; Resource type + Type *string `json:"type,omitempty"` + // Location - Resource location + Location *string `json:"location,omitempty"` + // Tags - Resource tags + Tags map[string]*string `json:"tags"` + // Etag - Resource etag + Etag *string `json:"etag,omitempty"` +} + +// MarshalJSON is the custom marshaler for Resource. +func (r Resource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if r.Location != nil { + objectMap["location"] = r.Location + } + if r.Tags != nil { + objectMap["tags"] = r.Tags + } + if r.Etag != nil { + objectMap["etag"] = r.Etag + } + return json.Marshal(objectMap) +} + +// ResourceForestSettings settings for Resource Forest +type ResourceForestSettings struct { + // Settings - List of settings for Resource Forest + Settings *[]ForestTrust `json:"settings,omitempty"` + // ResourceForest - Resource Forest + ResourceForest *string `json:"resourceForest,omitempty"` +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/oucontainer.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/oucontainer.go new file mode 100644 index 000000000000..a819296917fc --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/oucontainer.go @@ -0,0 +1,518 @@ +package aad + +// 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/autorest/validation" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// OuContainerClient is the the AAD Domain Services API. +type OuContainerClient struct { + BaseClient +} + +// NewOuContainerClient creates an instance of the OuContainerClient client. +func NewOuContainerClient(subscriptionID string) OuContainerClient { + return NewOuContainerClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewOuContainerClientWithBaseURI creates an instance of the OuContainerClient 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 NewOuContainerClientWithBaseURI(baseURI string, subscriptionID string) OuContainerClient { + return OuContainerClient{NewWithBaseURI(baseURI, subscriptionID)} +} + +// Create the Create OuContainer operation creates a new OuContainer under the specified Domain Service instance. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +// ouContainerName - the name of the OuContainer. +// containerAccount - container Account Description. +func (client OuContainerClient) Create(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string, containerAccount ContainerAccount) (result OuContainerCreateFuture, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerClient.Create") + defer func() { + sc := -1 + if result.FutureAPI != nil && result.FutureAPI.Response() != nil { + sc = result.FutureAPI.Response().StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.OuContainerClient", "Create", err.Error()) + } + + req, err := client.CreatePreparer(ctx, resourceGroupName, domainServiceName, ouContainerName, containerAccount) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Create", nil, "Failure preparing request") + return + } + + result, err = client.CreateSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Create", nil, "Failure sending request") + return + } + + return +} + +// CreatePreparer prepares the Create request. +func (client OuContainerClient) CreatePreparer(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string, containerAccount ContainerAccount) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "ouContainerName": autorest.Encode("path", ouContainerName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Aad/domainServices/{domainServiceName}/ouContainer/{ouContainerName}", pathParameters), + autorest.WithJSON(containerAccount), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// CreateSender sends the Create request. The method will close the +// http.Response Body if it receives an error. +func (client OuContainerClient) CreateSender(req *http.Request) (future OuContainerCreateFuture, err error) { + var resp *http.Response + resp, err = client.Send(req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + var azf azure.Future + azf, err = azure.NewFutureFromResponse(resp) + future.FutureAPI = &azf + future.Result = future.result + return +} + +// CreateResponder handles the response to the Create request. The method always +// closes the http.Response Body. +func (client OuContainerClient) CreateResponder(resp *http.Response) (result OuContainer, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusCreated, http.StatusAccepted), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// Delete the Delete OuContainer operation deletes specified OuContainer. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +// ouContainerName - the name of the OuContainer. +func (client OuContainerClient) Delete(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string) (result OuContainerDeleteFuture, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerClient.Delete") + defer func() { + sc := -1 + if result.FutureAPI != nil && result.FutureAPI.Response() != nil { + sc = result.FutureAPI.Response().StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.OuContainerClient", "Delete", err.Error()) + } + + req, err := client.DeletePreparer(ctx, resourceGroupName, domainServiceName, ouContainerName) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Delete", nil, "Failure preparing request") + return + } + + result, err = client.DeleteSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Delete", nil, "Failure sending request") + return + } + + return +} + +// DeletePreparer prepares the Delete request. +func (client OuContainerClient) DeletePreparer(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "ouContainerName": autorest.Encode("path", ouContainerName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsDelete(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Aad/domainServices/{domainServiceName}/ouContainer/{ouContainerName}", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// DeleteSender sends the Delete request. The method will close the +// http.Response Body if it receives an error. +func (client OuContainerClient) DeleteSender(req *http.Request) (future OuContainerDeleteFuture, err error) { + var resp *http.Response + resp, err = client.Send(req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + var azf azure.Future + azf, err = azure.NewFutureFromResponse(resp) + future.FutureAPI = &azf + future.Result = future.result + return +} + +// DeleteResponder handles the response to the Delete request. The method always +// closes the http.Response Body. +func (client OuContainerClient) DeleteResponder(resp *http.Response) (result autorest.Response, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted, http.StatusNoContent), + autorest.ByClosing()) + result.Response = resp + return +} + +// Get get OuContainer in DomainService instance. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +// ouContainerName - the name of the OuContainer. +func (client OuContainerClient) Get(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string) (result OuContainer, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerClient.Get") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.OuContainerClient", "Get", err.Error()) + } + + req, err := client.GetPreparer(ctx, resourceGroupName, domainServiceName, ouContainerName) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Get", nil, "Failure preparing request") + return + } + + resp, err := client.GetSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Get", resp, "Failure sending request") + return + } + + result, err = client.GetResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Get", resp, "Failure responding to request") + return + } + + return +} + +// GetPreparer prepares the Get request. +func (client OuContainerClient) GetPreparer(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "ouContainerName": autorest.Encode("path", ouContainerName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Aad/domainServices/{domainServiceName}/ouContainer/{ouContainerName}", 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 OuContainerClient) 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 OuContainerClient) GetResponder(resp *http.Response) (result OuContainer, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// List the List of OuContainers in DomainService instance. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +func (client OuContainerClient) List(ctx context.Context, resourceGroupName string, domainServiceName string) (result OuContainerListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerClient.List") + defer func() { + sc := -1 + if result.oclr.Response.Response != nil { + sc = result.oclr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.OuContainerClient", "List", err.Error()) + } + + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx, resourceGroupName, domainServiceName) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.oclr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "List", resp, "Failure sending request") + return + } + + result.oclr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "List", resp, "Failure responding to request") + return + } + if result.oclr.hasNextLink() && result.oclr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client OuContainerClient) ListPreparer(ctx context.Context, resourceGroupName string, domainServiceName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Aad/domainServices/{domainServiceName}/ouContainer", 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 OuContainerClient) 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 OuContainerClient) ListResponder(resp *http.Response) (result OuContainerListResult, 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 OuContainerClient) listNextResults(ctx context.Context, lastResults OuContainerListResult) (result OuContainerListResult, err error) { + req, err := lastResults.ouContainerListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "aad.OuContainerClient", "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, "aad.OuContainerClient", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client OuContainerClient) ListComplete(ctx context.Context, resourceGroupName string, domainServiceName string) (result OuContainerListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerClient.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, resourceGroupName, domainServiceName) + return +} + +// Update the Update OuContainer operation can be used to update the existing OuContainers. +// Parameters: +// resourceGroupName - the name of the resource group within the user's subscription. The name is case +// insensitive. +// domainServiceName - the name of the domain service. +// ouContainerName - the name of the OuContainer. +// containerAccount - container Account Description. +func (client OuContainerClient) Update(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string, containerAccount ContainerAccount) (result OuContainerUpdateFuture, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerClient.Update") + defer func() { + sc := -1 + if result.FutureAPI != nil && result.FutureAPI.Response() != nil { + sc = result.FutureAPI.Response().StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: resourceGroupName, + Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MaxLength, Rule: 90, Chain: nil}, + {Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}, + {Target: "resourceGroupName", Name: validation.Pattern, Rule: `^[-\w\._\(\)]+$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("aad.OuContainerClient", "Update", err.Error()) + } + + req, err := client.UpdatePreparer(ctx, resourceGroupName, domainServiceName, ouContainerName, containerAccount) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Update", nil, "Failure preparing request") + return + } + + result, err = client.UpdateSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerClient", "Update", nil, "Failure sending request") + return + } + + return +} + +// UpdatePreparer prepares the Update request. +func (client OuContainerClient) UpdatePreparer(ctx context.Context, resourceGroupName string, domainServiceName string, ouContainerName string, containerAccount ContainerAccount) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "domainServiceName": autorest.Encode("path", domainServiceName), + "ouContainerName": autorest.Encode("path", ouContainerName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPatch(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Aad/domainServices/{domainServiceName}/ouContainer/{ouContainerName}", pathParameters), + autorest.WithJSON(containerAccount), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// UpdateSender sends the Update request. The method will close the +// http.Response Body if it receives an error. +func (client OuContainerClient) UpdateSender(req *http.Request) (future OuContainerUpdateFuture, err error) { + var resp *http.Response + resp, err = client.Send(req, azure.DoRetryWithRegistration(client.Client)) + if err != nil { + return + } + var azf azure.Future + azf, err = azure.NewFutureFromResponse(resp) + future.FutureAPI = &azf + future.Result = future.result + return +} + +// UpdateResponder handles the response to the Update request. The method always +// closes the http.Response Body. +func (client OuContainerClient) UpdateResponder(resp *http.Response) (result OuContainer, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK, http.StatusAccepted), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/oucontaineroperations.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/oucontaineroperations.go new file mode 100644 index 000000000000..7a362cc3a67e --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/oucontaineroperations.go @@ -0,0 +1,141 @@ +package aad + +// 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" +) + +// OuContainerOperationsClient is the the AAD Domain Services API. +type OuContainerOperationsClient struct { + BaseClient +} + +// NewOuContainerOperationsClient creates an instance of the OuContainerOperationsClient client. +func NewOuContainerOperationsClient(subscriptionID string) OuContainerOperationsClient { + return NewOuContainerOperationsClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewOuContainerOperationsClientWithBaseURI creates an instance of the OuContainerOperationsClient 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 NewOuContainerOperationsClientWithBaseURI(baseURI string, subscriptionID string) OuContainerOperationsClient { + return OuContainerOperationsClient{NewWithBaseURI(baseURI, subscriptionID)} +} + +// List lists all the available OuContainer operations. +func (client OuContainerOperationsClient) List(ctx context.Context) (result OperationEntityListResultPage, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerOperationsClient.List") + defer func() { + sc := -1 + if result.oelr.Response.Response != nil { + sc = result.oelr.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + result.fn = client.listNextResults + req, err := client.ListPreparer(ctx) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerOperationsClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.oelr.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "aad.OuContainerOperationsClient", "List", resp, "Failure sending request") + return + } + + result.oelr, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerOperationsClient", "List", resp, "Failure responding to request") + return + } + if result.oelr.hasNextLink() && result.oelr.IsEmpty() { + err = result.NextWithContext(ctx) + return + } + + return +} + +// ListPreparer prepares the List request. +func (client OuContainerOperationsClient) ListPreparer(ctx context.Context) (*http.Request, error) { + const APIVersion = "2020-01-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPath("/providers/Microsoft.Aad/operations"), + 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 OuContainerOperationsClient) ListSender(req *http.Request) (*http.Response, error) { + return client.Send(req, autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client OuContainerOperationsClient) ListResponder(resp *http.Response) (result OperationEntityListResult, 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 OuContainerOperationsClient) listNextResults(ctx context.Context, lastResults OperationEntityListResult) (result OperationEntityListResult, err error) { + req, err := lastResults.operationEntityListResultPreparer(ctx) + if err != nil { + return result, autorest.NewErrorWithError(err, "aad.OuContainerOperationsClient", "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, "aad.OuContainerOperationsClient", "listNextResults", resp, "Failure sending next results request") + } + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "aad.OuContainerOperationsClient", "listNextResults", resp, "Failure responding to next results request") + } + return +} + +// ListComplete enumerates all values, automatically crossing page boundaries as required. +func (client OuContainerOperationsClient) ListComplete(ctx context.Context) (result OperationEntityListResultIterator, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/OuContainerOperationsClient.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) + return +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/version.go b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/version.go new file mode 100644 index 000000000000..69ad8c5ded28 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad/version.go @@ -0,0 +1,19 @@ +package aad + +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() + " aad/2020-01-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 b6b5ad5331a7..74a4fd91f345 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -46,6 +46,7 @@ github.com/Azure/azure-sdk-for-go/services/devspaces/mgmt/2019-04-01/devspaces github.com/Azure/azure-sdk-for-go/services/devtestlabs/mgmt/2016-05-15/dtl github.com/Azure/azure-sdk-for-go/services/digitaltwins/mgmt/2020-10-31/digitaltwins github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns +github.com/Azure/azure-sdk-for-go/services/domainservices/mgmt/2020-01-01/aad github.com/Azure/azure-sdk-for-go/services/frontdoor/mgmt/2020-01-01/frontdoor github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac github.com/Azure/azure-sdk-for-go/services/guestconfiguration/mgmt/2020-06-25/guestconfiguration diff --git a/website/allowed-subcategories b/website/allowed-subcategories index 2a72258dabce..771e6f688b63 100644 --- a/website/allowed-subcategories +++ b/website/allowed-subcategories @@ -1,4 +1,5 @@ API Management +Active Directory Domain Services Advisor Analysis Services App Configuration diff --git a/website/docs/d/active_directory_domain_service.html.markdown b/website/docs/d/active_directory_domain_service.html.markdown new file mode 100644 index 000000000000..c4c63a08f8b6 --- /dev/null +++ b/website/docs/d/active_directory_domain_service.html.markdown @@ -0,0 +1,114 @@ +--- +subcategory: "Active Directory Domain Services" +layout: "azurerm" +page_title: "Azure Resource Manager: Data Source: azurerm_active_directory_domain_service" +description: |- + Gets information about an Active Directory Domain Service. +--- + +# Data Source: azurerm_active_directory_domain_service + +Gets information about an Active Directory Domain Service. + +-> **Supported Modes:** At present this data source only supports **User Forest** mode and _not_ **Resource Forest** mode. [Read more](https://docs.microsoft.com/en-us/azure/active-directory-domain-services/concepts-resource-forest) about the different operation modes for this service. + +## Example Usage + +```hcl +data "azurerm_active_directory_domain_service" "example" { + name = "example-aadds" + resource_group_name = "example-aadds-rg" +} +``` + +## Argument Reference + +* `name` - (Required) The display name for your managed Active Directory Domain Service resource. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the Resource Group in which the Domain Service should exist. Changing this forces a new resource to be created. + +## Attributes Reference + +* `id` - The ID of the Domain Service. + +* `deployment_id` - A unique ID for the managed domain deployment. + +* `domain_configuration_type` - The forest type used by the managed domain. One of `ResourceTrusting`, for a _Resource Forest_, or blank, for a _User Forest_. + +* `domain_name` - The Active Directory domain of the Domain Service. See [official documentation](https://docs.microsoft.com/en-us/azure/active-directory-domain-services/tutorial-create-instance#create-a-managed-domain) for constraints and recommendations. + +* `filtered_sync_enabled` - Whether group-based filtered sync (also called scoped synchronisation) is enabled. + +* `secure_ldap` - A `secure_ldap` block as defined below. + +* `location` - The Azure location where the Domain Service exists. + +* `notifications` - A `notifications` block as defined below. + +* `initial_replica_set` - A `replica_set` block as defined below. + +* `additional_replica_sets` - Zero or more `replica_set` block as defined below. + +* `security` - A `security` block as defined below. + +* `sku` - The SKU of the Domain Service resource. One of `Standard`, `Enterprise` or `Premium`. + +* `tags` - A mapping of tags assigned to the resource. + +--- + +A `secure_ldap` block exports the following: + +* `enabled` - Whether secure LDAP is enabled for the managed domain. + +* `external_access_enabled` - Whether external access to LDAPS over the Internet, is enabled. + +* `external_access_ip_address` - The publicly routable IP address for LDAPS clients to connect to. + +* `pfx_certificate` - The certificate to use for LDAPS, as a base64-encoded TripleDES-SHA1 encrypted PKCS#12 bundle (PFX file). + +--- + +A `notifications` block exports the following: + +* `additional_recipients` - A list of additional email addresses to notify when there are alerts in the managed domain. + +* `notify_dc_admins` - Whethermembers of the _AAD DC Administrators_ group are notified when there are alerts in the managed domain. + +* `notify_global_admins` - Whether all Global Administrators are notified when there are alerts in the managed domain. + +--- + +A `replica_set` block exports the following: + +* `domain_controller_ip_addresses` - A list of subnet IP addresses for the domain controllers in the replica set, typically two. + +* `external_access_ip_address` - The publicly routable IP address for the domain controllers in the replica set. + +* `location` - The Azure location in which the replica set resides. + +* `replica_set_id` - A unique ID for the replica set. + +* `service_status` - The current service status for the replica set. + +* `subnet_id` - The ID of the subnet in which the replica set resides. + +--- + +A `security` block exports the following: + +* `ntlm_v1_enabled` - Whether legacy NTLM v1 support is enabled. + +* `sync_kerberos_passwords` - Whether Kerberos password hashes are synchronized to the managed domain. + +* `sync_ntlm_passwords` - Whether NTLM password hashes are synchronized to the managed domain. + +* `sync_on_prem_passwords` - Whether on-premises password hashes are synchronized to the managed domain. + +* `tls_v1_enabled` - Whether legacy TLS v1 support is enabled. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Domain Service. diff --git a/website/docs/r/active_directory_domain_service.html.markdown b/website/docs/r/active_directory_domain_service.html.markdown new file mode 100644 index 000000000000..b23806fe52ff --- /dev/null +++ b/website/docs/r/active_directory_domain_service.html.markdown @@ -0,0 +1,270 @@ +--- +subcategory: "Active Directory Domain Services" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_active_directory_domain_service" +description: |- + Manages an Active Directory Domain Service. +--- + +# azurerm_active_directory_domain_service + +Manages an Active Directory Domain Service. + +~> **Implementation Note:** Before using this resource, there must exist in your tenant a service principal for the Domain Services published application. This service principal cannot be easily managed by Terraform and it's recommended to create this manually, as it does not exist by default. See [official documentation](https://docs.microsoft.com/en-us/azure/active-directory-domain-services/powershell-create-instance#create-required-azure-ad-resources) for details. + +-> **Supported Modes:** At present this resource only supports **User Forest** mode and _not_ **Resource Forest** mode. [Read more](https://docs.microsoft.com/en-us/azure/active-directory-domain-services/concepts-resource-forest) about the different operation modes for this service. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "deploy" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_virtual_network" "deploy" { + name = "deploy-vnet" + location = azurerm_resource_group.deploy.location + resource_group_name = azurerm_resource_group.deploy.name + address_space = ["10.0.1.0/16"] +} + +resource "azurerm_subnet" "deploy" { + name = "deploy-subnet" + resource_group_name = azurerm_resource_group.deploy.name + virtual_network_name = azurerm_virtual_network.deploy.name + address_prefixes = ["10.0.1.0/24"] +} + +resource "azurerm_network_security_group" "deploy" { + name = "deploy-nsg" + location = azurerm_resource_group.deploy.location + resource_group_name = azurerm_resource_group.deploy.name + + security_rule { + name = "AllowSyncWithAzureAD" + priority = 101 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "AzureActiveDirectoryDomainServices" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowRD" + priority = 201 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "CorpNetSaw" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowPSRemoting" + priority = 301 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "5986" + source_address_prefix = "AzureActiveDirectoryDomainServices" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowLDAPS" + priority = 401 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "636" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +resource azurerm_subnet_network_security_group_association "deploy" { + subnet_id = azurerm_subnet.deploy.id + network_security_group_id = azurerm_network_security_group.deploy.id +} + +resource "azuread_group" "dc_admins" { + name = "AAD DC Administrators" +} + +resource "azuread_user" "admin" { + user_principal_name = "dc-admin@$hashicorp-example.net" + display_name = "DC Administrator" + password = "Pa55w0Rd!!1" +} + +resource "azuread_group_member" "admin" { + group_object_id = azuread_group.dc_admins.object_id + member_object_id = azuread_user.admin.object_id +} + +resource "azuread_service_principal" "example" { + application_id = "2565bd9d-da50-47d4-8b85-4c97f669dc36" // published app for domain services +} + +resource "azurerm_resource_group" "aadds" { + name = "aadds-rg" + location = "westeurope" +} + +resource "azurerm_active_directory_domain_service" "example" { + name = "example-aadds" + location = azurerm_resource_group.aadds.location + resource_group_name = azurerm_resource_group.aadds.name + + domain_name = "widgetslogin.net" + sku = "Enterprise" + filtered_sync_enabled = false + + initial_replica_set { + location = azurerm_virtual_network.deploy.location + subnet_id = azurerm_subnet.deploy.id + } + + notifications { + additional_recipients = ["notifyA@example.net", "notifyB@example.org"] + notify_dc_admins = true + notify_global_admins = true + } + + security { + sync_kerberos_passwords = true + sync_ntlm_passwords = true + sync_on_prem_passwords = true + } + + tags = { + Environment = "prod" + } + + depends_on = [ + azuread_service_principal.example, + azurerm_subnet_network_security_group_association.deploy, + ] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `domain_name` - (Required) The Active Directory domain to use. See [official documentation](https://docs.microsoft.com/en-us/azure/active-directory-domain-services/tutorial-create-instance#create-a-managed-domain) for constraints and recommendations. + +* `filtered_sync_enabled` - Whether to enable group-based filtered sync (also called scoped synchronisation). Defaults to `false`. + +* `secure_ldap` - (Optional) A `secure_ldap` block as defined below. + +* `location` - (Required) The Azure location where the Domain Service exists. Changing this forces a new resource to be created. + +* `name` - (Required) The display name for your managed Active Directory Domain Service resource. Changing this forces a new resource to be created. + +* `notifications` - (Optional) A `notifications` block as defined below. + +* `initial_replica_set` - (Required) An `initial_replica_set` block as defined below. The initial replica set inherits the same location as the Domain Service resource. + +* `resource_group_name` - (Required) The name of the Resource Group in which the Domain Service should exist. Changing this forces a new resource to be created. + +* `security` - (Optional) A `security` block as defined below. + +* `sku` - (Required) The SKU to use when provisioning the Domain Service resource. One of `Standard`, `Enterprise` or `Premium`. + +* `tags` - (Optional) A mapping of tags assigned to the resource. + +--- + +A `secure_ldap` block supports the following: + +* `enabled` - (Required) Whether to enable secure LDAP for the managed domain. Defaults to `false`. + +* `external_access_enabled` - (Optional) Whether to enable external access to LDAPS over the Internet. Defaults to `false`. + +* `pfx_certificate` - (Required) The certificate/private key to use for LDAPS, as a base64-encoded TripleDES-SHA1 encrypted PKCS#12 bundle (PFX file). + +* `pfx_certificate_password` - (Required) The password to use for decrypting the PKCS#12 bundle (PFX file). + +--- + +A `notifications` block supports the following: + +* `additional_recipients` - (Optional) A list of additional email addresses to notify when there are alerts in the managed domain. + +* `notify_dc_admins` - (Optional) Whether to notify members of the _AAD DC Administrators_ group when there are alerts in the managed domain. + +* `notify_global_admins` - (Optional) Whether to notify all Global Administrators when there are alerts in the managed domain. + +--- + +An `initial_replica_set` block supports the following: + +* `subnet_id` - (Required) The ID of the subnet in which to place the initial replica set. + +--- + +A `security` block supports the following: + +* `ntlm_v1_enabled` - (Optional) Whether to enable legacy NTLM v1 support. Defaults to `false`. + +* `sync_kerberos_passwords` - (Optional) Whether to synchronize Kerberos password hashes to the managed domain. Defaults to `false`. + +* `sync_ntlm_passwords` - (Optional) Whether to synchronize NTLM password hashes to the managed domain. Defaults to `false`. + +* `sync_on_prem_passwords` - (Optional) Whether to synchronize on-premises password hashes to the managed domain. Defaults to `false`. + +* `tls_v1_enabled` - (Optional) Whether to enable legacy TLS v1 support. Defaults to `false`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the Domain Service. + +* `deployment_id` - A unique ID for the managed domain deployment. + +--- + +A `secure_ldap` block exports the following: + +* `external_access_ip_address` - The publicly routable IP address for LDAPS clients to connect to. + +--- + +An `initial_replica_set` block exports the following: + +* `domain_controller_ip_addresses` - A list of subnet IP addresses for the domain controllers in the initial replica set, typically two. + +* `external_access_ip_address` - The publicly routable IP address for the domain controllers in the initial replica set. + +* `location` - The Azure location in which the initialreplica set resides. + +* `replica_set_id` - A unique ID for the replica set. + +* `service_status` - The current service status for the initial replica set. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 2 hours) Used when creating the Domain Service. +* `update` - (Defaults to 2 hours) Used when updating the Domain Service. +* `read` - (Defaults to 5 minutes) Used when retrieving the Domain Service. +* `delete` - (Defaults to 30 minutes) Used when deleting the Domain Service. + +## Import + +Domain Services can be imported using the resource ID, e.g. + +```shell +terraform import azurerm_active_directory_domain_service.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.AAD/domainServices/instance1 +``` diff --git a/website/docs/r/active_directory_domain_service_replica_set.html.markdown b/website/docs/r/active_directory_domain_service_replica_set.html.markdown new file mode 100644 index 000000000000..0dbb96183204 --- /dev/null +++ b/website/docs/r/active_directory_domain_service_replica_set.html.markdown @@ -0,0 +1,311 @@ +--- +subcategory: "Active Directory Domain Services" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_active_directory_domain_service_replica_set" +description: |- + Manages a Replica Set for an Active Directory Domain Service. +--- + +# azurerm_active_directory_domain_service_replica_set + +Manages a Replica Set for an Active Directory Domain Service. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "primary" { + name = "aadds-primary-rg" + location = "West Europe" +} + +resource "azurerm_virtual_network" "primary" { + name = "aadds-primary-vnet" + location = azurerm_resource_group.primary.location + resource_group_name = azurerm_resource_group.primary.name + address_space = ["10.0.1.0/16"] +} + +resource "azurerm_subnet" "primary" { + name = "aadds-primary-subnet" + resource_group_name = azurerm_resource_group.primary.name + virtual_network_name = azurerm_virtual_network.primary.name + address_prefixes = ["10.0.1.0/24"] +} + +resource "azurerm_network_security_group" "primary" { + name = "aadds-primary-nsg" + location = azurerm_resource_group.primary.location + resource_group_name = azurerm_resource_group.primary.name + + security_rule { + name = "AllowSyncWithAzureAD" + priority = 101 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "AzureActiveDirectoryDomainServices" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowRD" + priority = 201 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "CorpNetSaw" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowPSRemoting" + priority = 301 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "5986" + source_address_prefix = "AzureActiveDirectoryDomainServices" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowLDAPS" + priority = 401 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "636" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +resource azurerm_subnet_network_security_group_association "primary" { + subnet_id = azurerm_subnet.primary.id + network_security_group_id = azurerm_network_security_group.primary.id +} + +resource "azuread_group" "dc_admins" { + name = "AAD DC Administrators" +} + +resource "azuread_user" "admin" { + user_principal_name = "dc-admin@$hashicorp-example.net" + display_name = "DC Administrator" + password = "Pa55w0Rd!!1" +} + +resource "azuread_group_member" "admin" { + group_object_id = azuread_group.dc_admins.object_id + member_object_id = azuread_user.admin.object_id +} + +resource "azuread_service_principal" "example" { + application_id = "2565bd9d-da50-47d4-8b85-4c97f669dc36" // published app for domain services +} + +resource "azurerm_resource_group" "aadds" { + name = "aadds-rg" + location = "westeurope" +} + +resource "azurerm_active_directory_domain_service" "example" { + name = "example-aadds" + location = azurerm_resource_group.aadds.location + resource_group_name = azurerm_resource_group.aadds.name + + domain_name = "widgetslogin.net" + sku = "Enterprise" + filtered_sync_enabled = false + + initial_replica_set { + location = azurerm_virtual_network.primary.location + subnet_id = azurerm_subnet.primary.id + } + + notifications { + additional_recipients = ["notifyA@example.net", "notifyB@example.org"] + notify_dc_admins = true + notify_global_admins = true + } + + security { + sync_kerberos_passwords = true + sync_ntlm_passwords = true + sync_on_prem_passwords = true + } + + tags = { + Environment = "prod" + } + + depends_on = [ + azuread_service_principal.example, + azurerm_subnet_network_security_group_association.primary, + ] +} + +resource "azurerm_resource_group" "replica" { + name = "aadds-replica-rg" + location = "North Europe" +} + +resource "azurerm_virtual_network" "replica" { + name = "aadds-replica-vnet" + location = azurerm_resource_group.replica.location + resource_group_name = azurerm_resource_group.replica.name + address_space = ["10.20.0.0/16"] +} + +resource "azurerm_subnet" "aadds_replica" { + name = "aadds-replica-subnet" + resource_group_name = azurerm_resource_group.replica.name + virtual_network_name = azurerm_virtual_network.replica.name + address_prefixes = ["10.20.0.0/24"] +} + +resource "azurerm_network_security_group" "aadds_replica" { + name = "aadds-replica-nsg" + location = azurerm_resource_group.replica.location + resource_group_name = azurerm_resource_group.replica.name + + security_rule { + name = "AllowSyncWithAzureAD" + priority = 101 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "443" + source_address_prefix = "AzureActiveDirectoryDomainServices" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowRD" + priority = 201 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "3389" + source_address_prefix = "CorpNetSaw" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowPSRemoting" + priority = 301 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "5986" + source_address_prefix = "AzureActiveDirectoryDomainServices" + destination_address_prefix = "*" + } + + security_rule { + name = "AllowLDAPS" + priority = 401 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "636" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +resource azurerm_subnet_network_security_group_association "replica" { + subnet_id = azurerm_subnet.aadds_replica.id + network_security_group_id = azurerm_network_security_group.aadds_replica.id +} + +resource "azurerm_virtual_network_peering" "primary_replica" { + name = "aadds-primary-replica" + resource_group_name = azurerm_virtual_network.primary.resource_group_name + virtual_network_name = azurerm_virtual_network.primary.name + remote_virtual_network_id = azurerm_virtual_network.replica.id + + allow_forwarded_traffic = true + allow_gateway_transit = false + allow_virtual_network_access = true + use_remote_gateways = false +} + +resource "azurerm_virtual_network_peering" "replica_primary" { + name = "aadds-replica-primary" + resource_group_name = azurerm_virtual_network.replica.resource_group_name + virtual_network_name = azurerm_virtual_network.replica.name + remote_virtual_network_id = azurerm_virtual_network.primary.id + + allow_forwarded_traffic = true + allow_gateway_transit = false + allow_virtual_network_access = true + use_remote_gateways = false +} + +resource "azurerm_virtual_network_dns_servers" "replica" { + virtual_network_id = azurerm_virtual_network.replica.id + dns_servers = azurerm_active_directory_domain_service.example.initial_replica_set.0.domain_controller_ip_addresses +} + +resource "azurerm_active_directory_domain_service_replica_set" "replica" { + domain_service_id = azurerm_active_directory_domain_service.example.id + location = azurerm_resource_group.replica.location + subnet_id = azurerm_subnet.aadds_replica.id + + depends_on = [ + azurerm_subnet_network_security_group_association.replica, + azurerm_virtual_network_peering.primary_replica, + azurerm_virtual_network_peering.replica_primary, + ] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `domain_service_id` - (Required) The ID of the Domain Service for which to create this Replica Set. Changing this forces a new resource to be created. + +* `location` - (Required) The Azure location where this Replica Set should exist. Changing this forces a new resource to be created. + +* `subnet_id` - (Required) The ID of the subnet in which to place this Replica Set. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the Domain Service Replica Set. + +* `domain_controller_ip_addresses` - A list of subnet IP addresses for the domain controllers in this Replica Set, typically two. + +* `external_access_ip_address` - The publicly routable IP address for the domain controllers in this Replica Set. + +* `service_status` - The current service status for the replica set. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 2 hours) Used when creating the Domain Service. +* `update` - (Defaults to 2 hours) Used when updating the Domain Service. +* `read` - (Defaults to 5 minutes) Used when retrieving the Domain Service. +* `delete` - (Defaults to 30 minutes) Used when deleting the Domain Service. + +## Import + +Domain Services can be imported using the resource ID, e.g. + +```shell +terraform import azurerm_active_directory_domain_service.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.AAD/domainServices/instance1 +```