Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apple-silicon): add support vpc #2875

Merged
merged 26 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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 docs/resources/apple_silicon.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The following arguments are supported:

- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the server is
associated with.
- `enable_vpc` - (Optional, Default: false): Enables the VPC option when set to true.

## Attributes Reference

Expand All @@ -50,6 +51,7 @@ In addition to all arguments above, the following attributes are exported:
- `updated_at` - The date and time of the last update of the Apple Silicon server.
- `deleted_at` - The minimal date and time on which you can delete this server due to Apple licence.
- `organization_id` - The organization ID the server is associated with.
- `vpc_status` - The current status of the VPC option.

## Import

Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/nats-io/jwt/v2 v2.7.3
github.com/nats-io/nats.go v1.38.0
github.com/robfig/cron/v3 v3.0.1
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20250117133139-e360c98f921d
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32.0.20250206152403-1eed2f2ce9d3
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.32.0
gopkg.in/dnaeon/go-vcr.v3 v3.2.0
Expand Down Expand Up @@ -125,9 +125,9 @@ require (
go.opentelemetry.io/otel/trace v1.31.0 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/appengine v1.6.8 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXq
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20250117133139-e360c98f921d h1:npDtKGreHq1EA6DoHo18YG25bsvZVlo4XlNm822GZ7A=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30.0.20250117133139-e360c98f921d/go.mod h1:kzh+BSAvpoyHHdHBCDhmSWtBc1NbLMZ2lWHqnBoxFks=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32.0.20250206152403-1eed2f2ce9d3 h1:wNQbwsFYaWiqTRtAgO5uroCTsS0o8FPGdI/x4hCJqtM=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32.0.20250206152403-1eed2f2ce9d3/go.mod h1:792k1RTU+5JeMXm35/e2Wgp71qPH/DmDoZrRc+EFZDk=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
Expand Down Expand Up @@ -370,8 +370,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -401,8 +401,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
11 changes: 11 additions & 0 deletions internal/services/applesilicon/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,14 @@ func NewAPIWithZoneAndID(m interface{}, id string) (*applesilicon.API, scw.Zone,

return asAPI, zone, ID, nil
}

func newPrivateNetworkAPIWithZone(d *schema.ResourceData, m interface{}) (*applesilicon.PrivateNetworkAPI, scw.Zone, error) {
privateNetworkAPI := applesilicon.NewPrivateNetworkAPI(meta.ExtractScwClient(m))

zone, err := meta.ExtractZone(d, m)
if err != nil {
return nil, "", err
}

return privateNetworkAPI, zone, nil
}
43 changes: 43 additions & 0 deletions internal/services/applesilicon/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package applesilicon

import (
"context"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
applesilicon "github.com/scaleway/scaleway-sdk-go/api/applesilicon/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
)

func detachAllPrivateNetworkFromServer(ctx context.Context, d *schema.ResourceData, m interface{}, serverID string) error {
privateNetworkAPI, zone, err := newPrivateNetworkAPIWithZone(d, m)
if err != nil {
return err
}

listPrivateNetwork, err := privateNetworkAPI.ListServerPrivateNetworks(&applesilicon.PrivateNetworkAPIListServerPrivateNetworksRequest{
Zone: zone,
ServerID: &serverID,
}, scw.WithContext(ctx))
if err != nil {
return err
}

for _, pn := range listPrivateNetwork.ServerPrivateNetworks {
err := privateNetworkAPI.DeleteServerPrivateNetwork(&applesilicon.PrivateNetworkAPIDeleteServerPrivateNetworkRequest{
Zone: zone,
ServerID: serverID,
PrivateNetworkID: pn.PrivateNetworkID,
}, scw.WithContext(ctx))
if err != nil {
return err
}
}

_, err = waitForAppleSiliconPrivateNetworkServer(ctx, privateNetworkAPI, zone, serverID, d.Timeout(schema.TimeoutDelete))
if err != nil && !httperrors.Is404(err) {
return err
}

return nil
}
141 changes: 140 additions & 1 deletion internal/services/applesilicon/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
applesilicon "github.com/scaleway/scaleway-sdk-go/api/applesilicon/v1alpha1"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
)

