forked from mirrors/terraform-provider-binarylane
Accept 202 for reverse name changes and add unit and destroy checks
This commit is contained in:
@@ -259,9 +259,13 @@ func (r *serverReverseNameResource) changeReverseName(ctx context.Context, serve
|
||||
if err != nil {
|
||||
return fmt.Errorf("error changing reverse name for server: server_id=%d, error: %w", serverId, err)
|
||||
}
|
||||
if actionResp.StatusCode() != http.StatusOK {
|
||||
if actionResp.StatusCode() != http.StatusOK && actionResp.StatusCode() != http.StatusAccepted {
|
||||
return fmt.Errorf("unexpected HTTP status code changing reverse name for server: server_id=%d, details: %s", serverId, actionResp.Body)
|
||||
}
|
||||
// 202 Accepted carries no action ID to poll
|
||||
if actionResp.JSON200 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sr := serverResource{bc: r.bc}
|
||||
if err := sr.waitForServerAction(ctx, serverId, actionResp.JSON200.Action.Id); err != nil {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"terraform-provider-binarylane/internal/binarylane"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||
)
|
||||
@@ -47,8 +53,14 @@ resource "binarylane_server" "test" {
|
||||
}
|
||||
`
|
||||
|
||||
var serverId int64
|
||||
var ipv4Address string
|
||||
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
CheckDestroy: func(_ *terraform.State) error {
|
||||
return testAccCheckServerReverseNameCleared(serverId, ipv4Address)
|
||||
},
|
||||
Steps: []resource.TestStep{
|
||||
// Create and Read testing
|
||||
{
|
||||
@@ -64,6 +76,13 @@ resource "binarylane_server_reverse_name" "test" {
|
||||
resource.TestCheckResourceAttrPair("binarylane_server_reverse_name.test", "ipv4_address", "binarylane_server.test", "public_ipv4_addresses.0"),
|
||||
resource.TestCheckResourceAttr("binarylane_server_reverse_name.test", "reverse_name", "tf-test-ptr.example.com"),
|
||||
resource.TestCheckResourceAttrSet("binarylane_server_reverse_name.test", "id"),
|
||||
func(s *terraform.State) error {
|
||||
attrs := s.RootModule().Resources["binarylane_server_reverse_name.test"].Primary.Attributes
|
||||
var err error
|
||||
serverId, err = strconv.ParseInt(attrs["server_id"], 10, 64)
|
||||
ipv4Address = attrs["ipv4_address"]
|
||||
return err
|
||||
},
|
||||
),
|
||||
},
|
||||
// ImportState testing
|
||||
@@ -89,7 +108,41 @@ resource "binarylane_server_reverse_name" "test" {
|
||||
resource.TestCheckResourceAttr("binarylane_server_reverse_name.test", "reverse_name", "tf-test-ptr-updated.example.com"),
|
||||
),
|
||||
},
|
||||
// Removing the resource clears the reverse name while the server still exists
|
||||
{
|
||||
Config: providerConfig + serverConfig,
|
||||
Check: func(_ *terraform.State) error {
|
||||
return testAccCheckServerReverseNameCleared(serverId, ipv4Address)
|
||||
},
|
||||
},
|
||||
// Delete testing automatically occurs in TestCase
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckServerReverseNameCleared(serverId int64, ipv4Address string) error {
|
||||
client, err := binarylane.NewClientWithConfig("", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := client.GetServersServerIdWithResponse(context.Background(), serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode() == http.StatusNotFound {
|
||||
return nil
|
||||
}
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
return fmt.Errorf("unexpected status %s reading server %d: %s", resp.Status(), serverId, resp.Body)
|
||||
}
|
||||
for _, n := range resp.JSON200.Server.Networks.V4 {
|
||||
if n.IpAddress != ipv4Address || n.ReverseName == nil {
|
||||
continue
|
||||
}
|
||||
switch *n.ReverseName {
|
||||
case "tf-test-ptr.example.com", "tf-test-ptr-updated.example.com":
|
||||
return fmt.Errorf("reverse name for %s on server %d not cleared: %s", ipv4Address, serverId, *n.ReverseName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"terraform-provider-binarylane/internal/binarylane"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
)
|
||||
|
||||
func TestServerReverseNameResourceUnit(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
var (
|
||||
postStatus = http.StatusOK
|
||||
serverFound = true
|
||||
serverIp = "203.0.113.7"
|
||||
serverName = "ptr.example.com"
|
||||
lastBody map[string]any
|
||||
)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch {
|
||||
case r.Method == http.MethodPost && r.URL.Path == "/servers/1/actions":
|
||||
b, _ := io.ReadAll(r.Body)
|
||||
lastBody = nil
|
||||
if err := json.Unmarshal(b, &lastBody); err != nil {
|
||||
t.Errorf("decode POST body: %v", err)
|
||||
}
|
||||
w.WriteHeader(postStatus)
|
||||
if postStatus == http.StatusOK {
|
||||
_, _ = w.Write([]byte(`{"action":{"id":9,"status":"in-progress"}}`))
|
||||
}
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/servers/1/actions/9":
|
||||
_, _ = w.Write([]byte(`{"action":{"id":9,"status":"completed","completed_at":"2026-01-01T00:00:00Z"}}`))
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/servers/1":
|
||||
if !serverFound {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
_, _ = fmt.Fprintf(w, `{"server":{"id":1,"networks":{"v4":[{"ip_address":%q,"type":"public","reverse_name":%q}]}}}`, serverIp, serverName)
|
||||
default:
|
||||
t.Errorf("unexpected request %s %s", r.Method, r.URL.Path)
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client, err := binarylane.NewClientWithConfig(srv.URL, "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r := &serverReverseNameResource{bc: &BinarylaneClient{client: client}}
|
||||
|
||||
schemaResp := resource.SchemaResponse{}
|
||||
r.Schema(ctx, resource.SchemaRequest{}, &schemaResp)
|
||||
s := schemaResp.Schema
|
||||
emptyState := func() tfsdk.State {
|
||||
return tfsdk.State{Schema: s, Raw: tftypes.NewValue(s.Type().TerraformType(ctx), nil)}
|
||||
}
|
||||
model := serverReverseNameResourceModel{
|
||||
Id: types.StringUnknown(),
|
||||
ServerId: types.Int64Value(1),
|
||||
Ipv4Address: types.StringValue("203.0.113.7"),
|
||||
ReverseName: types.StringValue("ptr.example.com"),
|
||||
}
|
||||
plan := tfsdk.Plan{Schema: s, Raw: tftypes.NewValue(s.Type().TerraformType(ctx), nil)}
|
||||
if diags := plan.Set(ctx, &model); diags.HasError() {
|
||||
t.Fatal(diags)
|
||||
}
|
||||
|
||||
createResp := resource.CreateResponse{State: emptyState()}
|
||||
r.Create(ctx, resource.CreateRequest{Plan: plan}, &createResp)
|
||||
if createResp.Diagnostics.HasError() {
|
||||
t.Fatal(createResp.Diagnostics)
|
||||
}
|
||||
if lastBody["reverse_name"] != "ptr.example.com" || lastBody["ipv4_address"] != "203.0.113.7" {
|
||||
t.Fatalf("create: unexpected request body %v", lastBody)
|
||||
}
|
||||
state := createResp.State
|
||||
|
||||
read := func() (serverReverseNameResourceModel, bool) {
|
||||
t.Helper()
|
||||
readResp := resource.ReadResponse{State: state}
|
||||
r.Read(ctx, resource.ReadRequest{State: state}, &readResp)
|
||||
if readResp.Diagnostics.HasError() {
|
||||
t.Fatal(readResp.Diagnostics)
|
||||
}
|
||||
if readResp.State.Raw.IsNull() {
|
||||
return serverReverseNameResourceModel{}, false
|
||||
}
|
||||
var got serverReverseNameResourceModel
|
||||
if diags := readResp.State.Get(ctx, &got); diags.HasError() {
|
||||
t.Fatal(diags)
|
||||
}
|
||||
return got, true
|
||||
}
|
||||
|
||||
serverName = "drifted.example.com"
|
||||
if got, ok := read(); !ok || got.ReverseName.ValueString() != "drifted.example.com" {
|
||||
t.Fatalf("read: expected drift to drifted.example.com, got %v (present=%v)", got.ReverseName, ok)
|
||||
}
|
||||
|
||||
serverIp = "198.51.100.1"
|
||||
if _, ok := read(); ok {
|
||||
t.Fatal("read: expected state removed when IP is not on the server")
|
||||
}
|
||||
|
||||
serverFound = false
|
||||
if _, ok := read(); ok {
|
||||
t.Fatal("read: expected state removed when server is 404")
|
||||
}
|
||||
|
||||
postStatus = http.StatusAccepted
|
||||
updateResp := resource.UpdateResponse{State: emptyState()}
|
||||
r.Update(ctx, resource.UpdateRequest{Plan: plan, State: state}, &updateResp)
|
||||
if updateResp.Diagnostics.HasError() {
|
||||
t.Fatalf("update: 202 without action should succeed: %v", updateResp.Diagnostics)
|
||||
}
|
||||
|
||||
deleteResp := resource.DeleteResponse{State: state}
|
||||
r.Delete(ctx, resource.DeleteRequest{State: state}, &deleteResp)
|
||||
if deleteResp.Diagnostics.HasError() {
|
||||
t.Fatalf("delete: 202 without action should succeed: %v", deleteResp.Diagnostics)
|
||||
}
|
||||
if _, ok := lastBody["reverse_name"]; ok {
|
||||
t.Fatalf("delete: request body must not contain reverse_name, got %v", lastBody)
|
||||
}
|
||||
if lastBody["ipv4_address"] != "203.0.113.7" {
|
||||
t.Fatalf("delete: unexpected request body %v", lastBody)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user