diff --git a/.github/labeler-pull-request-triage.yml b/.github/labeler-pull-request-triage.yml index 3b7ff3cd4853..6fb7ff96aea3 100644 --- a/.github/labeler-pull-request-triage.yml +++ b/.github/labeler-pull-request-triage.yml @@ -108,6 +108,9 @@ service/dns: service/domain-services: - internal/services/domainservices/**/* +service/elastic: + - internal/services/elastic/**/* + service/event-grid: - internal/services/eventgrid/**/* diff --git a/.teamcity/components/generated/services.kt b/.teamcity/components/generated/services.kt index 19632b39c827..1cfc96510486 100644 --- a/.teamcity/components/generated/services.kt +++ b/.teamcity/components/generated/services.kt @@ -39,6 +39,7 @@ var services = mapOf( "digitaltwins" to "Digital Twins", "disks" to "Disks", "domainservices" to "DomainServices", + "elastic" to "Elastic", "eventgrid" to "EventGrid", "eventhub" to "EventHub", "firewall" to "Firewall", diff --git a/.teamcity/components/settings.kt b/.teamcity/components/settings.kt index 3aca653dac19..ac5df9be34cf 100644 --- a/.teamcity/components/settings.kt +++ b/.teamcity/components/settings.kt @@ -60,6 +60,9 @@ var serviceTestConfigurationOverrides = mapOf( // "hdinsight" is super expensive - G class VM's are not available in westus2, quota only available in westeurope currently "hdinsight" to testConfiguration(daysOfWeek = "2,4,6", locationOverride = LocationConfiguration("westeurope", "southeastasia", "eastus2", false)), + // Elastic can't provision many in parallel + "elastic" to testConfiguration(parallelism = 1), + // HPC Cache has a 4 instance per subscription quota as of early 2021 "hpccache" to testConfiguration(parallelism = 3, daysOfWeek = "2,4,6"), diff --git a/internal/clients/client.go b/internal/clients/client.go index 5cc9ceb8e354..f460294421c9 100644 --- a/internal/clients/client.go +++ b/internal/clients/client.go @@ -44,6 +44,7 @@ import ( disks "github.com/hashicorp/terraform-provider-azurerm/internal/services/disks/client" dns "github.com/hashicorp/terraform-provider-azurerm/internal/services/dns/client" domainservices "github.com/hashicorp/terraform-provider-azurerm/internal/services/domainservices/client" + elastic "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/client" eventgrid "github.com/hashicorp/terraform-provider-azurerm/internal/services/eventgrid/client" eventhub "github.com/hashicorp/terraform-provider-azurerm/internal/services/eventhub/client" firewall "github.com/hashicorp/terraform-provider-azurerm/internal/services/firewall/client" @@ -154,6 +155,7 @@ type Client struct { Disks *disks.Client Dns *dns.Client DomainServices *domainservices.Client + Elastic *elastic.Client EventGrid *eventgrid.Client Eventhub *eventhub.Client Firewall *firewall.Client @@ -266,6 +268,7 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error client.Disks = disks.NewClient(o) client.Dns = dns.NewClient(o) client.DomainServices = domainservices.NewClient(o) + client.Elastic = elastic.NewClient(o) client.EventGrid = eventgrid.NewClient(o) client.Eventhub = eventhub.NewClient(o) client.Firewall = firewall.NewClient(o) diff --git a/internal/provider/services.go b/internal/provider/services.go index 13cfcbe75030..ca6cd4ec3882 100644 --- a/internal/provider/services.go +++ b/internal/provider/services.go @@ -40,6 +40,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/services/disks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/dns" "github.com/hashicorp/terraform-provider-azurerm/internal/services/domainservices" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic" "github.com/hashicorp/terraform-provider-azurerm/internal/services/eventgrid" "github.com/hashicorp/terraform-provider-azurerm/internal/services/eventhub" "github.com/hashicorp/terraform-provider-azurerm/internal/services/firewall" @@ -171,6 +172,7 @@ func SupportedUntypedServices() []sdk.UntypedServiceRegistration { digitaltwins.Registration{}, dns.Registration{}, domainservices.Registration{}, + elastic.Registration{}, eventgrid.Registration{}, eventhub.Registration{}, firewall.Registration{}, diff --git a/internal/services/elastic/client/client.go b/internal/services/elastic/client/client.go new file mode 100644 index 000000000000..f81b893fbdcf --- /dev/null +++ b/internal/services/elastic/client/client.go @@ -0,0 +1,25 @@ +package client + +import ( + "github.com/hashicorp/terraform-provider-azurerm/internal/common" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/monitorsresource" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/rules" +) + +type Client struct { + MonitorClient *monitorsresource.MonitorsResourceClient + TagRuleClient *rules.RulesClient +} + +func NewClient(o *common.ClientOptions) *Client { + monitorClient := monitorsresource.NewMonitorsResourceClientWithBaseURI(o.ResourceManagerEndpoint) + o.ConfigureClient(&monitorClient.Client, o.ResourceManagerAuthorizer) + + tagRuleClient := rules.NewRulesClientWithBaseURI(o.ResourceManagerEndpoint) + o.ConfigureClient(&tagRuleClient.Client, o.ResourceManagerAuthorizer) + + return &Client{ + MonitorClient: &monitorClient, + TagRuleClient: &tagRuleClient, + } +} diff --git a/internal/services/elastic/elasticsearch_data_source.go b/internal/services/elastic/elasticsearch_data_source.go new file mode 100644 index 000000000000..eac1ce68b357 --- /dev/null +++ b/internal/services/elastic/elasticsearch_data_source.go @@ -0,0 +1,204 @@ +package elastic + +import ( + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/monitorsresource" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/rules" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" +) + +func dataSourceElasticsearch() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceElasticsearchRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + // Required + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.ElasticsearchName, + }, + + "resource_group_name": commonschema.ResourceGroupNameForDataSource(), + + // Computed + "location": commonschema.LocationComputed(), + + "sku_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "elastic_cloud_email_address": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "monitoring_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "logs": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "filtering_tag": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "value": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "action": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "send_azuread_logs": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "send_activity_logs": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "send_subscription_logs": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + }, + }, + }, + + "tags": commonschema.TagsDataSource(), + + "elastic_cloud_deployment_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "elastic_cloud_sso_default_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "elastic_cloud_user_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "elasticsearch_service_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "kibana_service_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "kibana_sso_uri": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceElasticsearchRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Elastic.MonitorClient + logsClient := meta.(*clients.Client).Elastic.TagRuleClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := monitorsresource.NewMonitorID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + resp, err := client.MonitorsGet(ctx, id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("%s was not found", id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + tagRuleId := rules.NewTagRuleID(id.SubscriptionId, id.ResourceGroupName, id.MonitorName, "default") + rulesResp, err := logsClient.TagRulesGet(ctx, tagRuleId) + if err != nil { + if !response.WasNotFound(rulesResp.HttpResponse) { + return fmt.Errorf("retrieving logs for %s: %+v", id, err) + } + } + + d.Set("name", id.MonitorName) + d.Set("resource_group_name", id.ResourceGroupName) + + if model := resp.Model; model != nil { + d.Set("location", location.Normalize(model.Location)) + + if props := model.Properties; props != nil { + monitoringEnabled := false + if props.MonitoringStatus != nil { + monitoringEnabled = *props.MonitoringStatus == monitorsresource.MonitoringStatusEnabled + } + d.Set("monitoring_enabled", monitoringEnabled) + + if elastic := props.ElasticProperties; elastic != nil { + if elastic.ElasticCloudDeployment != nil { + // AzureSubscriptionId is the same as the subscription deployed into, so no point exposing it + // ElasticsearchRegion is `{Cloud}-{Region}` - so the same as location/not worth exposing for now? + d.Set("elastic_cloud_deployment_id", elastic.ElasticCloudDeployment.DeploymentId) + d.Set("elasticsearch_service_url", elastic.ElasticCloudDeployment.ElasticsearchServiceUrl) + d.Set("kibana_service_url", elastic.ElasticCloudDeployment.KibanaServiceUrl) + d.Set("kibana_sso_uri", elastic.ElasticCloudDeployment.KibanaSsoUrl) + } + if elastic.ElasticCloudUser != nil { + d.Set("elastic_cloud_user_id", elastic.ElasticCloudUser.Id) + d.Set("elastic_cloud_email_address", elastic.ElasticCloudUser.EmailAddress) + d.Set("elastic_cloud_sso_default_url", elastic.ElasticCloudUser.ElasticCloudSsoDefaultUrl) + } + } + } + + skuName := "" + if model.Sku != nil { + skuName = model.Sku.Name + } + d.Set("sku_name", skuName) + + if err := tags.FlattenAndSet(d, model.Tags); err != nil { + return err + } + } + + if err := d.Set("logs", flattenTagRule(rulesResp.Model)); err != nil { + return fmt.Errorf("setting `logs`: %+v", err) + } + + d.SetId(id.ID()) + + return nil +} diff --git a/internal/services/elastic/elasticsearch_data_source_test.go b/internal/services/elastic/elasticsearch_data_source_test.go new file mode 100644 index 000000000000..d7c3e63193ac --- /dev/null +++ b/internal/services/elastic/elasticsearch_data_source_test.go @@ -0,0 +1,46 @@ +package elastic_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type ElasticsearchDataSourceTest struct{} + +func TestAccElasticsearchDataSource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchDataSourceTest{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("elastic_cloud_email_address").Exists(), + check.That(data.ResourceName).Key("location").Exists(), + check.That(data.ResourceName).Key("sku_name").Exists(), + check.That(data.ResourceName).Key("monitoring_enabled").Exists(), + check.That(data.ResourceName).Key("elastic_cloud_deployment_id").Exists(), + check.That(data.ResourceName).Key("elastic_cloud_sso_default_url").Exists(), + check.That(data.ResourceName).Key("elastic_cloud_user_id").Exists(), + check.That(data.ResourceName).Key("elasticsearch_service_url").Exists(), + check.That(data.ResourceName).Key("kibana_service_url").Exists(), + check.That(data.ResourceName).Key("kibana_sso_uri").Exists(), + ), + }, + }) +} + +func (ElasticsearchDataSourceTest) basic(data acceptance.TestData) string { + template := ElasticsearchResourceTest{}.basic(data) + return fmt.Sprintf(` +%s + +data "azurerm_elastic_cloud_elasticsearch" "test" { + name = azurerm_elastic_cloud_elasticsearch.test.name + resource_group_name = azurerm_elastic_cloud_elasticsearch.test.resource_group_name +} +`, template) +} diff --git a/internal/services/elastic/elasticsearch_resource.go b/internal/services/elastic/elasticsearch_resource.go new file mode 100644 index 000000000000..217eaf83893a --- /dev/null +++ b/internal/services/elastic/elasticsearch_resource.go @@ -0,0 +1,434 @@ +package elastic + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/rules" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/monitorsresource" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func resourceElasticsearch() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceElasticsearchCreate, + Read: resourceElasticsearchRead, + Update: resourceElasticsearchUpdate, + Delete: resourceElasticsearchDelete, + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(60 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(60 * time.Minute), + Delete: pluginsdk.DefaultTimeout(60 * time.Minute), + }, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := monitorsresource.ParseMonitorID(id) + return err + }), + + Schema: map[string]*pluginsdk.Schema{ + // Required + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ElasticsearchName, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "location": commonschema.Location(), + + "sku_name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "elastic_cloud_email_address": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ElasticEmailAddress, + }, + + // Optional + "monitoring_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + ForceNew: true, + }, + + "logs": { + Type: pluginsdk.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "filtering_tag": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "value": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "action": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(rules.TagActionExclude), + string(rules.TagActionInclude), + }, false), + }, + }, + }, + }, + + "send_activity_logs": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "send_azuread_logs": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + + "send_subscription_logs": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, + + "tags": commonschema.Tags(), + + // Computed + "elastic_cloud_deployment_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "elastic_cloud_sso_default_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "elastic_cloud_user_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "elasticsearch_service_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "kibana_service_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + "kibana_sso_uri": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + } +} + +func resourceElasticsearchCreate(d *pluginsdk.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + client := meta.(*clients.Client).Elastic.MonitorClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := monitorsresource.NewMonitorID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + existing, err := client.MonitorsGet(ctx, id) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for existing %q: %+v", id, err) + } + } + if !response.WasNotFound(existing.HttpResponse) { + return tf.ImportAsExistsError("azurerm_elastic_cloud_elasticsearch", id.ID()) + } + + monitoringStatus := monitorsresource.MonitoringStatusDisabled + if d.Get("monitoring_enabled").(bool) { + monitoringStatus = monitorsresource.MonitoringStatusEnabled + } + + body := monitorsresource.ElasticMonitorResource{ + Location: location.Normalize(d.Get("location").(string)), + Properties: &monitorsresource.MonitorProperties{ + MonitoringStatus: &monitoringStatus, + UserInfo: &monitorsresource.UserInfo{ + EmailAddress: utils.String(d.Get("elastic_cloud_email_address").(string)), + }, + }, + Sku: &monitorsresource.ResourceSku{ + Name: d.Get("sku_name").(string), + }, + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } + + if err := client.MonitorsCreateThenPoll(ctx, id, body); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + d.SetId(id.ID()) + + if v, ok := d.GetOk("logs"); ok { + tagRulesClient := meta.(*clients.Client).Elastic.TagRuleClient + tagRuleId := rules.NewTagRuleID(id.SubscriptionId, id.ResourceGroupName, id.MonitorName, "default") + tagRule := rules.MonitoringTagRules{ + Properties: &rules.MonitoringTagRulesProperties{ + LogRules: expandTagRule(v.([]interface{})), + }, + } + if _, err := tagRulesClient.TagRulesCreateOrUpdate(ctx, tagRuleId, tagRule); err != nil { + return fmt.Errorf("updating the logs for %s: %+v", id, err) + } + } + + return resourceElasticsearchRead(d, meta) +} + +func resourceElasticsearchRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Elastic.MonitorClient + logsClient := meta.(*clients.Client).Elastic.TagRuleClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := monitorsresource.ParseMonitorID(d.Id()) + if err != nil { + return err + } + + resp, err := client.MonitorsGet(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[INFO] %s was not found", *id) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + tagRuleId := rules.NewTagRuleID(id.SubscriptionId, id.ResourceGroupName, id.MonitorName, "default") + rulesResp, err := logsClient.TagRulesGet(ctx, tagRuleId) + if err != nil { + if !response.WasNotFound(rulesResp.HttpResponse) { + return fmt.Errorf("retrieving logs for %s: %+v", *id, err) + } + } + + d.Set("name", id.MonitorName) + d.Set("resource_group_name", id.ResourceGroupName) + + if model := resp.Model; model != nil { + d.Set("location", location.Normalize(model.Location)) + + if props := model.Properties; props != nil { + monitoringEnabled := false + if props.MonitoringStatus != nil { + monitoringEnabled = *props.MonitoringStatus == monitorsresource.MonitoringStatusEnabled + } + d.Set("monitoring_enabled", monitoringEnabled) + + if elastic := props.ElasticProperties; elastic != nil { + if elastic.ElasticCloudDeployment != nil { + // AzureSubscriptionId is the same as the subscription deployed into, so no point exposing it + // ElasticsearchRegion is `{Cloud}-{Region}` - so the same as location/not worth exposing for now? + d.Set("elastic_cloud_deployment_id", elastic.ElasticCloudDeployment.DeploymentId) + d.Set("elasticsearch_service_url", elastic.ElasticCloudDeployment.ElasticsearchServiceUrl) + d.Set("kibana_service_url", elastic.ElasticCloudDeployment.KibanaServiceUrl) + d.Set("kibana_sso_uri", elastic.ElasticCloudDeployment.KibanaSsoUrl) + } + if elastic.ElasticCloudUser != nil { + d.Set("elastic_cloud_user_id", elastic.ElasticCloudUser.Id) + d.Set("elastic_cloud_email_address", elastic.ElasticCloudUser.EmailAddress) + d.Set("elastic_cloud_sso_default_url", elastic.ElasticCloudUser.ElasticCloudSsoDefaultUrl) + } + } + } + + skuName := "" + if model.Sku != nil { + skuName = model.Sku.Name + } + d.Set("sku_name", skuName) + + if err := tags.FlattenAndSet(d, model.Tags); err != nil { + return err + } + } + + if err := d.Set("logs", flattenTagRule(rulesResp.Model)); err != nil { + return fmt.Errorf("setting `logs`: %+v", err) + } + + return nil +} + +func resourceElasticsearchUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := monitorsresource.ParseMonitorID(d.Id()) + if err != nil { + return err + } + + if d.HasChange("logs") { + client := meta.(*clients.Client).Elastic.TagRuleClient + tagRuleId := rules.NewTagRuleID(id.SubscriptionId, id.ResourceGroupName, id.MonitorName, "default") + tagRule := expandTagRule(d.Get("logs").([]interface{})) + body := rules.MonitoringTagRules{ + Properties: &rules.MonitoringTagRulesProperties{ + LogRules: tagRule, + }, + } + if _, err := client.TagRulesCreateOrUpdate(ctx, tagRuleId, body); err != nil { + return fmt.Errorf("updating `logs` from %s: %+v", *id, err) + } + } + + if d.HasChange("tags") { + client := meta.(*clients.Client).Elastic.MonitorClient + body := monitorsresource.ElasticMonitorResourceUpdateParameters{ + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } + if _, err := client.MonitorsUpdate(ctx, *id, body); err != nil { + return fmt.Errorf("updating %s: %+v", *id, err) + } + } + + return resourceElasticsearchRead(d, meta) +} + +func resourceElasticsearchDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Elastic.MonitorClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := monitorsresource.ParseMonitorID(d.Id()) + if err != nil { + return err + } + + if err := client.MonitorsDeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil +} + +func expandTagRule(input []interface{}) *rules.LogRules { + if len(input) == 0 { + return nil + } + + raw := input[0].(map[string]interface{}) + filteringTags := make([]rules.FilteringTag, 0) + for _, v := range raw["filtering_tag"].([]interface{}) { + item := v.(map[string]interface{}) + + action := rules.TagAction(item["action"].(string)) + filteringTags = append(filteringTags, rules.FilteringTag{ + Action: &action, + Name: utils.String(item["name"].(string)), + Value: utils.String(item["value"].(string)), + }) + } + + sendAzureAdLogs := raw["send_azuread_logs"].(bool) + sendActivityLogs := raw["send_activity_logs"].(bool) + sendSubscriptionLogs := raw["send_subscription_logs"].(bool) + + return &rules.LogRules{ + FilteringTags: &filteringTags, + SendAadLogs: utils.Bool(sendAzureAdLogs), + SendActivityLogs: utils.Bool(sendActivityLogs), + SendSubscriptionLogs: utils.Bool(sendSubscriptionLogs), + } +} + +func flattenTagRule(input *rules.MonitoringTagRules) []interface{} { + if input == nil || input.Properties == nil || input.Properties.LogRules == nil { + return []interface{}{} + } + + rules := input.Properties.LogRules + + filteringTags := make([]interface{}, 0) + if rules.FilteringTags != nil { + for _, v := range *rules.FilteringTags { + action := "" + if v.Action != nil { + action = string(*v.Action) + } + name := "" + if v.Name != nil { + name = *v.Name + } + value := "" + if v.Value != nil { + value = *v.Value + } + + filteringTags = append(filteringTags, map[string]interface{}{ + "action": action, + "name": name, + "value": value, + }) + } + } + + sendActivityLogs := false + if rules.SendActivityLogs != nil { + sendActivityLogs = *rules.SendActivityLogs + } + sendAzureAdLogs := false + if rules.SendAadLogs != nil { + sendAzureAdLogs = *rules.SendAadLogs + } + sendSubscriptionLogs := false + if rules.SendSubscriptionLogs != nil { + sendSubscriptionLogs = *rules.SendSubscriptionLogs + } + + return []interface{}{ + map[string]interface{}{ + "filtering_tag": filteringTags, + "send_activity_logs": sendActivityLogs, + "send_azuread_logs": sendAzureAdLogs, + "send_subscription_logs": sendSubscriptionLogs, + }, + } +} diff --git a/internal/services/elastic/elasticsearch_resource_test.go b/internal/services/elastic/elasticsearch_resource_test.go new file mode 100644 index 000000000000..b226415a9659 --- /dev/null +++ b/internal/services/elastic/elasticsearch_resource_test.go @@ -0,0 +1,314 @@ +package elastic_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elastic/sdk/2020-07-01/monitorsresource" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type ElasticsearchResourceTest struct{} + +func TestAccElasticsearch_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchResourceTest{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("elastic_cloud_deployment_id").Exists(), + check.That(data.ResourceName).Key("elastic_cloud_sso_default_url").Exists(), + check.That(data.ResourceName).Key("elastic_cloud_user_id").Exists(), + check.That(data.ResourceName).Key("elasticsearch_service_url").Exists(), + check.That(data.ResourceName).Key("kibana_service_url").Exists(), + check.That(data.ResourceName).Key("kibana_sso_uri").Exists(), + ), + }, + data.ImportStep(), + }) +} + +func TestAccElasticsearch_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchResourceTest{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccElasticsearch_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchResourceTest{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccElasticsearch_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchResourceTest{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccElasticsearch_logs(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchResourceTest{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + // this proves that we don't need to destroy the `logs` block separately + Config: r.logs(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccElasticsearch_logsUpdate(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_elastic_cloud_elasticsearch", "test") + r := ElasticsearchResourceTest{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + // create with it + Config: r.logs(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + // update it + Config: r.logsUpdated(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + // remove just the `logs` block + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (r ElasticsearchResourceTest) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := monitorsresource.ParseMonitorID(state.ID) + if err != nil { + return nil, err + } + + resp, err := client.Elastic.MonitorClient.MonitorsGet(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return utils.Bool(false), nil + } + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) + } + return utils.Bool(resp.Model != nil), nil +} + +func (r ElasticsearchResourceTest) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestrg-elastic-%[1]d" + location = "%[2]s" +} + +resource "azurerm_elastic_cloud_elasticsearch" "test" { + name = "acctest-estc%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku_name = "ess-monthly-consumption_Monthly" + elastic_cloud_email_address = "terraform-acctest@hashicorp.com" +} +`, data.RandomInteger, data.Locations.Primary) +} + +func (r ElasticsearchResourceTest) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_elastic_cloud_elasticsearch" "import" { + name = azurerm_elastic_cloud_elasticsearch.test.name + resource_group_name = azurerm_elastic_cloud_elasticsearch.test.resource_group_name + location = azurerm_elastic_cloud_elasticsearch.test.location + sku_name = azurerm_elastic_cloud_elasticsearch.test.sku_name + elastic_cloud_email_address = azurerm_elastic_cloud_elasticsearch.test.elastic_cloud_email_address +} +`, r.basic(data)) +} + +func (r ElasticsearchResourceTest) update(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestrg-elastic-%[1]d" + location = "%[2]s" +} + +resource "azurerm_elastic_cloud_elasticsearch" "test" { + name = "acctest-estc%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku_name = "ess-monthly-consumption_Monthly" + elastic_cloud_email_address = "terraform-acctest@hashicorp.com" + + tags = { + ENV = "Test" + } +} +`, data.RandomInteger, data.Locations.Primary) +} + +func (r ElasticsearchResourceTest) complete(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestrg-elastic-%[1]d" + location = "%[2]s" +} + +resource "azurerm_elastic_cloud_elasticsearch" "test" { + name = "acctest-estc%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku_name = "ess-monthly-consumption_Monthly" + elastic_cloud_email_address = "terraform-acctest@hashicorp.com" + monitoring_enabled = false + + tags = { + ENV = "Test" + } +} +`, data.RandomInteger, data.Locations.Primary) +} + +func (r ElasticsearchResourceTest) logs(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestrg-elastic-%[1]d" + location = "%[2]s" +} + +resource "azurerm_elastic_cloud_elasticsearch" "test" { + name = "acctest-estc%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku_name = "ess-monthly-consumption_Monthly" + elastic_cloud_email_address = "terraform-acctest@hashicorp.com" + + logs { + filtering_tag { + action = "Include" + name = "TerraformAccTest" + value = "RandomValue%[1]d" + } + + # NOTE: these are intentionally not set to true here for testing purposes + send_activity_logs = false + send_azuread_logs = false + send_subscription_logs = false + } +} +`, data.RandomInteger, data.Locations.Primary) +} + +func (r ElasticsearchResourceTest) logsUpdated(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestrg-elastic-%[1]d" + location = "%[2]s" +} + +resource "azurerm_elastic_cloud_elasticsearch" "test" { + name = "acctest-estc%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku_name = "ess-monthly-consumption_Monthly" + elastic_cloud_email_address = "terraform-acctest@hashicorp.com" + + logs { + filtering_tag { + action = "Include" + name = "TerraformAccTest" + value = "UpdatedValue-%[1]d" + } + + # NOTE: these are intentionally not set to true here for testing purposes + send_activity_logs = false + send_azuread_logs = false + send_subscription_logs = false + } + + tags = { + ENV = "Test" + } +} +`, data.RandomInteger, data.Locations.Primary) +} diff --git a/internal/services/elastic/registration.go b/internal/services/elastic/registration.go new file mode 100644 index 000000000000..2d3c7b113bdf --- /dev/null +++ b/internal/services/elastic/registration.go @@ -0,0 +1,40 @@ +package elastic + +import ( + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +var _ sdk.UntypedServiceRegistrationWithAGitHubLabel = Registration{} + +type Registration struct{} + +func (r Registration) AssociatedGitHubLabel() string { + return "service/elastic" +} + +// Name is the name of this Service +func (r Registration) Name() string { + return "Elastic" +} + +// WebsiteCategories returns a list of categories which can be used for the sidebar +func (r Registration) WebsiteCategories() []string { + return []string{ + "Elastic", + } +} + +// SupportedDataSources returns the supported Data Sources supported by this Service +func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { + return map[string]*pluginsdk.Resource{ + "azurerm_elastic_cloud_elasticsearch": dataSourceElasticsearch(), + } +} + +// SupportedResources returns the supported Resources supported by this Service +func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { + return map[string]*pluginsdk.Resource{ + "azurerm_elastic_cloud_elasticsearch": resourceElasticsearch(), + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/client.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/client.go new file mode 100644 index 000000000000..8587ab507613 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/client.go @@ -0,0 +1,15 @@ +package deploymentinfo + +import "github.com/Azure/go-autorest/autorest" + +type DeploymentInfoClient struct { + Client autorest.Client + baseUri string +} + +func NewDeploymentInfoClientWithBaseURI(endpoint string) DeploymentInfoClient { + return DeploymentInfoClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/constants.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/constants.go new file mode 100644 index 000000000000..91612c6cfbda --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/constants.go @@ -0,0 +1,31 @@ +package deploymentinfo + +import "strings" + +type ElasticDeploymentStatus string + +const ( + ElasticDeploymentStatusHealthy ElasticDeploymentStatus = "Healthy" + ElasticDeploymentStatusUnhealthy ElasticDeploymentStatus = "Unhealthy" +) + +func PossibleValuesForElasticDeploymentStatus() []string { + return []string{ + string(ElasticDeploymentStatusHealthy), + string(ElasticDeploymentStatusUnhealthy), + } +} + +func parseElasticDeploymentStatus(input string) (*ElasticDeploymentStatus, error) { + vals := map[string]ElasticDeploymentStatus{ + "healthy": ElasticDeploymentStatusHealthy, + "unhealthy": ElasticDeploymentStatusUnhealthy, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ElasticDeploymentStatus(input) + return &out, nil +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/id_monitor.go new file mode 100644 index 000000000000..5aec2238a889 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/id_monitor.go @@ -0,0 +1,124 @@ +package deploymentinfo + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/id_monitor_test.go new file mode 100644 index 000000000000..3bcded00d7e6 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/id_monitor_test.go @@ -0,0 +1,279 @@ +package deploymentinfo + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/method_list_autorest.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/method_list_autorest.go new file mode 100644 index 000000000000..839ab1c174e4 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/method_list_autorest.go @@ -0,0 +1,65 @@ +package deploymentinfo + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type ListOperationResponse struct { + HttpResponse *http.Response + Model *DeploymentInfoResponse +} + +// List ... +func (c DeploymentInfoClient) List(ctx context.Context, id MonitorId) (result ListOperationResponse, err error) { + req, err := c.preparerForList(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "deploymentinfo.DeploymentInfoClient", "List", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "deploymentinfo.DeploymentInfoClient", "List", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForList(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "deploymentinfo.DeploymentInfoClient", "List", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForList prepares the List request. +func (c DeploymentInfoClient) preparerForList(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/listDeploymentInfo", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForList handles the response to the List request. The method always +// closes the http.Response Body. +func (c DeploymentInfoClient) responderForList(resp *http.Response) (result ListOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/model_deploymentinforesponse.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/model_deploymentinforesponse.go new file mode 100644 index 000000000000..f4289c1b85c5 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/model_deploymentinforesponse.go @@ -0,0 +1,8 @@ +package deploymentinfo + +type DeploymentInfoResponse struct { + DiskCapacity *string `json:"diskCapacity,omitempty"` + MemoryCapacity *string `json:"memoryCapacity,omitempty"` + Status *ElasticDeploymentStatus `json:"status,omitempty"` + Version *string `json:"version,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/deploymentinfo/version.go b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/version.go new file mode 100644 index 000000000000..104f1689e911 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/deploymentinfo/version.go @@ -0,0 +1,9 @@ +package deploymentinfo + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/deploymentinfo/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/client.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/client.go new file mode 100644 index 000000000000..825da9f22895 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/client.go @@ -0,0 +1,15 @@ +package monitoredresources + +import "github.com/Azure/go-autorest/autorest" + +type MonitoredResourcesClient struct { + Client autorest.Client + baseUri string +} + +func NewMonitoredResourcesClientWithBaseURI(endpoint string) MonitoredResourcesClient { + return MonitoredResourcesClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/constants.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/constants.go new file mode 100644 index 000000000000..c4c7c11ee9ec --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/constants.go @@ -0,0 +1,31 @@ +package monitoredresources + +import "strings" + +type SendingLogs string + +const ( + SendingLogsFalse SendingLogs = "False" + SendingLogsTrue SendingLogs = "True" +) + +func PossibleValuesForSendingLogs() []string { + return []string{ + string(SendingLogsFalse), + string(SendingLogsTrue), + } +} + +func parseSendingLogs(input string) (*SendingLogs, error) { + vals := map[string]SendingLogs{ + "false": SendingLogsFalse, + "true": SendingLogsTrue, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := SendingLogs(input) + return &out, nil +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/id_monitor.go new file mode 100644 index 000000000000..0686177c0ea1 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/id_monitor.go @@ -0,0 +1,124 @@ +package monitoredresources + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/id_monitor_test.go new file mode 100644 index 000000000000..6e18085fab80 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/id_monitor_test.go @@ -0,0 +1,279 @@ +package monitoredresources + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/method_list_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/method_list_autorest.go new file mode 100644 index 000000000000..9c5bf1a0cd5a --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/method_list_autorest.go @@ -0,0 +1,183 @@ +package monitoredresources + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type ListOperationResponse struct { + HttpResponse *http.Response + Model *[]MonitoredResource + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (ListOperationResponse, error) +} + +type ListCompleteResult struct { + Items []MonitoredResource +} + +func (r ListOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r ListOperationResponse) LoadMore(ctx context.Context) (resp ListOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// List ... +func (c MonitoredResourcesClient) List(ctx context.Context, id MonitorId) (resp ListOperationResponse, err error) { + req, err := c.preparerForList(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "monitoredresources.MonitoredResourcesClient", "List", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitoredresources.MonitoredResourcesClient", "List", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForList(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitoredresources.MonitoredResourcesClient", "List", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// ListComplete retrieves all of the results into a single object +func (c MonitoredResourcesClient) ListComplete(ctx context.Context, id MonitorId) (ListCompleteResult, error) { + return c.ListCompleteMatchingPredicate(ctx, id, MonitoredResourceOperationPredicate{}) +} + +// ListCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c MonitoredResourcesClient) ListCompleteMatchingPredicate(ctx context.Context, id MonitorId, predicate MonitoredResourceOperationPredicate) (resp ListCompleteResult, err error) { + items := make([]MonitoredResource, 0) + + page, err := c.List(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := ListCompleteResult{ + Items: items, + } + return out, nil +} + +// preparerForList prepares the List request. +func (c MonitoredResourcesClient) preparerForList(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/listMonitoredResources", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForListWithNextLink prepares the List request with the given nextLink token. +func (c MonitoredResourcesClient) preparerForListWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForList handles the response to the List request. The method always +// closes the http.Response Body. +func (c MonitoredResourcesClient) responderForList(resp *http.Response) (result ListOperationResponse, err error) { + type page struct { + Values []MonitoredResource `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result ListOperationResponse, err error) { + req, err := c.preparerForListWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "monitoredresources.MonitoredResourcesClient", "List", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitoredresources.MonitoredResourcesClient", "List", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForList(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitoredresources.MonitoredResourcesClient", "List", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/model_monitoredresource.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/model_monitoredresource.go new file mode 100644 index 000000000000..f227dd911589 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/model_monitoredresource.go @@ -0,0 +1,7 @@ +package monitoredresources + +type MonitoredResource struct { + Id *string `json:"id,omitempty"` + ReasonForLogsStatus *string `json:"reasonForLogsStatus,omitempty"` + SendingLogs *SendingLogs `json:"sendingLogs,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/predicates.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/predicates.go new file mode 100644 index 000000000000..80ddd7bd8025 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/predicates.go @@ -0,0 +1,19 @@ +package monitoredresources + +type MonitoredResourceOperationPredicate struct { + Id *string + ReasonForLogsStatus *string +} + +func (p MonitoredResourceOperationPredicate) Matches(input MonitoredResource) bool { + + if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + return false + } + + if p.ReasonForLogsStatus != nil && (input.ReasonForLogsStatus == nil && *p.ReasonForLogsStatus != *input.ReasonForLogsStatus) { + return false + } + + return true +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitoredresources/version.go b/internal/services/elastic/sdk/2020-07-01/monitoredresources/version.go new file mode 100644 index 000000000000..a8ea37a260be --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitoredresources/version.go @@ -0,0 +1,9 @@ +package monitoredresources + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/monitoredresources/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/client.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/client.go new file mode 100644 index 000000000000..87685bfe28cb --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/client.go @@ -0,0 +1,15 @@ +package monitorsresource + +import "github.com/Azure/go-autorest/autorest" + +type MonitorsResourceClient struct { + Client autorest.Client + baseUri string +} + +func NewMonitorsResourceClientWithBaseURI(endpoint string) MonitorsResourceClient { + return MonitorsResourceClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/constants.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/constants.go new file mode 100644 index 000000000000..eb470e798bde --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/constants.go @@ -0,0 +1,142 @@ +package monitorsresource + +import "strings" + +type CreatedByType string + +const ( + CreatedByTypeApplication CreatedByType = "Application" + CreatedByTypeKey CreatedByType = "Key" + CreatedByTypeManagedIdentity CreatedByType = "ManagedIdentity" + CreatedByTypeUser CreatedByType = "User" +) + +func PossibleValuesForCreatedByType() []string { + return []string{ + string(CreatedByTypeApplication), + string(CreatedByTypeKey), + string(CreatedByTypeManagedIdentity), + string(CreatedByTypeUser), + } +} + +func parseCreatedByType(input string) (*CreatedByType, error) { + vals := map[string]CreatedByType{ + "application": CreatedByTypeApplication, + "key": CreatedByTypeKey, + "managedidentity": CreatedByTypeManagedIdentity, + "user": CreatedByTypeUser, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := CreatedByType(input) + return &out, nil +} + +type LiftrResourceCategories string + +const ( + LiftrResourceCategoriesMonitorLogs LiftrResourceCategories = "MonitorLogs" + LiftrResourceCategoriesUnknown LiftrResourceCategories = "Unknown" +) + +func PossibleValuesForLiftrResourceCategories() []string { + return []string{ + string(LiftrResourceCategoriesMonitorLogs), + string(LiftrResourceCategoriesUnknown), + } +} + +func parseLiftrResourceCategories(input string) (*LiftrResourceCategories, error) { + vals := map[string]LiftrResourceCategories{ + "monitorlogs": LiftrResourceCategoriesMonitorLogs, + "unknown": LiftrResourceCategoriesUnknown, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := LiftrResourceCategories(input) + return &out, nil +} + +type MonitoringStatus string + +const ( + MonitoringStatusDisabled MonitoringStatus = "Disabled" + MonitoringStatusEnabled MonitoringStatus = "Enabled" +) + +func PossibleValuesForMonitoringStatus() []string { + return []string{ + string(MonitoringStatusDisabled), + string(MonitoringStatusEnabled), + } +} + +func parseMonitoringStatus(input string) (*MonitoringStatus, error) { + vals := map[string]MonitoringStatus{ + "disabled": MonitoringStatusDisabled, + "enabled": MonitoringStatusEnabled, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := MonitoringStatus(input) + return &out, nil +} + +type ProvisioningState string + +const ( + ProvisioningStateAccepted ProvisioningState = "Accepted" + ProvisioningStateCanceled ProvisioningState = "Canceled" + ProvisioningStateCreating ProvisioningState = "Creating" + ProvisioningStateDeleted ProvisioningState = "Deleted" + ProvisioningStateDeleting ProvisioningState = "Deleting" + ProvisioningStateFailed ProvisioningState = "Failed" + ProvisioningStateNotSpecified ProvisioningState = "NotSpecified" + ProvisioningStateSucceeded ProvisioningState = "Succeeded" + ProvisioningStateUpdating ProvisioningState = "Updating" +) + +func PossibleValuesForProvisioningState() []string { + return []string{ + string(ProvisioningStateAccepted), + string(ProvisioningStateCanceled), + string(ProvisioningStateCreating), + string(ProvisioningStateDeleted), + string(ProvisioningStateDeleting), + string(ProvisioningStateFailed), + string(ProvisioningStateNotSpecified), + string(ProvisioningStateSucceeded), + string(ProvisioningStateUpdating), + } +} + +func parseProvisioningState(input string) (*ProvisioningState, error) { + vals := map[string]ProvisioningState{ + "accepted": ProvisioningStateAccepted, + "canceled": ProvisioningStateCanceled, + "creating": ProvisioningStateCreating, + "deleted": ProvisioningStateDeleted, + "deleting": ProvisioningStateDeleting, + "failed": ProvisioningStateFailed, + "notspecified": ProvisioningStateNotSpecified, + "succeeded": ProvisioningStateSucceeded, + "updating": ProvisioningStateUpdating, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ProvisioningState(input) + return &out, nil +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/id_monitor.go new file mode 100644 index 000000000000..51fcbc93681b --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/id_monitor.go @@ -0,0 +1,124 @@ +package monitorsresource + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/id_monitor_test.go new file mode 100644 index 000000000000..c54195ad0f63 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/id_monitor_test.go @@ -0,0 +1,279 @@ +package monitorsresource + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorscreate_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorscreate_autorest.go new file mode 100644 index 000000000000..04bb8ab0d371 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorscreate_autorest.go @@ -0,0 +1,75 @@ +package monitorsresource + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +type MonitorsCreateOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// MonitorsCreate ... +func (c MonitorsResourceClient) MonitorsCreate(ctx context.Context, id MonitorId, input ElasticMonitorResource) (result MonitorsCreateOperationResponse, err error) { + req, err := c.preparerForMonitorsCreate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsCreate", nil, "Failure preparing request") + return + } + + result, err = c.senderForMonitorsCreate(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsCreate", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// MonitorsCreateThenPoll performs MonitorsCreate then polls until it's completed +func (c MonitorsResourceClient) MonitorsCreateThenPoll(ctx context.Context, id MonitorId, input ElasticMonitorResource) error { + result, err := c.MonitorsCreate(ctx, id, input) + if err != nil { + return fmt.Errorf("performing MonitorsCreate: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after MonitorsCreate: %+v", err) + } + + return nil +} + +// preparerForMonitorsCreate prepares the MonitorsCreate request. +func (c MonitorsResourceClient) preparerForMonitorsCreate(ctx context.Context, id MonitorId, input ElasticMonitorResource) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForMonitorsCreate sends the MonitorsCreate request. The method will close the +// http.Response Body if it receives an error. +func (c MonitorsResourceClient) senderForMonitorsCreate(ctx context.Context, req *http.Request) (future MonitorsCreateOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + future.Poller, err = polling.NewLongRunningPollerFromResponse(ctx, resp, c.Client) + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsdelete_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsdelete_autorest.go new file mode 100644 index 000000000000..b9c96c57b73b --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsdelete_autorest.go @@ -0,0 +1,74 @@ +package monitorsresource + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +type MonitorsDeleteOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// MonitorsDelete ... +func (c MonitorsResourceClient) MonitorsDelete(ctx context.Context, id MonitorId) (result MonitorsDeleteOperationResponse, err error) { + req, err := c.preparerForMonitorsDelete(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsDelete", nil, "Failure preparing request") + return + } + + result, err = c.senderForMonitorsDelete(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsDelete", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// MonitorsDeleteThenPoll performs MonitorsDelete then polls until it's completed +func (c MonitorsResourceClient) MonitorsDeleteThenPoll(ctx context.Context, id MonitorId) error { + result, err := c.MonitorsDelete(ctx, id) + if err != nil { + return fmt.Errorf("performing MonitorsDelete: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after MonitorsDelete: %+v", err) + } + + return nil +} + +// preparerForMonitorsDelete prepares the MonitorsDelete request. +func (c MonitorsResourceClient) preparerForMonitorsDelete(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsDelete(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForMonitorsDelete sends the MonitorsDelete request. The method will close the +// http.Response Body if it receives an error. +func (c MonitorsResourceClient) senderForMonitorsDelete(ctx context.Context, req *http.Request) (future MonitorsDeleteOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + future.Poller, err = polling.NewLongRunningPollerFromResponse(ctx, resp, c.Client) + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsget_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsget_autorest.go new file mode 100644 index 000000000000..a22b3884c401 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsget_autorest.go @@ -0,0 +1,64 @@ +package monitorsresource + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type MonitorsGetOperationResponse struct { + HttpResponse *http.Response + Model *ElasticMonitorResource +} + +// MonitorsGet ... +func (c MonitorsResourceClient) MonitorsGet(ctx context.Context, id MonitorId) (result MonitorsGetOperationResponse, err error) { + req, err := c.preparerForMonitorsGet(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsGet", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsGet", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForMonitorsGet(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsGet", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForMonitorsGet prepares the MonitorsGet request. +func (c MonitorsResourceClient) preparerForMonitorsGet(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForMonitorsGet handles the response to the MonitorsGet request. The method always +// closes the http.Response Body. +func (c MonitorsResourceClient) responderForMonitorsGet(resp *http.Response) (result MonitorsGetOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorslist_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorslist_autorest.go new file mode 100644 index 000000000000..4ed609fb4943 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorslist_autorest.go @@ -0,0 +1,184 @@ +package monitorsresource + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +) + +type MonitorsListOperationResponse struct { + HttpResponse *http.Response + Model *[]ElasticMonitorResource + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (MonitorsListOperationResponse, error) +} + +type MonitorsListCompleteResult struct { + Items []ElasticMonitorResource +} + +func (r MonitorsListOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r MonitorsListOperationResponse) LoadMore(ctx context.Context) (resp MonitorsListOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// MonitorsList ... +func (c MonitorsResourceClient) MonitorsList(ctx context.Context, id commonids.SubscriptionId) (resp MonitorsListOperationResponse, err error) { + req, err := c.preparerForMonitorsList(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsList", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsList", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForMonitorsList(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsList", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// MonitorsListComplete retrieves all of the results into a single object +func (c MonitorsResourceClient) MonitorsListComplete(ctx context.Context, id commonids.SubscriptionId) (MonitorsListCompleteResult, error) { + return c.MonitorsListCompleteMatchingPredicate(ctx, id, ElasticMonitorResourceOperationPredicate{}) +} + +// MonitorsListCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c MonitorsResourceClient) MonitorsListCompleteMatchingPredicate(ctx context.Context, id commonids.SubscriptionId, predicate ElasticMonitorResourceOperationPredicate) (resp MonitorsListCompleteResult, err error) { + items := make([]ElasticMonitorResource, 0) + + page, err := c.MonitorsList(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := MonitorsListCompleteResult{ + Items: items, + } + return out, nil +} + +// preparerForMonitorsList prepares the MonitorsList request. +func (c MonitorsResourceClient) preparerForMonitorsList(ctx context.Context, id commonids.SubscriptionId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/providers/Microsoft.Elastic/monitors", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForMonitorsListWithNextLink prepares the MonitorsList request with the given nextLink token. +func (c MonitorsResourceClient) preparerForMonitorsListWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForMonitorsList handles the response to the MonitorsList request. The method always +// closes the http.Response Body. +func (c MonitorsResourceClient) responderForMonitorsList(resp *http.Response) (result MonitorsListOperationResponse, err error) { + type page struct { + Values []ElasticMonitorResource `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result MonitorsListOperationResponse, err error) { + req, err := c.preparerForMonitorsListWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsList", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsList", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForMonitorsList(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsList", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorslistbyresourcegroup_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorslistbyresourcegroup_autorest.go new file mode 100644 index 000000000000..6e6e6bfaaf45 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorslistbyresourcegroup_autorest.go @@ -0,0 +1,184 @@ +package monitorsresource + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +) + +type MonitorsListByResourceGroupOperationResponse struct { + HttpResponse *http.Response + Model *[]ElasticMonitorResource + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (MonitorsListByResourceGroupOperationResponse, error) +} + +type MonitorsListByResourceGroupCompleteResult struct { + Items []ElasticMonitorResource +} + +func (r MonitorsListByResourceGroupOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r MonitorsListByResourceGroupOperationResponse) LoadMore(ctx context.Context) (resp MonitorsListByResourceGroupOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// MonitorsListByResourceGroup ... +func (c MonitorsResourceClient) MonitorsListByResourceGroup(ctx context.Context, id commonids.ResourceGroupId) (resp MonitorsListByResourceGroupOperationResponse, err error) { + req, err := c.preparerForMonitorsListByResourceGroup(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsListByResourceGroup", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsListByResourceGroup", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForMonitorsListByResourceGroup(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsListByResourceGroup", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// MonitorsListByResourceGroupComplete retrieves all of the results into a single object +func (c MonitorsResourceClient) MonitorsListByResourceGroupComplete(ctx context.Context, id commonids.ResourceGroupId) (MonitorsListByResourceGroupCompleteResult, error) { + return c.MonitorsListByResourceGroupCompleteMatchingPredicate(ctx, id, ElasticMonitorResourceOperationPredicate{}) +} + +// MonitorsListByResourceGroupCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c MonitorsResourceClient) MonitorsListByResourceGroupCompleteMatchingPredicate(ctx context.Context, id commonids.ResourceGroupId, predicate ElasticMonitorResourceOperationPredicate) (resp MonitorsListByResourceGroupCompleteResult, err error) { + items := make([]ElasticMonitorResource, 0) + + page, err := c.MonitorsListByResourceGroup(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := MonitorsListByResourceGroupCompleteResult{ + Items: items, + } + return out, nil +} + +// preparerForMonitorsListByResourceGroup prepares the MonitorsListByResourceGroup request. +func (c MonitorsResourceClient) preparerForMonitorsListByResourceGroup(ctx context.Context, id commonids.ResourceGroupId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/providers/Microsoft.Elastic/monitors", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForMonitorsListByResourceGroupWithNextLink prepares the MonitorsListByResourceGroup request with the given nextLink token. +func (c MonitorsResourceClient) preparerForMonitorsListByResourceGroupWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForMonitorsListByResourceGroup handles the response to the MonitorsListByResourceGroup request. The method always +// closes the http.Response Body. +func (c MonitorsResourceClient) responderForMonitorsListByResourceGroup(resp *http.Response) (result MonitorsListByResourceGroupOperationResponse, err error) { + type page struct { + Values []ElasticMonitorResource `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result MonitorsListByResourceGroupOperationResponse, err error) { + req, err := c.preparerForMonitorsListByResourceGroupWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsListByResourceGroup", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsListByResourceGroup", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForMonitorsListByResourceGroup(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsListByResourceGroup", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsupdate_autorest.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsupdate_autorest.go new file mode 100644 index 000000000000..c38b0dcd9092 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/method_monitorsupdate_autorest.go @@ -0,0 +1,65 @@ +package monitorsresource + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type MonitorsUpdateOperationResponse struct { + HttpResponse *http.Response + Model *ElasticMonitorResource +} + +// MonitorsUpdate ... +func (c MonitorsResourceClient) MonitorsUpdate(ctx context.Context, id MonitorId, input ElasticMonitorResourceUpdateParameters) (result MonitorsUpdateOperationResponse, err error) { + req, err := c.preparerForMonitorsUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsUpdate", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsUpdate", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForMonitorsUpdate(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "monitorsresource.MonitorsResourceClient", "MonitorsUpdate", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForMonitorsUpdate prepares the MonitorsUpdate request. +func (c MonitorsResourceClient) preparerForMonitorsUpdate(ctx context.Context, id MonitorId, input ElasticMonitorResourceUpdateParameters) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPatch(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForMonitorsUpdate handles the response to the MonitorsUpdate request. The method always +// closes the http.Response Body. +func (c MonitorsResourceClient) responderForMonitorsUpdate(resp *http.Response) (result MonitorsUpdateOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_companyinfo.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_companyinfo.go new file mode 100644 index 000000000000..0160e8a21321 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_companyinfo.go @@ -0,0 +1,9 @@ +package monitorsresource + +type CompanyInfo struct { + Business *string `json:"business,omitempty"` + Country *string `json:"country,omitempty"` + Domain *string `json:"domain,omitempty"` + EmployeesNumber *string `json:"employeesNumber,omitempty"` + State *string `json:"state,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticclouddeployment.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticclouddeployment.go new file mode 100644 index 000000000000..389dd80a707d --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticclouddeployment.go @@ -0,0 +1,11 @@ +package monitorsresource + +type ElasticCloudDeployment struct { + AzureSubscriptionId *string `json:"azureSubscriptionId,omitempty"` + DeploymentId *string `json:"deploymentId,omitempty"` + ElasticsearchRegion *string `json:"elasticsearchRegion,omitempty"` + ElasticsearchServiceUrl *string `json:"elasticsearchServiceUrl,omitempty"` + KibanaServiceUrl *string `json:"kibanaServiceUrl,omitempty"` + KibanaSsoUrl *string `json:"kibanaSsoUrl,omitempty"` + Name *string `json:"name,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticclouduser.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticclouduser.go new file mode 100644 index 000000000000..bb816ea50b41 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticclouduser.go @@ -0,0 +1,7 @@ +package monitorsresource + +type ElasticCloudUser struct { + ElasticCloudSsoDefaultUrl *string `json:"elasticCloudSsoDefaultUrl,omitempty"` + EmailAddress *string `json:"emailAddress,omitempty"` + Id *string `json:"id,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticmonitorresource.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticmonitorresource.go new file mode 100644 index 000000000000..be36fa4277f2 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticmonitorresource.go @@ -0,0 +1,17 @@ +package monitorsresource + +import ( + "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" +) + +type ElasticMonitorResource struct { + Id *string `json:"id,omitempty"` + Identity *identity.SystemAssigned `json:"identity,omitempty"` + Location string `json:"location"` + Name *string `json:"name,omitempty"` + Properties *MonitorProperties `json:"properties,omitempty"` + Sku *ResourceSku `json:"sku,omitempty"` + SystemData *SystemData `json:"systemData,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticmonitorresourceupdateparameters.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticmonitorresourceupdateparameters.go new file mode 100644 index 000000000000..da1382568acd --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticmonitorresourceupdateparameters.go @@ -0,0 +1,5 @@ +package monitorsresource + +type ElasticMonitorResourceUpdateParameters struct { + Tags *map[string]string `json:"tags,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticproperties.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticproperties.go new file mode 100644 index 000000000000..9d710750b049 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_elasticproperties.go @@ -0,0 +1,6 @@ +package monitorsresource + +type ElasticProperties struct { + ElasticCloudDeployment *ElasticCloudDeployment `json:"elasticCloudDeployment,omitempty"` + ElasticCloudUser *ElasticCloudUser `json:"elasticCloudUser,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_monitorproperties.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_monitorproperties.go new file mode 100644 index 000000000000..513e2f5e2f49 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_monitorproperties.go @@ -0,0 +1,10 @@ +package monitorsresource + +type MonitorProperties struct { + ElasticProperties *ElasticProperties `json:"elasticProperties,omitempty"` + LiftrResourceCategory *LiftrResourceCategories `json:"liftrResourceCategory,omitempty"` + LiftrResourcePreference *int64 `json:"liftrResourcePreference,omitempty"` + MonitoringStatus *MonitoringStatus `json:"monitoringStatus,omitempty"` + ProvisioningState *ProvisioningState `json:"provisioningState,omitempty"` + UserInfo *UserInfo `json:"userInfo,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_resourcesku.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_resourcesku.go new file mode 100644 index 000000000000..3cb90dce09ec --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_resourcesku.go @@ -0,0 +1,5 @@ +package monitorsresource + +type ResourceSku struct { + Name string `json:"name"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_systemdata.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_systemdata.go new file mode 100644 index 000000000000..bce9879bdb8c --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_systemdata.go @@ -0,0 +1,40 @@ +package monitorsresource + +import ( + "time" + + "github.com/hashicorp/go-azure-helpers/lang/dates" +) + +type SystemData struct { + CreatedAt *string `json:"createdAt,omitempty"` + CreatedBy *string `json:"createdBy,omitempty"` + CreatedByType *CreatedByType `json:"createdByType,omitempty"` + LastModifiedAt *string `json:"lastModifiedAt,omitempty"` + LastModifiedBy *string `json:"lastModifiedBy,omitempty"` + LastModifiedByType *CreatedByType `json:"lastModifiedByType,omitempty"` +} + +func (o SystemData) GetCreatedAtAsTime() (*time.Time, error) { + if o.CreatedAt == nil { + return nil, nil + } + return dates.ParseAsFormat(o.CreatedAt, "2006-01-02T15:04:05Z07:00") +} + +func (o SystemData) SetCreatedAtAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.CreatedAt = &formatted +} + +func (o SystemData) GetLastModifiedAtAsTime() (*time.Time, error) { + if o.LastModifiedAt == nil { + return nil, nil + } + return dates.ParseAsFormat(o.LastModifiedAt, "2006-01-02T15:04:05Z07:00") +} + +func (o SystemData) SetLastModifiedAtAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.LastModifiedAt = &formatted +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_userinfo.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_userinfo.go new file mode 100644 index 000000000000..a5ca34135061 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/model_userinfo.go @@ -0,0 +1,9 @@ +package monitorsresource + +type UserInfo struct { + CompanyInfo *CompanyInfo `json:"companyInfo,omitempty"` + CompanyName *string `json:"companyName,omitempty"` + EmailAddress *string `json:"emailAddress,omitempty"` + FirstName *string `json:"firstName,omitempty"` + LastName *string `json:"lastName,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/predicates.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/predicates.go new file mode 100644 index 000000000000..02ecd67d13d4 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/predicates.go @@ -0,0 +1,29 @@ +package monitorsresource + +type ElasticMonitorResourceOperationPredicate struct { + Id *string + Location *string + Name *string + Type *string +} + +func (p ElasticMonitorResourceOperationPredicate) Matches(input ElasticMonitorResource) bool { + + if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + return false + } + + if p.Location != nil && *p.Location != input.Location { + return false + } + + if p.Name != nil && (input.Name == nil && *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil && *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/internal/services/elastic/sdk/2020-07-01/monitorsresource/version.go b/internal/services/elastic/sdk/2020-07-01/monitorsresource/version.go new file mode 100644 index 000000000000..541ec56a0578 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/monitorsresource/version.go @@ -0,0 +1,9 @@ +package monitorsresource + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/monitorsresource/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/client.go b/internal/services/elastic/sdk/2020-07-01/rules/client.go new file mode 100644 index 000000000000..5240d317139d --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/client.go @@ -0,0 +1,15 @@ +package rules + +import "github.com/Azure/go-autorest/autorest" + +type RulesClient struct { + Client autorest.Client + baseUri string +} + +func NewRulesClientWithBaseURI(endpoint string) RulesClient { + return RulesClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/constants.go b/internal/services/elastic/sdk/2020-07-01/rules/constants.go new file mode 100644 index 000000000000..4f2789d74cf8 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/constants.go @@ -0,0 +1,114 @@ +package rules + +import "strings" + +type CreatedByType string + +const ( + CreatedByTypeApplication CreatedByType = "Application" + CreatedByTypeKey CreatedByType = "Key" + CreatedByTypeManagedIdentity CreatedByType = "ManagedIdentity" + CreatedByTypeUser CreatedByType = "User" +) + +func PossibleValuesForCreatedByType() []string { + return []string{ + string(CreatedByTypeApplication), + string(CreatedByTypeKey), + string(CreatedByTypeManagedIdentity), + string(CreatedByTypeUser), + } +} + +func parseCreatedByType(input string) (*CreatedByType, error) { + vals := map[string]CreatedByType{ + "application": CreatedByTypeApplication, + "key": CreatedByTypeKey, + "managedidentity": CreatedByTypeManagedIdentity, + "user": CreatedByTypeUser, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := CreatedByType(input) + return &out, nil +} + +type ProvisioningState string + +const ( + ProvisioningStateAccepted ProvisioningState = "Accepted" + ProvisioningStateCanceled ProvisioningState = "Canceled" + ProvisioningStateCreating ProvisioningState = "Creating" + ProvisioningStateDeleted ProvisioningState = "Deleted" + ProvisioningStateDeleting ProvisioningState = "Deleting" + ProvisioningStateFailed ProvisioningState = "Failed" + ProvisioningStateNotSpecified ProvisioningState = "NotSpecified" + ProvisioningStateSucceeded ProvisioningState = "Succeeded" + ProvisioningStateUpdating ProvisioningState = "Updating" +) + +func PossibleValuesForProvisioningState() []string { + return []string{ + string(ProvisioningStateAccepted), + string(ProvisioningStateCanceled), + string(ProvisioningStateCreating), + string(ProvisioningStateDeleted), + string(ProvisioningStateDeleting), + string(ProvisioningStateFailed), + string(ProvisioningStateNotSpecified), + string(ProvisioningStateSucceeded), + string(ProvisioningStateUpdating), + } +} + +func parseProvisioningState(input string) (*ProvisioningState, error) { + vals := map[string]ProvisioningState{ + "accepted": ProvisioningStateAccepted, + "canceled": ProvisioningStateCanceled, + "creating": ProvisioningStateCreating, + "deleted": ProvisioningStateDeleted, + "deleting": ProvisioningStateDeleting, + "failed": ProvisioningStateFailed, + "notspecified": ProvisioningStateNotSpecified, + "succeeded": ProvisioningStateSucceeded, + "updating": ProvisioningStateUpdating, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ProvisioningState(input) + return &out, nil +} + +type TagAction string + +const ( + TagActionExclude TagAction = "Exclude" + TagActionInclude TagAction = "Include" +) + +func PossibleValuesForTagAction() []string { + return []string{ + string(TagActionExclude), + string(TagActionInclude), + } +} + +func parseTagAction(input string) (*TagAction, error) { + vals := map[string]TagAction{ + "exclude": TagActionExclude, + "include": TagActionInclude, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := TagAction(input) + return &out, nil +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/rules/id_monitor.go new file mode 100644 index 000000000000..e0d894032fed --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/id_monitor.go @@ -0,0 +1,124 @@ +package rules + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/rules/id_monitor_test.go new file mode 100644 index 000000000000..09fd750e8f8e --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/id_monitor_test.go @@ -0,0 +1,279 @@ +package rules + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/id_tagrule.go b/internal/services/elastic/sdk/2020-07-01/rules/id_tagrule.go new file mode 100644 index 000000000000..d7176bac76d8 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/id_tagrule.go @@ -0,0 +1,137 @@ +package rules + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = TagRuleId{} + +// TagRuleId is a struct representing the Resource ID for a Tag Rule +type TagRuleId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string + RuleSetName string +} + +// NewTagRuleID returns a new TagRuleId struct +func NewTagRuleID(subscriptionId string, resourceGroupName string, monitorName string, ruleSetName string) TagRuleId { + return TagRuleId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + RuleSetName: ruleSetName, + } +} + +// ParseTagRuleID parses 'input' into a TagRuleId +func ParseTagRuleID(input string) (*TagRuleId, error) { + parser := resourceids.NewParserFromResourceIdType(TagRuleId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := TagRuleId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + if id.RuleSetName, ok = parsed.Parsed["ruleSetName"]; !ok { + return nil, fmt.Errorf("the segment 'ruleSetName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseTagRuleIDInsensitively parses 'input' case-insensitively into a TagRuleId +// note: this method should only be used for API response data and not user input +func ParseTagRuleIDInsensitively(input string) (*TagRuleId, error) { + parser := resourceids.NewParserFromResourceIdType(TagRuleId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := TagRuleId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + if id.RuleSetName, ok = parsed.Parsed["ruleSetName"]; !ok { + return nil, fmt.Errorf("the segment 'ruleSetName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateTagRuleID checks that 'input' can be parsed as a Tag Rule ID +func ValidateTagRuleID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseTagRuleID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Tag Rule ID +func (id TagRuleId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s/tagRules/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName, id.RuleSetName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Tag Rule ID +func (id TagRuleId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + resourceids.StaticSegment("staticTagRules", "tagRules", "tagRules"), + resourceids.UserSpecifiedSegment("ruleSetName", "ruleSetValue"), + } +} + +// String returns a human-readable description of this Tag Rule ID +func (id TagRuleId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + fmt.Sprintf("Rule Set Name: %q", id.RuleSetName), + } + return fmt.Sprintf("Tag Rule (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/id_tagrule_test.go b/internal/services/elastic/sdk/2020-07-01/rules/id_tagrule_test.go new file mode 100644 index 000000000000..ae962d4fe45d --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/id_tagrule_test.go @@ -0,0 +1,324 @@ +package rules + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = TagRuleId{} + +func TestNewTagRuleID(t *testing.T) { + id := NewTagRuleID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue", "ruleSetValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } + + if id.RuleSetName != "ruleSetValue" { + t.Fatalf("Expected %q but got %q for Segment 'RuleSetName'", id.RuleSetName, "ruleSetValue") + } +} + +func TestFormatTagRuleID(t *testing.T) { + actual := NewTagRuleID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue", "ruleSetValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules/ruleSetValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseTagRuleID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *TagRuleId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules/ruleSetValue", + Expected: &TagRuleId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + RuleSetName: "ruleSetValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules/ruleSetValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseTagRuleID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + if actual.RuleSetName != v.Expected.RuleSetName { + t.Fatalf("Expected %q but got %q for RuleSetName", v.Expected.RuleSetName, actual.RuleSetName) + } + + } +} + +func TestParseTagRuleIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *TagRuleId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/tAgRuLeS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules/ruleSetValue", + Expected: &TagRuleId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + RuleSetName: "ruleSetValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/tagRules/ruleSetValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/tAgRuLeS/rUlEsEtVaLuE", + Expected: &TagRuleId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + RuleSetName: "rUlEsEtVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/tAgRuLeS/rUlEsEtVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseTagRuleIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + if actual.RuleSetName != v.Expected.RuleSetName { + t.Fatalf("Expected %q but got %q for RuleSetName", v.Expected.RuleSetName, actual.RuleSetName) + } + + } +} + +func TestSegmentsForTagRuleId(t *testing.T) { + segments := TagRuleId{}.Segments() + if len(segments) == 0 { + t.Fatalf("TagRuleId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulescreateorupdate_autorest.go b/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulescreateorupdate_autorest.go new file mode 100644 index 000000000000..5b198ff510a2 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulescreateorupdate_autorest.go @@ -0,0 +1,65 @@ +package rules + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type TagRulesCreateOrUpdateOperationResponse struct { + HttpResponse *http.Response + Model *MonitoringTagRules +} + +// TagRulesCreateOrUpdate ... +func (c RulesClient) TagRulesCreateOrUpdate(ctx context.Context, id TagRuleId, input MonitoringTagRules) (result TagRulesCreateOrUpdateOperationResponse, err error) { + req, err := c.preparerForTagRulesCreateOrUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesCreateOrUpdate", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesCreateOrUpdate", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForTagRulesCreateOrUpdate(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesCreateOrUpdate", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForTagRulesCreateOrUpdate prepares the TagRulesCreateOrUpdate request. +func (c RulesClient) preparerForTagRulesCreateOrUpdate(ctx context.Context, id TagRuleId, input MonitoringTagRules) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForTagRulesCreateOrUpdate handles the response to the TagRulesCreateOrUpdate request. The method always +// closes the http.Response Body. +func (c RulesClient) responderForTagRulesCreateOrUpdate(resp *http.Response) (result TagRulesCreateOrUpdateOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulesdelete_autorest.go b/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulesdelete_autorest.go new file mode 100644 index 000000000000..3eea0efaf57b --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulesdelete_autorest.go @@ -0,0 +1,74 @@ +package rules + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +type TagRulesDeleteOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// TagRulesDelete ... +func (c RulesClient) TagRulesDelete(ctx context.Context, id TagRuleId) (result TagRulesDeleteOperationResponse, err error) { + req, err := c.preparerForTagRulesDelete(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesDelete", nil, "Failure preparing request") + return + } + + result, err = c.senderForTagRulesDelete(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesDelete", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// TagRulesDeleteThenPoll performs TagRulesDelete then polls until it's completed +func (c RulesClient) TagRulesDeleteThenPoll(ctx context.Context, id TagRuleId) error { + result, err := c.TagRulesDelete(ctx, id) + if err != nil { + return fmt.Errorf("performing TagRulesDelete: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after TagRulesDelete: %+v", err) + } + + return nil +} + +// preparerForTagRulesDelete prepares the TagRulesDelete request. +func (c RulesClient) preparerForTagRulesDelete(ctx context.Context, id TagRuleId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsDelete(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForTagRulesDelete sends the TagRulesDelete request. The method will close the +// http.Response Body if it receives an error. +func (c RulesClient) senderForTagRulesDelete(ctx context.Context, req *http.Request) (future TagRulesDeleteOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + future.Poller, err = polling.NewLongRunningPollerFromResponse(ctx, resp, c.Client) + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulesget_autorest.go b/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulesget_autorest.go new file mode 100644 index 000000000000..71b8d21a9df9 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/method_tagrulesget_autorest.go @@ -0,0 +1,64 @@ +package rules + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type TagRulesGetOperationResponse struct { + HttpResponse *http.Response + Model *MonitoringTagRules +} + +// TagRulesGet ... +func (c RulesClient) TagRulesGet(ctx context.Context, id TagRuleId) (result TagRulesGetOperationResponse, err error) { + req, err := c.preparerForTagRulesGet(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesGet", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesGet", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForTagRulesGet(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesGet", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForTagRulesGet prepares the TagRulesGet request. +func (c RulesClient) preparerForTagRulesGet(ctx context.Context, id TagRuleId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForTagRulesGet handles the response to the TagRulesGet request. The method always +// closes the http.Response Body. +func (c RulesClient) responderForTagRulesGet(resp *http.Response) (result TagRulesGetOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/method_tagruleslist_autorest.go b/internal/services/elastic/sdk/2020-07-01/rules/method_tagruleslist_autorest.go new file mode 100644 index 000000000000..877714695246 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/method_tagruleslist_autorest.go @@ -0,0 +1,183 @@ +package rules + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type TagRulesListOperationResponse struct { + HttpResponse *http.Response + Model *[]MonitoringTagRules + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (TagRulesListOperationResponse, error) +} + +type TagRulesListCompleteResult struct { + Items []MonitoringTagRules +} + +func (r TagRulesListOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r TagRulesListOperationResponse) LoadMore(ctx context.Context) (resp TagRulesListOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// TagRulesList ... +func (c RulesClient) TagRulesList(ctx context.Context, id MonitorId) (resp TagRulesListOperationResponse, err error) { + req, err := c.preparerForTagRulesList(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesList", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesList", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForTagRulesList(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesList", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// TagRulesListComplete retrieves all of the results into a single object +func (c RulesClient) TagRulesListComplete(ctx context.Context, id MonitorId) (TagRulesListCompleteResult, error) { + return c.TagRulesListCompleteMatchingPredicate(ctx, id, MonitoringTagRulesOperationPredicate{}) +} + +// TagRulesListCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c RulesClient) TagRulesListCompleteMatchingPredicate(ctx context.Context, id MonitorId, predicate MonitoringTagRulesOperationPredicate) (resp TagRulesListCompleteResult, err error) { + items := make([]MonitoringTagRules, 0) + + page, err := c.TagRulesList(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := TagRulesListCompleteResult{ + Items: items, + } + return out, nil +} + +// preparerForTagRulesList prepares the TagRulesList request. +func (c RulesClient) preparerForTagRulesList(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/tagRules", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForTagRulesListWithNextLink prepares the TagRulesList request with the given nextLink token. +func (c RulesClient) preparerForTagRulesListWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForTagRulesList handles the response to the TagRulesList request. The method always +// closes the http.Response Body. +func (c RulesClient) responderForTagRulesList(resp *http.Response) (result TagRulesListOperationResponse, err error) { + type page struct { + Values []MonitoringTagRules `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result TagRulesListOperationResponse, err error) { + req, err := c.preparerForTagRulesListWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesList", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesList", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForTagRulesList(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "rules.RulesClient", "TagRulesList", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/model_filteringtag.go b/internal/services/elastic/sdk/2020-07-01/rules/model_filteringtag.go new file mode 100644 index 000000000000..d55b98d6ca09 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/model_filteringtag.go @@ -0,0 +1,7 @@ +package rules + +type FilteringTag struct { + Action *TagAction `json:"action,omitempty"` + Name *string `json:"name,omitempty"` + Value *string `json:"value,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/model_logrules.go b/internal/services/elastic/sdk/2020-07-01/rules/model_logrules.go new file mode 100644 index 000000000000..a4c8706b82b4 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/model_logrules.go @@ -0,0 +1,8 @@ +package rules + +type LogRules struct { + FilteringTags *[]FilteringTag `json:"filteringTags,omitempty"` + SendAadLogs *bool `json:"sendAadLogs,omitempty"` + SendActivityLogs *bool `json:"sendActivityLogs,omitempty"` + SendSubscriptionLogs *bool `json:"sendSubscriptionLogs,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/model_monitoringtagrules.go b/internal/services/elastic/sdk/2020-07-01/rules/model_monitoringtagrules.go new file mode 100644 index 000000000000..3a9b5e287d33 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/model_monitoringtagrules.go @@ -0,0 +1,9 @@ +package rules + +type MonitoringTagRules struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *MonitoringTagRulesProperties `json:"properties,omitempty"` + SystemData *SystemData `json:"systemData,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/model_monitoringtagrulesproperties.go b/internal/services/elastic/sdk/2020-07-01/rules/model_monitoringtagrulesproperties.go new file mode 100644 index 000000000000..369405b7e341 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/model_monitoringtagrulesproperties.go @@ -0,0 +1,6 @@ +package rules + +type MonitoringTagRulesProperties struct { + LogRules *LogRules `json:"logRules,omitempty"` + ProvisioningState *ProvisioningState `json:"provisioningState,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/model_systemdata.go b/internal/services/elastic/sdk/2020-07-01/rules/model_systemdata.go new file mode 100644 index 000000000000..559b614791f9 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/model_systemdata.go @@ -0,0 +1,40 @@ +package rules + +import ( + "time" + + "github.com/hashicorp/go-azure-helpers/lang/dates" +) + +type SystemData struct { + CreatedAt *string `json:"createdAt,omitempty"` + CreatedBy *string `json:"createdBy,omitempty"` + CreatedByType *CreatedByType `json:"createdByType,omitempty"` + LastModifiedAt *string `json:"lastModifiedAt,omitempty"` + LastModifiedBy *string `json:"lastModifiedBy,omitempty"` + LastModifiedByType *CreatedByType `json:"lastModifiedByType,omitempty"` +} + +func (o SystemData) GetCreatedAtAsTime() (*time.Time, error) { + if o.CreatedAt == nil { + return nil, nil + } + return dates.ParseAsFormat(o.CreatedAt, "2006-01-02T15:04:05Z07:00") +} + +func (o SystemData) SetCreatedAtAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.CreatedAt = &formatted +} + +func (o SystemData) GetLastModifiedAtAsTime() (*time.Time, error) { + if o.LastModifiedAt == nil { + return nil, nil + } + return dates.ParseAsFormat(o.LastModifiedAt, "2006-01-02T15:04:05Z07:00") +} + +func (o SystemData) SetLastModifiedAtAsTime(input time.Time) { + formatted := input.Format("2006-01-02T15:04:05Z07:00") + o.LastModifiedAt = &formatted +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/predicates.go b/internal/services/elastic/sdk/2020-07-01/rules/predicates.go new file mode 100644 index 000000000000..7b4b95e3c7e3 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/predicates.go @@ -0,0 +1,24 @@ +package rules + +type MonitoringTagRulesOperationPredicate struct { + Id *string + Name *string + Type *string +} + +func (p MonitoringTagRulesOperationPredicate) Matches(input MonitoringTagRules) bool { + + if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + return false + } + + if p.Name != nil && (input.Name == nil && *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil && *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/internal/services/elastic/sdk/2020-07-01/rules/version.go b/internal/services/elastic/sdk/2020-07-01/rules/version.go new file mode 100644 index 000000000000..049bf83f2aa8 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/rules/version.go @@ -0,0 +1,9 @@ +package rules + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/rules/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/client.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/client.go new file mode 100644 index 000000000000..c4d17c409e17 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/client.go @@ -0,0 +1,15 @@ +package vmcollectionupdate + +import "github.com/Azure/go-autorest/autorest" + +type VMCollectionUpdateClient struct { + Client autorest.Client + baseUri string +} + +func NewVMCollectionUpdateClientWithBaseURI(endpoint string) VMCollectionUpdateClient { + return VMCollectionUpdateClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/constants.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/constants.go new file mode 100644 index 000000000000..67642bd42ebb --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/constants.go @@ -0,0 +1,31 @@ +package vmcollectionupdate + +import "strings" + +type OperationName string + +const ( + OperationNameAdd OperationName = "Add" + OperationNameDelete OperationName = "Delete" +) + +func PossibleValuesForOperationName() []string { + return []string{ + string(OperationNameAdd), + string(OperationNameDelete), + } +} + +func parseOperationName(input string) (*OperationName, error) { + vals := map[string]OperationName{ + "add": OperationNameAdd, + "delete": OperationNameDelete, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := OperationName(input) + return &out, nil +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/id_monitor.go new file mode 100644 index 000000000000..70e20f03caea --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/id_monitor.go @@ -0,0 +1,124 @@ +package vmcollectionupdate + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/id_monitor_test.go new file mode 100644 index 000000000000..2fa62b0154ca --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/id_monitor_test.go @@ -0,0 +1,279 @@ +package vmcollectionupdate + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/method_vmcollectionupdate_autorest.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/method_vmcollectionupdate_autorest.go new file mode 100644 index 000000000000..8ef855f4d89d --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/method_vmcollectionupdate_autorest.go @@ -0,0 +1,64 @@ +package vmcollectionupdate + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type VMCollectionUpdateOperationResponse struct { + HttpResponse *http.Response +} + +// VMCollectionUpdate ... +func (c VMCollectionUpdateClient) VMCollectionUpdate(ctx context.Context, id MonitorId, input VMCollectionUpdate) (result VMCollectionUpdateOperationResponse, err error) { + req, err := c.preparerForVMCollectionUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "vmcollectionupdate.VMCollectionUpdateClient", "VMCollectionUpdate", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "vmcollectionupdate.VMCollectionUpdateClient", "VMCollectionUpdate", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForVMCollectionUpdate(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "vmcollectionupdate.VMCollectionUpdateClient", "VMCollectionUpdate", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForVMCollectionUpdate prepares the VMCollectionUpdate request. +func (c VMCollectionUpdateClient) preparerForVMCollectionUpdate(ctx context.Context, id MonitorId, input VMCollectionUpdate) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/vmCollectionUpdate", id.ID())), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForVMCollectionUpdate handles the response to the VMCollectionUpdate request. The method always +// closes the http.Response Body. +func (c VMCollectionUpdateClient) responderForVMCollectionUpdate(resp *http.Response) (result VMCollectionUpdateOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/model_vmcollectionupdate.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/model_vmcollectionupdate.go new file mode 100644 index 000000000000..c0919473b6fd --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/model_vmcollectionupdate.go @@ -0,0 +1,6 @@ +package vmcollectionupdate + +type VMCollectionUpdate struct { + OperationName *OperationName `json:"operationName,omitempty"` + VmResourceId *string `json:"vmResourceId,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/version.go b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/version.go new file mode 100644 index 000000000000..2843533f1b90 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmcollectionupdate/version.go @@ -0,0 +1,9 @@ +package vmcollectionupdate + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/vmcollectionupdate/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/client.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/client.go new file mode 100644 index 000000000000..02aedeec9c2e --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/client.go @@ -0,0 +1,15 @@ +package vmhhostlist + +import "github.com/Azure/go-autorest/autorest" + +type VMHHostListClient struct { + Client autorest.Client + baseUri string +} + +func NewVMHHostListClientWithBaseURI(endpoint string) VMHHostListClient { + return VMHHostListClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/id_monitor.go new file mode 100644 index 000000000000..5065ea5852b1 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/id_monitor.go @@ -0,0 +1,124 @@ +package vmhhostlist + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/id_monitor_test.go new file mode 100644 index 000000000000..31433d32d2c9 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/id_monitor_test.go @@ -0,0 +1,279 @@ +package vmhhostlist + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/method_vmhostlist_autorest.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/method_vmhostlist_autorest.go new file mode 100644 index 000000000000..84ff0a2fb903 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/method_vmhostlist_autorest.go @@ -0,0 +1,183 @@ +package vmhhostlist + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type VMHostListOperationResponse struct { + HttpResponse *http.Response + Model *[]VMResources + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (VMHostListOperationResponse, error) +} + +type VMHostListCompleteResult struct { + Items []VMResources +} + +func (r VMHostListOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r VMHostListOperationResponse) LoadMore(ctx context.Context) (resp VMHostListOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// VMHostList ... +func (c VMHHostListClient) VMHostList(ctx context.Context, id MonitorId) (resp VMHostListOperationResponse, err error) { + req, err := c.preparerForVMHostList(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "vmhhostlist.VMHHostListClient", "VMHostList", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "vmhhostlist.VMHHostListClient", "VMHostList", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForVMHostList(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "vmhhostlist.VMHHostListClient", "VMHostList", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// VMHostListComplete retrieves all of the results into a single object +func (c VMHHostListClient) VMHostListComplete(ctx context.Context, id MonitorId) (VMHostListCompleteResult, error) { + return c.VMHostListCompleteMatchingPredicate(ctx, id, VMResourcesOperationPredicate{}) +} + +// VMHostListCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c VMHHostListClient) VMHostListCompleteMatchingPredicate(ctx context.Context, id MonitorId, predicate VMResourcesOperationPredicate) (resp VMHostListCompleteResult, err error) { + items := make([]VMResources, 0) + + page, err := c.VMHostList(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := VMHostListCompleteResult{ + Items: items, + } + return out, nil +} + +// preparerForVMHostList prepares the VMHostList request. +func (c VMHHostListClient) preparerForVMHostList(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/listVMHost", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForVMHostListWithNextLink prepares the VMHostList request with the given nextLink token. +func (c VMHHostListClient) preparerForVMHostListWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForVMHostList handles the response to the VMHostList request. The method always +// closes the http.Response Body. +func (c VMHHostListClient) responderForVMHostList(resp *http.Response) (result VMHostListOperationResponse, err error) { + type page struct { + Values []VMResources `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result VMHostListOperationResponse, err error) { + req, err := c.preparerForVMHostListWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "vmhhostlist.VMHHostListClient", "VMHostList", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "vmhhostlist.VMHHostListClient", "VMHostList", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForVMHostList(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "vmhhostlist.VMHHostListClient", "VMHostList", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/model_vmresources.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/model_vmresources.go new file mode 100644 index 000000000000..b3981b5d5022 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/model_vmresources.go @@ -0,0 +1,5 @@ +package vmhhostlist + +type VMResources struct { + VmResourceId *string `json:"vmResourceId,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/predicates.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/predicates.go new file mode 100644 index 000000000000..1c2bc004b26b --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/predicates.go @@ -0,0 +1,14 @@ +package vmhhostlist + +type VMResourcesOperationPredicate struct { + VmResourceId *string +} + +func (p VMResourcesOperationPredicate) Matches(input VMResources) bool { + + if p.VmResourceId != nil && (input.VmResourceId == nil && *p.VmResourceId != *input.VmResourceId) { + return false + } + + return true +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmhhostlist/version.go b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/version.go new file mode 100644 index 000000000000..f6ea05ac2bae --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmhhostlist/version.go @@ -0,0 +1,9 @@ +package vmhhostlist + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/vmhhostlist/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/client.go b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/client.go new file mode 100644 index 000000000000..869686aeb22a --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/client.go @@ -0,0 +1,15 @@ +package vmingestiondetails + +import "github.com/Azure/go-autorest/autorest" + +type VMIngestionDetailsClient struct { + Client autorest.Client + baseUri string +} + +func NewVMIngestionDetailsClientWithBaseURI(endpoint string) VMIngestionDetailsClient { + return VMIngestionDetailsClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/id_monitor.go b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/id_monitor.go new file mode 100644 index 000000000000..2cbb50539682 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/id_monitor.go @@ -0,0 +1,124 @@ +package vmingestiondetails + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +// MonitorId is a struct representing the Resource ID for a Monitor +type MonitorId struct { + SubscriptionId string + ResourceGroupName string + MonitorName string +} + +// NewMonitorID returns a new MonitorId struct +func NewMonitorID(subscriptionId string, resourceGroupName string, monitorName string) MonitorId { + return MonitorId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + MonitorName: monitorName, + } +} + +// ParseMonitorID parses 'input' into a MonitorId +func ParseMonitorID(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseMonitorIDInsensitively parses 'input' case-insensitively into a MonitorId +// note: this method should only be used for API response data and not user input +func ParseMonitorIDInsensitively(input string) (*MonitorId, error) { + parser := resourceids.NewParserFromResourceIdType(MonitorId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := MonitorId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.MonitorName, ok = parsed.Parsed["monitorName"]; !ok { + return nil, fmt.Errorf("the segment 'monitorName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateMonitorID checks that 'input' can be parsed as a Monitor ID +func ValidateMonitorID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseMonitorID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Monitor ID +func (id MonitorId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Elastic/monitors/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.MonitorName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Monitor ID +func (id MonitorId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftElastic", "Microsoft.Elastic", "Microsoft.Elastic"), + resourceids.StaticSegment("staticMonitors", "monitors", "monitors"), + resourceids.UserSpecifiedSegment("monitorName", "monitorValue"), + } +} + +// String returns a human-readable description of this Monitor ID +func (id MonitorId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Monitor Name: %q", id.MonitorName), + } + return fmt.Sprintf("Monitor (%s)", strings.Join(components, "\n")) +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/id_monitor_test.go b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/id_monitor_test.go new file mode 100644 index 000000000000..a6cf872fd8fc --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/id_monitor_test.go @@ -0,0 +1,279 @@ +package vmingestiondetails + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.ResourceId = MonitorId{} + +func TestNewMonitorID(t *testing.T) { + id := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue") + + if id.SubscriptionId != "12345678-1234-9876-4563-123456789012" { + t.Fatalf("Expected %q but got %q for Segment 'SubscriptionId'", id.SubscriptionId, "12345678-1234-9876-4563-123456789012") + } + + if id.ResourceGroupName != "example-resource-group" { + t.Fatalf("Expected %q but got %q for Segment 'ResourceGroupName'", id.ResourceGroupName, "example-resource-group") + } + + if id.MonitorName != "monitorValue" { + t.Fatalf("Expected %q but got %q for Segment 'MonitorName'", id.MonitorName, "monitorValue") + } +} + +func TestFormatMonitorID(t *testing.T) { + actual := NewMonitorID("12345678-1234-9876-4563-123456789012", "example-resource-group", "monitorValue").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue" + if actual != expected { + t.Fatalf("Expected the Formatted ID to be %q but got %q", expected, actual) + } +} + +func TestParseMonitorID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestParseMonitorIDInsensitively(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *MonitorId + }{ + { + // Incomplete URI + Input: "", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc", + Error: true, + }, + { + // Incomplete URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors", + Error: true, + }, + { + // Incomplete URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS", + Error: true, + }, + { + // Valid URI + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "example-resource-group", + MonitorName: "monitorValue", + }, + }, + { + // Invalid (Valid Uri with Extra segment) + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/example-resource-group/providers/Microsoft.Elastic/monitors/monitorValue/extra", + Error: true, + }, + { + // Valid URI (mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE", + Expected: &MonitorId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroupName: "eXaMpLe-rEsOuRcE-GrOuP", + MonitorName: "mOnItOrVaLuE", + }, + }, + { + // Invalid (Valid Uri with Extra segment - mIxEd CaSe since this is insensitive) + Input: "/sUbScRiPtIoNs/12345678-1234-9876-4563-123456789012/rEsOuRcEgRoUpS/eXaMpLe-rEsOuRcE-GrOuP/pRoViDeRs/mIcRoSoFt.eLaStIc/mOnItOrS/mOnItOrVaLuE/extra", + Error: true, + }, + } + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ParseMonitorIDInsensitively(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %+v", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + + if actual.ResourceGroupName != v.Expected.ResourceGroupName { + t.Fatalf("Expected %q but got %q for ResourceGroupName", v.Expected.ResourceGroupName, actual.ResourceGroupName) + } + + if actual.MonitorName != v.Expected.MonitorName { + t.Fatalf("Expected %q but got %q for MonitorName", v.Expected.MonitorName, actual.MonitorName) + } + + } +} + +func TestSegmentsForMonitorId(t *testing.T) { + segments := MonitorId{}.Segments() + if len(segments) == 0 { + t.Fatalf("MonitorId has no segments") + } + + uniqueNames := make(map[string]struct{}, 0) + for _, segment := range segments { + uniqueNames[segment.Name] = struct{}{} + } + if len(uniqueNames) != len(segments) { + t.Fatalf("Expected the Segments to be unique but got %q unique segments and %d total segments", len(uniqueNames), len(segments)) + } +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/method_vmingestiondetails_autorest.go b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/method_vmingestiondetails_autorest.go new file mode 100644 index 000000000000..bbcacd16cdf4 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/method_vmingestiondetails_autorest.go @@ -0,0 +1,65 @@ +package vmingestiondetails + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +type VMIngestionDetailsOperationResponse struct { + HttpResponse *http.Response + Model *VMIngestionDetailsResponse +} + +// VMIngestionDetails ... +func (c VMIngestionDetailsClient) VMIngestionDetails(ctx context.Context, id MonitorId) (result VMIngestionDetailsOperationResponse, err error) { + req, err := c.preparerForVMIngestionDetails(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "vmingestiondetails.VMIngestionDetailsClient", "VMIngestionDetails", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "vmingestiondetails.VMIngestionDetailsClient", "VMIngestionDetails", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForVMIngestionDetails(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "vmingestiondetails.VMIngestionDetailsClient", "VMIngestionDetails", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForVMIngestionDetails prepares the VMIngestionDetails request. +func (c VMIngestionDetailsClient) preparerForVMIngestionDetails(ctx context.Context, id MonitorId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPost(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/vmIngestionDetails", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForVMIngestionDetails handles the response to the VMIngestionDetails request. The method always +// closes the http.Response Body. +func (c VMIngestionDetailsClient) responderForVMIngestionDetails(resp *http.Response) (result VMIngestionDetailsOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + return +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/model_vmingestiondetailsresponse.go b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/model_vmingestiondetailsresponse.go new file mode 100644 index 000000000000..858032219fe9 --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/model_vmingestiondetailsresponse.go @@ -0,0 +1,6 @@ +package vmingestiondetails + +type VMIngestionDetailsResponse struct { + CloudId *string `json:"cloudId,omitempty"` + IngestionKey *string `json:"ingestionKey,omitempty"` +} diff --git a/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/version.go b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/version.go new file mode 100644 index 000000000000..ed1abc07e2be --- /dev/null +++ b/internal/services/elastic/sdk/2020-07-01/vmingestiondetails/version.go @@ -0,0 +1,9 @@ +package vmingestiondetails + +import "fmt" + +const defaultApiVersion = "2020-07-01" + +func userAgent() string { + return fmt.Sprintf("pandora/vmingestiondetails/%s", defaultApiVersion) +} diff --git a/internal/services/elastic/validate/elasticsearch_name.go b/internal/services/elastic/validate/elasticsearch_name.go new file mode 100644 index 000000000000..44caa92fbedc --- /dev/null +++ b/internal/services/elastic/validate/elasticsearch_name.go @@ -0,0 +1,20 @@ +package validate + +import ( + "fmt" + "regexp" +) + +func ElasticsearchName(i interface{}, k string) (warnings []string, errors []error) { + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) + return + } + + if !regexp.MustCompile(`^[a-zA-Z0-9_-]{2,32}$`).MatchString(v) { + errors = append(errors, fmt.Errorf("%q must be between 2 and 32 characters in length, can only contain alphanumeric characters, underscore and hyphen symbols", k)) + } + + return +} diff --git a/internal/services/elastic/validate/elasticsearch_name_test.go b/internal/services/elastic/validate/elasticsearch_name_test.go new file mode 100644 index 000000000000..29f938ca380d --- /dev/null +++ b/internal/services/elastic/validate/elasticsearch_name_test.go @@ -0,0 +1,61 @@ +package validate + +import "testing" + +func TestElasticMonitorsName(t *testing.T) { + testData := []struct { + input string + expected bool + }{ + { + // empty + input: "", + expected: false, + }, + { + // proper string + input: "hello", + expected: true, + }, + { + // end with exclamation + input: "hello!", + expected: false, + }, + { + // with hypen + input: "malcolm-in-the-middle", + expected: true, + }, + { + // end with fullstop + input: "hello.", + expected: false, + }, + { + // less than 32 + input: "qwertyuioplkjhgfdsazxcv", + expected: true, + }, + { + // with underscore + input: "qwertyuiop_jhgfdsazxcva", + expected: true, + }, + { + // more than 32 + input: "qwertyuioplkjhgfdsazxcvggeitofkjhkt", + expected: false, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q..", v.input) + + _, errors := ElasticsearchName(v.input, "name") + actual := len(errors) == 0 + if v.expected != actual { + t.Fatalf("Expected %t but got %t", v.expected, actual) + } + } +} diff --git a/internal/services/elastic/validate/email_address.go b/internal/services/elastic/validate/email_address.go new file mode 100644 index 000000000000..368f791f9524 --- /dev/null +++ b/internal/services/elastic/validate/email_address.go @@ -0,0 +1,19 @@ +package validate + +import ( + "fmt" + "regexp" +) + +func ElasticEmailAddress(i interface{}, k string) (warnings []string, errors []error) { + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) + return + } + if !regexp.MustCompile(`^[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,}$`).MatchString(v) { + errors = append(errors, fmt.Errorf("expected value of %s not match regular expression, got %v", k, v)) + return + } + return +} diff --git a/internal/services/elastic/validate/email_address_test.go b/internal/services/elastic/validate/email_address_test.go new file mode 100644 index 000000000000..e3debc259171 --- /dev/null +++ b/internal/services/elastic/validate/email_address_test.go @@ -0,0 +1,38 @@ +package validate + +import "testing" + +func TestElasticEmailAddress(t *testing.T) { + testCases := []struct { + Input string + Expected bool + }{ + { + Input: "abc@xyz.com", + Expected: true, + }, + { + Input: "abc@dyg@jad.com", + Expected: false, + }, + { + Input: "abc@", + Expected: false, + }, + { + Input: "abc@xyz", + Expected: false, + }, + { + Input: "abcdyg@jad.com.cdhc", + Expected: true, + }, + } + for _, v := range testCases { + _, errors := ElasticEmailAddress(v.Input, "email_address") + result := len(errors) == 0 + if result != v.Expected { + t.Fatalf("Expected the result to be %t but got %t (and %d errors)", v.Expected, result, len(errors)) + } + } +} diff --git a/website/allowed-subcategories b/website/allowed-subcategories index 2aaafde39eac..51d664b4bd6e 100644 --- a/website/allowed-subcategories +++ b/website/allowed-subcategories @@ -39,6 +39,7 @@ Desktop Virtualization Dev Test Digital Twins Disks +Elastic HDInsight Hardware Security Module Healthcare diff --git a/website/docs/d/elastic_cloud_elasticsearch.html.markdown b/website/docs/d/elastic_cloud_elasticsearch.html.markdown new file mode 100644 index 000000000000..c570a1d254d9 --- /dev/null +++ b/website/docs/d/elastic_cloud_elasticsearch.html.markdown @@ -0,0 +1,96 @@ +--- +subcategory: "Elastic" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_elastic_cloud_elasticsearch" +description: |- + Gets information about an existing Elasticsearch resource. + +--- + +# Data Source: azurerm_elastic_cloud_elasticsearch + +Use this data source to access information about an existing Elasticsearch resource. + +## Example Usage + +```hcl +data "azurerm_elastic_cloud_elasticsearch" "example" { + name = "my-elastic-search" + resource_group_name = "example-resources" +} + +output "elasticsearch_endpoint" { + value = data.azurerm_elastic_cloud_elasticsearch.example.elasticsearch_service_url +} + +output "kibana_endpoint" { + value = data.azurerm_elastic_cloud_elasticsearch.example.kibana_service_url +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Elasticsearch resource. + +* `resource_group_name` - (Required) The name of the resource group in which the Elasticsearch exists. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Elasticsearch. + +* `elastic_cloud_deployment_id` - The ID of the Deployment within Elastic Cloud. + +* `elastic_cloud_email_address` - The Email Address which is associated with this Elasticsearch account. + +* `elastic_cloud_sso_default_url` - The Default URL used for Single Sign On (SSO) to Elastic Cloud. + +* `elastic_cloud_user_id` - The ID of the User Account within Elastic Cloud. + +* `elasticsearch_service_url` - The URL to the Elasticsearch Service associated with this Elasticsearch. + +* `kibana_service_url` - The URL to the Kibana Dashboard associated with this Elasticsearch. + +* `kibana_sso_uri` - The URI used for SSO to the Kibana Dashboard associated with this Elasticsearch. + +* `location` - The Azure Region in which this Elasticsearch exists. + +* `logs` - A `logs` block as defined below. + +* `monitoring_enabled` - Specifies if monitoring is enabled on this Elasticsearch or not. + +* `sku_name` - The name of the SKU used for this Elasticsearch. + +* `tags` - A mapping of tags assigned to the Elasticsearch. + +--- + +The `filtering_tag` block exports the following: + +* `action` - The type of action which is taken when the Tag matches the `name` and `value`. + +* `name` - The name (key) of the Tag which should be filtered. + +* `value` - The value of the Tag which should be filtered. + +--- + +The `logs` block exports the following: + +* `filtering_tag` - A list of `filtering_tag` blocks as defined above. + +* `send_activity_logs` - Should the Azure Activity Logs should be sent to the Elasticsearch cluster? + +* `send_azuread_logs` - Should the AzureAD Logs should be sent to the Elasticsearch cluster? + +* `send_subscription_logs` - Should the Azure Subscription Logs should be sent to the Elasticsearch cluster? + + +## 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 Elasticsearch. diff --git a/website/docs/r/elastic_cloud_elasticsearch.html.markdown b/website/docs/r/elastic_cloud_elasticsearch.html.markdown new file mode 100644 index 000000000000..573601bd514d --- /dev/null +++ b/website/docs/r/elastic_cloud_elasticsearch.html.markdown @@ -0,0 +1,107 @@ +--- +subcategory: "Elastic" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_elastic_cloud_elasticsearch" +description: |- + Manages an Elasticsearch cluster in Elastic Cloud. +--- + +# azurerm_elastic_cloud_elasticsearch + +Manages an Elasticsearch in Elastic Cloud. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "test" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_elastic_cloud_elasticsearch" "test" { + name = "example-elasticsearch" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sku_name = "ess-monthly-consumption_Monthly" + elastic_cloud_email_address = "user@example.com" +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `elastic_cloud_email_address` - (Required) Specifies the Email Address which should be associated with this Elasticsearch account. Changing this forces a new Elasticsearch to be created. + +* `location` - (Required) The Azure Region where the Elasticsearch resource should exist. Changing this forces a new Elasticsearch to be created. + +* `name` - (Required) The name which should be used for this Elasticsearch resource. Changing this forces a new Elasticsearch to be created. + +* `resource_group_name` - (Required) The name of the Resource Group where the Elasticsearch resource should exist. Changing this forces a new Elasticsearch to be created. + +* `sku_name` - (Required) Specifies the name of the SKU for this Elasticsearch. Changing this forces a new Elasticsearch to be created. + +--- + +* `logs` - (Optional) A `logs` block as defined below. + +* `monitoring_enabled` - (Optional) Specifies if the Elasticsearch should have monitoring configured? Defaults to `true`. Changing this forces a new Elasticsearch to be created. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Elasticsearch resource. + +--- + +The `filtering_tag` block supports the following: + +* `action` - (Required) Specifies the type of action which should be taken when the Tag matches the `name` and `value`. Possible values are `Exclude` and `Include`. + +* `name` - (Required) Specifies the name (key) of the Tag which should be filtered. + +* `value` - (Required) Specifies the value of the Tag which should be filtered. + +--- + +The `logs` block supports the following: + +* `filtering_tag` - (Optional) A list of `filtering_tag` blocks as defined above. + +* `send_activity_logs` - (Optional) Specifies if the Azure Activity Logs should be sent to the Elasticsearch cluster. Defaults to `false`. + +* `send_azuread_logs` - (Optional) Specifies if the AzureAD Logs should be sent to the Elasticsearch cluster. Defaults to `false`. + +* `send_subscription_logs` - (Optional) Specifies if the Azure Subscription Logs should be sent to the Elasticsearch cluster. Defaults to `false`. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Elasticsearch. + +* `elastic_cloud_deployment_id` - The ID of the Deployment within Elastic Cloud. + +* `elastic_cloud_sso_default_url` - The Default URL used for Single Sign On (SSO) to Elastic Cloud. + +* `elastic_cloud_user_id` - The ID of the User Account within Elastic Cloud. + +* `elasticsearch_service_url` - The URL to the Elasticsearch Service associated with this Elasticsearch. + +* `kibana_service_url` - The URL to the Kibana Dashboard associated with this Elasticsearch. + +* `kibana_sso_uri` - The URI used for SSO to the Kibana Dashboard associated with this Elasticsearch. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Elasticsearch. +* `read` - (Defaults to 5 minutes) Used when retrieving the Elasticsearch. +* `update` - (Defaults to 30 minutes) Used when updating the Elasticsearch. +* `delete` - (Defaults to 30 minutes) Used when deleting the Elasticsearch. + +## Import + +Elasticsearch's can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_elastic_cloud_elasticsearch.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Elastic/monitors/monitor1 +```