Skip to content
Draft
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
130 changes: 89 additions & 41 deletions .github/workflows/acceptance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,72 +44,120 @@ jobs:
with:
go-version-file: ./go.mod

- name: Install Go modules
run: go mod download

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.9.0"
terraform_wrapper: false

- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 24

- name: Install grit
run: npm install -g @getgrit/cli

- name: Bootstrap
run: ./scripts/bootstrap

- name: Build tf-migrate
run: ./scripts/build-tf-migrate.sh

######## Magic Tests ########
- name: Run Magic Acceptance Tests
id: magic_acceptance_tests
run: ./scripts/run-ci-tests magic acceptance
- name: Build provider
run: go build -o terraform-provider-cloudflare .
env:
TF_ACC: 1
TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
continue-on-error: true
GOGC: "50"

- name: Run Magic Migration Tests
id: magic_migration_tests
run: ./scripts/run-ci-tests magic migration
env:
TF_ACC: 1
TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
continue-on-error: true
######## Magic Tests ########
# - name: Run Magic Acceptance Tests
# id: magic_acceptance_tests
# timeout-minutes: 120
# run: ./scripts/run-ci-tests magic acceptance
# env:
# TF_ACC: 1
# TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
# TF_LOG: DEBUG
# TF_LOG_PATH_MASK: ${{ github.workspace }}/test-logs/terraform-%s.log
# DEBUG_LOGS: "true"
# TEST_TIMEOUT: "30m"
# SWEEP_TIMEOUT: "10m"
# PARALLEL_JOBS: "3"
# GOGC: "50"
# continue-on-error: true

# - name: Run Magic Migration Tests
# id: magic_migration_tests
# timeout-minutes: 120
# run: ./scripts/run-ci-tests magic migration
# env:
# TF_ACC: 1
# TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
# TF_LOG: DEBUG
# TF_LOG_PATH_MASK: ${{ github.workspace }}/test-logs/terraform-%s.log
# DEBUG_LOGS: "true"
# TEST_TIMEOUT: "30m"
# SWEEP_TIMEOUT: "10m"
# PARALLEL_JOBS: "3"
# GOGC: "50"
# continue-on-error: true

######## Organization Tests ########
# These tests require a specific user with organization permissions
- name: Run Organization Acceptance Tests
id: organization_acceptance_tests
run: ./scripts/run-ci-tests organization acceptance
env:
TF_ACC: 1
# - name: Run Organization Acceptance Tests
# id: organization_acceptance_tests
# timeout-minutes: 120
# run: ./scripts/run-ci-tests organization acceptance
# env:
# TF_ACC: 1
# Override credentials for organization tests
CLOUDFLARE_EMAIL: orgs-terraform-user@cfapi.net
CLOUDFLARE_API_KEY: ${{ secrets.CLOUDFLARE_ORG_API_KEY }}
CLOUDFLARE_ORGANIZATION_ID: 48684ccf40084424e26b7c0ab79e09dc
continue-on-error: true
# CLOUDFLARE_EMAIL: orgs-terraform-user@cfapi.net
# CLOUDFLARE_API_KEY: ${{ secrets.CLOUDFLARE_ORG_API_KEY }}
# CLOUDFLARE_ORGANIZATION_ID: 48684ccf40084424e26b7c0ab79e09dc
# TF_LOG: DEBUG
# TF_LOG_PATH_MASK: ${{ github.workspace }}/test-logs/terraform-%s.log
# DEBUG_LOGS: "true"
# TEST_TIMEOUT: "30m"
# SWEEP_TIMEOUT: "10m"
# PARALLEL_JOBS: "3"
# GOGC: "50"
# continue-on-error: true

