2016-06-25 23:45:33 +00:00
|
|
|
package internal
|
|
|
|
|
|
|
|
import (
|
2016-06-26 05:27:09 +00:00
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2016-08-30 01:23:59 +00:00
|
|
|
"strconv"
|
2016-06-25 23:45:33 +00:00
|
|
|
log "github.com/Sirupsen/logrus"
|
|
|
|
"github.com/drone/drone/model"
|
2016-06-26 05:27:09 +00:00
|
|
|
"github.com/mrjones/oauth"
|
2016-06-25 23:45:33 +00:00
|
|
|
"io/ioutil"
|
2016-06-26 05:27:09 +00:00
|
|
|
"net/http"
|
2016-08-14 02:06:15 +00:00
|
|
|
"io"
|
2016-06-25 23:45:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2016-06-26 05:27:09 +00:00
|
|
|
currentUserId = "%s/plugins/servlet/applinks/whoami"
|
|
|
|
pathUser = "%s/rest/api/1.0/users/%s"
|
|
|
|
pathRepo = "%s/rest/api/1.0/projects/%s/repos/%s"
|
2016-08-30 01:23:59 +00:00
|
|
|
pathRepos = "%s/rest/api/1.0/repos?start=%s&limit=%s"
|
2016-06-26 05:27:09 +00:00
|
|
|
pathHook = "%s/rest/api/1.0/projects/%s/repos/%s/settings/hooks/%s"
|
2016-08-11 20:35:47 +00:00
|
|
|
pathSource = "%s/projects/%s/repos/%s/browse/%s?at=%s&raw"
|
2016-06-26 05:27:09 +00:00
|
|
|
hookName = "com.atlassian.stash.plugin.stash-web-post-receive-hooks-plugin:postReceiveHook"
|
2016-06-25 23:45:33 +00:00
|
|
|
pathHookEnabled = "%s/rest/api/1.0/projects/%s/repos/%s/settings/hooks/%s/enabled"
|
2016-08-14 02:06:15 +00:00
|
|
|
pathStatus = "%s/rest/build-status/1.0/commits/%s"
|
2016-06-25 23:45:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Client struct {
|
2016-06-26 05:27:09 +00:00
|
|
|
client *http.Client
|
|
|
|
base string
|
2016-06-25 23:45:33 +00:00
|
|
|
accessToken string
|
|
|
|
}
|
|
|
|
|
2016-07-24 21:07:44 +00:00
|
|
|
func NewClientWithToken(url string, consumer *oauth.Consumer, AccessToken string) *Client {
|
2016-06-25 23:45:33 +00:00
|
|
|
var token oauth.AccessToken
|
|
|
|
token.Token = AccessToken
|
2016-07-24 21:07:44 +00:00
|
|
|
client, err := consumer.MakeHttpClient(&token)
|
2016-06-26 05:27:09 +00:00
|
|
|
log.Debug(fmt.Printf("Create client: %+v %s\n", token, url))
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
|
|
|
return &Client{client, url, AccessToken}
|
|
|
|
}
|
|
|
|
|
2016-07-24 21:07:44 +00:00
|
|
|
func (c *Client) FindCurrentUser() (*User, error) {
|
2016-06-26 05:27:09 +00:00
|
|
|
CurrentUserIdResponse, err := c.client.Get(fmt.Sprintf(currentUserId, c.base))
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer CurrentUserIdResponse.Body.Close()
|
|
|
|
bits, err := ioutil.ReadAll(CurrentUserIdResponse.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
login := string(bits)
|
|
|
|
|
2016-06-26 05:27:09 +00:00
|
|
|
CurrentUserResponse, err := c.client.Get(fmt.Sprintf(pathUser, c.base, login))
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer CurrentUserResponse.Body.Close()
|
|
|
|
|
|
|
|
contents, err := ioutil.ReadAll(CurrentUserResponse.Body)
|
2016-06-26 05:27:09 +00:00
|
|
|
if err != nil {
|
2016-06-25 23:45:33 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var user User
|
|
|
|
err = json.Unmarshal(contents, &user)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-06-26 05:27:09 +00:00
|
|
|
|
2016-07-24 21:07:44 +00:00
|
|
|
return &user, nil
|
2016-06-25 23:45:33 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-07-24 21:07:44 +00:00
|
|
|
func (c *Client) FindRepo(owner string, name string) (*Repo, error) {
|
2016-06-25 23:45:33 +00:00
|
|
|
urlString := fmt.Sprintf(pathRepo, c.base, owner, name)
|
2016-06-26 05:27:09 +00:00
|
|
|
response, err := c.client.Get(urlString)
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
contents, err := ioutil.ReadAll(response.Body)
|
2016-07-24 21:07:44 +00:00
|
|
|
repo := Repo{}
|
|
|
|
err = json.Unmarshal(contents, &repo)
|
2016-06-26 05:27:09 +00:00
|
|
|
if err != nil {
|
2016-06-25 23:45:33 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2016-07-24 21:07:44 +00:00
|
|
|
return &repo, nil
|
2016-06-25 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
2016-07-24 21:07:44 +00:00
|
|
|
func (c *Client) FindRepos() ([]*Repo, error) {
|
2016-08-30 01:23:59 +00:00
|
|
|
return c.paginatedRepos(0)
|
2016-06-25 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) FindRepoPerms(owner string, repo string) (*model.Perm, error) {
|
|
|
|
perms := new(model.Perm)
|
|
|
|
// If you don't have access return none right away
|
|
|
|
_, err := c.FindRepo(owner, repo)
|
|
|
|
if err != nil {
|
|
|
|
return perms, err
|
|
|
|
}
|
|
|
|
// Must have admin to be able to list hooks. If have access the enable perms
|
2016-06-26 05:27:09 +00:00
|
|
|
_, err = c.client.Get(fmt.Sprintf(pathHook, c.base, owner, repo, hookName))
|
2016-06-25 23:45:33 +00:00
|
|
|
if err == nil {
|
|
|
|
perms.Push = true
|
|
|
|
perms.Admin = true
|
|
|
|
}
|
|
|
|
perms.Pull = true
|
2016-06-26 05:27:09 +00:00
|
|
|
log.Debug(fmt.Printf("Perms: %+v\n", perms))
|
2016-06-25 23:45:33 +00:00
|
|
|
return perms, nil
|
|
|
|
}
|
|
|
|
|
2016-08-11 20:35:47 +00:00
|
|
|
func (c *Client) FindFileForRepo(owner string, repo string, fileName string, ref string) ([]byte, error) {
|
|
|
|
response, err := c.client.Get(fmt.Sprintf(pathSource, c.base, owner, repo, fileName, ref))
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
|
|
|
if response.StatusCode == 404 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
responseBytes, err := ioutil.ReadAll(response.Body)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
|
|
|
return responseBytes, nil
|
|
|
|
}
|
|
|
|
|
2016-06-26 05:27:09 +00:00
|
|
|
func (c *Client) CreateHook(owner string, name string, callBackLink string) error {
|
2016-06-25 23:45:33 +00:00
|
|
|
// Set hook
|
|
|
|
//TODO: Check existing and add up to 5
|
|
|
|
hookBytes := []byte(fmt.Sprintf(`{"hook-url-0":"%s"}`, callBackLink))
|
2016-06-26 05:27:09 +00:00
|
|
|
return c.doPut(fmt.Sprintf(pathHookEnabled, c.base, owner, name, hookName), hookBytes)
|
2016-06-25 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 02:06:15 +00:00
|
|
|
func (c *Client) CreateStatus(revision string, status *BuildStatus) error {
|
|
|
|
uri := fmt.Sprintf(pathStatus, c.base, revision)
|
|
|
|
return c.doPost(uri, status)
|
|
|
|
}
|
|
|
|
|
2016-06-26 05:27:09 +00:00
|
|
|
func (c *Client) DeleteHook(owner string, name string, link string) error {
|
2016-06-25 23:45:33 +00:00
|
|
|
//TODO: eventially should only delete the link callback
|
2016-06-26 05:27:09 +00:00
|
|
|
return c.doDelete(fmt.Sprintf(pathHookEnabled, c.base, owner, name, hookName))
|
2016-06-25 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 02:06:15 +00:00
|
|
|
//TODO: make these as as general do with the action
|
|
|
|
|
2016-06-25 23:45:33 +00:00
|
|
|
//Helper function to help create the hook
|
2016-06-26 05:27:09 +00:00
|
|
|
func (c *Client) doPut(url string, body []byte) error {
|
2016-06-25 23:45:33 +00:00
|
|
|
request, err := http.NewRequest("PUT", url, bytes.NewBuffer(body))
|
|
|
|
request.Header.Add("Content-Type", "application/json")
|
2016-06-26 05:27:09 +00:00
|
|
|
response, err := c.client.Do(request)
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
return nil
|
2016-08-14 02:06:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-25 23:45:33 +00:00
|
|
|
|
2016-08-14 02:06:15 +00:00
|
|
|
//Helper function to help create the hook
|
|
|
|
func (c *Client) doPost(url string, status *BuildStatus) error {
|
|
|
|
// write it to the body of the request.
|
|
|
|
var buf io.ReadWriter
|
|
|
|
if status != nil {
|
|
|
|
buf = new(bytes.Buffer)
|
|
|
|
err := json.NewEncoder(buf).Encode(status)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
request, err := http.NewRequest("POST", url, buf)
|
|
|
|
request.Header.Add("Content-Type", "application/json")
|
|
|
|
response, err := c.client.Do(request)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
return nil
|
2016-06-25 23:45:33 +00:00
|
|
|
}
|
|
|
|
|
2016-08-14 02:06:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-25 23:45:33 +00:00
|
|
|
//Helper function to do delete on the hook
|
2016-06-26 05:27:09 +00:00
|
|
|
func (c *Client) doDelete(url string) error {
|
2016-06-25 23:45:33 +00:00
|
|
|
request, err := http.NewRequest("DELETE", url, nil)
|
2016-06-26 05:27:09 +00:00
|
|
|
response, err := c.client.Do(request)
|
2016-06-25 23:45:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
return nil
|
2016-06-26 05:27:09 +00:00
|
|
|
}
|
2016-08-30 01:23:59 +00:00
|
|
|
|
|
|
|
//Helper function to get repos paginated
|
|
|
|
func (c *Client) paginatedRepos(start int) ([]*Repo, error) {
|
|
|
|
limit := 1000
|
|
|
|
requestUrl := fmt.Sprintf(pathRepos, c.base, strconv.Itoa(start), strconv.Itoa(limit))
|
2016-08-30 03:06:35 +00:00
|
|
|
log.Debugf("request :%s", requestUrl)
|
2016-08-30 01:23:59 +00:00
|
|
|
response, err := c.client.Get(requestUrl)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
var repoResponse Repos
|
2016-08-30 03:06:35 +00:00
|
|
|
err = json.NewDecoder(response.Body).Decode(&repoResponse)
|
2016-08-30 01:23:59 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-08-30 03:06:35 +00:00
|
|
|
log.Debugf("repoResponse: %+v", repoResponse)
|
2016-08-30 01:23:59 +00:00
|
|
|
if(!repoResponse.IsLastPage){
|
|
|
|
reposList, err := c.paginatedRepos(start + limit);
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
repoResponse.Values = append(repoResponse.Values, reposList...)
|
|
|
|
}
|
|
|
|
return repoResponse.Values, nil
|
|
|
|
}
|