Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add b2_bucket_notification_rules resource and data source #91

Merged
merged 3 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
* Added support for Event Notifications via `b2_bucket_notification_rules` resource and data source

### Infrastructure
* Use Python 3.13 for embedded pybindings

Expand Down
2 changes: 1 addition & 1 deletion b2/bindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,6 @@ func GetBindings() (string, error) {
}

bindings = &destinationPath
log.Printf("[TRACE] Extracted pybindings: %s\n", *bindings)
log.Printf("Extracted pybindings: %s\n", *bindings)
return *bindings, nil
}
29 changes: 21 additions & 8 deletions b2/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ package b2

import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"os"
"os/exec"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

Expand All @@ -42,9 +43,15 @@ type Client struct {
SensitiveResources map[string]map[string]bool
}

func (c Client) apply(name string, op string, input map[string]interface{}) (map[string]interface{}, error) {
log.Printf("[TRACE] Executing pybindings for '%s' and '%s' operation\n", name, op)
log.Printf("[TRACE] Input for pybindings: %+v\n", input)
func (c Client) apply(ctx context.Context, name string, op string, input map[string]interface{}) (map[string]interface{}, error) {
tflog.Info(ctx, "Executing pybindings", map[string]interface{}{
"name": name,
"op": op,
})

tflog.Debug(ctx, "Input for pybindings", map[string]interface{}{
"input": input,
})

cmd := exec.Command(c.Exec, name, op)
cmd.Env = os.Environ()
Expand All @@ -66,12 +73,16 @@ func (c Client) apply(name string, op string, input map[string]interface{}) (map
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
if exitErr.Stderr != nil && len(exitErr.Stderr) > 0 {
log.Printf("[ERROR] Error in pybindings: %+v\n", string(exitErr.Stderr))
tflog.Error(ctx, "Error in pybindings", map[string]interface{}{
"stderr": fmt.Errorf(string(exitErr.Stderr)),
})
return nil, fmt.Errorf(string(exitErr.Stderr))
}
return nil, fmt.Errorf("failed to execute")
} else {
log.Println(err)
tflog.Error(ctx, "Error", map[string]interface{}{
"err": err,
})
return nil, err
}
}
Expand Down Expand Up @@ -99,12 +110,14 @@ func (c Client) apply(name string, op string, input map[string]interface{}) (map
safeOutput[k] = v
}
}
log.Printf("[TRACE] Safe output from pybindings: %+v\n", safeOutput)
tflog.Debug(ctx, "Safe output from pybindings", map[string]interface{}{
"output": safeOutput,
})

return output, nil
}

func (c Client) populate(name string, op string, output map[string]interface{}, d *schema.ResourceData) error {
func (c Client) populate(ctx context.Context, name string, op string, output map[string]interface{}, d *schema.ResourceData) error {
resourceName := "b2_" + name
var schemaList []string
if op == DATA_SOURCE_READ {
Expand Down
4 changes: 2 additions & 2 deletions b2/data_source_b2_account_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ func dataSourceB2AccountInfoRead(ctx context.Context, d *schema.ResourceData, me

input := map[string]interface{}{}

output, err := client.apply(name, op, input)
output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["account_id"].(string))

err = client.populate(name, op, output, d)
err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
4 changes: 2 additions & 2 deletions b2/data_source_b2_application_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ func dataSourceB2ApplicationKeyRead(ctx context.Context, d *schema.ResourceData,
"key_name": d.Get("key_name").(string),
}

output, err := client.apply(name, op, input)
output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["application_key_id"].(string))

err = client.populate(name, op, output, d)
err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
4 changes: 2 additions & 2 deletions b2/data_source_b2_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ func dataSourceB2BucketRead(ctx context.Context, d *schema.ResourceData, meta in
"bucket_name": d.Get("bucket_name").(string),
}

output, err := client.apply(name, op, input)
output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["bucket_id"].(string))

err = client.populate(name, op, output, d)
err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
4 changes: 2 additions & 2 deletions b2/data_source_b2_bucket_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ func dataSourceB2BucketFileRead(ctx context.Context, d *schema.ResourceData, met
"show_versions": d.Get("show_versions").(bool),
}

output, err := client.apply(name, op, input)
output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["_sha1"].(string))

err = client.populate(name, op, output, d)
err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
4 changes: 2 additions & 2 deletions b2/data_source_b2_bucket_file_signed_url.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ func dataSourceB2BucketFileSignedUrlRead(ctx context.Context, d *schema.Resource
"duration": d.Get("duration").(int),
}

output, err := client.apply(name, op, input)
output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["signed_url"].(string))

err = client.populate(name, op, output, d)
err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
4 changes: 2 additions & 2 deletions b2/data_source_b2_bucket_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ func dataSourceB2BucketFilesRead(ctx context.Context, d *schema.ResourceData, me
"recursive": d.Get("recursive").(bool),
}

output, err := client.apply(name, op, input)
output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["_sha1"].(string))

err = client.populate(name, op, output, d)
err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}
Expand Down
66 changes: 66 additions & 0 deletions b2/data_source_b2_bucket_notification_rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//####################################################################
//
// File: b2/data_source_b2_bucket_notification_rules.go
//
// Copyright 2024 Backblaze Inc. All Rights Reserved.
//
// License https://www.backblaze.com/using_b2_code.html
//
//####################################################################