######## Everything Else ########
- name: Run Default Acceptance Tests
id: default_acceptance_tests
run: ./scripts/run-ci-tests default acceptance
env:
TF_ACC: 1
TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
continue-on-error: true
# - name: Run Default Acceptance Tests
# id: default_acceptance_tests
# timeout-minutes: 120
# run: ./scripts/run-ci-tests default acceptance
# env:
# TF_ACC: 1
# TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
# TF_LOG: DEBUG
# TF_LOG_PATH_MASK: ${{ github.workspace }}/test-logs/terraform-%s.log
# DEBUG_LOGS: "true"
# TEST_TIMEOUT: "30m"
# SWEEP_TIMEOUT: "10m"
# PARALLEL_JOBS: "3"
# GOGC: "50"
# continue-on-error: true

- name: Run Default Migration Tests
id: default_migration_tests
timeout-minutes: 120
run: ./scripts/run-ci-tests default migration
env:
TF_ACC: 1
TF_MIGRATE_BINARY_PATH: ${{ github.workspace }}/tf-migrate
TEST_TIMEOUT: "30m"
SWEEP_TIMEOUT: "10m"
PARALLEL_JOBS: "3"
GOGC: "50"
continue-on-error: true

- name: Check Test Status
if: ${{
steps.magic_acceptance_tests.outcome == 'failure' ||
steps.magic_migration_tests.outcome == 'failure' ||
steps.default_acceptance_tests.outcome == 'failure' ||
steps.default_migration_tests.outcome == 'failure' ||
steps.organization_acceptance_tests.outcome == 'failure'}}
run: exit 1
# - name: Check Test Status
# if: ${{
# steps.magic_acceptance_tests.outcome == 'failure' ||
# steps.magic_migration_tests.outcome == 'failure' ||
# steps.default_acceptance_tests.outcome == 'failure' ||
# steps.default_migration_tests.outcome == 'failure' ||
# steps.organization_acceptance_tests.outcome == 'failure'}}
# run: exit 1
181 changes: 181 additions & 0 deletions internal/services/account_member/migrations_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package account_member_test

import (
"fmt"
"os"
"testing"

"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/tfjsonpath"

"github.com/cloudflare/terraform-provider-cloudflare/internal/acctest"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/cloudflare/terraform-provider-cloudflare/internal/utils"
)

func TestMain(m *testing.M) {
// Write IMMEDIATELY to confirm binary execution - before any other calls
os.Stderr.WriteString("\n===========================================\n")
os.Stderr.WriteString("=== TestMain: ENTRY POINT ===\n")
os.Stderr.WriteString("=== Test binary started successfully ===\n")
os.Stderr.WriteString("===========================================\n")

fmt.Println("TestMain: About to call resource.TestMain")
fmt.Println("TestMain: This call may hang if provider setup blocks")

// This call is suspected to hang
resource.TestMain(m)

// If we see this, resource.TestMain completed
os.Stderr.WriteString("=== TestMain: resource.TestMain returned successfully ===\n")
fmt.Println("TestMain: Completed")
}

