-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SCALRCORE-25214 - Provider > Add Slack Integration
- Loading branch information
Showing
9 changed files
with
419 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
|
||
# Resource `scalr_slack_integration` | ||
|
||
Manage the state of Slack integrations in Scalr. Create, update and destroy. | ||
Slack workspace should be connected to Scalr account before using this resource. | ||
|
||
## Example Usage | ||
|
||
Basic usage: | ||
|
||
```hcl | ||
resource "scalr_slack_integration" "test" { | ||
name = "my-channel" | ||
account_id = "acc-xxxx" | ||
events = ["run_approval_required", "run_success", "run_errored"] | ||
channel_id = "xxxx" # Can be found in slack UI (channel settings/info popup) | ||
environments = ["env-xxxxx"] | ||
workspaces = ["ws-xxxx", "ws-xxxx"] | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
* `name` - (Required) Name of the Slack integration. | ||
* `channel_id` - (Required) Slack channel ID the event will be sent to. | ||
* `events` - (Required) Terraform run events you would like to receive a Slack notifications for. | ||
Supported values are `run_approval_required`, `run_success`, `run_errored`. | ||
* `environments` - (Required) List of environments where events should be triggered. | ||
* `workspaces` - (Optional) List of workspaces where events should be triggered. | ||
Workspaces should be in provided environments. If no workspace is given for a specified environment, | ||
events will trigger in all of its workspaces. | ||
* `account_id` - (Optional) ID of the account. | ||
|
||
|
||
## Attribute Reference | ||
|
||
All arguments plus: | ||
|
||
* `id` - The ID of the Slack integration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
package scalr | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||
"github.com/scalr/go-scalr" | ||
"log" | ||
) | ||
|
||
func resourceScalrSlackIntegration() *schema.Resource { | ||
return &schema.Resource{ | ||
CreateContext: resourceScalrSlackIntegrationCreate, | ||
ReadContext: resourceScalrSlackIntegrationRead, | ||
UpdateContext: resourceScalrSlackIntegrationUpdate, | ||
DeleteContext: resourceSlackIntegrationDelete, | ||
Importer: &schema.ResourceImporter{ | ||
StateContext: schema.ImportStatePassthroughContext, | ||
}, | ||
SchemaVersion: 0, | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace), | ||
}, | ||
"events": { | ||
Type: schema.TypeSet, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
ValidateDiagFunc: validation.ToDiagFunc( | ||
validation.StringInSlice( | ||
[]string{ | ||
scalr.SlackIntegrationEventRunApprovalRequired, | ||
scalr.SlackIntegrationEventRunSuccess, | ||
scalr.SlackIntegrationEventRunErrored, | ||
}, | ||
false, | ||
), | ||
), | ||
}, | ||
Required: true, | ||
MinItems: 1, | ||
}, | ||
"channel_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace), | ||
}, | ||
"account_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
DefaultFunc: scalrAccountIDDefaultFunc, | ||
ForceNew: true, | ||
}, | ||
"environments": { | ||
Type: schema.TypeSet, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace), | ||
}, | ||
Required: true, | ||
MinItems: 1, | ||
}, | ||
"workspaces": { | ||
Type: schema.TypeSet, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace), | ||
}, | ||
Optional: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func parseEvents(d *schema.ResourceData) []string { | ||
events := d.Get("events").(*schema.Set).List() | ||
eventValues := make([]string, 0) | ||
|
||
for _, event := range events { | ||
eventValues = append(eventValues, event.(string)) | ||
} | ||
|
||
return eventValues | ||
} | ||
|
||
func parseEnvironments(d *schema.ResourceData) []*scalr.Environment { | ||
environments := d.Get("environments").(*schema.Set).List() | ||
environmentValues := make([]*scalr.Environment, 0) | ||
|
||
for _, env := range environments { | ||
environmentValues = append(environmentValues, &scalr.Environment{ID: env.(string)}) | ||
} | ||
|
||
return environmentValues | ||
} | ||
|
||
func parseWorkspaces(d *schema.ResourceData) []*scalr.Workspace { | ||
workspacesI, ok := d.GetOk("workspaces") | ||
if !ok { | ||
return nil | ||
} | ||
workspaces := workspacesI.(*schema.Set).List() | ||
workspaceValues := make([]*scalr.Workspace, 0) | ||
|
||
for _, ws := range workspaces { | ||
workspaceValues = append(workspaceValues, &scalr.Workspace{ID: ws.(string)}) | ||
} | ||
|
||
return workspaceValues | ||
} | ||
|
||
func resourceScalrSlackIntegrationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
scalrClient := meta.(*scalr.Client) | ||
// Get attributes. | ||
name := d.Get("name").(string) | ||
accountID := d.Get("account_id").(string) | ||
|
||
options := scalr.SlackIntegrationCreateOptions{ | ||
Name: &name, | ||
ChannelId: scalr.String(d.Get("channel_id").(string)), | ||
Events: parseEvents(d), | ||
Account: &scalr.Account{ID: accountID}, | ||
Environments: parseEnvironments(d), | ||
} | ||
workspaces := parseWorkspaces(d) | ||
if workspaces != nil { | ||
options.Workspaces = workspaces | ||
} | ||
|
||
connection, err := scalrClient.SlackIntegrations.GetConnection(ctx, options.Account.ID) | ||
if err != nil { | ||
return diag.Errorf("Error creating slack integration %s: %v", name, err) | ||
} | ||
|
||
if connection.ID == "" { | ||
return diag.Errorf( | ||
"Error creating Slack integration: account %s does not have Slack connection configured."+ | ||
" Connect your Slack workspace to Scalr using UI first.", | ||
accountID, | ||
) | ||
} | ||
|
||
options.Connection = connection | ||
|
||
log.Printf("[DEBUG] Create slack integration: %s", name) | ||
integration, err := scalrClient.SlackIntegrations.Create(ctx, options) | ||
if err != nil { | ||
return diag.Errorf("Error creating slack integration %s: %v", name, err) | ||
} | ||
d.SetId(integration.ID) | ||
|
||
return resourceScalrSlackIntegrationRead(ctx, d, meta) | ||
} | ||
|
||
func resourceScalrSlackIntegrationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
scalrClient := meta.(*scalr.Client) | ||
integrationID := d.Id() | ||
|
||
log.Printf("[DEBUG] Read slack integration with ID: %s", integrationID) | ||
slackIntegration, err := scalrClient.SlackIntegrations.Read(ctx, integrationID) | ||
if err != nil { | ||
log.Printf("[DEBUG] slack integration %s no longer exists", integrationID) | ||
d.SetId("") | ||
return nil | ||
} | ||
_ = d.Set("name", slackIntegration.Name) | ||
_ = d.Set("channel_id", slackIntegration.ChannelId) | ||
_ = d.Set("events", slackIntegration.Events) | ||
_ = d.Set("account_id", slackIntegration.Account.ID) | ||
|
||
environmentIDs := make([]string, 0) | ||
for _, environment := range slackIntegration.Environments { | ||
environmentIDs = append(environmentIDs, environment.ID) | ||
} | ||
|
||
_ = d.Set("environments", environmentIDs) | ||
|
||
wsIDs := make([]string, 0) | ||
for _, ws := range slackIntegration.Workspaces { | ||
wsIDs = append(wsIDs, ws.ID) | ||
} | ||
_ = d.Set("workspaces", wsIDs) | ||
|
||
return nil | ||
} | ||
|
||
func resourceScalrSlackIntegrationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
scalrClient := meta.(*scalr.Client) | ||
options := scalr.SlackIntegrationUpdateOptions{} | ||
|
||
if d.HasChange("name") { | ||
options.Name = scalr.String(d.Get("name").(string)) | ||
} | ||
|
||
if d.HasChange("channel_id") { | ||
options.ChannelId = scalr.String(d.Get("channel_id").(string)) | ||
} | ||
|
||
if d.HasChange("events") { | ||
events := parseEvents(d) | ||
options.Events = events | ||
} | ||
|
||
if d.HasChange("environments") { | ||
envs := parseEnvironments(d) | ||
options.Environments = envs | ||
} | ||
|
||
workspaces := parseWorkspaces(d) | ||
if workspaces != nil { | ||
options.Workspaces = workspaces | ||
} | ||
|
||
log.Printf("[DEBUG] Update slack integration: %s", d.Id()) | ||
_, err := scalrClient.SlackIntegrations.Update(ctx, d.Id(), options) | ||
if err != nil { | ||
return diag.Errorf("Error updating slack integration %s: %v", d.Id(), err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceSlackIntegrationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
scalrClient := meta.(*scalr.Client) | ||
|
||
log.Printf("[DEBUG] Delete slack integration: %s", d.Id()) | ||
err := scalrClient.SlackIntegrations.Delete(ctx, d.Id()) | ||
if err != nil { | ||
if errors.Is(err, scalr.ErrResourceNotFound) { | ||
return nil | ||
} | ||
return diag.Errorf("Error deleting slack integration %s: %v", d.Id(), err) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.