diff --git a/internal/services/baremetal/helpers.go b/internal/services/baremetal/helpers.go index 3bd5db38c1..2588dceb95 100644 --- a/internal/services/baremetal/helpers.go +++ b/internal/services/baremetal/helpers.go @@ -5,6 +5,8 @@ import ( "context" "errors" "fmt" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/logging" "sort" "time" @@ -224,3 +226,46 @@ func privateNetworkSetHash(v interface{}) int { return schema.HashString(buf.String()) } + +func customDiffOffer() func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error { + return func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error { + logging.L.Debugf("customDiffOffer() function") + + if diff.Get("offer") == "" || !diff.HasChange("offer") || diff.Id() == "" { + return nil + } + api, zone, err := NewAPIWithZoneAndID(i, diff.Id()) + logging.L.Debugf("value of api is %v and zone is %v", api, zone) + if err != nil { + return err + } + + oldOffer, newOffer := diff.GetChange("offer") + newOfferID := regional.ExpandID(newOffer.(string)) + oldOfferID := regional.ExpandID(oldOffer.(string)) + oldOfferDetails, err := FindOfferByID(ctx, api, zone.Zone, oldOfferID.ID) + if err != nil { + return errors.New("can not find the offer by id" + err.Error()) + } + + newOfferDetails, err := FindOfferByID(ctx, api, zone.Zone, newOfferID.ID) + if err != nil { + return errors.New("can not find the offer by id" + err.Error()) + } + if oldOfferDetails.Name != newOfferDetails.Name { + return diff.ForceNew("offer") + } + if oldOfferDetails.SubscriptionPeriod == baremetal.OfferSubscriptionPeriodMonthly && newOfferDetails.SubscriptionPeriod == baremetal.OfferSubscriptionPeriodHourly { + return errors.New("invalid plan transition: you cannot transition from a monthly plan to an hourly plan. Only the reverse (hourly to monthly) is supported. Please update your configuration accordingly") + } + ServerID := regional.ExpandID(diff.Id()) + _, err = api.MigrateServerToMonthlyOffer(&baremetal.MigrateServerToMonthlyOfferRequest{ + Zone: zone.Zone, + ServerID: ServerID.ID, + }, scw.WithContext(ctx)) + if err != nil { + return errors.New("migration to monthly plan failed: " + err.Error()) + } + return nil + } +} diff --git a/internal/services/baremetal/offer_data_source_test.go b/internal/services/baremetal/offer_data_source_test.go index 9c5ec6ff6c..4a6f9608da 100644 --- a/internal/services/baremetal/offer_data_source_test.go +++ b/internal/services/baremetal/offer_data_source_test.go @@ -131,9 +131,9 @@ func TestAccDataSourceOffer_SubscriptionPeriodMonthly(t *testing.T) { tt := acctest.NewTestTools(t) defer tt.Cleanup() - if !IsOfferAvailable(OfferID, Zone, tt) { - t.Skip("Offer is out of stock") - } + //if !IsOfferAvailable(OfferID, Zone, tt) { + // t.Skip("Offer is out of stock") + //} resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(t) }, diff --git a/internal/services/baremetal/server.go b/internal/services/baremetal/server.go index cd59797fad..1ba822579e 100644 --- a/internal/services/baremetal/server.go +++ b/internal/services/baremetal/server.go @@ -54,20 +54,10 @@ func ResourceServer() *schema.Resource { Description: "Hostname of the server", }, "offer": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: "ID or name of the server offer", - DiffSuppressFunc: func(_, oldValue, newValue string, d *schema.ResourceData) bool { - // remove the locality from the IDs when checking diff - if locality.ExpandID(newValue) == locality.ExpandID(oldValue) { - return true - } - // if the offer was provided by name - offerName, ok := d.GetOk("offer_name") - - return ok && newValue == offerName - }, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "ID or name of the server offer", ValidateDiagFunc: verify.IsUUIDOrNameOffer(), }, "offer_id": { @@ -267,6 +257,7 @@ If this behaviour is wanted, please set 'reinstall_on_ssh_key_changes' argument CustomizeDiff: customdiff.Sequence( cdf.LocalityCheck("private_network.#.id"), + customDiffOffer(), customDiffPrivateNetworkOption(), ), } diff --git a/internal/services/baremetal/server_test.go b/internal/services/baremetal/server_test.go index 56e4fec4e4..bbb4d562e9 100644 --- a/internal/services/baremetal/server_test.go +++ b/internal/services/baremetal/server_test.go @@ -1039,6 +1039,103 @@ func TestAccServer_WithIPAMPrivateNetwork(t *testing.T) { }) } +func TestAccServer_UpdateSubscriptionPeriod(t *testing.T) { + tt := acctest.NewTestTools(t) + defer tt.Cleanup() + + //if !IsOfferAvailable(OfferID, "fr-par-2", tt) { + // t.Skip("Offer is out of stock") + //} + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProviderFactories: tt.ProviderFactories, + CheckDestroy: resource.ComposeTestCheckFunc( + baremetalchecks.CheckServerDestroy(tt), + ), + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` + + data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-B112X-SSD" + subscription_period = "hourly" + + } + + resource "scaleway_baremetal_server" "server01" { + name = "TestAccServer_UpdateSubscriptionPeriod" + offer = data.scaleway_baremetal_offer.my_offer.offer_id + zone = "fr-par-2" + install_config_afterward = true + + }`, + ), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("scaleway_baremetal_server.server01", "subscription_period", "hourly"), + resource.TestCheckResourceAttr("scaleway_baremetal_server.server01", "zone", "fr-par-2"), + ), + }, + { + Config: fmt.Sprintf(` + data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-B112X-SSD" + subscription_period = "hourly" + + } + + data "scaleway_baremetal_offer" "my_offer_monthly" { + zone = "fr-par-2" + name = "EM-B112X-SSD" + subscription_period = "monthly" + + } + + resource "scaleway_baremetal_server" "server01" { + name = "TestAccServer_UpdateSubscriptionPeriod" + offer = data.scaleway_baremetal_offer.my_offer_monthly.offer_id + zone = "fr-par-2" + install_config_afterward = true + + }`, + ), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("scaleway_baremetal_server.server01", "subscription_period", "monthly"), + resource.TestCheckResourceAttr("scaleway_baremetal_server.server01", "zone", "fr-par-2"), + ), + }, + { + Config: fmt.Sprintf(` + data "scaleway_baremetal_offer" "my_offer" { + zone = "fr-par-2" + name = "EM-B112X-SSD" + subscription_period = "hourly" + + } + data "scaleway_baremetal_offer" "my_offer_monthly" { + zone = "fr-par-2" + name = "EM-B112X-SSD" + subscription_period = "monthly" + + } + + resource "scaleway_baremetal_server" "server01" { + name = "Test_UpdateSubscriptionPeriod" + offer = data.scaleway_baremetal_offer.my_offer.offer_id + zone = "fr-par-2" + install_config_afterward = true + + }`, + ), + ExpectError: regexp.MustCompile("invalid plan transition: you cannot transition from a monthly plan to an hourly plan. Only the reverse (hourly to monthly) is supported. Please update your configuration accordingly"), + }, + }, + }) + +} + func testAccCheckBaremetalServerExists(tt *acctest.TestTools, n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] diff --git a/internal/services/baremetal/testdata/server-update-subscription-period.cassette.yaml b/internal/services/baremetal/testdata/server-update-subscription-period.cassette.yaml new file mode 100644 index 0000000000..2797c38e00 --- /dev/null +++ b/internal/services/baremetal/testdata/server-update-subscription-period.cassette.yaml @@ -0,0 +1,3 @@ +--- +version: 2 +interactions: []