Skip to content

Commit c5fdeef

Browse files
committed
feat: add support for action reboot
1 parent f4a52e4 commit c5fdeef

File tree

11 files changed

+2032
-9
lines changed

11 files changed

+2032
-9
lines changed

.github/workflows/documentation.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ jobs:
5959
- uses: actions/setup-go@v6
6060
with:
6161
go-version: stable
62-
- uses: hashicorp/setup-terraform@v3
62+
- name: Install Terraform
63+
uses: hashicorp/setup-terraform@v3
6364
- run: go tool tfplugindocs validate
6465
- run: rm -fr ./docs
6566
- run: go tool tfplugindocs generate
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
subcategory: "Instances"
3+
page_title: "Scaleway: scaleway_instance_server_action"
4+
---
5+
6+
# scaleway_instance_server_action (Action)
7+
8+
<!-- action schema generated by tfplugindocs -->
9+
## Schema
10+
11+
### Required
12+
13+
- `action` (String) Type of action to perform
14+
- `server_id` (String) Server id to send the action to
15+
16+
### Optional
17+
18+
- `wait` (Boolean) Wait for server to finish action
19+
- `zone` (String) Zone of server to send the action to
20+
21+

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ require (
2222
github.com/hashicorp/go-multierror v1.1.1
2323
github.com/hashicorp/go-retryablehttp v0.7.8
2424
github.com/hashicorp/terraform-plugin-framework v1.16.0
25+
github.com/hashicorp/terraform-plugin-framework-validators v0.18.1-0.20250909114857-8e55d8ccabdb
2526
github.com/hashicorp/terraform-plugin-go v0.29.0
2627
github.com/hashicorp/terraform-plugin-log v0.9.0
2728
github.com/hashicorp/terraform-plugin-mux v0.21.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@ github.com/hashicorp/terraform-plugin-docs v0.24.0 h1:YNZYd+8cpYclQyXbl1EEngbld8
328328
github.com/hashicorp/terraform-plugin-docs v0.24.0/go.mod h1:YLg+7LEwVmRuJc0EuCw0SPLxuQXw5mW8iJ5ml/kvi+o=
329329
github.com/hashicorp/terraform-plugin-framework v1.16.0 h1:tP0f+yJg0Z672e7levixDe5EpWwrTrNryPM9kDMYIpE=
330330
github.com/hashicorp/terraform-plugin-framework v1.16.0/go.mod h1:0xFOxLy5lRzDTayc4dzK/FakIgBhNf/lC4499R9cV4Y=
331+
github.com/hashicorp/terraform-plugin-framework-validators v0.18.1-0.20250909114857-8e55d8ccabdb h1:wRiOv+xaGRrBuc8r774OtrELwQCiSLLQNrkH00ZLO90=
332+
github.com/hashicorp/terraform-plugin-framework-validators v0.18.1-0.20250909114857-8e55d8ccabdb/go.mod h1:vU2y54LtDNHGLjDD7LH/if+4KBKZ5ljTrgDdrM6y8Pc=
331333
github.com/hashicorp/terraform-plugin-go v0.29.0 h1:1nXKl/nSpaYIUBU1IG/EsDOX0vv+9JxAltQyDMpq5mU=
332334
github.com/hashicorp/terraform-plugin-go v0.29.0/go.mod h1:vYZbIyvxyy0FWSmDHChCqKvI40cFTDGSb3D8D70i9GM=
333335
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package instance
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
8+
"github.com/hashicorp/terraform-plugin-framework/action"
9+
"github.com/hashicorp/terraform-plugin-framework/action/schema"
10+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
11+
"github.com/hashicorp/terraform-plugin-framework/types"
12+
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
13+
"github.com/scaleway/scaleway-sdk-go/scw"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
15+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/meta"
16+
)
17+
18+
var (
19+
_ action.Action = (*ServerAction)(nil)
20+
_ action.ActionWithConfigure = (*ServerAction)(nil)
21+
)
22+
23+
type ServerAction struct {
24+
instanceAPI *instance.API
25+
}
26+
27+
func (a *ServerAction) Configure(ctx context.Context, req action.ConfigureRequest, resp *action.ConfigureResponse) {
28+
if req.ProviderData == nil {
29+
return
30+
}
31+
32+
m, ok := req.ProviderData.(*meta.Meta)
33+
if !ok {
34+
resp.Diagnostics.AddError(
35+
"Unexpected Action Configure Type",
36+
fmt.Sprintf("Expected *scw.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
37+
)
38+
39+
return
40+
}
41+
42+
client := m.ScwClient()
43+
a.instanceAPI = instance.NewAPI(client)
44+
}
45+
46+
func (a *ServerAction) Metadata(ctx context.Context, req action.MetadataRequest, resp *action.MetadataResponse) {
47+
resp.TypeName = req.ProviderTypeName + "_instance_server_action"
48+
}
49+
50+
type ServerActionModel struct {
51+
ServerID types.String `tfsdk:"server_id"`
52+
Zone types.String `tfsdk:"zone"`
53+
Action types.String `tfsdk:"action"`
54+
Wait types.Bool `tfsdk:"wait"`
55+
}
56+
57+
func NewServerAction() action.Action {
58+
return &ServerAction{}
59+
}
60+
61+
func (a *ServerAction) Schema(ctx context.Context, req action.SchemaRequest, resp *action.SchemaResponse) {
62+
actionsValues := instance.ServerAction("").Values()
63+
64+
actionStringValues := make([]string, 0, len(actionsValues))
65+
for _, actionValue := range actionsValues {
66+
actionStringValues = append(actionStringValues, actionValue.String())
67+
}
68+
69+
resp.Schema = schema.Schema{
70+
Attributes: map[string]schema.Attribute{
71+
"action": schema.StringAttribute{
72+
Required: true,
73+
Description: "Type of action to perform",
74+
Validators: []validator.String{
75+
stringvalidator.OneOfCaseInsensitive(actionStringValues...),
76+
},
77+
},
78+
"server_id": schema.StringAttribute{
79+
Required: true,
80+
Description: "Server id to send the action to",
81+
},
82+
"zone": schema.StringAttribute{
83+
Optional: true,
84+
Description: "Zone of server to send the action to",
85+
},
86+
"wait": schema.BoolAttribute{
87+
Optional: true,
88+
Description: "Wait for server to finish action",
89+
},
90+
},
91+
}
92+
}
93+
94+
func (a *ServerAction) Invoke(ctx context.Context, req action.InvokeRequest, resp *action.InvokeResponse) {
95+
var data ServerActionModel
96+
// Read action config data into the model
97+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
98+
99+
if resp.Diagnostics.HasError() {
100+
return
101+
}
102+
103+
if a.instanceAPI == nil {
104+
resp.Diagnostics.AddError(
105+
"Unconfigured instanceAPI",
106+
"The action was not properly configured. The Scaleway client is missing. "+
107+
"This is usually a bug in the provider. Please report it to the maintainers.",
108+
)
109+
110+
return
111+
}
112+
113+
actionReq := &instance.ServerActionRequest{
114+
ServerID: locality.ExpandID(data.ServerID.ValueString()),
115+
Action: instance.ServerAction(data.Action.ValueString()),
116+
}
117+
if !data.Zone.IsNull() {
118+
actionReq.Zone = scw.Zone(data.Zone.String())
119+
}
120+
121+
_, err := a.instanceAPI.ServerAction(actionReq)
122+
if err != nil {
123+
resp.Diagnostics.AddError(
124+
"error in server action",
125+
fmt.Sprintf("%s", err))
126+
}
127+
128+
if data.Wait.ValueBool() {
129+
waitReq := &instance.WaitForServerRequest{
130+
ServerID: locality.ExpandID(data.ServerID.ValueString()),
131+
Zone: scw.Zone(data.Zone.String()),
132+
}
133+
134+
if !data.Zone.IsNull() {
135+
waitReq.Zone = scw.Zone(data.Zone.String())
136+
}
137+
138+
_, errWait := a.instanceAPI.WaitForServer(waitReq)
139+
if errWait != nil {
140+
resp.Diagnostics.AddError(
141+
"error in wait server",
142+
fmt.Sprintf("%s", err))
143+
}
144+
}
145+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package instance_test
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strconv"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-testing/terraform"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
12+
)
13+
14+
func TestAccActionServer_Basic(t *testing.T) {
15+
tt := acctest.NewTestTools(t)
16+
defer tt.Cleanup()
17+
18+
resource.ParallelTest(t, resource.TestCase{
19+
ProtoV6ProviderFactories: tt.ProviderFactories,
20+
Steps: []resource.TestStep{
21+
{
22+
Config: `
23+
resource "scaleway_instance_server" "main" {
24+
name = "test-terraform-datasource-private-nic"
25+
type = "DEV1-S"
26+
image = "ubuntu_jammy"
27+
28+
lifecycle {
29+
action_trigger {
30+
events = [after_create]
31+
actions = [action.scaleway_instance_server_action.main]
32+
}
33+
}
34+
}
35+
36+
action "scaleway_instance_server_action" "main" {
37+
config {
38+
action = "reboot"
39+
server_id = scaleway_instance_server.main.id
40+
}
41+
}`,
42+
},
43+
{
44+
Config: `
45+
resource "scaleway_instance_server" "main" {
46+
name = "test-terraform-datasource-private-nic"
47+
type = "DEV1-S"
48+
image = "ubuntu_jammy"
49+
50+
lifecycle {
51+
action_trigger {
52+
events = [after_create]
53+
actions = [action.scaleway_instance_server_action.main]
54+
}
55+
}
56+
}
57+
58+
action "scaleway_instance_server_action" "main" {
59+
config {
60+
action = "reboot"
61+
server_id = scaleway_instance_server.main.id
62+
}
63+
}
64+
65+
data "scaleway_audit_trail_event" "instance" {
66+
resource_type = "instance_server"
67+
resource_id = scaleway_instance_server.main.id
68+
method_name = "ServerAction"
69+
}`,
70+
Check: resource.ComposeTestCheckFunc(
71+
resource.TestCheckResourceAttrSet("data.scaleway_audit_trail_event.instance", "events.#"),
72+
func(state *terraform.State) error {
73+
rs, ok := state.RootModule().Resources["data.scaleway_audit_trail_event.instance"]
74+
if !ok {
75+
return fmt.Errorf("not found: data.scaleway_audit_trail_event.instance")
76+
}
77+
countStr := rs.Primary.Attributes["events.#"]
78+
count, err := strconv.Atoi(countStr)
79+
if err != nil {
80+
return fmt.Errorf("could not parse events.# as integer: %v", err)
81+
}
82+
if count < 1 {
83+
return fmt.Errorf("expected events count > 1, got %d", count)
84+
}
85+
86+
return nil
87+
},
88+
),
89+
},
90+
},
91+
})
92+
}
93+
94+
func TestAccActionServer_UnknownVerb(t *testing.T) {
95+
tt := acctest.NewTestTools(t)
96+
defer tt.Cleanup()
97+
98+
resource.ParallelTest(t, resource.TestCase{
99+
ProtoV6ProviderFactories: tt.ProviderFactories,
100+
Steps: []resource.TestStep{
101+
{
102+
Config: `
103+
action "scaleway_instance_server_action" "main" {
104+
config {
105+
action = "unknownVerb"
106+
server_id = "11111111-1111-1111-1111-111111111111"
107+
}
108+
}
109+
`,
110+
ExpectError: regexp.MustCompile("Invalid Attribute Value Match"),
111+
},
112+
},
113+
})
114+
}

internal/services/instance/testdata/action-server-basic.cassette.yaml

Lines changed: 1661 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
version: 2
3+
interactions: []

0 commit comments

Comments
 (0)