github.com/astaxie/beego@v1.12.3/logs/alils/log_project.go (about)

     1  /*
     2  Package alils implements the SDK(v0.5.0) of Simple Log Service(abbr. SLS).
     3  
     4  For more description about SLS, please read this article:
     5  http://gitlab.alibaba-inc.com/sls/doc.
     6  */
     7  package alils
     8  
     9  import (
    10  	"encoding/json"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"net/http"
    14  	"net/http/httputil"
    15  )
    16  
    17  // Error message in SLS HTTP response.
    18  type errorMessage struct {
    19  	Code    string `json:"errorCode"`
    20  	Message string `json:"errorMessage"`
    21  }
    22  
    23  // LogProject Define the Ali Project detail
    24  type LogProject struct {
    25  	Name            string // Project name
    26  	Endpoint        string // IP or hostname of SLS endpoint
    27  	AccessKeyID     string
    28  	AccessKeySecret string
    29  }
    30  
    31  // NewLogProject creates a new SLS project.
    32  func NewLogProject(name, endpoint, AccessKeyID, accessKeySecret string) (p *LogProject, err error) {
    33  	p = &LogProject{
    34  		Name:            name,
    35  		Endpoint:        endpoint,
    36  		AccessKeyID:     AccessKeyID,
    37  		AccessKeySecret: accessKeySecret,
    38  	}
    39  	return p, nil
    40  }
    41  
    42  // ListLogStore returns all logstore names of project p.
    43  func (p *LogProject) ListLogStore() (storeNames []string, err error) {
    44  	h := map[string]string{
    45  		"x-sls-bodyrawsize": "0",
    46  	}
    47  
    48  	uri := fmt.Sprintf("/logstores")
    49  	r, err := request(p, "GET", uri, h, nil)
    50  	if err != nil {
    51  		return
    52  	}
    53  
    54  	buf, err := ioutil.ReadAll(r.Body)
    55  	if err != nil {
    56  		return
    57  	}
    58  
    59  	if r.StatusCode != http.StatusOK {
    60  		errMsg := &errorMessage{}
    61  		err = json.Unmarshal(buf, errMsg)
    62  		if err != nil {
    63  			err = fmt.Errorf("failed to list logstore")
    64  			dump, _ := httputil.DumpResponse(r, true)
    65  			fmt.Printf("%s\n", dump)
    66  			return
    67  		}
    68  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
    69  		return
    70  	}
    71  
    72  	type Body struct {
    73  		Count     int
    74  		LogStores []string
    75  	}
    76  	body := &Body{}
    77  
    78  	err = json.Unmarshal(buf, body)
    79  	if err != nil {
    80  		return
    81  	}
    82  
    83  	storeNames = body.LogStores
    84  
    85  	return
    86  }
    87  
    88  // GetLogStore returns logstore according by logstore name.
    89  func (p *LogProject) GetLogStore(name string) (s *LogStore, err error) {
    90  	h := map[string]string{
    91  		"x-sls-bodyrawsize": "0",
    92  	}
    93  
    94  	r, err := request(p, "GET", "/logstores/"+name, h, nil)
    95  	if err != nil {
    96  		return
    97  	}
    98  
    99  	buf, err := ioutil.ReadAll(r.Body)
   100  	if err != nil {
   101  		return
   102  	}
   103  
   104  	if r.StatusCode != http.StatusOK {
   105  		errMsg := &errorMessage{}
   106  		err = json.Unmarshal(buf, errMsg)
   107  		if err != nil {
   108  			err = fmt.Errorf("failed to get logstore")
   109  			dump, _ := httputil.DumpResponse(r, true)
   110  			fmt.Printf("%s\n", dump)
   111  			return
   112  		}
   113  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   114  		return
   115  	}
   116  
   117  	s = &LogStore{}
   118  	err = json.Unmarshal(buf, s)
   119  	if err != nil {
   120  		return
   121  	}
   122  	s.project = p
   123  	return
   124  }
   125  
   126  // CreateLogStore creates a new logstore in SLS,
   127  // where name is logstore name,
   128  // and ttl is time-to-live(in day) of logs,
   129  // and shardCnt is the number of shards.
   130  func (p *LogProject) CreateLogStore(name string, ttl, shardCnt int) (err error) {
   131  
   132  	type Body struct {
   133  		Name       string `json:"logstoreName"`
   134  		TTL        int    `json:"ttl"`
   135  		ShardCount int    `json:"shardCount"`
   136  	}
   137  
   138  	store := &Body{
   139  		Name:       name,
   140  		TTL:        ttl,
   141  		ShardCount: shardCnt,
   142  	}
   143  
   144  	body, err := json.Marshal(store)
   145  	if err != nil {
   146  		return
   147  	}
   148  
   149  	h := map[string]string{
   150  		"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
   151  		"Content-Type":      "application/json",
   152  		"Accept-Encoding":   "deflate", // TODO: support lz4
   153  	}
   154  
   155  	r, err := request(p, "POST", "/logstores", h, body)
   156  	if err != nil {
   157  		return
   158  	}
   159  
   160  	body, err = ioutil.ReadAll(r.Body)
   161  	if err != nil {
   162  		return
   163  	}
   164  
   165  	if r.StatusCode != http.StatusOK {
   166  		errMsg := &errorMessage{}
   167  		err = json.Unmarshal(body, errMsg)
   168  		if err != nil {
   169  			err = fmt.Errorf("failed to create logstore")
   170  			dump, _ := httputil.DumpResponse(r, true)
   171  			fmt.Printf("%s\n", dump)
   172  			return
   173  		}
   174  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   175  		return
   176  	}
   177  
   178  	return
   179  }
   180  
   181  // DeleteLogStore deletes a logstore according by logstore name.
   182  func (p *LogProject) DeleteLogStore(name string) (err error) {
   183  	h := map[string]string{
   184  		"x-sls-bodyrawsize": "0",
   185  	}
   186  
   187  	r, err := request(p, "DELETE", "/logstores/"+name, h, nil)
   188  	if err != nil {
   189  		return
   190  	}
   191  
   192  	body, err := ioutil.ReadAll(r.Body)
   193  	if err != nil {
   194  		return
   195  	}
   196  
   197  	if r.StatusCode != http.StatusOK {
   198  		errMsg := &errorMessage{}
   199  		err = json.Unmarshal(body, errMsg)
   200  		if err != nil {
   201  			err = fmt.Errorf("failed to delete logstore")
   202  			dump, _ := httputil.DumpResponse(r, true)
   203  			fmt.Printf("%s\n", dump)
   204  			return
   205  		}
   206  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   207  		return
   208  	}
   209  	return
   210  }
   211  
   212  // UpdateLogStore updates a logstore according by logstore name,
   213  // obviously we can't modify the logstore name itself.
   214  func (p *LogProject) UpdateLogStore(name string, ttl, shardCnt int) (err error) {
   215  
   216  	type Body struct {
   217  		Name       string `json:"logstoreName"`
   218  		TTL        int    `json:"ttl"`
   219  		ShardCount int    `json:"shardCount"`
   220  	}
   221  
   222  	store := &Body{
   223  		Name:       name,
   224  		TTL:        ttl,
   225  		ShardCount: shardCnt,
   226  	}
   227  
   228  	body, err := json.Marshal(store)
   229  	if err != nil {
   230  		return
   231  	}
   232  
   233  	h := map[string]string{
   234  		"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
   235  		"Content-Type":      "application/json",
   236  		"Accept-Encoding":   "deflate", // TODO: support lz4
   237  	}
   238  
   239  	r, err := request(p, "PUT", "/logstores", h, body)
   240  	if err != nil {
   241  		return
   242  	}
   243  
   244  	body, err = ioutil.ReadAll(r.Body)
   245  	if err != nil {
   246  		return
   247  	}
   248  
   249  	if r.StatusCode != http.StatusOK {
   250  		errMsg := &errorMessage{}
   251  		err = json.Unmarshal(body, errMsg)
   252  		if err != nil {
   253  			err = fmt.Errorf("failed to update logstore")
   254  			dump, _ := httputil.DumpResponse(r, true)
   255  			fmt.Printf("%s\n", dump)
   256  			return
   257  		}
   258  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   259  		return
   260  	}
   261  
   262  	return
   263  }
   264  
   265  // ListMachineGroup returns machine group name list and the total number of machine groups.
   266  // The offset starts from 0 and the size is the max number of machine groups could be returned.
   267  func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int, err error) {
   268  	h := map[string]string{
   269  		"x-sls-bodyrawsize": "0",
   270  	}
   271  
   272  	if size <= 0 {
   273  		size = 500
   274  	}
   275  
   276  	uri := fmt.Sprintf("/machinegroups?offset=%v&size=%v", offset, size)
   277  	r, err := request(p, "GET", uri, h, nil)
   278  	if err != nil {
   279  		return
   280  	}
   281  
   282  	buf, err := ioutil.ReadAll(r.Body)
   283  	if err != nil {
   284  		return
   285  	}
   286  
   287  	if r.StatusCode != http.StatusOK {
   288  		errMsg := &errorMessage{}
   289  		err = json.Unmarshal(buf, errMsg)
   290  		if err != nil {
   291  			err = fmt.Errorf("failed to list machine group")
   292  			dump, _ := httputil.DumpResponse(r, true)
   293  			fmt.Printf("%s\n", dump)
   294  			return
   295  		}
   296  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   297  		return
   298  	}
   299  
   300  	type Body struct {
   301  		MachineGroups []string
   302  		Count         int
   303  		Total         int
   304  	}
   305  	body := &Body{}
   306  
   307  	err = json.Unmarshal(buf, body)
   308  	if err != nil {
   309  		return
   310  	}
   311  
   312  	m = body.MachineGroups
   313  	total = body.Total
   314  
   315  	return
   316  }
   317  
   318  // GetMachineGroup retruns machine group according by machine group name.
   319  func (p *LogProject) GetMachineGroup(name string) (m *MachineGroup, err error) {
   320  	h := map[string]string{
   321  		"x-sls-bodyrawsize": "0",
   322  	}
   323  
   324  	r, err := request(p, "GET", "/machinegroups/"+name, h, nil)
   325  	if err != nil {
   326  		return
   327  	}
   328  
   329  	buf, err := ioutil.ReadAll(r.Body)
   330  	if err != nil {
   331  		return
   332  	}
   333  
   334  	if r.StatusCode != http.StatusOK {
   335  		errMsg := &errorMessage{}
   336  		err = json.Unmarshal(buf, errMsg)
   337  		if err != nil {
   338  			err = fmt.Errorf("failed to get machine group:%v", name)
   339  			dump, _ := httputil.DumpResponse(r, true)
   340  			fmt.Printf("%s\n", dump)
   341  			return
   342  		}
   343  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   344  		return
   345  	}
   346  
   347  	m = &MachineGroup{}
   348  	err = json.Unmarshal(buf, m)
   349  	if err != nil {
   350  		return
   351  	}
   352  	m.project = p
   353  	return
   354  }
   355  
   356  // CreateMachineGroup creates a new machine group in SLS.
   357  func (p *LogProject) CreateMachineGroup(m *MachineGroup) (err error) {
   358  
   359  	body, err := json.Marshal(m)
   360  	if err != nil {
   361  		return
   362  	}
   363  
   364  	h := map[string]string{
   365  		"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
   366  		"Content-Type":      "application/json",
   367  		"Accept-Encoding":   "deflate", // TODO: support lz4
   368  	}
   369  
   370  	r, err := request(p, "POST", "/machinegroups", h, body)
   371  	if err != nil {
   372  		return
   373  	}
   374  
   375  	body, err = ioutil.ReadAll(r.Body)
   376  	if err != nil {
   377  		return
   378  	}
   379  
   380  	if r.StatusCode != http.StatusOK {
   381  		errMsg := &errorMessage{}
   382  		err = json.Unmarshal(body, errMsg)
   383  		if err != nil {
   384  			err = fmt.Errorf("failed to create machine group")
   385  			dump, _ := httputil.DumpResponse(r, true)
   386  			fmt.Printf("%s\n", dump)
   387  			return
   388  		}
   389  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   390  		return
   391  	}
   392  
   393  	return
   394  }
   395  
   396  // UpdateMachineGroup updates a machine group.
   397  func (p *LogProject) UpdateMachineGroup(m *MachineGroup) (err error) {
   398  
   399  	body, err := json.Marshal(m)
   400  	if err != nil {
   401  		return
   402  	}
   403  
   404  	h := map[string]string{
   405  		"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
   406  		"Content-Type":      "application/json",
   407  		"Accept-Encoding":   "deflate", // TODO: support lz4
   408  	}
   409  
   410  	r, err := request(p, "PUT", "/machinegroups/"+m.Name, h, body)
   411  	if err != nil {
   412  		return
   413  	}
   414  
   415  	body, err = ioutil.ReadAll(r.Body)
   416  	if err != nil {
   417  		return
   418  	}
   419  
   420  	if r.StatusCode != http.StatusOK {
   421  		errMsg := &errorMessage{}
   422  		err = json.Unmarshal(body, errMsg)
   423  		if err != nil {
   424  			err = fmt.Errorf("failed to update machine group")
   425  			dump, _ := httputil.DumpResponse(r, true)
   426  			fmt.Printf("%s\n", dump)
   427  			return
   428  		}
   429  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   430  		return
   431  	}
   432  
   433  	return
   434  }
   435  
   436  // DeleteMachineGroup deletes machine group according machine group name.
   437  func (p *LogProject) DeleteMachineGroup(name string) (err error) {
   438  	h := map[string]string{
   439  		"x-sls-bodyrawsize": "0",
   440  	}
   441  
   442  	r, err := request(p, "DELETE", "/machinegroups/"+name, h, nil)
   443  	if err != nil {
   444  		return
   445  	}
   446  
   447  	body, err := ioutil.ReadAll(r.Body)
   448  	if err != nil {
   449  		return
   450  	}
   451  
   452  	if r.StatusCode != http.StatusOK {
   453  		errMsg := &errorMessage{}
   454  		err = json.Unmarshal(body, errMsg)
   455  		if err != nil {
   456  			err = fmt.Errorf("failed to delete machine group")
   457  			dump, _ := httputil.DumpResponse(r, true)
   458  			fmt.Printf("%s\n", dump)
   459  			return
   460  		}
   461  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   462  		return
   463  	}
   464  	return
   465  }
   466  
   467  // ListConfig returns config names list and the total number of configs.
   468  // The offset starts from 0 and the size is the max number of configs could be returned.
   469  func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int, err error) {
   470  	h := map[string]string{
   471  		"x-sls-bodyrawsize": "0",
   472  	}
   473  
   474  	if size <= 0 {
   475  		size = 100
   476  	}
   477  
   478  	uri := fmt.Sprintf("/configs?offset=%v&size=%v", offset, size)
   479  	r, err := request(p, "GET", uri, h, nil)
   480  	if err != nil {
   481  		return
   482  	}
   483  
   484  	buf, err := ioutil.ReadAll(r.Body)
   485  	if err != nil {
   486  		return
   487  	}
   488  
   489  	if r.StatusCode != http.StatusOK {
   490  		errMsg := &errorMessage{}
   491  		err = json.Unmarshal(buf, errMsg)
   492  		if err != nil {
   493  			err = fmt.Errorf("failed to delete machine group")
   494  			dump, _ := httputil.DumpResponse(r, true)
   495  			fmt.Printf("%s\n", dump)
   496  			return
   497  		}
   498  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   499  		return
   500  	}
   501  
   502  	type Body struct {
   503  		Total   int
   504  		Configs []string
   505  	}
   506  	body := &Body{}
   507  
   508  	err = json.Unmarshal(buf, body)
   509  	if err != nil {
   510  		return
   511  	}
   512  
   513  	cfgNames = body.Configs
   514  	total = body.Total
   515  	return
   516  }
   517  
   518  // GetConfig returns config according by config name.
   519  func (p *LogProject) GetConfig(name string) (c *LogConfig, err error) {
   520  	h := map[string]string{
   521  		"x-sls-bodyrawsize": "0",
   522  	}
   523  
   524  	r, err := request(p, "GET", "/configs/"+name, h, nil)
   525  	if err != nil {
   526  		return
   527  	}
   528  
   529  	buf, err := ioutil.ReadAll(r.Body)
   530  	if err != nil {
   531  		return
   532  	}
   533  
   534  	if r.StatusCode != http.StatusOK {
   535  		errMsg := &errorMessage{}
   536  		err = json.Unmarshal(buf, errMsg)
   537  		if err != nil {
   538  			err = fmt.Errorf("failed to delete config")
   539  			dump, _ := httputil.DumpResponse(r, true)
   540  			fmt.Printf("%s\n", dump)
   541  			return
   542  		}
   543  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   544  		return
   545  	}
   546  
   547  	c = &LogConfig{}
   548  	err = json.Unmarshal(buf, c)
   549  	if err != nil {
   550  		return
   551  	}
   552  	c.project = p
   553  	return
   554  }
   555  
   556  // UpdateConfig updates a config.
   557  func (p *LogProject) UpdateConfig(c *LogConfig) (err error) {
   558  
   559  	body, err := json.Marshal(c)
   560  	if err != nil {
   561  		return
   562  	}
   563  
   564  	h := map[string]string{
   565  		"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
   566  		"Content-Type":      "application/json",
   567  		"Accept-Encoding":   "deflate", // TODO: support lz4
   568  	}
   569  
   570  	r, err := request(p, "PUT", "/configs/"+c.Name, h, body)
   571  	if err != nil {
   572  		return
   573  	}
   574  
   575  	body, err = ioutil.ReadAll(r.Body)
   576  	if err != nil {
   577  		return
   578  	}
   579  
   580  	if r.StatusCode != http.StatusOK {
   581  		errMsg := &errorMessage{}
   582  		err = json.Unmarshal(body, errMsg)
   583  		if err != nil {
   584  			err = fmt.Errorf("failed to update config")
   585  			dump, _ := httputil.DumpResponse(r, true)
   586  			fmt.Printf("%s\n", dump)
   587  			return
   588  		}
   589  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   590  		return
   591  	}
   592  
   593  	return
   594  }
   595  
   596  // CreateConfig creates a new config in SLS.
   597  func (p *LogProject) CreateConfig(c *LogConfig) (err error) {
   598  
   599  	body, err := json.Marshal(c)
   600  	if err != nil {
   601  		return
   602  	}
   603  
   604  	h := map[string]string{
   605  		"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
   606  		"Content-Type":      "application/json",
   607  		"Accept-Encoding":   "deflate", // TODO: support lz4
   608  	}
   609  
   610  	r, err := request(p, "POST", "/configs", h, body)
   611  	if err != nil {
   612  		return
   613  	}
   614  
   615  	body, err = ioutil.ReadAll(r.Body)
   616  	if err != nil {
   617  		return
   618  	}
   619  
   620  	if r.StatusCode != http.StatusOK {
   621  		errMsg := &errorMessage{}
   622  		err = json.Unmarshal(body, errMsg)
   623  		if err != nil {
   624  			err = fmt.Errorf("failed to update config")
   625  			dump, _ := httputil.DumpResponse(r, true)
   626  			fmt.Printf("%s\n", dump)
   627  			return
   628  		}
   629  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   630  		return
   631  	}
   632  
   633  	return
   634  }
   635  
   636  // DeleteConfig deletes a config according by config name.
   637  func (p *LogProject) DeleteConfig(name string) (err error) {
   638  	h := map[string]string{
   639  		"x-sls-bodyrawsize": "0",
   640  	}
   641  
   642  	r, err := request(p, "DELETE", "/configs/"+name, h, nil)
   643  	if err != nil {
   644  		return
   645  	}
   646  
   647  	body, err := ioutil.ReadAll(r.Body)
   648  	if err != nil {
   649  		return
   650  	}
   651  
   652  	if r.StatusCode != http.StatusOK {
   653  		errMsg := &errorMessage{}
   654  		err = json.Unmarshal(body, errMsg)
   655  		if err != nil {
   656  			err = fmt.Errorf("failed to delete config")
   657  			dump, _ := httputil.DumpResponse(r, true)
   658  			fmt.Printf("%s\n", dump)
   659  			return
   660  		}
   661  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   662  		return
   663  	}
   664  	return
   665  }
   666  
   667  // GetAppliedMachineGroups returns applied machine group names list according config name.
   668  func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []string, err error) {
   669  	h := map[string]string{
   670  		"x-sls-bodyrawsize": "0",
   671  	}
   672  
   673  	uri := fmt.Sprintf("/configs/%v/machinegroups", confName)
   674  	r, err := request(p, "GET", uri, h, nil)
   675  	if err != nil {
   676  		return
   677  	}
   678  
   679  	buf, err := ioutil.ReadAll(r.Body)
   680  	if err != nil {
   681  		return
   682  	}
   683  
   684  	if r.StatusCode != http.StatusOK {
   685  		errMsg := &errorMessage{}
   686  		err = json.Unmarshal(buf, errMsg)
   687  		if err != nil {
   688  			err = fmt.Errorf("failed to get applied machine groups")
   689  			dump, _ := httputil.DumpResponse(r, true)
   690  			fmt.Printf("%s\n", dump)
   691  			return
   692  		}
   693  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   694  		return
   695  	}
   696  
   697  	type Body struct {
   698  		Count         int
   699  		Machinegroups []string
   700  	}
   701  
   702  	body := &Body{}
   703  	err = json.Unmarshal(buf, body)
   704  	if err != nil {
   705  		return
   706  	}
   707  
   708  	groupNames = body.Machinegroups
   709  	return
   710  }
   711  
   712  // GetAppliedConfigs returns applied config names list according machine group name groupName.
   713  func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, err error) {
   714  	h := map[string]string{
   715  		"x-sls-bodyrawsize": "0",
   716  	}
   717  
   718  	uri := fmt.Sprintf("/machinegroups/%v/configs", groupName)
   719  	r, err := request(p, "GET", uri, h, nil)
   720  	if err != nil {
   721  		return
   722  	}
   723  
   724  	buf, err := ioutil.ReadAll(r.Body)
   725  	if err != nil {
   726  		return
   727  	}
   728  
   729  	if r.StatusCode != http.StatusOK {
   730  		errMsg := &errorMessage{}
   731  		err = json.Unmarshal(buf, errMsg)
   732  		if err != nil {
   733  			err = fmt.Errorf("failed to applied configs")
   734  			dump, _ := httputil.DumpResponse(r, true)
   735  			fmt.Printf("%s\n", dump)
   736  			return
   737  		}
   738  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   739  		return
   740  	}
   741  
   742  	type Cfg struct {
   743  		Count   int      `json:"count"`
   744  		Configs []string `json:"configs"`
   745  	}
   746  
   747  	body := &Cfg{}
   748  	err = json.Unmarshal(buf, body)
   749  	if err != nil {
   750  		return
   751  	}
   752  
   753  	confNames = body.Configs
   754  	return
   755  }
   756  
   757  // ApplyConfigToMachineGroup applies config to machine group.
   758  func (p *LogProject) ApplyConfigToMachineGroup(confName, groupName string) (err error) {
   759  	h := map[string]string{
   760  		"x-sls-bodyrawsize": "0",
   761  	}
   762  
   763  	uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
   764  	r, err := request(p, "PUT", uri, h, nil)
   765  	if err != nil {
   766  		return
   767  	}
   768  
   769  	buf, err := ioutil.ReadAll(r.Body)
   770  	if err != nil {
   771  		return
   772  	}
   773  
   774  	if r.StatusCode != http.StatusOK {
   775  		errMsg := &errorMessage{}
   776  		err = json.Unmarshal(buf, errMsg)
   777  		if err != nil {
   778  			err = fmt.Errorf("failed to apply config to machine group")
   779  			dump, _ := httputil.DumpResponse(r, true)
   780  			fmt.Printf("%s\n", dump)
   781  			return
   782  		}
   783  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   784  		return
   785  	}
   786  	return
   787  }
   788  
   789  // RemoveConfigFromMachineGroup removes config from machine group.
   790  func (p *LogProject) RemoveConfigFromMachineGroup(confName, groupName string) (err error) {
   791  	h := map[string]string{
   792  		"x-sls-bodyrawsize": "0",
   793  	}
   794  
   795  	uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
   796  	r, err := request(p, "DELETE", uri, h, nil)
   797  	if err != nil {
   798  		return
   799  	}
   800  
   801  	buf, err := ioutil.ReadAll(r.Body)
   802  	if err != nil {
   803  		return
   804  	}
   805  
   806  	if r.StatusCode != http.StatusOK {
   807  		errMsg := &errorMessage{}
   808  		err = json.Unmarshal(buf, errMsg)
   809  		if err != nil {
   810  			err = fmt.Errorf("failed to remove config from machine group")
   811  			dump, _ := httputil.DumpResponse(r, true)
   812  			fmt.Printf("%s\n", dump)
   813  			return
   814  		}
   815  		err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
   816  		return
   817  	}
   818  	return
   819  }