Update Request Header Prefixes and Upgrade API Version to 0.6.0 (#5772)
* Update Request Header Prefixes and Upgrade API Version to 0.6.0 - Changed all HTTP request header prefixes from `x-sls-` to `x-log-` to comply with the latest API specifications. - Adjusted header prefix validation in `signature.go` to support `x-log-` and `x-acs-`. - Replaced `x-sls-bodyrawsize` with `x-log-bodyrawsize` in multiple files (`log_project.go`, `request.go`, etc.). - Updated header fields for compression type and signing method (e.g., `x-sls-compresstype` to `x-log-compresstype`). - Modified authorization logic to replace `SLS` with `LOG`. * Refactor signature generation logic for improved readability and maintainability Split the signature generation logic into several independent functions, including header extraction, standardized header construction, and resource string generation. This modular design enhances code clarity, reduces redundant logic, and improves error handling mechanisms. Additionally, comments and code structure have been optimized to ensure easier extension and debugging. --------- Co-authored-by: 优胜 <zhushaofei.zsf@alibaba-inc.com>
This commit is contained in:
parent
8b65fc75c4
commit
3000824ac5
@ -1,7 +1,7 @@
|
||||
package alils
|
||||
|
||||
const (
|
||||
version = "0.5.0" // SDK version
|
||||
version = "0.6.0" // SDK version
|
||||
signatureMethod = "hmac-sha1" // Signature method
|
||||
|
||||
// OffsetNewest is the log head offset, i.e. the offset that will be
|
||||
|
||||
@ -39,33 +39,62 @@ func NewLogProject(name, endpoint, AccessKeyID, accessKeySecret string) (p *LogP
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// ListLogStore returns all logstore names of project p.
|
||||
func (p *LogProject) ListLogStore() (storeNames []string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := "/logstores"
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
// handleResponse is a helper function to process HTTP response and handle common error cases
|
||||
// Returns response body as []byte and error if any
|
||||
func handleResponse(r *http.Response, actionDesc string) ([]byte, error) {
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to list logstore")
|
||||
err = fmt.Errorf("failed to %s", actionDesc)
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return nil, fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// sendRequest is a helper function to send HTTP request with specified method, uri, headers and body
|
||||
// Returns response body as []byte and error if any
|
||||
func (p *LogProject) sendRequest(method, uri string, headers map[string]string, body []byte) ([]byte, error) {
|
||||
r, err := request(p, method, uri, headers, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return handleResponse(r, "process request "+method+" "+uri)
|
||||
}
|
||||
|
||||
// createStandardHeaders creates a map with standard headers for requests
|
||||
func createStandardHeaders(bodyLen int) map[string]string {
|
||||
if bodyLen <= 0 {
|
||||
return map[string]string{
|
||||
"x-log-bodyrawsize": "0",
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]string{
|
||||
"x-log-bodyrawsize": fmt.Sprintf("%v", bodyLen),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
}
|
||||
|
||||
// ListLogStore returns all logstore names of project p.
|
||||
func (p *LogProject) ListLogStore() (storeNames []string, err error) {
|
||||
h := createStandardHeaders(0)
|
||||
uri := "/logstores"
|
||||
|
||||
buf, err := p.sendRequest("GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -81,39 +110,18 @@ func (p *LogProject) ListLogStore() (storeNames []string, err error) {
|
||||
}
|
||||
|
||||
storeNames = body.LogStores
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetLogStore returns logstore according by logstore name.
|
||||
func (p *LogProject) GetLogStore(name string) (s *LogStore, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
r, err := request(p, "GET", "/logstores/"+name, h, nil)
|
||||
buf, err := p.sendRequest("GET", "/logstores/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
s = &LogStore{}
|
||||
err = json.Unmarshal(buf, s)
|
||||
if err != nil {
|
||||
@ -145,66 +153,15 @@ func (p *LogProject) CreateLogStore(name string, ttl, shardCnt int) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "POST", "/logstores", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
h := createStandardHeaders(len(body))
|
||||
_, err = p.sendRequest("POST", "/logstores", h, body)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteLogStore deletes a logstore according by logstore name.
|
||||
func (p *LogProject) DeleteLogStore(name string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "DELETE", "/logstores/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
_, err = p.sendRequest("DELETE", "/logstores/"+name, h, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@ -228,73 +185,26 @@ func (p *LogProject) UpdateLogStore(name string, ttl, shardCnt int) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "PUT", "/logstores", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
h := createStandardHeaders(len(body))
|
||||
_, err = p.sendRequest("PUT", "/logstores", h, body)
|
||||
return
|
||||
}
|
||||
|
||||
// ListMachineGroup returns machine group name list and the total number of machine groups.
|
||||
// The offset starts from 0 and the size is the max number of machine groups could be returned.
|
||||
func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
if size <= 0 {
|
||||
size = 500
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups?offset=%v&size=%v", offset, size)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
buf, err := p.sendRequest("GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to list machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
MachineGroups []string
|
||||
Count int
|
||||
@ -309,39 +219,18 @@ func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int,
|
||||
|
||||
m = body.MachineGroups
|
||||
total = body.Total
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetMachineGroup retruns machine group according by machine group name.
|
||||
func (p *LogProject) GetMachineGroup(name string) (m *MachineGroup, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
r, err := request(p, "GET", "/machinegroups/"+name, h, nil)
|
||||
buf, err := p.sendRequest("GET", "/machinegroups/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get machine group:%v", name)
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
m = &MachineGroup{}
|
||||
err = json.Unmarshal(buf, m)
|
||||
if err != nil {
|
||||
@ -358,35 +247,8 @@ func (p *LogProject) CreateMachineGroup(m *MachineGroup) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "POST", "/machinegroups", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
h := createStandardHeaders(len(body))
|
||||
_, err = p.sendRequest("POST", "/machinegroups", h, body)
|
||||
return
|
||||
}
|
||||
|
||||
@ -397,104 +259,33 @@ func (p *LogProject) UpdateMachineGroup(m *MachineGroup) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "PUT", "/machinegroups/"+m.Name, h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
h := createStandardHeaders(len(body))
|
||||
_, err = p.sendRequest("PUT", "/machinegroups/"+m.Name, h, body)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMachineGroup deletes machine group according machine group name.
|
||||
func (p *LogProject) DeleteMachineGroup(name string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "DELETE", "/machinegroups/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
_, err = p.sendRequest("DELETE", "/machinegroups/"+name, h, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListConfig returns config names list and the total number of configs.
|
||||
// The offset starts from 0 and the size is the max number of configs could be returned.
|
||||
func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
if size <= 0 {
|
||||
size = 100
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/configs?offset=%v&size=%v", offset, size)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
buf, err := p.sendRequest("GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
Total int
|
||||
Configs []string
|
||||
@ -513,33 +304,13 @@ func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int,
|
||||
|
||||
// GetConfig returns config according by config name.
|
||||
func (p *LogProject) GetConfig(name string) (c *LogConfig, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
r, err := request(p, "GET", "/configs/"+name, h, nil)
|
||||
buf, err := p.sendRequest("GET", "/configs/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
c = &LogConfig{}
|
||||
err = json.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
@ -556,35 +327,8 @@ func (p *LogProject) UpdateConfig(c *LogConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "PUT", "/configs/"+c.Name, h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
h := createStandardHeaders(len(body))
|
||||
_, err = p.sendRequest("PUT", "/configs/"+c.Name, h, body)
|
||||
return
|
||||
}
|
||||
|
||||
@ -595,99 +339,28 @@ func (p *LogProject) CreateConfig(c *LogConfig) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "POST", "/configs", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
h := createStandardHeaders(len(body))
|
||||
_, err = p.sendRequest("POST", "/configs", h, body)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteConfig deletes a config according by config name.
|
||||
func (p *LogProject) DeleteConfig(name string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "DELETE", "/configs/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
_, err = p.sendRequest("DELETE", "/configs/"+name, h, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// GetAppliedMachineGroups returns applied machine group names list according config name.
|
||||
func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
uri := fmt.Sprintf("/configs/%v/machinegroups", confName)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
buf, err := p.sendRequest("GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get applied machine groups")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
Count int
|
||||
Machinegroups []string
|
||||
@ -705,34 +378,14 @@ func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []stri
|
||||
|
||||
// GetAppliedConfigs returns applied config names list according machine group name groupName.
|
||||
func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/configs", groupName)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
buf, err := p.sendRequest("GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to applied configs")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Cfg struct {
|
||||
Count int `json:"count"`
|
||||
Configs []string `json:"configs"`
|
||||
@ -750,64 +403,18 @@ func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, er
|
||||
|
||||
// ApplyConfigToMachineGroup applies config to machine group.
|
||||
func (p *LogProject) ApplyConfigToMachineGroup(confName, groupName string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
|
||||
r, err := request(p, "PUT", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to apply config to machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
_, err = p.sendRequest("PUT", uri, h, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveConfigFromMachineGroup removes config from machine group.
|
||||
func (p *LogProject) RemoveConfigFromMachineGroup(confName, groupName string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
h := createStandardHeaders(0)
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
|
||||
r, err := request(p, "DELETE", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to remove config from machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
_, err = p.sendRequest("DELETE", uri, h, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ type Shard struct {
|
||||
// ListShards returns shard id list of this logstore.
|
||||
func (s *LogStore) ListShards() (shardIDs []int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
"x-log-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores/%v/shards", s.Name)
|
||||
@ -87,8 +87,8 @@ func (s *LogStore) PutLogs(lg *LogGroup) (err error) {
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-compresstype": "lz4",
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"x-log-compresstype": "lz4",
|
||||
"x-log-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/x-protobuf",
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ func (s *LogStore) PutLogs(lg *LogGroup) (err error) {
|
||||
// For more detail please read: http://gitlab.alibaba-inc.com/sls/doc/blob/master/api/shard.md#logstore
|
||||
func (s *LogStore) GetCursor(shardID int, from string) (cursor string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
"x-log-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=cursor&from=%v",
|
||||
@ -172,7 +172,7 @@ func (s *LogStore) GetLogsBytes(shardID int, cursor string,
|
||||
logGroupMaxCount int) (out []byte, nextCursor string, err error) {
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
"x-log-bodyrawsize": "0",
|
||||
"Accept": "application/x-protobuf",
|
||||
"Accept-Encoding": "lz4",
|
||||
}
|
||||
@ -203,9 +203,9 @@ func (s *LogStore) GetLogsBytes(shardID int, cursor string,
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := r.Header["X-Sls-Compresstype"]
|
||||
v, ok := r.Header["X-Log-Compresstype"]
|
||||
if !ok || len(v) == 0 {
|
||||
err = fmt.Errorf("can't find 'x-sls-compresstype' header")
|
||||
err = fmt.Errorf("can't find 'x-log-compresstype' header")
|
||||
return
|
||||
}
|
||||
if v[0] != "lz4" {
|
||||
@ -213,16 +213,16 @@ func (s *LogStore) GetLogsBytes(shardID int, cursor string,
|
||||
return
|
||||
}
|
||||
|
||||
v, ok = r.Header["X-Sls-Cursor"]
|
||||
v, ok = r.Header["X-Log-Cursor"]
|
||||
if !ok || len(v) == 0 {
|
||||
err = fmt.Errorf("can't find 'x-sls-cursor' header")
|
||||
err = fmt.Errorf("can't find 'x-log-cursor' header")
|
||||
return
|
||||
}
|
||||
nextCursor = v[0]
|
||||
|
||||
v, ok = r.Header["X-Sls-Bodyrawsize"]
|
||||
v, ok = r.Header["X-Log-Bodyrawsize"]
|
||||
if !ok || len(v) == 0 {
|
||||
err = fmt.Errorf("can't find 'x-sls-bodyrawsize' header")
|
||||
err = fmt.Errorf("can't find 'x-log-bodyrawsize' header")
|
||||
return
|
||||
}
|
||||
bodyRawSize, err := strconv.Atoi(v[0])
|
||||
|
||||
@ -45,7 +45,7 @@ type MachineList struct {
|
||||
// ListMachines returns the machine list of this machine group.
|
||||
func (m *MachineGroup) ListMachines() (ms []*Machine, total int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
"x-log-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/machines", m.Name)
|
||||
|
||||
@ -11,17 +11,17 @@ import (
|
||||
func request(project *LogProject, method, uri string, headers map[string]string,
|
||||
body []byte) (resp *http.Response, err error) {
|
||||
|
||||
// The caller should provide 'x-sls-bodyrawsize' header
|
||||
if _, ok := headers["x-sls-bodyrawsize"]; !ok {
|
||||
err = fmt.Errorf("can't find 'x-sls-bodyrawsize' header")
|
||||
// The caller should provide 'x-log-bodyrawsize' header
|
||||
if _, ok := headers["x-log-bodyrawsize"]; !ok {
|
||||
err = fmt.Errorf("can't find 'x-log-bodyrawsize' header")
|
||||
return
|
||||
}
|
||||
|
||||
// SLS public request headers
|
||||
headers["Host"] = project.Name + "." + project.Endpoint
|
||||
headers["Date"] = nowRFC1123()
|
||||
headers["x-sls-apiversion"] = version
|
||||
headers["x-sls-signaturemethod"] = signatureMethod
|
||||
headers["x-log-apiversion"] = version
|
||||
headers["x-log-signaturemethod"] = signatureMethod
|
||||
if body != nil {
|
||||
bodyMD5 := fmt.Sprintf("%X", md5.Sum(body))
|
||||
headers["Content-MD5"] = bodyMD5
|
||||
@ -33,12 +33,12 @@ func request(project *LogProject, method, uri string, headers map[string]string,
|
||||
}
|
||||
|
||||
// Calc Authorization
|
||||
// Authorization = "SLS <AccessKeyID>:<Signature>"
|
||||
// Authorization = "LOG <AccessKeyID>:<Signature>"
|
||||
digest, err := signature(project, method, uri, headers)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auth := fmt.Sprintf("SLS %v:%v", project.AccessKeyID, digest)
|
||||
auth := fmt.Sprintf("LOG %v:%v", project.AccessKeyID, digest)
|
||||
headers["Authorization"] = auth
|
||||
|
||||
// Initialize http request
|
||||
|
||||
@ -20,92 +20,133 @@ func nowRFC1123() string {
|
||||
return time.Now().In(gmtLoc).Format(time.RFC1123)
|
||||
}
|
||||
|
||||
// signature calculates a request's signature digest.
|
||||
// signature calculates a request's signature digest
|
||||
func signature(project *LogProject, method, uri string,
|
||||
headers map[string]string) (digest string, err error) {
|
||||
var contentMD5, contentType, date, canoHeaders, canoResource string
|
||||
|
||||
// 1. Extract basic header information
|
||||
contentMD5 := getHeaderSafe(headers, "Content-MD5")
|
||||
contentType := getHeaderSafe(headers, "Content-Type")
|
||||
|
||||
date, ok := headers["Date"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("Can't find 'Date' header")
|
||||
}
|
||||
|
||||
// 2. Calculate CanonicalizedSLSHeaders
|
||||
canoHeaders := buildCanonicalHeaders(headers)
|
||||
|
||||
// 3. Calculate CanonicalizedResource
|
||||
canoResource, err := buildCanonicalResource(uri)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 4. Build the signature string
|
||||
signStr := buildSignString(method, contentMD5, contentType, date, canoHeaders, canoResource)
|
||||
|
||||
// 5. Calculate HMAC-SHA1 signature and encode with Base64
|
||||
// Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret))
|
||||
return calculateHmacSha1(signStr, project.AccessKeySecret)
|
||||
}
|
||||
|
||||
// getHeaderSafe safely retrieves a header value, returns empty string if not exists
|
||||
func getHeaderSafe(headers map[string]string, key string) string {
|
||||
if val, ok := headers[key]; ok {
|
||||
return val
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// buildCanonicalHeaders constructs normalized SLS headers
|
||||
func buildCanonicalHeaders(headers map[string]string) string {
|
||||
slsHeaders := make(map[string]string)
|
||||
var slsHeaderKeys sort.StringSlice
|
||||
|
||||
// Extract headers prefixed with x-log- and x-acs-
|
||||
for k, v := range headers {
|
||||
l := strings.TrimSpace(strings.ToLower(k))
|
||||
if strings.HasPrefix(l, "x-log-") || strings.HasPrefix(l, "x-acs-") {
|
||||
slsHeaders[l] = strings.TrimSpace(v)
|
||||
slsHeaderKeys = append(slsHeaderKeys, l)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort headers alphabetically
|
||||
sort.Sort(slsHeaderKeys)
|
||||
|
||||
// Build the canonical header string
|
||||
var result strings.Builder
|
||||
for i, k := range slsHeaderKeys {
|
||||
result.WriteString(k)
|
||||
result.WriteString(":")
|
||||
result.WriteString(slsHeaders[k])
|
||||
if i+1 < len(slsHeaderKeys) {
|
||||
result.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// buildCanonicalResource constructs a normalized resource string
|
||||
func buildCanonicalResource(uri string) (string, error) {
|
||||
u, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := u.Path
|
||||
|
||||
// Process query parameters
|
||||
if u.RawQuery != "" {
|
||||
var keys sort.StringSlice
|
||||
vals := u.Query()
|
||||
|
||||
for k := range vals {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
sort.Sort(keys)
|
||||
result += "?"
|
||||
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
result += "&"
|
||||
}
|
||||
|
||||
for _, v := range vals[k] {
|
||||
result += k + "=" + v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// buildSignString constructs the complete signature string
|
||||
func buildSignString(method, contentMD5, contentType, date, canoHeaders, canoResource string) string {
|
||||
// SignString = VERB + "\n"
|
||||
// + CONTENT-MD5 + "\n"
|
||||
// + CONTENT-TYPE + "\n"
|
||||
// + DATE + "\n"
|
||||
// + CanonicalizedSLSHeaders + "\n"
|
||||
// + CanonicalizedResource
|
||||
|
||||
if val, ok := headers["Content-MD5"]; ok {
|
||||
contentMD5 = val
|
||||
}
|
||||
|
||||
if val, ok := headers["Content-Type"]; ok {
|
||||
contentType = val
|
||||
}
|
||||
|
||||
date, ok := headers["Date"]
|
||||
if !ok {
|
||||
err = fmt.Errorf("Can't find 'Date' header")
|
||||
return
|
||||
}
|
||||
|
||||
// Calc CanonicalizedSLSHeaders
|
||||
slsHeaders := make(map[string]string, len(headers))
|
||||
for k, v := range headers {
|
||||
l := strings.TrimSpace(strings.ToLower(k))
|
||||
if strings.HasPrefix(l, "x-sls-") {
|
||||
slsHeaders[l] = strings.TrimSpace(v)
|
||||
slsHeaderKeys = append(slsHeaderKeys, l)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(slsHeaderKeys)
|
||||
for i, k := range slsHeaderKeys {
|
||||
canoHeaders += k + ":" + slsHeaders[k]
|
||||
if i+1 < len(slsHeaderKeys) {
|
||||
canoHeaders += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Calc CanonicalizedResource
|
||||
u, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
canoResource += url.QueryEscape(u.Path)
|
||||
if u.RawQuery != "" {
|
||||
var keys sort.StringSlice
|
||||
|
||||
vals := u.Query()
|
||||
for k := range vals {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
sort.Sort(keys)
|
||||
canoResource += "?"
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
canoResource += "&"
|
||||
}
|
||||
|
||||
for _, v := range vals[k] {
|
||||
canoResource += k + "=" + v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signStr := method + "\n" +
|
||||
return method + "\n" +
|
||||
contentMD5 + "\n" +
|
||||
contentType + "\n" +
|
||||
date + "\n" +
|
||||
canoHeaders + "\n" +
|
||||
canoResource
|
||||
}
|
||||
|
||||
// Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret))
|
||||
mac := hmac.New(sha1.New, []byte(project.AccessKeySecret))
|
||||
_, err = mac.Write([]byte(signStr))
|
||||
// calculateHmacSha1 calculates the HMAC-SHA1 signature and encodes it with Base64
|
||||
func calculateHmacSha1(signStr, secret string) (string, error) {
|
||||
mac := hmac.New(sha1.New, []byte(secret))
|
||||
_, err := mac.Write([]byte(signStr))
|
||||
if err != nil {
|
||||
return
|
||||
return "", err
|
||||
}
|
||||
digest = base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
return
|
||||
|
||||
return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user