package b2

import (
"context"

"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"
)

func dataSourceB2BucketNotificationRules() *schema.Resource {
return &schema.Resource{
Description: "B2 bucket notification rules data source.",

ReadContext: dataSourceB2BucketNotificationRulesRead,

Schema: map[string]*schema.Schema{
"bucket_id": {
Description: "The ID of the bucket.",
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.NoZeroValues,
},
"notification_rules": {
Description: "An array of Event Notification Rules.",
Type: schema.TypeList,
Elem: getNotificationRulesElem(true),
Computed: true,
},
},
}
}

func dataSourceB2BucketNotificationRulesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*Client)
const name = "bucket_notification_rules"
const op = DATA_SOURCE_READ

input := map[string]interface{}{
"bucket_id": d.Get("bucket_id").(string),
}

output, err := client.apply(ctx, name, op, input)
if err != nil {
return diag.FromErr(err)
}

d.SetId(output["bucket_id"].(string))

err = client.populate(ctx, name, op, output, d)
if err != nil {
return diag.FromErr(err)
}

return nil
}
71 changes: 71 additions & 0 deletions b2/data_source_b2_bucket_notification_rules_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//####################################################################
//
// File: b2/data_source_b2_bucket_notification_rules_test.go
//
// Copyright 2024 Backblaze Inc. All Rights Reserved.
//
// License https://www.backblaze.com/using_b2_code.html
//
//####################################################################

package b2

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccDataSourceB2BucketNotificationRules_basic(t *testing.T) {
parentResourceName := "b2_bucket.test"
resourceName := "b2_bucket_notification_rules.test"
dataSourceName := "data.b2_bucket_notification_rules.test"

bucketName := acctest.RandomWithPrefix("test-b2-tfp")
ruleName := acctest.RandomWithPrefix("test-b2-tfp")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccDataSourceB2BucketNotificationRulesConfig_basic(bucketName, ruleName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "bucket_id", resourceName, "bucket_id"),
resource.TestCheckResourceAttrPair(dataSourceName, "bucket_id", parentResourceName, "bucket_id"),
resource.TestCheckResourceAttrPair(dataSourceName, "notification_rules", resourceName, "notification_rules"),
),
},
},
})
}

func testAccDataSourceB2BucketNotificationRulesConfig_basic(bucketName string, ruleName string) string {
return fmt.Sprintf(`
resource "b2_bucket" "test" {
bucket_name = "%s"
bucket_type = "allPublic"
}

resource "b2_bucket_notification_rules" "test" {
bucket_id = b2_bucket.test.id
notification_rules {
name = "%s"
event_types = ["b2:ObjectCreated:*"]
target_configuration {
target_type = "webhook"
url = "https://example.com/webhook"
}
}
}

data "b2_bucket_notification_rules" "test" {
bucket_id = b2_bucket.test.bucket_id
depends_on = [
b2_bucket_notification_rules.test,
]
}
`, bucketName, ruleName)
}
26 changes: 15 additions & 11 deletions b2/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package b2
import (
"context"
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
Expand Down Expand Up @@ -58,17 +58,19 @@ func New(version string, exec string) func() *schema.Provider {
},
},
DataSourcesMap: map[string]*schema.Resource{
"b2_account_info": dataSourceB2AccountInfo(),
"b2_application_key": dataSourceB2ApplicationKey(),
"b2_bucket": dataSourceB2Bucket(),
"b2_bucket_file": dataSourceB2BucketFile(),
"b2_bucket_file_signed_url": dataSourceB2BucketFileSignedUrl(),
"b2_bucket_files": dataSourceB2BucketFiles(),
"b2_account_info": dataSourceB2AccountInfo(),
"b2_application_key": dataSourceB2ApplicationKey(),
"b2_bucket": dataSourceB2Bucket(),
"b2_bucket_file": dataSourceB2BucketFile(),
"b2_bucket_file_signed_url": dataSourceB2BucketFileSignedUrl(),
"b2_bucket_files": dataSourceB2BucketFiles(),
"b2_bucket_notification_rules": dataSourceB2BucketNotificationRules(),
},
ResourcesMap: map[string]*schema.Resource{
"b2_application_key": resourceB2ApplicationKey(),
"b2_bucket": resourceB2Bucket(),
"b2_bucket_file_version": resourceB2BucketFileVersion(),
"b2_application_key": resourceB2ApplicationKey(),
"b2_bucket": resourceB2Bucket(),
"b2_bucket_file_version": resourceB2BucketFileVersion(),
"b2_bucket_notification_rules": resourceB2BucketNotificationRules(),
},
}

Expand Down Expand Up @@ -117,7 +119,9 @@ func configure(version string, exec string, p *schema.Provider) func(context.Con
SensitiveResources: sensitiveResources,
}

log.Printf("[DEBUG] User Agent append: %s\n", userAgent)
tflog.Info(ctx, "User Agent append", map[string]interface{}{
"user_agent_append": userAgent,
})

return client, nil
}
Expand Down
Loading
Loading