// TestMigrateAccountMember_Basic tests basic migration from v4 to v5
// This test verifies that:
// - email_address is renamed to email
// - role_ids is renamed to roles
func TestMigrateAccountMember_Basic(t *testing.T) {
t.Logf("=== TEST START: TestMigrateAccountMember_Basic ===")
t.Logf("=== This log confirms test code is running and producing output ===")

accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")
rnd := utils.GenerateRandomResourceName()
email := fmt.Sprintf("%s@example.com", rnd)
resourceName := "cloudflare_account_member." + rnd
tmpDir := t.TempDir()

t.Logf("=== Test setup complete. About to call resource.Test() which will download v4 provider ===")
t.Logf("=== Resource name: %s, TempDir: %s ===", resourceName, tmpDir)

// V4 config using old attribute names
v4Config := fmt.Sprintf(`
resource "cloudflare_account_member" "%[1]s" {
account_id = "%[2]s"
email_address = "%[3]s"
role_ids = ["05784afa30c1afe1440e79d9351c7430"]
}`, rnd, accountID, email)

resource.Test(t, resource.TestCase{
PreCheck: func() {
t.Logf("=== PreCheck: Running pre-flight checks ===")
acctest.TestAccPreCheck(t)
acctest.TestAccPreCheck_AccountID(t)
t.Logf("=== PreCheck: Checks passed. Provider download will happen next ===")
},
WorkingDir: tmpDir,
Steps: []resource.TestStep{
{
// Step 1: Create with v4 provider (this will download v4.52.1 if not cached)
ExternalProviders: map[string]resource.ExternalProvider{
"cloudflare": {
Source: "cloudflare/cloudflare",
VersionConstraint: "4.52.1",
},
},
Config: v4Config,
},
// Step 2: Run migration and verify state
acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(consts.AccountIDSchemaKey), knownvalue.StringExact(accountID)),
// Verify email_address was renamed to email
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("email"), knownvalue.StringExact(email)),
// Verify role_ids was renamed to roles
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("roles"), knownvalue.SetExact([]knownvalue.Check{
knownvalue.StringExact("05784afa30c1afe1440e79d9351c7430"),
})),
}),
},
})
}

// TestMigrateAccountMember_MultipleRoles tests migration with multiple roles
func TestMigrateAccountMember_MultipleRoles(t *testing.T) {
accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")
rnd := utils.GenerateRandomResourceName()
email := fmt.Sprintf("%s@example.com", rnd)
resourceName := "cloudflare_account_member." + rnd
tmpDir := t.TempDir()

// V4 config with multiple role_ids
v4Config := fmt.Sprintf(`
resource "cloudflare_account_member" "%[1]s" {
account_id = "%[2]s"
email_address = "%[3]s"
role_ids = [
"05784afa30c1afe1440e79d9351c7430",
"3536bcfad5faccb999b47003c79917fb"
]
}`, rnd, accountID, email)

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.TestAccPreCheck(t)
acctest.TestAccPreCheck_AccountID(t)
},
WorkingDir: tmpDir,
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"cloudflare": {
Source: "cloudflare/cloudflare",
VersionConstraint: "4.52.1",
},
},
Config: v4Config,
},
acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(consts.AccountIDSchemaKey), knownvalue.StringExact(accountID)),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("email"), knownvalue.StringExact(email)),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("roles"), knownvalue.SetSizeExact(2)),
}),
},
})
}

// TestMigrateAccountMember_WithStatus tests migration with explicit status
func TestMigrateAccountMember_WithStatus(t *testing.T) {
accountID := os.Getenv("CLOUDFLARE_ACCOUNT_ID")
rnd := utils.GenerateRandomResourceName()
email := fmt.Sprintf("%s@example.com", rnd)
resourceName := "cloudflare_account_member." + rnd
tmpDir := t.TempDir()

// V4 config with status
v4Config := fmt.Sprintf(`
resource "cloudflare_account_member" "%[1]s" {
account_id = "%[2]s"
email_address = "%[3]s"
role_ids = ["05784afa30c1afe1440e79d9351c7430"]
status = "accepted"
}`, rnd, accountID, email)

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.TestAccPreCheck(t)
acctest.TestAccPreCheck_AccountID(t)
},
WorkingDir: tmpDir,
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"cloudflare": {
Source: "cloudflare/cloudflare",
VersionConstraint: "4.52.1",
},
},
Config: v4Config,
},
acctest.MigrationV2TestStep(t, v4Config, tmpDir, "4.52.1", "v4", "v5", []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(consts.AccountIDSchemaKey), knownvalue.StringExact(accountID)),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("email"), knownvalue.StringExact(email)),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("roles"), knownvalue.SetExact([]knownvalue.Check{
knownvalue.StringExact("05784afa30c1afe1440e79d9351c7430"),
})),
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("status"), knownvalue.StringExact("accepted")),
}),
},
})
}
Loading
Loading