diff --git a/VERSION b/VERSION index 30f6cf8..894542a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.26.1 +0.26.2 diff --git a/go.mod b/go.mod index da1e054..d7fd2cd 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,8 @@ require ( github.com/spf13/afero v1.2.0 // indirect github.com/spf13/cobra v0.0.3 github.com/spf13/viper v1.3.1 + github.com/stretchr/objx v0.3.0 // indirect + github.com/stretchr/testify v1.3.0 golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb // indirect gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 87362f0..ea03c6c 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= @@ -45,8 +46,12 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.1 h1:5+8j8FTpnFV4nEImW/ofkzEt8VoOiLXxdYIDsB73T38= github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= +github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/pkg/codefresh/codefresh.go b/pkg/codefresh/codefresh.go index fce546e..fe23f83 100644 --- a/pkg/codefresh/codefresh.go +++ b/pkg/codefresh/codefresh.go @@ -2,14 +2,20 @@ package codefresh import ( "bytes" + "context" "encoding/json" "fmt" - "github.com/google/go-querystring/query" "io/ioutil" "net/http" "strings" + + "github.com/google/go-querystring/query" ) +//go:generate mockery -name Codefresh -filename codefresh.go + +//go:generate mockery -name UsersAPI -filename users.go + type ( Codefresh interface { Pipelines() IPipelineAPI @@ -19,6 +25,7 @@ type ( Progresses() IProgressAPI Clusters() IClusterAPI Contexts() IContextAPI + Users() UsersAPI Argo() ArgoAPI Gitops() GitopsAPI } @@ -41,6 +48,10 @@ func (c *codefresh) Pipelines() IPipelineAPI { return newPipelineAPI(c) } +func (c *codefresh) Users() UsersAPI { + return newUsersAPI(c) +} + func (c *codefresh) Tokens() ITokenAPI { return newTokenAPI(c) } @@ -74,6 +85,10 @@ func (c *codefresh) Gitops() GitopsAPI { } func (c *codefresh) requestAPI(opt *requestOptions) (*http.Response, error) { + return c.requestAPIWithContext(context.Background(), opt) +} + +func (c *codefresh) requestAPIWithContext(ctx context.Context, opt *requestOptions) (*http.Response, error) { var body []byte finalURL := fmt.Sprintf("%s%s", c.host, opt.path) if opt.qs != nil { @@ -82,7 +97,10 @@ func (c *codefresh) requestAPI(opt *requestOptions) (*http.Response, error) { if opt.body != nil { body, _ = json.Marshal(opt.body) } - request, err := http.NewRequest(opt.method, finalURL, bytes.NewBuffer(body)) + request, err := http.NewRequestWithContext(ctx, opt.method, finalURL, bytes.NewBuffer(body)) + if err != nil { + return nil, err + } request.Header.Set("Authorization", c.token) request.Header.Set("Content-Type", "application/json") diff --git a/pkg/codefresh/contexts.go b/pkg/codefresh/contexts.go index c4982c2..210efc7 100644 --- a/pkg/codefresh/contexts.go +++ b/pkg/codefresh/contexts.go @@ -7,7 +7,7 @@ type ( GetDefaultGitContext() (error, *ContextPayload) } - context struct { + contexts struct { codefresh *codefresh } @@ -42,10 +42,10 @@ type ( ) func newContextAPI(codefresh *codefresh) IContextAPI { - return &context{codefresh} + return &contexts{codefresh} } -func (c context) GetGitContexts() (error, *[]ContextPayload) { +func (c contexts) GetGitContexts() (error, *[]ContextPayload) { var result []ContextPayload qs := GitContextsQs{ @@ -67,7 +67,7 @@ func (c context) GetGitContexts() (error, *[]ContextPayload) { return err, &result } -func (c context) GetGitContextByName(name string) (error, *ContextPayload) { +func (c contexts) GetGitContextByName(name string) (error, *ContextPayload) { var result ContextPayload var qs = map[string]string{ "decrypt": "true", @@ -87,7 +87,7 @@ func (c context) GetGitContextByName(name string) (error, *ContextPayload) { return nil, &result } -func (c context) GetDefaultGitContext() (error, *ContextPayload) { +func (c contexts) GetDefaultGitContext() (error, *ContextPayload) { var result ContextPayload resp, err := c.codefresh.requestAPI(&requestOptions{ diff --git a/pkg/codefresh/gitops.go b/pkg/codefresh/gitops.go index 99a5e7a..61c476d 100644 --- a/pkg/codefresh/gitops.go +++ b/pkg/codefresh/gitops.go @@ -69,17 +69,19 @@ type ( Current int64 `json:"current"` Desired int64 `json:"desired"` } - User struct { - Name string `json:"name"` - Avatar string `json:"avatar"` - } + Annotation struct { Key string `json:"key"` Value string `json:"value"` } + GitopsUser struct { + Name string `json:"name"` + Avatar string `json:"avatar"` + } + Gitops struct { - Comitters []User `json:"comitters"` + Comitters []GitopsUser `json:"comitters"` Prs []Annotation `json:"prs"` Issues []Annotation `json:"issues"` } diff --git a/pkg/codefresh/mocks/codefresh.go b/pkg/codefresh/mocks/codefresh.go new file mode 100644 index 0000000..d924579 --- /dev/null +++ b/pkg/codefresh/mocks/codefresh.go @@ -0,0 +1,173 @@ +// Code generated by mockery v1.1.1. DO NOT EDIT. + +package mocks + +import ( + codefresh "github.com/codefresh-io/go-sdk/pkg/codefresh" + mock "github.com/stretchr/testify/mock" +) + +// Codefresh is an autogenerated mock type for the Codefresh type +type Codefresh struct { + mock.Mock +} + +// Argo provides a mock function with given fields: +func (_m *Codefresh) Argo() codefresh.ArgoAPI { + ret := _m.Called() + + var r0 codefresh.ArgoAPI + if rf, ok := ret.Get(0).(func() codefresh.ArgoAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.ArgoAPI) + } + } + + return r0 +} + +// Clusters provides a mock function with given fields: +func (_m *Codefresh) Clusters() codefresh.IClusterAPI { + ret := _m.Called() + + var r0 codefresh.IClusterAPI + if rf, ok := ret.Get(0).(func() codefresh.IClusterAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.IClusterAPI) + } + } + + return r0 +} + +// Contexts provides a mock function with given fields: +func (_m *Codefresh) Contexts() codefresh.IContextAPI { + ret := _m.Called() + + var r0 codefresh.IContextAPI + if rf, ok := ret.Get(0).(func() codefresh.IContextAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.IContextAPI) + } + } + + return r0 +} + +// Gitops provides a mock function with given fields: +func (_m *Codefresh) Gitops() codefresh.GitopsAPI { + ret := _m.Called() + + var r0 codefresh.GitopsAPI + if rf, ok := ret.Get(0).(func() codefresh.GitopsAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.GitopsAPI) + } + } + + return r0 +} + +// Pipelines provides a mock function with given fields: +func (_m *Codefresh) Pipelines() codefresh.IPipelineAPI { + ret := _m.Called() + + var r0 codefresh.IPipelineAPI + if rf, ok := ret.Get(0).(func() codefresh.IPipelineAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.IPipelineAPI) + } + } + + return r0 +} + +// Progresses provides a mock function with given fields: +func (_m *Codefresh) Progresses() codefresh.IProgressAPI { + ret := _m.Called() + + var r0 codefresh.IProgressAPI + if rf, ok := ret.Get(0).(func() codefresh.IProgressAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.IProgressAPI) + } + } + + return r0 +} + +// RuntimeEnvironments provides a mock function with given fields: +func (_m *Codefresh) RuntimeEnvironments() codefresh.IRuntimeEnvironmentAPI { + ret := _m.Called() + + var r0 codefresh.IRuntimeEnvironmentAPI + if rf, ok := ret.Get(0).(func() codefresh.IRuntimeEnvironmentAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.IRuntimeEnvironmentAPI) + } + } + + return r0 +} + +// Tokens provides a mock function with given fields: +func (_m *Codefresh) Tokens() codefresh.ITokenAPI { + ret := _m.Called() + + var r0 codefresh.ITokenAPI + if rf, ok := ret.Get(0).(func() codefresh.ITokenAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.ITokenAPI) + } + } + + return r0 +} + +// Users provides a mock function with given fields: +func (_m *Codefresh) Users() codefresh.UsersAPI { + ret := _m.Called() + + var r0 codefresh.UsersAPI + if rf, ok := ret.Get(0).(func() codefresh.UsersAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.UsersAPI) + } + } + + return r0 +} + +// Workflows provides a mock function with given fields: +func (_m *Codefresh) Workflows() codefresh.IWorkflowAPI { + ret := _m.Called() + + var r0 codefresh.IWorkflowAPI + if rf, ok := ret.Get(0).(func() codefresh.IWorkflowAPI); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(codefresh.IWorkflowAPI) + } + } + + return r0 +} diff --git a/pkg/codefresh/mocks/users.go b/pkg/codefresh/mocks/users.go new file mode 100644 index 0000000..700d911 --- /dev/null +++ b/pkg/codefresh/mocks/users.go @@ -0,0 +1,39 @@ +// Code generated by mockery v1.1.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + codefresh "github.com/codefresh-io/go-sdk/pkg/codefresh" + + mock "github.com/stretchr/testify/mock" +) + +// UsersAPI is an autogenerated mock type for the UsersAPI type +type UsersAPI struct { + mock.Mock +} + +// GetCurrent provides a mock function with given fields: ctx +func (_m *UsersAPI) GetCurrent(ctx context.Context) (*codefresh.User, error) { + ret := _m.Called(ctx) + + var r0 *codefresh.User + if rf, ok := ret.Get(0).(func(context.Context) *codefresh.User); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*codefresh.User) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/pkg/codefresh/users.go b/pkg/codefresh/users.go new file mode 100644 index 0000000..ca73af9 --- /dev/null +++ b/pkg/codefresh/users.go @@ -0,0 +1,65 @@ +package codefresh + +import ( + "context" + "fmt" +) + +type ( + UsersAPI interface { + GetCurrent(ctx context.Context) (*User, error) + } + + User struct { + ID string `json:"_id"` + Name string `json:"userName"` + Email string `json:"email"` + Accounts []Account `json:"account"` + ActiveAccountName string `json:"activeAccountName"` + Roles []string `json:"roles"` + UserData struct { + Avatar string `json:"image"` + } `json:"user_data"` + } + + Account struct { + Name string `json:"name"` + } + + users struct { + *codefresh + } +) + +func newUsersAPI(codefresh *codefresh) UsersAPI { + return &users{codefresh} +} + +func (u *users) GetCurrent(ctx context.Context) (*User, error) { + result := &User{} + resp, err := u.codefresh.requestAPIWithContext(ctx, &requestOptions{ + method: "GET", + path: "/api/user", + }) + if err != nil { + return nil, err + } + if resp.StatusCode >= 400 { + return nil, fmt.Errorf(resp.Status) + } + + if err := u.codefresh.decodeResponseInto(resp, &result); err != nil { + return nil, err + } + + return result, nil +} + +func (u *User) GetActiveAccount() *Account { + for i := 0; i < len(u.Accounts); i++ { + if u.Accounts[i].Name == u.ActiveAccountName { + return &u.Accounts[i] + } + } + return nil +}