Skip to content

Commit

Permalink
Merge pull request #2 from matthisholleville/fix/verify-if-maps-reall…
Browse files Browse the repository at this point in the history
…y-added

fix: verify if mapEntrie is really added.
  • Loading branch information
matthisholleville authored Feb 14, 2022
2 parents e949043 + 8b7badc commit 1dcbe8b
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 1 deletion.
10 changes: 10 additions & 0 deletions internal/haproxy/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package haproxy

import (
"encoding/base64"
"regexp"
"strings"
)

Expand All @@ -13,3 +14,12 @@ func basicAuth(username, password string) string {
func replaceSlashInString(value string) string {
return strings.Replace(value, "/", "%2F", -1)
}

func ExtractStringWithRegex(value string, regex string) string {
re := regexp.MustCompile(regex)
res := re.FindAllStringSubmatch(value, 1)
for i := range res {
return res[i][1]
}
return value
}
57 changes: 56 additions & 1 deletion internal/provider/resource_maps.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package provider

import (
"context"
"errors"
"fmt"
"regexp"

"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/matthisholleville/terraform-provider-haproxy/internal/haproxy"
"github.com/matthisholleville/terraform-provider-haproxy/internal/haproxy/models"
)
Expand All @@ -15,25 +19,37 @@ func resourceMaps() *schema.Resource {
ReadContext: resourceMapsRead,
UpdateContext: resourceMapsUpdate,
DeleteContext: resourceMapsDelete,
Importer: &schema.ResourceImporter{
State: resourceMapEntrieImport,
},

Schema: map[string]*schema.Schema{
"map": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "The HAProxy map name. More informations : https://www.haproxy.com/fr/blog/introduction-to-haproxy-maps/",
ValidateFunc: func(i interface{}, s string) ([]string, []error) {
return validation.StringIsNotWhiteSpace(i, s)
},
},
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Key name",
ValidateFunc: func(i interface{}, s string) ([]string, []error) {
return validation.StringIsNotWhiteSpace(i, s)
},
},
"value": {
Type: schema.TypeString,
Optional: true,
Default: "defaultValue",
Description: "Value name. Default value 'defaultValue'",
ValidateFunc: func(i interface{}, s string) ([]string, []error) {
return validation.StringIsNotWhiteSpace(i, s)
},
},
"force_sync": {
Type: schema.TypeBool,
Expand All @@ -45,6 +61,28 @@ func resourceMaps() *schema.Resource {
}
}

func resourceMapEntrieImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
client := meta.(*haproxy.Client)

idMatchFormat, _ := regexp.MatchString("map/(.*?)/entrie/(.*?)", d.Id())
if !idMatchFormat {
return nil, fmt.Errorf("invalid format: expected map/<mapName>/entrie/<entrieName>, e.g. map/test/entrie/my-key, actual id is %s", d.Id())
}

mapName := haproxy.ExtractStringWithRegex(d.Id(), "map/(.*?)/")
mapEntrie := haproxy.ExtractStringWithRegex(d.Id(), "entrie/(.*?)$")

d.SetId(mapEntrie)
d.Set("map", mapName)

_, err := client.GetMapEntrie(mapEntrie, mapName)
if err != nil {
return nil, fmt.Errorf("error on getting map entrie during import: %s", err)
}

return []*schema.ResourceData{d}, nil
}

func resourceMapsCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*haproxy.Client)
mapName := d.Get("map").(string)
Expand All @@ -57,12 +95,29 @@ func resourceMapsCreate(ctx context.Context, d *schema.ResourceData, meta interf
if err != nil {
return diag.FromErr(err)
}

_, err = client.GetMapEntrie(newEntrie.Key, mapName)
if err != nil {
errMessage := errors.New("Cannot insert " + newEntrie.Key + ". Space is not allowed.")
return diag.FromErr(errMessage)
}

d.SetId(newEntrie.Key)

return nil
return resourceMapsRead(ctx, d, meta)
}

func resourceMapsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*haproxy.Client)

mapEntrie, err := client.GetMapEntrie(d.Id(), d.Get("map").(string))
if err != nil {
diag.FromErr(err)
}
d.Set("key", mapEntrie.Key)
d.Set("value", mapEntrie.Value)
d.Set("map", d.Get("map").(string))
d.Set("force_sync", d.Get("force_sync").(bool))
return nil
}

Expand Down
95 changes: 95 additions & 0 deletions internal/provider/resource_maps_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package provider

import (
"fmt"
"regexp"
"testing"

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

func TestResourceMaps(t *testing.T) {
//var mapEntrieId string
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccMapEntrie("test", "/metrics", "50", "test"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("haproxy_maps.test", "map", "test"),
),
},
{
ResourceName: "haproxy_maps.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_sync"},
ImportStateIdFunc: func(s *terraform.State) (string, error) {
mapEntrieKey := s.RootModule().Resources["haproxy_maps.test"].Primary.Attributes["id"]
return fmt.Sprintf("map/%s/entrie/%s", "test", mapEntrieKey), nil
},
},
{
Config: testAccMapEntrie("test", "super_key", "50", "test-2"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("haproxy_maps.test-2", "map", "test"),
),
},
{
ResourceName: "haproxy_maps.test-2",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_sync"},
ImportStateIdFunc: func(s *terraform.State) (string, error) {
mapEntrieKey := s.RootModule().Resources["haproxy_maps.test-2"].Primary.Attributes["id"]
return fmt.Sprintf("map/%s/entrie/%s", "test", mapEntrieKey), nil
},
},
{
Config: testAccMapEntrie("test", "/test1/test2", "50", "test-3"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("haproxy_maps.test-3", "map", "test"),
),
},
{
ResourceName: "haproxy_maps.test-3",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_sync"},
ImportStateIdFunc: func(s *terraform.State) (string, error) {
mapEntrieKey := s.RootModule().Resources["haproxy_maps.test-3"].Primary.Attributes["id"]
return fmt.Sprintf("map/%s/entrie/%s", "test", mapEntrieKey), nil
},
},
},
})
}

func TestCreateMapEntrie_with_invalid_key(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { preCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccMapEntrie("test", "test with bad key", "default_value", "test-bad1"),
ExpectError: regexp.MustCompile("Cannot insert test with bad key. Space is not allowed."),
},
{
Config: testAccMapEntrie("test", "test-with-bad: key", "default_value", "test-bad2"),
ExpectError: regexp.MustCompile("Cannot insert test-with-bad: key. Space is not allowed."),
},
},
})
}

func testAccMapEntrie(mapName string, key string, value string, resourceName string) string {
return fmt.Sprintf(`
resource "haproxy_maps" "%[4]s" {
map = "%[1]s"
key = "%[2]s"
value = "%[3]s"
}
`, mapName, key, value, resourceName)
}

0 comments on commit 1dcbe8b

Please sign in to comment.