From 7e083280054a2e48043ee1278b48d32099795245 Mon Sep 17 00:00:00 2001 From: Naama Bendalak <74866605+8naama@users.noreply.github.com> Date: Sun, 21 Apr 2024 09:22:14 +0300 Subject: [PATCH] update version to add metrics accounts support (#177) * implement metrics accounts --- go.mod | 2 +- go.sum | 4 +- logzio/datasource_metrics_account.go | 120 +++++++++++ logzio/datasource_metrics_account_test.go | 128 ++++++++++++ logzio/provider.go | 3 + logzio/resource_metrics_account.go | 237 ++++++++++++++++++++++ logzio/resource_metrics_account_test.go | 220 ++++++++++++++++++++ readme.md | 58 +++--- 8 files changed, 742 insertions(+), 30 deletions(-) create mode 100644 logzio/datasource_metrics_account.go create mode 100644 logzio/datasource_metrics_account_test.go create mode 100644 logzio/resource_metrics_account.go create mode 100644 logzio/resource_metrics_account_test.go diff --git a/go.mod b/go.mod index a0fd63d..d62b3b0 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-log v0.8.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1 - github.com/logzio/logzio_terraform_client v1.20.1 + github.com/logzio/logzio_terraform_client v1.21.0 github.com/stoewer/go-strcase v1.3.0 github.com/stretchr/testify v1.8.1 ) diff --git a/go.sum b/go.sum index 290320e..f50a676 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/logzio/logzio_terraform_client v1.20.1 h1:ZSrYwKqYavvPNUfjV4R1Ld+Aa13dmCaxhL6bsiUN7TY= -github.com/logzio/logzio_terraform_client v1.20.1/go.mod h1:hEQixCq9RPpvyzWerxIWKf0SYgangyWpPeogN7nytC0= +github.com/logzio/logzio_terraform_client v1.21.0 h1:LVGyek1qsZmo7nL/7V0VOOZ6udiFqqlgUjzaASNmb3c= +github.com/logzio/logzio_terraform_client v1.21.0/go.mod h1:hEQixCq9RPpvyzWerxIWKf0SYgangyWpPeogN7nytC0= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= diff --git a/logzio/datasource_metrics_account.go b/logzio/datasource_metrics_account.go new file mode 100644 index 0000000..10e3a0e --- /dev/null +++ b/logzio/datasource_metrics_account.go @@ -0,0 +1,120 @@ +package logzio + +import ( + "context" + "fmt" + "github.com/avast/retry-go" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/logzio/logzio_terraform_client/metrics_accounts" + "strconv" + "strings" + "time" +) + +func dataSourceMetricsAccount() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceMetricsAccountReadWrapper, + Schema: map[string]*schema.Schema{ + metricsAccountId: { + Type: schema.TypeInt, + Optional: true, + }, + metricsAccountName: { + Type: schema.TypeString, + Optional: true, + }, + metricsAccountEmail: { + Type: schema.TypeString, + Optional: true, + }, + metricsAccountToken: { + Type: schema.TypeString, + Optional: true, + }, + metricsAccountPlanUts: { + Type: schema.TypeInt, + Optional: true, + }, + metricsAccountAuthorizedAccounts: { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + Optional: true, + }, + }, + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Second), + }, + } +} + +func dataSourceMetricsAccountReadWrapper(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + var err error + readErr := retry.Do( + func() error { + if err = dataSourceMetricsAccountRead(d, m); err != nil { + return err + } + + return nil + }, + retry.RetryIf( + func(err error) bool { + if err != nil { + if strings.Contains(err.Error(), "failed with missing metrics account") || + strings.Contains(err.Error(), "failed with status code 500") { + return true + } + } + return false + }), + retry.DelayType(retry.BackOffDelay), + retry.Attempts(15), + ) + + if readErr != nil { + return diag.FromErr(readErr) + } + + return nil +} + +func dataSourceMetricsAccountRead(d *schema.ResourceData, m interface{}) error { + var client *metrics_accounts.MetricsAccountClient + var clientErr error + client, clientErr = metrics_accounts.New(m.(Config).apiToken, m.(Config).baseUrl) + + if clientErr != nil { + return clientErr + } + + accountId, ok := d.GetOk(metricsAccountId) + if ok { + metricsAccount, err := client.GetMetricsAccount(int64(accountId.(int))) + if err != nil { + return err + } + d.SetId(strconv.FormatInt(int64(accountId.(int)), 10)) + setMetricsAccount(d, metricsAccount) + return nil + } + + accountName, ok := d.GetOk(metricsAccountName) + if ok { + metricsAccounts, err := client.ListMetricsAccounts() + if err != nil { + return err + } + + for _, account := range metricsAccounts { + if account.AccountName == accountName.(string) { + d.SetId(strconv.FormatInt(int64(account.Id), 10)) + setMetricsAccount(d, &account) + return nil + } + } + } + return fmt.Errorf("couldn't find metrics account with specified attributes") +} diff --git a/logzio/datasource_metrics_account_test.go b/logzio/datasource_metrics_account_test.go new file mode 100644 index 0000000..f16bc7b --- /dev/null +++ b/logzio/datasource_metrics_account_test.go @@ -0,0 +1,128 @@ +package logzio + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/logzio/logzio_terraform_provider/logzio/utils" + "os" + "regexp" + "strconv" + "testing" +) + +func TestAccDataSourceMetricsAccount(t *testing.T) { + resourceName := "logzio_metrics_account.metrics_account_datasource" + dataSourceName := "data.logzio_metrics_account.metrics_account_datasource_by_id" + accountId, _ := strconv.ParseInt(os.Getenv(envLogzioAccountId), utils.BASE_10, utils.BITSIZE_64) + email := os.Getenv(envLogzioEmail) + accountName := "test_datasource_create" + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckEmail(t) + testAccPreCheckAccountId(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccMetricsAccountDataSourceResource(email, accountId, accountName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "account_name", accountName), + resource.TestCheckResourceAttr(resourceName, "plan_uts", "100"), + ), + }, + { + Config: testAccMetricsAccountDataSourceResource(email, accountId, accountName) + + testAccCheckLogzioMetricsAccountDatasourceConfig(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "account_name", accountName), + resource.TestCheckResourceAttr(dataSourceName, "plan_uts", "100"), + ), + }, + }, + }) +} + +func TestAccDataSourceMetricsAccountByAccountName(t *testing.T) { + resourceName := "logzio_metrics_account.metrics_account_datasource" + dataSourceName := "data.logzio_metrics_account.metrics_account_datasource_by_id" + accountId, _ := strconv.ParseInt(os.Getenv(envLogzioAccountId), utils.BASE_10, utils.BITSIZE_64) + email := os.Getenv(envLogzioEmail) + accountName := "test_datasource_account_name" + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckEmail(t) + testAccPreCheckAccountId(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccMetricsAccountDataSourceResource(email, accountId, accountName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "account_name", accountName), + resource.TestCheckResourceAttr(resourceName, "plan_uts", "100"), + ), + }, + { + Config: testAccMetricsAccountDataSourceResource(email, accountId, accountName) + + testAccCheckLogzioMetricsAccountDatasourceConfigAccountName(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "account_name", accountName), + resource.TestCheckResourceAttr(dataSourceName, "plan_uts", "100"), + ), + }, + }, + }) +} + +func TestAccDataSourceMetricsAccountNotExists(t *testing.T) { + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccCheckLogzioMetricsAccountDatasourceConfigNotExist(), + ExpectError: regexp.MustCompile("couldn't find metrics account with specified attributes"), + }, + }, + }) +} + +func testAccMetricsAccountDataSourceResource(email string, accountId int64, accountName string) string { + return fmt.Sprintf(`resource "logzio_metrics_account" "metrics_account_datasource" { + email = "%s" + account_name = "%s" + plan_uts = 100 + authorized_accounts = [ + %d + ] +} +`, email, accountName, accountId) +} + +func testAccCheckLogzioMetricsAccountDatasourceConfig() string { + return fmt.Sprint(`data "logzio_metrics_account" "metrics_account_datasource_by_id" { + account_id = "${logzio_metrics_account.metrics_account_datasource.Id}" +} +`) +} + +func testAccCheckLogzioMetricsAccountDatasourceConfigAccountName() string { + return fmt.Sprint(`data "logzio_metrics_account" "metrics_account_datasource_by_id" { + account_name = "${logzio_metrics_account.metrics_account_datasource.account_name}" +} +`) +} + +func testAccCheckLogzioMetricsAccountDatasourceConfigNotExist() string { + return fmt.Sprint(`data "logzio_metrics_account" "metrics_account_datasource_by_id" { + account_name = "name_not_exist" +} +`) +} diff --git a/logzio/provider.go b/logzio/provider.go index be04175..562d4bb 100644 --- a/logzio/provider.go +++ b/logzio/provider.go @@ -16,6 +16,7 @@ const ( resourceEndpointType = "logzio_endpoint" resourceUserType = "logzio_user" resourceSubAccountType = "logzio_subaccount" + resourceMetricsAccountType = "logzio_metrics_account" resourceLogShippingTokenType = "logzio_log_shipping_token" resourceDropFilterType = "logzio_drop_filter" resourceArchiveLogsType = "logzio_archive_logs" @@ -58,6 +59,7 @@ func Provider() *schema.Provider { resourceEndpointType: dataSourceEndpoint(), resourceUserType: dataSourceUser(), resourceSubAccountType: dataSourceSubAccount(), + resourceMetricsAccountType: dataSourceMetricsAccount(), resourceAlertV2Type: dataSourceAlertV2(), resourceLogShippingTokenType: dataSourceLogShippingToken(), resourceDropFilterType: dataSourceDropFilter(), @@ -73,6 +75,7 @@ func Provider() *schema.Provider { resourceEndpointType: resourceEndpoint(), resourceUserType: resourceUser(), resourceSubAccountType: resourceSubAccount(), + resourceMetricsAccountType: resourceMetricsAccount(), resourceAlertV2Type: resourceAlertV2(), resourceLogShippingTokenType: resourceLogShippingToken(), resourceDropFilterType: resourceDropFilter(), diff --git a/logzio/resource_metrics_account.go b/logzio/resource_metrics_account.go new file mode 100644 index 0000000..fe7ac8d --- /dev/null +++ b/logzio/resource_metrics_account.go @@ -0,0 +1,237 @@ +package logzio + +import ( + "context" + "fmt" + "github.com/avast/retry-go" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/logzio/logzio_terraform_client/metrics_accounts" + "github.com/logzio/logzio_terraform_provider/logzio/utils" + "reflect" + "strconv" + "strings" +) + +const ( + metricsAccountId string = "account_id" + metricsAccountEmail string = "email" + metricsAccountName string = "account_name" + metricsAccountToken string = "account_token" + metricsAccountPlanUts string = "plan_uts" + metricsAccountAuthorizedAccounts string = "authorized_accounts" + + metricsAccountRetryAttempts = 8 +) + +// The endpoint resource schema, what terraform uses to parse and read the template +func resourceMetricsAccount() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceMetricsAccountCreate, + ReadContext: resourceMetricsAccountRead, + UpdateContext: resourceMetricsAccountUpdate, + DeleteContext: resourceMetricsAccountDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + metricsAccountId: { + Type: schema.TypeInt, + Computed: true, + }, + metricsAccountToken: { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + metricsAccountEmail: { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + metricsAccountName: { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + metricsAccountPlanUts: { + Type: schema.TypeInt, + Optional: true, + }, + metricsAccountAuthorizedAccounts: { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + Optional: true, + Computed: true, + }, + }, + } +} + +func MetricsAccountClient(m interface{}) (*metrics_accounts.MetricsAccountClient, error) { + var client *metrics_accounts.MetricsAccountClient + var clientError error + client, clientError = metrics_accounts.New(m.(Config).apiToken, m.(Config).baseUrl) + + if clientError != nil { + return nil, clientError + } + return client, nil +} + +func resourceMetricsAccountCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + createSubAccount := getCreateMetricsAccountFromSchema(d) + MetricsClient, err := MetricsAccountClient(m) + if err != nil { + return diag.FromErr(err) + } + + metricsAccount, err := MetricsClient.CreateMetricsAccount(createSubAccount) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(strconv.FormatInt(int64(metricsAccount.Id), 10)) + d.Set(metricsAccountToken, metricsAccount.Token) + d.Set(metricsAccountId, metricsAccount.Id) + return resourceMetricsAccountRead(ctx, d, m) +} + +func resourceMetricsAccountRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + id, err := utils.IdFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + MetricsClient, err := MetricsAccountClient(m) + if err != nil { + return diag.FromErr(err) + } + + metricsAccount, err := MetricsClient.GetMetricsAccount(id) + if err != nil { + tflog.Error(ctx, err.Error()) + if strings.Contains(err.Error(), "missing metrics account") { + // If we were not able to find the resource - delete from state + d.SetId("") + return diag.Diagnostics{} + } else { + return diag.FromErr(err) + } + + } + + setMetricsAccount(d, metricsAccount) + + return nil +} + +func resourceMetricsAccountUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + id, err := utils.IdFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + MetricsClient, err := MetricsAccountClient(m) + if err != nil { + return diag.FromErr(err) + } + + updateMetricsAccount := getCreateMetricsAccountFromSchema(d) + err = MetricsClient.UpdateMetricsAccount(id, updateMetricsAccount) + if err != nil { + return diag.FromErr(err) + } + + var diagRet diag.Diagnostics + readErr := retry.Do( + func() error { + diagRet = resourceMetricsAccountRead(ctx, d, m) + if diagRet.HasError() { + return fmt.Errorf("received error from read subaccount") + } + + return nil + }, + retry.RetryIf( + // Retry ONLY if the resource was not updated yet + func(err error) bool { + if err != nil { + return false + } else { + // Check if the update shows on read + // if not updated yet - retry + MetricsAccountFromSchema := getCreateMetricsAccountFromSchema(d) + return !reflect.DeepEqual(MetricsAccountFromSchema, updateMetricsAccount) + } + }), + retry.DelayType(retry.BackOffDelay), + retry.Attempts(metricsAccountRetryAttempts), + ) + + if readErr != nil { + tflog.Error(ctx, "could not update schema") + return diagRet + } + + return nil +} + +func resourceMetricsAccountDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + id, err := utils.IdFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + MetricsClient, err := MetricsAccountClient(m) + if err != nil { + return diag.FromErr(err) + } + + err = MetricsClient.DeleteMetricsAccount(id) + + if err != nil { + return diag.FromErr(err) + } + + d.SetId("") + return nil +} + +func setMetricsAccount(d *schema.ResourceData, metricsAccount *metrics_accounts.MetricsAccount) { + d.Set(metricsAccountId, metricsAccount.Id) + d.Set(metricsAccountName, metricsAccount.AccountName) + d.Set(metricsAccountPlanUts, metricsAccount.PlanUts) + d.Set(metricsAccountToken, metricsAccount.AccountToken) + + sharingObjectAccounts := make([]int32, 0) + for _, accountId := range metricsAccount.AuthorizedAccountsIds { + sharingObjectAccounts = append(sharingObjectAccounts, accountId) + } + + d.Set(metricsAccountAuthorizedAccounts, sharingObjectAccounts) +} + +func getCreateMetricsAccountFromSchema(d *schema.ResourceData) metrics_accounts.CreateOrUpdateMetricsAccount { + accounts := d.Get(metricsAccountAuthorizedAccounts).([]interface{}) + // Allows users to insert empty array of authorizedAccounts, but avoiding `nil` + authorizedAccounts := make([]int32, 0) + for _, accountId := range accounts { + authorizedAccounts = append(authorizedAccounts, int32(accountId.(int))) + } + + PlanUtsVal := int32(d.Get(metricsAccountPlanUts).(int)) + var planUts *int32 + planUts = new(int32) + *planUts = PlanUtsVal + + createMetricsAccount := metrics_accounts.CreateOrUpdateMetricsAccount{ + Email: d.Get(metricsAccountEmail).(string), + AccountName: d.Get(metricsAccountName).(string), + PlanUts: planUts, + AuthorizedAccountsIds: authorizedAccounts, + } + + return createMetricsAccount +} diff --git a/logzio/resource_metrics_account_test.go b/logzio/resource_metrics_account_test.go new file mode 100644 index 0000000..b9e0b04 --- /dev/null +++ b/logzio/resource_metrics_account_test.go @@ -0,0 +1,220 @@ +package logzio + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/logzio/logzio_terraform_provider/logzio/utils" + "os" + "regexp" + "testing" +) + +func TestAccLogzioMetricsAccount_CreateMetricsAccount(t *testing.T) { + accountId := os.Getenv(envLogzioAccountId) + email := os.Getenv(envLogzioEmail) + accountName := "test_create_subaccount" + terraformPlan := testAccCheckLogzioMetricsAccountConfig(email, accountName, accountId) + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckAccountId(t) + testAccPreCheckEmail(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: terraformPlan, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "logzio_metrics_account.test_subaccount", "email", email), + ), + }, + { + Config: terraformPlan, + ResourceName: "logzio_metrics_account.test_subaccount", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{metricsAccountEmail}, + }, + }, + }) +} + +func TestAccLogzioMetricsAccount_CreateMetricsAccountEmptyAuthorizedAccounts(t *testing.T) { + email := os.Getenv(envLogzioEmail) + accountName := "test_empty_sharing_object" + terraformPlan := testAccCheckLogzioMetricsAccountConfig(email, accountName, "") + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckEmail(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: terraformPlan, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "logzio_metrics_account.test_subaccount", "email", email), + ), + }, + { + Config: terraformPlan, + ResourceName: "logzio_metrics_account.test_subaccount", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{metricsAccountEmail}, + }, + }, + }) +} + +func TestAccLogzioMetricsAccount_CreateMetricsAccountNoEmail(t *testing.T) { + email := "" + accountName := "test_no_email" + terraformPlan := testAccCheckLogzioMetricsAccountConfig(email, accountName, "") + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: terraformPlan, + ExpectError: regexp.MustCompile("email must be set"), + }, + }, + }) +} + +func TestAccLogzioMetricsAccount_CreateMetricsAccountInvalidEmail(t *testing.T) { + email := "some@invalid.mail" + accountName := "test_invalid_email" + terraformPlan := testAccCheckLogzioMetricsAccountConfig(email, accountName, "") + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckEmail(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: terraformPlan, + ExpectError: regexp.MustCompile("There is no registered user for the passed email"), + }, + }, + }) +} + +func TestAccLogzioMetricsAccount_CreateMetricsAccountNoName(t *testing.T) { + accountId := os.Getenv(envLogzioAccountId) + email := os.Getenv(envLogzioEmail) + resourceName := "logzio_metrics_account.test_subaccount" + terraformPlan := testAccCheckLogzioMetricsAccountConfigNoName(email, accountId) + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckAccountId(t) + testAccPreCheckEmail(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: terraformPlan, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, metricsAccountPlanUts, "160"), + resource.TestCheckResourceAttr(resourceName, metricsAccountEmail, email), + resource.TestMatchResourceAttr(resourceName, metricsAccountName, regexp.MustCompile(".*_metrics")), + ), + }, + }, + }) +} + +func TestAccLogzioMetricsAccount_UpdateMetricsAccount(t *testing.T) { + accountId := os.Getenv(envLogzioAccountId) + email := os.Getenv(envLogzioEmail) + accountName := "test_update_before" + accountNameUpdate := "test_update_after" + resourceName := "logzio_metrics_account.test_subaccount" + terraformPlan := testAccCheckLogzioMetricsAccountConfig(email, accountName, accountId) + terraformPlanUpdate := testAccCheckLogzioMetricsAccountConfig(email, accountNameUpdate, accountId) + defer utils.SleepAfterTest() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckApiToken(t) + testAccPreCheckAccountId(t) + testAccPreCheckEmail(t) + }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: terraformPlan, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + resourceName, "email", email), + ), + }, + { + Config: terraformPlanUpdate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + resourceName, subAccountName, accountNameUpdate), + ), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{subAccountEmail}, + }, + }, + }) +} + +func testAccCheckLogzioMetricsAccountConfig(email string, accountName string, accountId string) string { + return fmt.Sprintf(` +resource "logzio_metrics_account" "test_subaccount" { + email = "%s" + account_name = "%s" + plan_uts = 100 + authorized_accounts = [ + %s + ] +} +`, email, accountName, accountId) +} + +func testAccCheckLogzioMetricsAccountConfigNoName(email string, accountId string) string { + return fmt.Sprintf(` +resource "logzio_metrics_account" "test_subaccount" { + email = "%s" + plan_uts = 160 + authorized_accounts = [ + %s + ] +} +`, email, accountId) +} + +func testAccCheckLogzioMetricsAccountFromDatasource(email string, accountId string) string { + return fmt.Sprintf(` +resource "logzio_metrics_account" "test_subaccount" { + email = "%s" + account_name = data.logzio_metrics_account.metrics_account_datasource_by_id.account_name + plan_uts = 100 + authorized_accounts = [ + %s + ] +} +`, email, accountId) +} diff --git a/readme.md b/readme.md index 2b00fd0..42c5a9c 100644 --- a/readme.md +++ b/readme.md @@ -12,23 +12,24 @@ You can use the Terraform Logz.io Provider to manage users and log accounts in L The following Logz.io API endpoints are supported by this provider: -* [User management](https://docs.logz.io/api/#tag/Manage-users) -* [Notification channels](https://docs.logz.io/api/#tag/Manage-notification-endpoints) +* [User management](https://api-docs.logz.io/docs/logz/manage-users) +* [Notification channels](https://api-docs.logz.io/docs/logz/manage-notification-endpoints) * [Log-based alerts](https://github.com/logzio/public-api/tree/master/alerts) -* [Sub accounts](https://docs.logz.io/api/#tag/Manage-sub-accounts) -* [Alerts(v2)](https://docs.logz.io/api/#tag/Alerts) -* [Log shipping token](https://docs.logz.io/api/#tag/Manage-log-shipping-tokens) -* [Drop filters](https://docs.logz.io/api/#tag/Drop-filters) -* [Archive logs](https://docs.logz.io/api/#tag/Archive-logs) -* [Restore logs](https://docs.logz.io/api/#tag/Restore-logs) -* [Authentication groups](https://docs.logz.io/api/#tag/Authentication-groups) -* [Kibana objects](https://docs.logz.io/api/#tag/Import-or-export-Kibana-objects) -* [S3 Fetcher](https://docs.logz.io/api/#tag/Connect-to-S3-Buckets) -* [Grafana Dashboards](https://docs.logz.io/api/#operation/createDashboard) -* Grafana folders -* [Grafana Alert Rules](https://docs.logz.io/api/#tag/Grafana-alerting-provisioning) -* [Grafana Contact Point](https://docs.logz.io/api/#tag/Grafana-contact-points) -* Grafana Notification Policy. +* [Sub accounts](https://api-docs.logz.io/docs/logz/manage-time-based-log-accounts) +* [Alerts(v2)](https://api-docs.logz.io/docs/logz/alerts) +* [Log shipping token](https://api-docs.logz.io/docs/logz/manage-log-shipping-tokens) +* [Drop filters](https://api-docs.logz.io/docs/logz/drop-filters) +* [Archive logs](https://api-docs.logz.io/docs/logz/archive-logs) +* [Restore logs](https://api-docs.logz.io/docs/logz/restore-logs) +* [Authentication groups](https://api-docs.logz.io/docs/logz/authentication-groups) +* [Kibana objects](https://api-docs.logz.io/docs/logz/import-or-export-kibana-objects) +* [S3 Fetcher](https://api-docs.logz.io/docs/logz/connect-to-s-3-buckets) +* [Grafana Dashboards](https://api-docs.logz.io/docs/logz/create-dashboard) +* [Grafana folders](https://api-docs.logz.io/docs/logz/get-all-folders) +* [Grafana Alert Rules](https://api-docs.logz.io/docs/logz/get-alert-rules) +* [Grafana Contact Point](https://api-docs.logz.io/docs/logz/route-get-contactpoints) +* [Grafana Notification Policy](https://api-docs.logz.io/docs/logz/route-get-policy-tree) +* [Metrics Accounts](https://api-docs.logz.io/docs/logz/create-a-new-metrics-account) #### Working with Terraform @@ -199,13 +200,16 @@ terraform import logzio_subaccount.my_subaccount ### Changelog +- **v1.15.0**: + - Upgrade `logzio_client_terraform` to `1.21.0`. + - Support [Metrics Accounts API](https://api-docs.logz.io/docs/logz/create-a-new-metrics-account) - **v1.14.1**: - - Upgrade `logzio_client_terraform to 1.20.1`. + - Upgrade `logzio_client_terraform` to `1.20.1`. - **v1.14.0**: - - Upgrade `logzio_client_terraform to 1.20.0`. + - Upgrade `logzio_client_terraform` to `1.20.0`. - Support Grafana folders. - - Support [Grafana Alert Rules](https://docs.logz.io/api/#tag/Grafana-alerting-provisioning). - - Support [Grafana Contact Point](https://docs.logz.io/api/#tag/Grafana-contact-points). + - Support [Grafana Alert Rules](https://api-docs.logz.io/docs/logz/get-alert-rules). + - Support [Grafana Contact Point](https://api-docs.logz.io/docs/logz/route-get-contactpoints). - Grafana Notification Policy. - **v1.13.2**: - **alerts v2**: @@ -221,10 +225,10 @@ terraform import logzio_subaccount.my_subaccount - **Bug fix**: `prefix` field now being applied. - **v1.13.0**: - Upgrade `logzio_client_terraform` to `1.16.0`. - - Support [Grafana Dashboards API](https://docs.logz.io/api/#operation/createDashboard). + - Support [Grafana Dashboards API](https://api-docs.logz.io/docs/logz/get-datasource-by-account). - **v1.12.0**: - Upgrade `logzio_client_terraform` to `1.15.0`. - - Support [S3 Fetcher API](https://docs.logz.io/api/#tag/Connect-to-S3-Buckets). + - Support [S3 Fetcher API](https://api-docs.logz.io/docs/logz/create-buckets). - **v1.11.0**: - Upgrade `terraform-plugin-sdk` to `v2.24.1`. - Upgrade `logzio_client_terraform` to `1.14.0`. @@ -263,7 +267,7 @@ terraform import logzio_subaccount.my_subaccount - *Bug fix*: plugin won't crash when import for `archive_logs` fails. - **v1.9.0** - Update client version(v1.11.0). - - Support [Kibana objects](https://docs.logz.io/api/#tag/Import-or-export-Kibana-objects) + - Support [Kibana objects](https://api-docs.logz.io/docs/logz/import-or-export-kibana-objects) - **v1.8.3** - Update client version(v1.10.3). - Bug fixes: @@ -285,15 +289,15 @@ terraform import logzio_subaccount.my_subaccount - Add to custom endpoint datasource Description field. - **v1.7.0** - Update client version (v1.10). - - Support [authentication groups resource](https://docs.logz.io/api/#tag/Authentication-groups). + - Support [authentication groups resource](https://api-docs.logz.io/docs/logz/authentication-groups). - `alerts_v2`: fix noisy diff for `severity_threshold_tiers`. - **v1.6.1** - Update client version (v1.9.1) - bug fix for not found messages. - **v1.6** - Update client version (v1.9). - - Support [archive logs resource](https://docs.logz.io/api/#tag/Archive-logs). - - Support [restore logs resource](https://docs.logz.io/api/#tag/Restore-logs). + - Support [archive logs resource](https://api-docs.logz.io/docs/logz/archive-logs). + - Support [restore logs resource](https://api-docs.logz.io/docs/logz/restore-logs). - **v1.5** - Update client version(v1.8). - `sub_account`: @@ -317,7 +321,7 @@ terraform import logzio_subaccount.my_subaccount - Improve tests. - v1.4 - Update client version(v1.7). - - Support [Drop Filter](https://docs.logz.io/api/#tag/Drop-filters) resource. + - Support [Drop Filter](https://api-docs.logz.io/docs/logz/drop-filters) resource. - v1.3 - Update client version(v1.6). - Support Log Shipping Token resource.