Skip to content

Commit 43b5fbf

Browse files
feat(css): add datasource CSS log backup records (#4963)
1 parent ef23436 commit 43b5fbf

File tree

4 files changed

+389
-0
lines changed

4 files changed

+389
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
subcategory: "Cloud Search Service (CSS)"
3+
layout: "huaweicloud"
4+
page_title: "HuaweiCloud: huaweicloud_css_log_backup_records"
5+
description: |-
6+
Use this data source to get the list of CSS cluster log backup records.
7+
---
8+
9+
# huaweicloud_css_log_backup_records
10+
11+
Use this data source to get the list of CSS cluster log backup records.
12+
13+
## Example Usage
14+
15+
```hcl
16+
variable "cluster_id" {}
17+
18+
data "huaweicloud_css_log_backup_records" "test" {
19+
cluster_id = var.cluster_id
20+
}
21+
```
22+
23+
## Argument Reference
24+
25+
The following arguments are supported:
26+
27+
* `region` - (Optional, String) Specifies the region in which to query the resource.
28+
If omitted, the provider-level region will be used.
29+
30+
* `cluster_id` - (Required, String) Specifies the ID of the CSS cluster.
31+
32+
* `job_id` - (Optional, String) Specifies the ID of the log backup job.
33+
34+
* `type` - (Optional, String) Specifies the type of the log backup job.
35+
36+
* `status` - (Optional, String) Specifies the status of the log backup job.
37+
38+
## Attribute Reference
39+
40+
In addition to all arguments above, the following attributes are exported:
41+
42+
* `id` - The data source ID.
43+
44+
* `records` - The list of the CSS cluster log backup records.
45+
46+
The [records](#records_struct) structure is documented below.
47+
48+
<a name="records_struct"></a>
49+
The `records` block supports:
50+
51+
* `id` - The ID of the log backup job.
52+
53+
* `type` - The type of the log backup job.
54+
+ **Manual:** Manual backup.
55+
+ **Auto:** Automatic backup.
56+
57+
* `status` - The status of the log backup job.
58+
59+
* `cluster_id` - The ID of the CSS cluster.
60+
61+
* `log_path` - The storage path of backed up logs in the OBS bucket.
62+
63+
* `create_at` - The creation time.
64+
65+
* `finished_at` - The end time.
66+
If the creation has not been completed, the end time is empty.
67+
68+
* `failed_msg` - The error information.
69+
If the task did not fail, the value of this parameter is empty.

huaweicloud/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ func Provider() *schema.Provider {
547547
"huaweicloud_css_upgrade_target_images": css.DataSourceCssUpgradeTargetImages(),
548548
"huaweicloud_css_logstash_templates": css.DataSourceCssLogstashTemplates(),
549549
"huaweicloud_css_cluster_tags": css.DataSourceCssClusterTags(),
550+
"huaweicloud_css_log_backup_records": css.DataSourceCssLogBackupRecords(),
550551

551552
"huaweicloud_dataarts_architecture_ds_template_optionals": dataarts.DataSourceTemplateOptionalFields(),
552553
"huaweicloud_dataarts_studio_data_connections": dataarts.DataSourceDataConnections(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package css
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
9+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
10+
)
11+
12+
func TestAccDataSourceCssLogBackupRecords_basic(t *testing.T) {
13+
dataSource := "data.huaweicloud_css_log_backup_records.test"
14+
rName := acceptance.RandomAccResourceName()
15+
dc := acceptance.InitDataSourceCheck(dataSource)
16+
17+
resource.ParallelTest(t, resource.TestCase{
18+
PreCheck: func() {
19+
acceptance.TestAccPreCheck(t)
20+
},
21+
ProviderFactories: acceptance.TestAccProviderFactories,
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testDataSourceDataSourceCssLogBackupRecords_basic(rName),
25+
Check: resource.ComposeTestCheckFunc(
26+
dc.CheckResourceExists(),
27+
resource.TestCheckResourceAttrSet(dataSource, "records.0.id"),
28+
resource.TestCheckResourceAttrSet(dataSource, "records.0.type"),
29+
resource.TestCheckResourceAttrSet(dataSource, "records.0.status"),
30+
31+
resource.TestCheckOutput("id_filter_is_useful", "true"),
32+
resource.TestCheckOutput("type_filter_is_useful", "true"),
33+
resource.TestCheckOutput("status_filter_is_useful", "true"),
34+
),
35+
},
36+
},
37+
})
38+
}
39+
40+
func testDataSourceDataSourceCssLogBackupRecords_basic(name string) string {
41+
return fmt.Sprintf(`
42+
%s
43+
44+
data "huaweicloud_css_log_backup_records" "test" {
45+
depends_on = [huaweicloud_css_manual_log_backup.test2]
46+
47+
cluster_id = huaweicloud_css_cluster.test.id
48+
}
49+
50+
output "records" {
51+
value = data.huaweicloud_css_log_backup_records.test.records
52+
}
53+
54+
locals {
55+
records = data.huaweicloud_css_log_backup_records.test.records
56+
job_id = local.records[0].id
57+
type = local.records[0].type
58+
status = local.records[0].status
59+
}
60+
61+
data "huaweicloud_css_log_backup_records" "filter_by_id" {
62+
cluster_id = huaweicloud_css_cluster.test.id
63+
job_id = local.job_id
64+
}
65+
66+
data "huaweicloud_css_log_backup_records" "filter_by_type" {
67+
cluster_id = huaweicloud_css_cluster.test.id
68+
type = local.type
69+
}
70+
71+
data "huaweicloud_css_log_backup_records" "filter_by_status" {
72+
cluster_id = huaweicloud_css_cluster.test.id
73+
status = local.status
74+
}
75+
76+
locals {
77+
list_by_id = data.huaweicloud_css_log_backup_records.filter_by_id.records
78+
list_by_type = data.huaweicloud_css_log_backup_records.filter_by_type.records
79+
list_by_status = data.huaweicloud_css_log_backup_records.filter_by_status.records
80+
}
81+
82+
output "id_filter_is_useful" {
83+
value = length(local.list_by_id) > 0 && alltrue(
84+
[for v in local.list_by_id[*].id : v == local.job_id]
85+
)
86+
}
87+
88+
output "type_filter_is_useful" {
89+
value = length(local.list_by_type) > 0 && alltrue(
90+
[for v in local.list_by_type[*].type : v == local.type]
91+
)
92+
}
93+
94+
output "status_filter_is_useful" {
95+
value = length(local.list_by_status) > 0 && alltrue(
96+
[for v in local.list_by_status[*].status : v == local.status]
97+
)
98+
}
99+
`, testCssLogBackupRecords_dataBasic(name))
100+
}
101+
102+
func testCssLogBackupRecords_dataBasic(name string) string {
103+
return fmt.Sprintf(`
104+
%s
105+
106+
resource "huaweicloud_css_manual_log_backup" "test" {
107+
depends_on = [huaweicloud_css_log_setting.test]
108+
109+
cluster_id = huaweicloud_css_cluster.test.id
110+
}
111+
112+
resource "huaweicloud_css_manual_log_backup" "test1" {
113+
depends_on = [huaweicloud_css_manual_log_backup.test]
114+
115+
cluster_id = huaweicloud_css_cluster.test.id
116+
}
117+
118+
resource "huaweicloud_css_manual_log_backup" "test2" {
119+
depends_on = [huaweicloud_css_manual_log_backup.test1]
120+
121+
cluster_id = huaweicloud_css_cluster.test.id
122+
}
123+
`, testLogSetting_elastic(name))
124+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// Generated by PMS #202
2+
package css
3+
4+
import (
5+
"context"
6+
"strings"
7+
8+
"github.com/hashicorp/go-multierror"
9+
"github.com/hashicorp/go-uuid"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
"github.com/tidwall/gjson"
13+
14+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
15+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/filters"
16+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/httphelper"
17+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/schemas"
18+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
19+
)
20+
21+
func DataSourceCssLogBackupRecords() *schema.Resource {
22+
return &schema.Resource{
23+
ReadContext: dataSourceCssLogBackupRecordsRead,
24+
25+
Schema: map[string]*schema.Schema{
26+
"region": {
27+
Type: schema.TypeString,
28+
Optional: true,
29+
Computed: true,
30+
Description: `Specifies the region in which to query the resource. If omitted, the provider-level region will be used.`,
31+
},
32+
"cluster_id": {
33+
Type: schema.TypeString,
34+
Required: true,
35+
Description: `Specifies the ID of the CSS cluster.`,
36+
},
37+
"job_id": {
38+
Type: schema.TypeString,
39+
Optional: true,
40+
Description: `Specifies the ID of the log backup job.`,
41+
},
42+
"type": {
43+
Type: schema.TypeString,
44+
Optional: true,
45+
Description: `Specifies the type of the log backup job.`,
46+
},
47+
"status": {
48+
Type: schema.TypeString,
49+
Optional: true,
50+
Description: `Specifies the status of the log backup job.`,
51+
},
52+
"records": {
53+
Type: schema.TypeList,
54+
Computed: true,
55+
Description: `The list of the CSS cluster log backup records.`,
56+
Elem: &schema.Resource{
57+
Schema: map[string]*schema.Schema{
58+
"id": {
59+
Type: schema.TypeString,
60+
Computed: true,
61+
Description: `The ID of the log backup job.`,
62+
},
63+
"type": {
64+
Type: schema.TypeString,
65+
Computed: true,
66+
Description: `The type of the log backup job.`,
67+
},
68+
"status": {
69+
Type: schema.TypeString,
70+
Computed: true,
71+
Description: `The status of the log backup job.`,
72+
},
73+
"cluster_id": {
74+
Type: schema.TypeString,
75+
Computed: true,
76+
Description: `The ID of the CSS cluster.`,
77+
},
78+
"log_path": {
79+
Type: schema.TypeString,
80+
Computed: true,
81+
Description: `The storage path of backed up logs in the OBS bucket.`,
82+
},
83+
"create_at": {
84+
Type: schema.TypeString,
85+
Computed: true,
86+
Description: `The creation time.`,
87+
},
88+
"finished_at": {
89+
Type: schema.TypeString,
90+
Computed: true,
91+
Description: `The end time.`,
92+
},
93+
"failed_msg": {
94+
Type: schema.TypeString,
95+
Computed: true,
96+
Description: `The error information.`,
97+
},
98+
},
99+
},
100+
},
101+
},
102+
}
103+
}
104+
105+
type LogBackupRecordsDSWrapper struct {
106+
*schemas.ResourceDataWrapper
107+
Config *config.Config
108+
}
109+
110+
func newLogBackupRecordsDSWrapper(d *schema.ResourceData, meta interface{}) *LogBackupRecordsDSWrapper {
111+
return &LogBackupRecordsDSWrapper{
112+
ResourceDataWrapper: schemas.NewSchemaWrapper(d),
113+
Config: meta.(*config.Config),
114+
}
115+
}
116+
117+
func dataSourceCssLogBackupRecordsRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
118+
wrapper := newLogBackupRecordsDSWrapper(d, meta)
119+
listLogsJobRst, err := wrapper.ListLogsJob()
120+
if err != nil {
121+
return diag.FromErr(err)
122+
}
123+
124+
id, err := uuid.GenerateUUID()
125+
if err != nil {
126+
return diag.FromErr(err)
127+
}
128+
d.SetId(id)
129+
130+
err = wrapper.listLogsJobToSchema(listLogsJobRst)
131+
if err != nil {
132+
return diag.FromErr(err)
133+
}
134+
135+
return nil
136+
}
137+
138+
// @API CSS GET /v1.0/{project_id}/clusters/{cluster_id}/logs/records
139+
func (w *LogBackupRecordsDSWrapper) ListLogsJob() (*gjson.Result, error) {
140+
client, err := w.NewClient(w.Config, "css")
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
uri := "/v1.0/{project_id}/clusters/{cluster_id}/logs/records"
146+
uri = strings.ReplaceAll(uri, "{cluster_id}", w.Get("cluster_id").(string))
147+
return httphelper.New(client).
148+
Method("GET").
149+
URI(uri).
150+
OffsetStart(1).
151+
OffsetPager("clusterLogRecord", "start", "limit", 10).
152+
Filter(
153+
filters.New().From("clusterLogRecord").
154+
Where("jobId", "=", w.Get("job_id")).
155+
Where("jobTypes", "=", w.Get("type")).
156+
Where("status", "=", w.Get("status")),
157+
).
158+
Request().
159+
Result()
160+
}
161+
162+
func (w *LogBackupRecordsDSWrapper) listLogsJobToSchema(body *gjson.Result) error {
163+
d := w.ResourceData
164+
mErr := multierror.Append(nil,
165+
d.Set("region", w.Config.GetRegion(w.ResourceData)),
166+
d.Set("records", schemas.SliceToList(body.Get("clusterLogRecord"),
167+
func(records gjson.Result) any {
168+
return map[string]any{
169+
"id": records.Get("jobId").Value(),
170+
"type": records.Get("jobTypes").Value(),
171+
"status": records.Get("status").Value(),
172+
"cluster_id": records.Get("clusterId").Value(),
173+
"log_path": records.Get("logPath").Value(),
174+
"create_at": w.setCluLogRecCreAt(records),
175+
"finished_at": w.setCluLogRecFinAt(records),
176+
"failed_msg": records.Get("failedMsg").Value(),
177+
}
178+
},
179+
)),
180+
)
181+
return mErr.ErrorOrNil()
182+
}
183+
184+
func (*LogBackupRecordsDSWrapper) setCluLogRecCreAt(data gjson.Result) string {
185+
return utils.FormatTimeStampRFC3339(data.Get("createAt").Int()/1000, false)
186+
}
187+
188+
func (*LogBackupRecordsDSWrapper) setCluLogRecFinAt(data gjson.Result) string {
189+
finishedAt := data.Get("finishedAt").Value()
190+
if finishedAt != nil {
191+
return utils.FormatTimeStampRFC3339(int64(finishedAt.(float64))/1000, false)
192+
}
193+
194+
return ""
195+
}

0 commit comments

Comments
 (0)