func ResourceServer() *schema.Resource {
Expand Down Expand Up @@ -41,6 +44,61 @@ func ResourceServer() *schema.Resource {
Required: true,
ForceNew: true,
},
"enable_vpc": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Whether or not to enable VPC access",
},
"private_network": {
Type: schema.TypeSet,
Optional: true,
Description: "The private networks to attach to the server",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Description: "The private network ID",
Required: true,
ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(),
StateFunc: func(i interface{}) string {
return locality.ExpandID(i.(string))
},
},
"ipam_ip_ids": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(),
},
Description: "List of IPAM IP IDs to attach to the server",
},
// computed
"vlan": {
Type: schema.TypeInt,
Computed: true,
Description: "The VLAN ID associated to the private network",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "The private network status",
},
"created_at": {
Type: schema.TypeString,
Computed: true,
Description: "The date and time of the creation of the private network",
},
"updated_at": {
Type: schema.TypeString,
Computed: true,
Description: "The date and time of the last update of the private network",
},
},
},
},
// Computed
"ip": {
Type: schema.TypeString,
Expand Down Expand Up @@ -72,6 +130,11 @@ func ResourceServer() *schema.Resource {
Computed: true,
Description: "The minimal date and time on which you can delete this server due to Apple licence",
},
"vpc_status": {
Type: schema.TypeString,
Computed: true,
Description: "The VPC status of the server",
},

// Common
"zone": zonal.Schema(),
Expand All @@ -91,6 +154,7 @@ func ResourceAppleSiliconServerCreate(ctx context.Context, d *schema.ResourceDat
Name: types.ExpandOrGenerateString(d.Get("name"), "m1"),
Type: d.Get("type").(string),
ProjectID: d.Get("project_id").(string),
EnableVpc: d.Get("enable_vpc").(bool),
}

res, err := asAPI.CreateServer(createReq, scw.WithContext(ctx))
Expand All @@ -105,6 +169,25 @@ func ResourceAppleSiliconServerCreate(ctx context.Context, d *schema.ResourceDat
return diag.FromErr(err)
}

if pn, ok := d.GetOk("private_network"); ok {
privateNetworkAPI := applesilicon.NewPrivateNetworkAPI(meta.ExtractScwClient(m))
req := &applesilicon.PrivateNetworkAPISetServerPrivateNetworksRequest{
Zone: zone,
ServerID: res.ID,
PerPrivateNetworkIpamIPIDs: expandPrivateNetworks(pn),
}

_, err := privateNetworkAPI.SetServerPrivateNetworks(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

_, err = waitForAppleSiliconPrivateNetworkServer(ctx, privateNetworkAPI, zone, res.ID, d.Timeout(schema.TimeoutCreate))
if err != nil {
return diag.FromErr(err)
}
}

return ResourceAppleSiliconServerRead(ctx, d, m)
}

Expand All @@ -114,6 +197,8 @@ func ResourceAppleSiliconServerRead(ctx context.Context, d *schema.ResourceData,
return diag.FromErr(err)
}

privateNetworkAPI := applesilicon.NewPrivateNetworkAPI(meta.ExtractScwClient(m))

res, err := asAPI.GetServer(&applesilicon.GetServerRequest{
Zone: zone,
ServerID: ID,
Expand All @@ -136,11 +221,26 @@ func ResourceAppleSiliconServerRead(ctx context.Context, d *schema.ResourceData,
_ = d.Set("deletable_at", res.DeletableAt.Format(time.RFC3339))
_ = d.Set("ip", res.IP.String())
_ = d.Set("vnc_url", res.VncURL)

_ = d.Set("vpc_status", res.VpcStatus)
_ = d.Set("zone", res.Zone.String())
_ = d.Set("organization_id", res.OrganizationID)
_ = d.Set("project_id", res.ProjectID)

listPrivateNetworks, err := privateNetworkAPI.ListServerPrivateNetworks(&applesilicon.PrivateNetworkAPIListServerPrivateNetworksRequest{
Zone: res.Zone,
ServerID: &res.ID,
})
if err != nil {
return diag.FromErr(err)
}

pnRegion, err := res.Zone.Region()
if err != nil {
return diag.FromErr(err)
}

_ = d.Set("private_network", flattenPrivateNetworks(pnRegion, listPrivateNetworks.ServerPrivateNetworks))

return nil
}

Expand All @@ -150,6 +250,11 @@ func ResourceAppleSiliconServerUpdate(ctx context.Context, d *schema.ResourceDat
return diag.FromErr(err)
}

appleSilisonPrivateNetworkAPI, zonePN, err := newPrivateNetworkAPIWithZone(d, m)
if err != nil {
return diag.FromErr(err)
}

req := &applesilicon.UpdateServerRequest{
Zone: zone,
ServerID: ID,
Expand All @@ -159,11 +264,40 @@ func ResourceAppleSiliconServerUpdate(ctx context.Context, d *schema.ResourceDat
req.Name = types.ExpandStringPtr(d.Get("name"))
}

if d.HasChange("enable_vpc") {
enableVpc := d.Get("enable_vpc").(bool)
req.EnableVpc = &enableVpc
}

_, err = asAPI.UpdateServer(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

err = waitForTerminalVPCState(ctx, asAPI, zone, ID, d.Timeout(schema.TimeoutCreate))
if err != nil {
return diag.FromErr(err)
}

if d.HasChange("private_network") && d.Get("enable_vpc").(bool) {
privateNetwork := d.Get("private_network")
req := &applesilicon.PrivateNetworkAPISetServerPrivateNetworksRequest{
Zone: zonePN,
ServerID: ID,
PerPrivateNetworkIpamIPIDs: expandPrivateNetworks(privateNetwork),
}

_, err := appleSilisonPrivateNetworkAPI.SetServerPrivateNetworks(req, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
}

_, err = waitForAppleSiliconPrivateNetworkServer(ctx, appleSilisonPrivateNetworkAPI, zone, ID, d.Timeout(schema.TimeoutCreate))
if err != nil {
return diag.FromErr(err)
}

return ResourceAppleSiliconServerRead(ctx, d, m)
}

Expand All @@ -173,6 +307,11 @@ func ResourceAppleSiliconServerDelete(ctx context.Context, d *schema.ResourceDat
return diag.FromErr(err)
}

err = detachAllPrivateNetworkFromServer(ctx, d, m, ID)
if err != nil {
return diag.FromErr(err)
}

err = asAPI.DeleteServer(&applesilicon.DeleteServerRequest{
Zone: zone,
ServerID: ID,
Expand Down
Loading
Loading