Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 6s
CI Workflow / CI (pull_request) Failing after 10m15s
CI Workflow / Code coverage report (pull_request) Has been skipped
CI Workflow / Test readiness for publishing provider (pull_request) Failing after 12m58s
430 lines
12 KiB
Go
430 lines
12 KiB
Go
package sqlserverflexbeta
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
"testing"
|
|
"text/template"
|
|
|
|
"github.com/hashicorp/terraform-plugin-testing/compare"
|
|
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
|
|
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
|
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
|
|
"github.com/hashicorp/terraform-plugin-testing/statecheck"
|
|
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
|
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
|
|
"github.com/hashicorp/terraform-plugin-testing/tfversion"
|
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/testutil"
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
|
|
)
|
|
|
|
const resourceString = "stackitprivatepreview_sqlserverflexbeta_instance"
|
|
|
|
var (
|
|
validSingleFlavor = "4.16-Single"
|
|
kekKeyRingId = ""
|
|
kekKeyVersion = ""
|
|
kekKeySA = ""
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
resource.TestMain(m)
|
|
}
|
|
|
|
func init() {
|
|
resource.AddTestSweepers(resourceString, &resource.Sweeper{
|
|
Name: resourceString,
|
|
F: func(region string) error {
|
|
client, err := sharedClientForRegion(region)
|
|
if err != nil {
|
|
return fmt.Errorf("error getting client: %s", err)
|
|
}
|
|
conn := client.(*sqlserverflexbeta.APIClient)
|
|
|
|
ctx := context.Background()
|
|
instances, err := conn.ListInstancesRequest(ctx, testutil.ProjectId, region).Execute()
|
|
if err != nil {
|
|
return fmt.Errorf("error getting instances: %s", err)
|
|
}
|
|
for _, instance := range instances.GetInstances() {
|
|
if strings.HasPrefix(instance.GetName(), "test-acc") {
|
|
err := conn.DeleteInstanceRequestExecute(ctx, testutil.ProjectId, region, instance.GetId())
|
|
if err != nil {
|
|
log.Printf("error destroying %s during sweep: %s", instance.GetName(), err)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
})
|
|
}
|
|
|
|
// sharedClientForRegion returns a common provider client configured for the specified region
|
|
func sharedClientForRegion(region string) (any, error) {
|
|
providerData := core.ProviderData{}
|
|
if region != "" {
|
|
providerData.DefaultRegion = region
|
|
}
|
|
apiClientConfigOptions := []config.ConfigurationOption{
|
|
config.WithCustomAuth(providerData.RoundTripper),
|
|
utils.UserAgentConfigOption(providerData.Version),
|
|
}
|
|
if providerData.SQLServerFlexCustomEndpoint != "" {
|
|
apiClientConfigOptions = append(apiClientConfigOptions, config.WithEndpoint(providerData.SQLServerFlexCustomEndpoint))
|
|
} else {
|
|
apiClientConfigOptions = append(apiClientConfigOptions, config.WithRegion(providerData.GetRegion()))
|
|
}
|
|
apiClient, err := sqlserverflexbeta.NewAPIClient(apiClientConfigOptions...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return apiClient, nil
|
|
}
|
|
|
|
func testAccPreCheck(t *testing.T) {
|
|
// TODO: if needed ...
|
|
}
|
|
|
|
type resData struct {
|
|
WithEncryption bool
|
|
ServiceAccountFilePath string
|
|
ProjectID string
|
|
Region string
|
|
TfName string
|
|
Name string
|
|
FlavorID string
|
|
BackupSchedule string
|
|
RetentionDays uint32
|
|
Replicas uint32
|
|
PerformanceClass string
|
|
Size uint32
|
|
Acl string
|
|
AccessScope string
|
|
Version string
|
|
KekKeyId string
|
|
KekKeyRingId string
|
|
KekKeyVersion uint8
|
|
KekSaEmail string
|
|
}
|
|
|
|
func getSingleExample() resData {
|
|
tmpName := acctest.RandomWithPrefix("tf-acc")
|
|
return resData{
|
|
WithEncryption: false,
|
|
Region: testutil.Region,
|
|
ServiceAccountFilePath: testutil.ServiceAccountFile,
|
|
ProjectID: testutil.ProjectId,
|
|
Name: tmpName,
|
|
TfName: tmpName,
|
|
FlavorID: validSingleFlavor,
|
|
BackupSchedule: "0 0 * * *",
|
|
RetentionDays: 33,
|
|
PerformanceClass: "premium-perf2-stackit",
|
|
Size: 10,
|
|
Acl: "0.0.0.0/0",
|
|
AccessScope: "PUBLIC",
|
|
Version: "2022",
|
|
}
|
|
}
|
|
|
|
func TestAccResourceExample_basic(t *testing.T) {
|
|
exData := getSingleExample()
|
|
t.Logf("[INFO] resource name: %s", exData.TfName)
|
|
|
|
exBefore := testAccResourceExampleConfig(exData)
|
|
|
|
updData := exData
|
|
// oldName := exData.Name
|
|
updData.Name = "newname"
|
|
updBefore := testAccResourceExampleConfig(updData)
|
|
|
|
resName := fmt.Sprintf("%s.%s", resourceString, exData.TfName)
|
|
var resourceID string
|
|
|
|
compareValuesSame := statecheck.CompareValue(compare.ValuesSame())
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
|
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
|
|
tfversion.SkipBelow(tfversion.Version1_10_0),
|
|
},
|
|
CheckDestroy: testAccCheckExampleResourceDestroy,
|
|
Steps: []resource.TestStep{
|
|
// test create
|
|
{
|
|
Config: exBefore,
|
|
ConfigStateChecks: []statecheck.StateCheck{
|
|
compareValuesSame.AddStateValue(
|
|
resName,
|
|
tfjsonpath.New("edition"),
|
|
),
|
|
statecheck.ExpectKnownValue(
|
|
resName,
|
|
tfjsonpath.New("edition"),
|
|
knownvalue.StringExact("Standard"),
|
|
),
|
|
//statecheck.ExpectSensitiveValue(resName,
|
|
// tfjsonpath.New("sensitive_string_attribute")),
|
|
},
|
|
Check: resource.ComposeAggregateTestCheckFunc(
|
|
func(s *terraform.State) error {
|
|
t.Logf("[INFO] resourceID: %+v", resourceID)
|
|
return nil
|
|
},
|
|
testAccGrabResourceID(resName, &resourceID),
|
|
func(s *terraform.State) error {
|
|
t.Logf("[INFO] resourceID: %s", resourceID)
|
|
return nil
|
|
},
|
|
testCheckResourceExists(resName),
|
|
resource.TestCheckResourceAttrSet(resName, "id"),
|
|
//resource.TestCheckResourceAttr(resName, "id", resourceID),
|
|
resource.TestCheckResourceAttr(resName, "name", exData.Name),
|
|
),
|
|
},
|
|
// up to here we should see no plan drift
|
|
{
|
|
Config: exBefore,
|
|
PlanOnly: true,
|
|
ExpectNonEmptyPlan: false,
|
|
},
|
|
// test update
|
|
{
|
|
Config: updBefore,
|
|
Check: resource.ComposeAggregateTestCheckFunc(
|
|
func(s *terraform.State) error {
|
|
t.Logf("[INFO] resourceID: %s", resourceID)
|
|
return nil
|
|
},
|
|
testCheckResourceExists(resName),
|
|
resource.TestCheckResourceAttrSet(resName, "id"),
|
|
//resource.TestCheckResourceAttr(resName, "id", resourceID),
|
|
resource.TestCheckResourceAttr(resName, "name", updData.Name),
|
|
),
|
|
},
|
|
// check for plan drift after update
|
|
{
|
|
Config: exBefore,
|
|
PlanOnly: true,
|
|
ExpectNonEmptyPlan: false,
|
|
},
|
|
//// Import test
|
|
//{
|
|
// ResourceName: resName,
|
|
// ImportState: true,
|
|
// ImportStateVerify: true,
|
|
//},
|
|
},
|
|
})
|
|
}
|
|
|
|
func testAccCheckExampleResourceDestroy(state *terraform.State) error {
|
|
//// retrieve the connection established in Provider configuration
|
|
//conn := testAccProvider.Meta().(*ExampleClient)
|
|
|
|
// loop through the resources in state, verifying each widget
|
|
// is destroyed
|
|
for _, rs := range state.RootModule().Resources {
|
|
if rs.Type != resourceString {
|
|
continue
|
|
}
|
|
|
|
fmt.Println(rs.String())
|
|
// rs.Primary.ID
|
|
|
|
//// Retrieve our widget by referencing it's state ID for API lookup
|
|
//request := &example.DescribeWidgets{
|
|
// IDs: []string{rs.Primary.ID},
|
|
//}
|
|
//
|
|
//response, err := conn.DescribeWidgets(request)
|
|
//if err == nil {
|
|
// if len(response.Widgets) > 0 && *response.Widgets[0].ID == rs.Primary.ID {
|
|
// return fmt.Errorf("Widget (%s) still exists.", rs.Primary.ID)
|
|
// }
|
|
//
|
|
// return nil
|
|
//}
|
|
//
|
|
//// If the error is equivalent to 404 not found, the widget is destroyed.
|
|
//// otherwise return the error
|
|
//if !strings.Contains(err.Error(), "Widget not found") {
|
|
// return err
|
|
//}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func testAccResourceExampleConfig(data resData) string {
|
|
tpl := `
|
|
resource "stackitprivatepreview_sqlserverflexbeta_instance" "{{ .TfName }}" {
|
|
project_id = "{{ .ProjectID }}"
|
|
name = "{{ .Name }}"
|
|
backup_schedule = "{{ .BackupSchedule }}"
|
|
retention_days = {{ .RetentionDays }}
|
|
flavor_id = "{{ .FlavorID }}"
|
|
storage = {
|
|
class = "{{ .PerformanceClass }}"
|
|
size = {{ .Size }}
|
|
}
|
|
network = {
|
|
acl = ["{{ .Acl }}"]
|
|
access_scope = "{{ .AccessScope }}"
|
|
}
|
|
{{ if .WithEncryption }}
|
|
encryption = {
|
|
kek_key_id = "{{ .KekKeyId }}"
|
|
kek_key_ring_id = "{{ .KekKeyRingId }}"
|
|
kek_key_version = {{ .KekKeyVersion }}
|
|
service_account = "{{ .KekSaEmail }}"
|
|
}
|
|
{{ end }}
|
|
version = "{{ .Version }}"
|
|
}
|
|
`
|
|
tmpl, err := template.New("").Parse(tpl)
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
buff := new(bytes.Buffer)
|
|
err = tmpl.Execute(buff, data)
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
|
|
res := fmt.Sprintf(`
|
|
%[1]s
|
|
|
|
%[2]s
|
|
`,
|
|
testutil.PostgresFlexProviderConfig(data.ServiceAccountFilePath),
|
|
buff.String(),
|
|
)
|
|
|
|
return res
|
|
}
|
|
|
|
func testCheckResourceExists(resourceName string) resource.TestCheckFunc {
|
|
return func(s *terraform.State) error {
|
|
rs, ok := s.RootModule().Resources[resourceName]
|
|
if !ok {
|
|
return fmt.Errorf("resource not found: %s", resourceName)
|
|
}
|
|
|
|
if rs.Primary.ID == "" {
|
|
return fmt.Errorf("resource ID not set")
|
|
}
|
|
|
|
// Verify resource exists in the API
|
|
//client := testAccProvider.Meta().(*APIClient)
|
|
//_, err := client.GetResource(rs.Primary.ID)
|
|
//if err != nil {
|
|
// return fmt.Errorf("error fetching resource: %w", err)
|
|
//}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func testAccGrabResourceID(resourceName string, id *string) resource.TestCheckFunc {
|
|
return func(s *terraform.State) error {
|
|
rs, ok := s.RootModule().Resources[resourceName]
|
|
if !ok {
|
|
return fmt.Errorf("ressource not found: %s", resourceName)
|
|
}
|
|
if rs.Primary.ID == "" {
|
|
return fmt.Errorf("no ID in state for %s", resourceName)
|
|
}
|
|
*id = rs.Primary.ID
|
|
return nil
|
|
}
|
|
}
|
|
|
|
//func setupMockServer() *httptest.Server {
|
|
// mux := http.NewServeMux()
|
|
//
|
|
// mux.HandleFunc("/api/resources", func(w http.ResponseWriter, r *http.Request) {
|
|
// switch r.Method {
|
|
// case http.MethodPost:
|
|
// w.WriteHeader(http.StatusCreated)
|
|
// json.NewEncoder(w).Encode(map[string]string{
|
|
// "id": "mock-id-123",
|
|
// "name": "test-resource",
|
|
// })
|
|
// case http.MethodGet:
|
|
// w.WriteHeader(http.StatusOK)
|
|
// json.NewEncoder(w).Encode([]map[string]string{})
|
|
// }
|
|
// })
|
|
//
|
|
// return httptest.NewServer(mux)
|
|
//}
|
|
//
|
|
//func TestUnitResourceCreate(t *testing.T) {
|
|
// server := setupMockServer()
|
|
// defer server.Close()
|
|
//
|
|
// // Configure provider to use mock server URL
|
|
// os.Setenv("API_ENDPOINT", server.URL)
|
|
//
|
|
// // Run unit tests against mock
|
|
//}
|
|
|
|
// type postgresFlexClientMocked struct {
|
|
// returnError bool
|
|
// getFlavorsResp *postgresflex.GetFlavorsResponse
|
|
// }
|
|
//
|
|
// func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*postgresflex.GetFlavorsResponse, error) {
|
|
// if c.returnError {
|
|
// return nil, fmt.Errorf("get flavors failed")
|
|
// }
|
|
//
|
|
// return c.getFlavorsResp, nil
|
|
// }
|
|
|
|
//func TestNewInstanceResource(t *testing.T) {
|
|
// exData := resData{
|
|
// Region: "eu01",
|
|
// ServiceAccountFilePath: sa_file,
|
|
// ProjectID: project_id,
|
|
// Name: "testRes",
|
|
// }
|
|
// resource.Test(t, resource.TestCase{
|
|
// ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
|
// Steps: []resource.TestStep{
|
|
// {
|
|
// Config: testAccResourceEncryptionExampleConfig(exData),
|
|
// Check: resource.ComposeAggregateTestCheckFunc(
|
|
// resource.TestCheckResourceAttr("example_resource.test", "name", exData.Name),
|
|
// resource.TestCheckResourceAttrSet("example_resource.test", "id"),
|
|
// ),
|
|
// },
|
|
// },
|
|
// })
|
|
//
|
|
// //tests := []struct {
|
|
// // name string
|
|
// // want resource.Resource
|
|
// //}{
|
|
// // {
|
|
// // name: "create empty instance resource",
|
|
// // want: &instanceResource{},
|
|
// // },
|
|
// //}
|
|
// //for _, tt := range tests {
|
|
// // t.Run(tt.name, func(t *testing.T) {
|
|
// // if got := NewInstanceResource(); !reflect.DeepEqual(got, tt.want) {
|
|
// // t.Errorf("NewInstanceResource() = %v, want %v", got, tt.want)
|
|
// // }
|
|
// // })
|
|
// //}
|
|
//}
|