Skip to content

Commit

Permalink
Merge branch 'master' into chore/updated-outdated-links-baremetal-ins…
Browse files Browse the repository at this point in the history
…tances-kubernetes-webhosting
  • Loading branch information
yfodil committed May 22, 2024
2 parents 3a9fce0 + c3109e5 commit 96b1587
Show file tree
Hide file tree
Showing 17 changed files with 9,921 additions and 1,486 deletions.
54 changes: 54 additions & 0 deletions docs/resources/cockpit_alert_manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
subcategory: "Cockpit"
page_title: "Scaleway: scaleway_cockpit_alert_manager"
---

# Resource: scaleway_cockpit_alert_manager

Creates and manages Scaleway Cockpit Alert Managers.

For more information consult the [documentation](https://www.scaleway.com/en/docs/observability/cockpit/concepts/#grafana-users).

## Example Usage

```terraform
resource "scaleway_account_project" "project" {
name = "tf_test_project"
}
resource "scaleway_cockpit_alert_manager" "alert_manager" {
project_id = scaleway_account_project.project.id
enable_managed_alerts = true
contact_points = [
{
email = "alert1@example.com"
},
{
email = "alert2@example.com"
}
]}
```


## Argument Reference

- `enable_managed_alerts` - (Optional, Boolean) Indicates whether the alert manager should be enabled. Defaults to true.
- `contact_points` - (Optional, List of Map) A list of contact points with email addresses for the alert receivers. Each map should contain a single key email.
- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the cockpit is associated with.
- `region` - (Defaults to [provider](../index.md#arguments-reference) `region`) The [region](../guides/regions_and_zones.md#regions) in which alert_manager should be created.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

- `alert_manager_url` - Alert manager URL.


## Import

Alert managers can be imported using the project ID, e.g.

```bash
$ terraform import scaleway_cockpit_alert_manager.main fr-par/11111111-1111-1111-1111-111111111111
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ func Provider(config *Config) plugin.ProviderFunc {
"scaleway_cockpit_source": cockpit.ResourceCockpitSource(),
"scaleway_cockpit_grafana_user": cockpit.ResourceCockpitGrafanaUser(),
"scaleway_cockpit_token": cockpit.ResourceToken(),
"scaleway_cockpit_alert_manager": cockpit.ResourceCockpitAlertManager(),
"scaleway_container": container.ResourceContainer(),
"scaleway_container_cron": container.ResourceCron(),
"scaleway_container_domain": container.ResourceDomain(),
Expand Down
283 changes: 283 additions & 0 deletions internal/services/cockpit/alert_manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package cockpit

import (
"context"
"errors"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/cockpit/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
)

func ResourceCockpitAlertManager() *schema.Resource {
return &schema.Resource{
CreateContext: ResourceCockpitAlertManagerCreate,
ReadContext: ResourceCockpitAlertManagerRead,
UpdateContext: ResourceCockpitAlertManagerUpdate,
DeleteContext: ResourceCockpitAlertManagerDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
"project_id": account.ProjectIDSchema(),
"enable_managed_alerts": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "Enable or disable the alert manager",
},

"contact_points": {
Type: schema.TypeList,
Optional: true,
Description: "A list of contact points",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"email": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.IsEmail(),
Description: "Email addresses for the alert receivers",
},
},
},
},
"region": regional.Schema(),
"alert_manager_url": {
Type: schema.TypeString,
Computed: true,
Description: "Alert manager URL",
},
},
}
}

func ResourceCockpitAlertManagerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
api, region, err := cockpitAPIWithRegion(d, meta)
if err != nil {
return diag.FromErr(err)
}

projectID := d.Get("project_id").(string)
contactPoints := d.Get("contact_points").([]interface{})
EnableManagedAlerts := d.Get("enable_managed_alerts").(bool)

_, err = api.EnableAlertManager(&cockpit.RegionalAPIEnableAlertManagerRequest{
Region: region,
ProjectID: projectID,
})
if err != nil {
return diag.FromErr(err)
}
if EnableManagedAlerts {
_, err = api.EnableManagedAlerts(&cockpit.RegionalAPIEnableManagedAlertsRequest{
Region: region,
ProjectID: projectID,
})
if err != nil {
return diag.FromErr(err)
}
}

if len(contactPoints) > 0 {
for _, cp := range contactPoints {
cpMap, ok := cp.(map[string]interface{})
if !ok {
return diag.FromErr(errors.New("invalid contact point format"))
}

email, ok := cpMap["email"].(string)
if !ok {
return diag.FromErr(errors.New("invalid email format"))
}

emailCP := &cockpit.ContactPointEmail{
To: email,
}

_, err = api.CreateContactPoint(&cockpit.RegionalAPICreateContactPointRequest{
ProjectID: projectID,
Email: emailCP,
Region: region,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
}
}

d.SetId(ResourceCockpitAlertManagerID(region, projectID))
return ResourceCockpitAlertManagerRead(ctx, d, meta)
}

func ResourceCockpitAlertManagerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
api, region, err := cockpitAPIWithRegion(d, meta)
if err != nil {
return diag.FromErr(err)
}

projectID := d.Get("project_id").(string)

alertManager, err := api.GetAlertManager(&cockpit.RegionalAPIGetAlertManagerRequest{
Region: region,
ProjectID: projectID,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

_ = d.Set("enable_managed_alerts", alertManager.ManagedAlertsEnabled)
_ = d.Set("region", alertManager.Region)
_ = d.Set("alert_manager_url", alertManager.AlertManagerURL)

contactPoints, err := api.ListContactPoints(&cockpit.RegionalAPIListContactPointsRequest{
Region: region,
ProjectID: projectID,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

var contactPointsList []map[string]interface{}
for _, cp := range contactPoints.ContactPoints {
if cp.Email != nil {
contactPoint := map[string]interface{}{
"email": cp.Email.To,
}
contactPointsList = append(contactPointsList, contactPoint)
}
}
_ = d.Set("contact_points", contactPointsList)
return nil
}

func ResourceCockpitAlertManagerUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
api, region, err := cockpitAPIWithRegion(d, meta)
if err != nil {
return diag.FromErr(err)
}
projectID := d.Get("project_id").(string)

if d.HasChange("enable_managed_alerts") {
enable := d.Get("enable_managed_alerts").(bool)
if enable {
_, err = api.EnableManagedAlerts(&cockpit.RegionalAPIEnableManagedAlertsRequest{
Region: region,
ProjectID: projectID,
})
} else {
_, err = api.DisableManagedAlerts(&cockpit.RegionalAPIDisableManagedAlertsRequest{
Region: region,
ProjectID: projectID,
}, scw.WithContext(ctx))
}
if err != nil {
return diag.FromErr(err)
}
}
if d.HasChange("contact_points") {
oldContactPointsInterface, newContactPointsInterface := d.GetChange("contact_points")
oldContactPoints := oldContactPointsInterface.([]interface{})
newContactPoints := newContactPointsInterface.([]interface{})

oldContactMap := make(map[string]map[string]interface{})
for _, oldCP := range oldContactPoints {
cp := oldCP.(map[string]interface{})
email := cp["email"].(string)
oldContactMap[email] = cp
}

newContactMap := make(map[string]map[string]interface{})
for _, newCP := range newContactPoints {
cp := newCP.(map[string]interface{})
email := cp["email"].(string)
newContactMap[email] = cp
}
for email := range oldContactMap {
if _, found := newContactMap[email]; !found {
err := api.DeleteContactPoint(&cockpit.RegionalAPIDeleteContactPointRequest{
Region: region,
ProjectID: projectID,
Email: &cockpit.ContactPointEmail{To: email},
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
}
}

for email := range newContactMap {
if _, found := oldContactMap[email]; !found {
contactPointEmail := &cockpit.ContactPointEmail{To: email}
_, err = api.CreateContactPoint(&cockpit.RegionalAPICreateContactPointRequest{
Region: region,
ProjectID: projectID,
Email: contactPointEmail,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
}
}
}

return ResourceCockpitAlertManagerRead(ctx, d, meta)
}

func ResourceCockpitAlertManagerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
api, region, err := cockpitAPIWithRegion(d, meta)
if err != nil {
return diag.FromErr(err)
}

projectID := d.Get("project_id").(string)

contactPoints, err := api.ListContactPoints(&cockpit.RegionalAPIListContactPointsRequest{
Region: region,
ProjectID: projectID,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

for _, cp := range contactPoints.ContactPoints {
if cp.Email != nil {
err = api.DeleteContactPoint(&cockpit.RegionalAPIDeleteContactPointRequest{
Region: region,
ProjectID: projectID,
Email: &cockpit.ContactPointEmail{To: cp.Email.To},
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
}
}

_, err = api.DisableManagedAlerts(&cockpit.RegionalAPIDisableManagedAlertsRequest{
Region: region,
ProjectID: projectID,
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
_, err = api.DisableAlertManager(&cockpit.RegionalAPIDisableAlertManagerRequest{
Region: region,
ProjectID: projectID,
})
if err != nil {
return diag.FromErr(err)
}

d.SetId("")

return nil
}

func ResourceCockpitAlertManagerID(region scw.Region, projectID string) (resourceID string) {
return fmt.Sprintf("%s/%s/1", region, projectID)
}

0 comments on commit 96b1587

Please sign in to comment.