Skip to content

Commit b5fa9c4

Browse files
committed
Maintenance window resource:
- uses the plugin framework - client generating the openApi specification
1 parent f106c32 commit b5fa9c4

File tree

14 files changed

+2147
-16
lines changed

14 files changed

+2147
-16
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ website/node_modules
2626
*.test
2727
*.iml
2828
*.vscode
29+
__debug_*
2930

3031
website/vendor
3132

generated/kbapi/kibana.gen.go

Lines changed: 1020 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

generated/kbapi/transform_schema.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ func (s Schema) MustGetPath(path string) *Path {
108108
type Path struct {
109109
Parameters []Map `yaml:"parameters,omitempty"`
110110
Get Map `yaml:"get,omitempty"`
111+
Patch Map `yaml:"patch,omitempty"`
111112
Post Map `yaml:"post,omitempty"`
112113
Put Map `yaml:"put,omitempty"`
113114
Delete Map `yaml:"delete,omitempty"`
@@ -123,6 +124,9 @@ func (p Path) Endpoints(yield func(key string, endpoint Map) bool) {
123124
if p.Put != nil {
124125
yield("put", p.Put)
125126
}
127+
if p.Patch != nil {
128+
yield("patch", p.Patch)
129+
}
126130
if p.Delete != nil {
127131
yield("delete", p.Delete)
128132
}
@@ -136,6 +140,8 @@ func (p Path) GetEndpoint(method string) Map {
136140
return p.Post
137141
case "put":
138142
return p.Put
143+
case "patch":
144+
return p.Patch
139145
case "delete":
140146
return p.Delete
141147
default:
@@ -160,6 +166,8 @@ func (p *Path) SetEndpoint(method string, endpoint Map) {
160166
p.Post = endpoint
161167
case "put":
162168
p.Put = endpoint
169+
case "patch":
170+
p.Put = endpoint
163171
case "delete":
164172
p.Delete = endpoint
165173
default:
@@ -571,6 +579,8 @@ func transformFilterPaths(schema *Schema) {
571579
"/api/synthetics/params": {"post"},
572580
"/api/synthetics/params/{id}": {"get", "put", "delete"},
573581
"/api/apm/settings/agent-configuration": {"get", "put", "delete"},
582+
"/api/maintenance_window": {"post"},
583+
"/api/maintenance_window/{id}": {"delete", "get", "patch"},
574584
}
575585

576586
for path, pathInfo := range schema.Paths {
@@ -717,6 +727,8 @@ func transformKibanaPaths(schema *Schema) {
717727
"/api/data_views",
718728
"/api/data_views/data_view",
719729
"/api/data_views/data_view/{viewId}",
730+
"/api/maintenance_window",
731+
"/api/maintenance_window/{id}",
720732
}
721733

722734
// Add a spaceId parameter if not already present
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package kibana_oapi
2+
3+
import (
4+
"context"
5+
"net/http"
6+
7+
"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
8+
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
9+
"github.com/hashicorp/terraform-plugin-framework/diag"
10+
)
11+
12+
// GetMaintenanceWindow reads a maintenance window from the API by ID
13+
func GetMaintenanceWindow(ctx context.Context, client *Client, spaceID string, maintenanceWindowID string) (*kbapi.GetMaintenanceWindowIdResponse, diag.Diagnostics) {
14+
resp, err := client.API.GetMaintenanceWindowIdWithResponse(ctx, spaceID, maintenanceWindowID)
15+
16+
if err != nil {
17+
return nil, utils.FrameworkDiagFromError(err)
18+
}
19+
20+
switch resp.StatusCode() {
21+
case http.StatusOK:
22+
return resp, nil
23+
default:
24+
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
25+
}
26+
}
27+
28+
// CreateMaintenanceWindow creates a new maintenance window.
29+
func CreateMaintenanceWindow(ctx context.Context, client *Client, spaceID string, body kbapi.PostMaintenanceWindowJSONRequestBody) (*kbapi.PostMaintenanceWindowResponse, diag.Diagnostics) {
30+
resp, err := client.API.PostMaintenanceWindowWithResponse(ctx, spaceID, body)
31+
if err != nil {
32+
return nil, utils.FrameworkDiagFromError(err)
33+
}
34+
35+
switch resp.StatusCode() {
36+
case http.StatusOK:
37+
return resp, nil
38+
default:
39+
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
40+
}
41+
}
42+
43+
// UpdateMaintenanceWindow updates an existing maintenance window.
44+
func UpdateMaintenanceWindow(ctx context.Context, client *Client, spaceID string, maintenanceWindowID string, req kbapi.PatchMaintenanceWindowIdJSONRequestBody) (*kbapi.PatchMaintenanceWindowIdResponse, diag.Diagnostics) {
45+
resp, err := client.API.PatchMaintenanceWindowIdWithResponse(ctx, spaceID, maintenanceWindowID, req)
46+
if err != nil {
47+
return nil, utils.FrameworkDiagFromError(err)
48+
}
49+
50+
switch resp.StatusCode() {
51+
case http.StatusOK:
52+
return resp, nil
53+
default:
54+
return nil, reportUnknownError(resp.StatusCode(), resp.Body)
55+
}
56+
}
57+
58+
// DeleteMaintenanceWindow deletes an existing maintenance window.
59+
func DeleteMaintenanceWindow(ctx context.Context, client *Client, spaceID string, maintenanceWindowID string) diag.Diagnostics {
60+
resp, err := client.API.DeleteMaintenanceWindowIdWithResponse(ctx, spaceID, maintenanceWindowID)
61+
if err != nil {
62+
return utils.FrameworkDiagFromError(err)
63+
}
64+
65+
switch resp.StatusCode() {
66+
case http.StatusNoContent:
67+
return nil
68+
case http.StatusNotFound:
69+
return nil
70+
default:
71+
return reportUnknownError(resp.StatusCode(), resp.Body)
72+
}
73+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package maintenance_window_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
8+
"github.com/elastic/terraform-provider-elasticstack/internal/versionutils"
9+
"github.com/hashicorp/go-version"
10+
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
12+
)
13+
14+
var minDataViewAPISupport = version.Must(version.NewVersion("8.1.0"))
15+
var minFullDataviewSupport = version.Must(version.NewVersion("8.8.0"))
16+
17+
func TestAccResourceDataView(t *testing.T) {
18+
indexName := "my-index-" + sdkacctest.RandStringFromCharSet(4, sdkacctest.CharSetAlphaNum)
19+
20+
resource.Test(t, resource.TestCase{
21+
PreCheck: func() { acctest.PreCheck(t) },
22+
ProtoV6ProviderFactories: acctest.Providers,
23+
Steps: []resource.TestStep{
24+
{
25+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minDataViewAPISupport),
26+
Config: testAccResourceDataViewPre8_8DV(indexName),
27+
Check: resource.ComposeTestCheckFunc(
28+
resource.TestCheckResourceAttrSet("elasticstack_kibana_data_view.dv", "id"),
29+
),
30+
},
31+
{
32+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minFullDataviewSupport),
33+
Config: testAccResourceDataViewBasicDV(indexName),
34+
Check: resource.ComposeTestCheckFunc(
35+
resource.TestCheckResourceAttrSet("elasticstack_kibana_data_view.dv", "id"),
36+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "override", "true"),
37+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.name", indexName),
38+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.source_filters.#", "2"),
39+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.field_formats.event_time.id", "date_nanos"),
40+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.field_formats.machine.ram.params.pattern", "0,0.[000] b"),
41+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.runtime_field_map.runtime_shape_name.script_source", "emit(doc['shape_name'].value)"),
42+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.field_attrs.ingest_failure.custom_label", "error.ingest_failure"),
43+
),
44+
},
45+
{
46+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minFullDataviewSupport),
47+
Config: testAccResourceDataViewBasicDVUpdated(indexName),
48+
Check: resource.ComposeTestCheckFunc(
49+
resource.TestCheckResourceAttrSet("elasticstack_kibana_data_view.dv", "id"),
50+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "override", "false"),
51+
resource.TestCheckResourceAttr("elasticstack_kibana_data_view.dv", "data_view.name", indexName),
52+
resource.TestCheckNoResourceAttr("elasticstack_kibana_data_view.dv", "data_view.source_filters"),
53+
resource.TestCheckNoResourceAttr("elasticstack_kibana_data_view.dv", "data_view.field_formats"),
54+
resource.TestCheckNoResourceAttr("elasticstack_kibana_data_view.dv", "data_view.runtime_field_map"),
55+
),
56+
},
57+
{
58+
SkipFunc: versionutils.CheckIfVersionIsUnsupported(minFullDataviewSupport),
59+
Config: testAccResourceDataViewBasicDVUpdated(indexName),
60+
ImportState: true,
61+
ImportStateVerify: true,
62+
ResourceName: "elasticstack_kibana_data_view.dv",
63+
},
64+
},
65+
})
66+
}
67+
68+
func testAccResourceDataViewPre8_8DV(indexName string) string {
69+
return fmt.Sprintf(`
70+
provider "elasticstack" {
71+
elasticsearch {}
72+
kibana {}
73+
}
74+
75+
resource "elasticstack_elasticsearch_index" "my_index" {
76+
name = "%s"
77+
deletion_protection = false
78+
}
79+
80+
resource "elasticstack_kibana_data_view" "dv" {
81+
data_view = {
82+
title = "%s*"
83+
}
84+
}`, indexName, indexName)
85+
}
86+
87+
func testAccResourceDataViewBasicDV(indexName string) string {
88+
return fmt.Sprintf(`
89+
provider "elasticstack" {
90+
elasticsearch {}
91+
kibana {}
92+
}
93+
94+
resource "elasticstack_elasticsearch_index" "my_index" {
95+
name = "%s"
96+
deletion_protection = false
97+
}
98+
99+
resource "elasticstack_kibana_data_view" "dv" {
100+
override = true
101+
data_view = {
102+
title = "%s*"
103+
name = "%s"
104+
time_field_name = "@timestamp"
105+
source_filters = ["event_time", "machine.ram"]
106+
allow_no_index = true
107+
namespaces = ["default", "foo", "bar"]
108+
field_formats = {
109+
event_time = {
110+
id = "date_nanos"
111+
}
112+
"machine.ram" = {
113+
id = "number"
114+
params = {
115+
pattern = "0,0.[000] b"
116+
}
117+
}
118+
}
119+
runtime_field_map = {
120+
runtime_shape_name = {
121+
type = "keyword"
122+
script_source = "emit(doc['shape_name'].value)"
123+
}
124+
}
125+
field_attrs = {
126+
ingest_failure = { custom_label = "error.ingest_failure", count = 6 },
127+
}
128+
}
129+
}`, indexName, indexName, indexName)
130+
}
131+
132+
func testAccResourceDataViewBasicDVUpdated(indexName string) string {
133+
return fmt.Sprintf(`
134+
provider "elasticstack" {
135+
elasticsearch {}
136+
kibana {}
137+
}
138+
139+
resource "elasticstack_elasticsearch_index" "my_index" {
140+
name = "%s"
141+
deletion_protection = false
142+
}
143+
144+
resource "elasticstack_kibana_data_view" "dv" {
145+
override = false
146+
data_view = {
147+
title = "%s*"
148+
name = "%s"
149+
time_field_name = "@timestamp"
150+
allow_no_index = true
151+
}
152+
}`, indexName, indexName, indexName)
153+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package maintenance_window
2+
3+
import (
4+
"context"
5+
6+
"github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana_oapi"
7+
"github.com/hashicorp/terraform-plugin-framework/resource"
8+
)
9+
10+
func (r *MaintenanceWindowResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
11+
// Retrieve values from plan
12+
var planMaintenanceWindow MaintenanceWindowModel
13+
14+
diags := req.Plan.Get(ctx, &planMaintenanceWindow)
15+
resp.Diagnostics.Append(diags...)
16+
if resp.Diagnostics.HasError() {
17+
return
18+
}
19+
20+
// Generate API request body from plan
21+
body, diags := planMaintenanceWindow.toAPICreateRequest(ctx)
22+
23+
resp.Diagnostics.Append(diags...)
24+
if resp.Diagnostics.HasError() {
25+
return
26+
}
27+
28+
client, err := r.client.GetKibanaOapiClient()
29+
if err != nil {
30+
resp.Diagnostics.AddError(err.Error(), "")
31+
return
32+
}
33+
34+
spaceID := planMaintenanceWindow.SpaceID.ValueString()
35+
maintenanceWindowAPIResponse, diags := kibana_oapi.CreateMaintenanceWindow(ctx, client, spaceID, body)
36+
37+
resp.Diagnostics.Append(diags...)
38+
if resp.Diagnostics.HasError() {
39+
return
40+
}
41+
42+
diags = planMaintenanceWindow.fromAPICreateResponse(ctx, maintenanceWindowAPIResponse)
43+
resp.Diagnostics.Append(diags...)
44+
if resp.Diagnostics.HasError() {
45+
return
46+
}
47+
48+
diags = resp.State.Set(ctx, planMaintenanceWindow)
49+
resp.Diagnostics.Append(diags...)
50+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package maintenance_window
2+
3+
import (
4+
"context"
5+
6+
"github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana_oapi"
7+
"github.com/hashicorp/terraform-plugin-framework/resource"
8+
)
9+
10+
func (r *MaintenanceWindowResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
11+
var stateModel MaintenanceWindowModel
12+
13+
diags := req.State.Get(ctx, &stateModel)
14+
resp.Diagnostics.Append(diags...)
15+
if resp.Diagnostics.HasError() {
16+
return
17+
}
18+
19+
client, err := r.client.GetKibanaOapiClient()
20+
if err != nil {
21+
resp.Diagnostics.AddError(err.Error(), "")
22+
return
23+
}
24+
25+
viewID, spaceID := stateModel.getMaintenanceWindowIDAndSpaceID()
26+
diags = kibana_oapi.DeleteMaintenanceWindow(ctx, client, spaceID, viewID)
27+
resp.Diagnostics.Append(diags...)
28+
}

0 commit comments

Comments
 (0)