From f78aa847a59993710004418e271e3724d487da7b Mon Sep 17 00:00:00 2001 From: chengxiangdong Date: Thu, 27 Jun 2024 19:16:43 +0800 Subject: [PATCH] feat: add `ToFile` support to write the response into a file --- huaweicloud/helper/httphelper/http_helper.go | 57 +++++++++++++++++++ huaweicloud/utils/utils.go | 58 ++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/huaweicloud/helper/httphelper/http_helper.go b/huaweicloud/helper/httphelper/http_helper.go index 3ac33648ebd..06af01773bb 100644 --- a/huaweicloud/helper/httphelper/http_helper.go +++ b/huaweicloud/helper/httphelper/http_helper.go @@ -5,11 +5,13 @@ import ( "encoding/json" "fmt" "io" + "log" "net/url" "reflect" "strconv" "strings" + "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-uuid" "github.com/tidwall/gjson" @@ -17,6 +19,7 @@ import ( "github.com/chnsz/golangsdk/pagination" "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/filters" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils" ) type HttpHelper struct { @@ -265,6 +268,60 @@ func (c *HttpHelper) ExtractInto(to any) error { return json.Unmarshal(c.responseBody, to) } +func (c *HttpHelper) ToFile(dataPath, filePath string) error { + err := utils.WriteToFile(filePath, "", false) + if err != nil { + return err + } + + var fileErr error + count := 0 + err = c.EachPage(func(jsonData *gjson.Result, err error) bool { + if err != nil { + fileErr = err + return true + } + + arr := jsonData.Get(dataPath).Array() + for _, v := range arr { + if err := utils.WriteToFile(filePath, fmt.Sprintf("%s\n", v.Raw), true); err != nil { + log.Printf("[ERROR] unable to write file: %s, error: %s", filePath, err) + count++ + fileErr = fmt.Errorf("%v items that failed to be written to the file %s", count, err) + } + } + return true + }) + + mErr := multierror.Append(nil, err, fileErr) + return mErr.ErrorOrNil() +} + +func (c *HttpHelper) EachPage(handler func(*gjson.Result, error) bool) error { + if c.method == "" { + c.result.Err = fmt.Errorf("`method` is empty, please specify the client through Client(method string)") + } + if c.result.Err != nil { + return c.result.Err + } + + if c.pager == nil { + return fmt.Errorf("`EachPage` only supports paginated query data") + } + + c.buildURL() + c.appendQueryParams() + + pager := pagination.NewPager(c.client, c.url, c.pager) + pager.Headers = c.requestOpts.MoreHeaders + + return pager.EachPage(func(page pagination.Page) (bool, error) { + jsonData, err := bodyToGJson(page.GetBody()) + b := handler(jsonData, err) + return b, nil + }) +} + func (c *HttpHelper) requestWithPage() { body := make(map[string]any) pager := pagination.NewPager(c.client, c.url, c.pager) diff --git a/huaweicloud/utils/utils.go b/huaweicloud/utils/utils.go index 5d571b98cdc..85efcca233e 100644 --- a/huaweicloud/utils/utils.go +++ b/huaweicloud/utils/utils.go @@ -556,3 +556,61 @@ func IsUUID(uuid string) bool { match, _ := regexp.MatchString(pattern, uuid) return match } + +func mkdirParentDir(filePath string) error { + filePath = strings.ReplaceAll(filePath, "\\", "/") + pos := strings.LastIndexByte(filePath, '/') + if pos == -1 { + return nil + } + directory := filePath[:pos] + + if err := os.MkdirAll(directory, os.ModePerm); err != nil && !os.IsExist(err) { + return fmt.Errorf("failed to create directory: %s, error: %s", directory, err) + } + return nil +} + +func WriteToFile(path, content string, append bool) error { + if err := mkdirParentDir(path); err != nil { + return err + } + + _, err := os.Stat(path) + if os.IsNotExist(err) { + file, err := os.Create(path) + if err != nil { + return fmt.Errorf("failed to create file: %s, error: %s", path, err) + } + defer file.Close() + + _, err = file.WriteString(content) + if err != nil { + return fmt.Errorf("failed to write data to %s, error: %s", path, err) + } + return nil + } + if err != nil { + return fmt.Errorf("failed to stat file: %s, error: %s", path, err) + } + + var file *os.File + if append { + file, err = os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("failed to open file for appending: %s, error: %s", path, err) + } + } else { + file, err = os.OpenFile(path, os.O_TRUNC|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("failed to open file for overwriting: %s, error: %s", path, err) + } + } + defer file.Close() + + _, err = file.WriteString(content) + if err != nil { + return fmt.Errorf("failed to write data to %s, error: %s", path, err) + } + return nil +}