Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ require (
golang.org/x/crypto v0.43.0
golang.org/x/sync v0.17.0
gopkg.in/dnaeon/go-vcr.v3 v3.2.0
gopkg.in/dnaeon/go-vcr.v4 v4.0.5
)

require (
Expand Down Expand Up @@ -85,6 +86,7 @@ require (
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gookit/color v1.5.1 // indirect
Expand Down
97 changes: 93 additions & 4 deletions internal/acctest/acctest.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package acctest

import (
"encoding/base64"
"encoding/json"
"encoding/xml"
"net/http"
"os"
"strconv"
"strings"
Expand All @@ -9,11 +13,15 @@ import (

"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-mux/tf6muxserver"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/scaleway-sdk-go/vcr"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/env"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/transport"
"github.com/scaleway/terraform-provider-scaleway/v2/provider"
"github.com/stretchr/testify/require"
"gopkg.in/dnaeon/go-vcr.v4/pkg/cassette"
"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
)

func PreCheck(_ *testing.T) {}
Expand All @@ -25,6 +33,77 @@ type TestTools struct {
Cleanup func()
}

var foldersUsingVCRv4 = []string{
"instance",
}

func folderUsesVCRv4(fullFolderPath string) bool {
fullPathSplit := strings.Split(fullFolderPath, "/")

folder := fullPathSplit[len(fullPathSplit)-1]
for _, migratedFolder := range foldersUsingVCRv4 {
if migratedFolder == folder {
return true
}
}

return false
}

// s3Encoder encodes binary payloads as base64 because serialization changed on go-vcr.v4
func s3Encoder(i *cassette.Interaction) error {
if !strings.HasSuffix(i.Request.Host, "scw.cloud") {
return nil
}

if i.Request.Body != "" && i.Request.Headers.Get("Content-Type") == "application/octet-stream" {
requestBody := []byte(i.Request.Body)
if !json.Valid(requestBody) {
err := xml.Unmarshal(requestBody, new(any))
if err != nil {
i.Request.Body = base64.StdEncoding.EncodeToString(requestBody)
}
}
}

if i.Response.Body != "" && i.Response.Headers.Get("Content-Type") == "binary/octet-stream" {
responseBody := []byte(i.Response.Body)
if !json.Valid(responseBody) {
err := xml.Unmarshal(responseBody, new(any))
if err != nil {
i.Response.Body = base64.StdEncoding.EncodeToString(responseBody)
}
}
}

return nil
}

func NewRecordedClient(t *testing.T, pkgFolder string, update bool) (client *http.Client, cleanup func(), err error) {
t.Helper()

s3EncoderHook := vcr.AdditionalHook{
HookFunc: s3Encoder,
Kind: recorder.AfterCaptureHook,
}

r, err := vcr.NewHTTPRecorder(t, pkgFolder, update, nil, s3EncoderHook)
if err != nil {
return nil, nil, err
}

retryOptions := transport.RetryableTransportOptions{}
if !update {
retryOptions.RetryWaitMax = scw.TimeDurationPtr(0)
}

return &http.Client{
Transport: transport.NewRetryableTransportWithOptions(r, retryOptions),
}, func() {
require.NoError(t, r.Stop()) // Make sure recorder is stopped once done with it
}, nil
}

func NewTestTools(t *testing.T) *TestTools {
t.Helper()

Expand All @@ -35,8 +114,18 @@ func NewTestTools(t *testing.T) *TestTools {
t.Fatalf("cannot detect working directory for testing")
}

// Create a http client with recording capabilities
httpClient, cleanup, err := getHTTPRecoder(t, folder, *UpdateCassettes)
// Create an HTTP client with recording capabilities
var (
httpClient *http.Client
cleanup func()
)

if folderUsesVCRv4(folder) {
httpClient, cleanup, err = NewRecordedClient(t, folder, *UpdateCassettes)
} else {
httpClient, cleanup, err = getHTTPRecoder(t, folder, *UpdateCassettes)
}

require.NoError(t, err)

// Create meta that will be passed in the provider config
Expand All @@ -48,11 +137,11 @@ func NewTestTools(t *testing.T) *TestTools {
require.NoError(t, err)

if !*UpdateCassettes {
// If no recording is happening, the delay to retry to interactions should be 0
// If no recording is happening, the delay to retry interactions should be 0
tmp := 0 * time.Second
transport.DefaultWaitRetryInterval = &tmp
} else if os.Getenv(env.RetryDelay) != "" {
// Overriding the delay interval is helpful to reduce the amount of requests performed while waiting for a ressource to be available
// Overriding the delay interval is helpful to reduce the amount of requests performed while waiting for a resource to be available
tmp, err := time.ParseDuration(os.Getenv(env.RetryDelay))
if err != nil {
t.Fatal(err)
Expand Down
22 changes: 14 additions & 8 deletions internal/services/instance/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -726,25 +726,25 @@ func TestAccServer_WithPlacementGroup(t *testing.T) {
policy_type = "max_availability"
}

resource "scaleway_instance_server" "base" {
resource "scaleway_instance_server" "ha" {
count = 3
name = "tf-tests-server-${count.index}-with-placement-group"
image = "ubuntu_focal"
type = "PLAY2-PICO"
placement_group_id = "${scaleway_instance_placement_group.ha.id}"
tags = [ "terraform-test", "scaleway_instance_server", "placement_group" ]
tags = [ "terraform-test", "scaleway_instance_server", "placement_group", "${count.index}" ]
}`,
Check: resource.ComposeTestCheckFunc(
isServerPresent(tt, "scaleway_instance_server.base.0"),
isServerPresent(tt, "scaleway_instance_server.base.1"),
isServerPresent(tt, "scaleway_instance_server.base.2"),
isServerPresent(tt, "scaleway_instance_server.ha.0"),
isServerPresent(tt, "scaleway_instance_server.ha.1"),
isServerPresent(tt, "scaleway_instance_server.ha.2"),
isPlacementGroupPresent(tt, "scaleway_instance_placement_group.ha"),
resource.TestCheckResourceAttr("scaleway_instance_placement_group.ha", "policy_respected", "true"),

// placement_group_policy_respected is deprecated and should always be false.
resource.TestCheckResourceAttr("scaleway_instance_server.base.0", "placement_group_policy_respected", "false"),
resource.TestCheckResourceAttr("scaleway_instance_server.base.1", "placement_group_policy_respected", "false"),
resource.TestCheckResourceAttr("scaleway_instance_server.base.2", "placement_group_policy_respected", "false"),
resource.TestCheckResourceAttr("scaleway_instance_server.ha.0", "placement_group_policy_respected", "false"),
resource.TestCheckResourceAttr("scaleway_instance_server.ha.1", "placement_group_policy_respected", "false"),
resource.TestCheckResourceAttr("scaleway_instance_server.ha.2", "placement_group_policy_respected", "false"),
),
},
},
Expand Down Expand Up @@ -1405,12 +1405,14 @@ func TestAccServer_CustomDiffImage(t *testing.T) {
image = "ubuntu_jammy"
type = "DEV1-S"
state = "stopped"
tags = [ "main" ]
}
resource "scaleway_instance_server" "control" {
name = "control-server"
image = "ubuntu_jammy"
type = "DEV1-S"
state = "stopped"
tags = [ "control" ]
}
`,
Check: resource.ComposeTestCheckFunc(
Expand All @@ -1433,12 +1435,14 @@ func TestAccServer_CustomDiffImage(t *testing.T) {
image = data.scaleway_marketplace_image.jammy.id
type = "DEV1-S"
state = "stopped"
tags = [ "main" ]
}
resource "scaleway_instance_server" "control" {
name = "control-server"
image = "ubuntu_jammy"
type = "DEV1-S"
state = "stopped"
tags = [ "conntrol" ]
}
`, marketplaceImageType),
Check: resource.ComposeTestCheckFunc(
Expand All @@ -1462,12 +1466,14 @@ func TestAccServer_CustomDiffImage(t *testing.T) {
image = data.scaleway_marketplace_image.focal.id
type = "DEV1-S"
state = "stopped"
tags = [ "main" ]
}
resource "scaleway_instance_server" "control" {
name = "control-server"
image = "ubuntu_jammy"
type = "DEV1-S"
state = "stopped"
tags = [ "conntrol" ]
}
`, marketplaceImageType),
Check: resource.ComposeTestCheckFunc(
Expand Down
Loading
Loading