Merge pull request #3801 from cappyzawa/feature/get-team
Enable to print specified team config (fly get-team)
This commit is contained in:
commit
431efe4874
|
@ -209,6 +209,7 @@ var requiredRoles = map[string]string{
|
|||
atc.ListDestroyingVolumes: "viewer",
|
||||
atc.ReportWorkerVolumes: "member",
|
||||
atc.ListTeams: "viewer",
|
||||
atc.GetTeam: "viewer",
|
||||
atc.SetTeam: "owner",
|
||||
atc.RenameTeam: "owner",
|
||||
atc.DestroyTeam: "owner",
|
||||
|
|
|
@ -760,6 +760,10 @@ var _ = Describe("Accessor", func() {
|
|||
Entry("pipeline-operator :: "+atc.ListTeams, atc.ListTeams, "pipeline-operator", true),
|
||||
Entry("viewer :: "+atc.ListTeams, atc.ListTeams, "viewer", true),
|
||||
|
||||
Entry("owner :: "+atc.GetTeam, atc.GetTeam, "owner", true),
|
||||
Entry("member :: "+atc.GetTeam, atc.GetTeam, "member", true),
|
||||
Entry("viewer :: "+atc.GetTeam, atc.GetTeam, "viewer", true),
|
||||
|
||||
Entry("owner :: "+atc.SetTeam, atc.SetTeam, "owner", true),
|
||||
Entry("member :: "+atc.SetTeam, atc.SetTeam, "member", false),
|
||||
Entry("pipeline-operator :: "+atc.SetTeam, atc.SetTeam, "pipeline-operator", false),
|
||||
|
|
|
@ -185,6 +185,7 @@ func NewHandler(
|
|||
atc.ReportWorkerVolumes: http.HandlerFunc(volumesServer.ReportWorkerVolumes),
|
||||
|
||||
atc.ListTeams: http.HandlerFunc(teamServer.ListTeams),
|
||||
atc.GetTeam: http.HandlerFunc(teamServer.GetTeam),
|
||||
atc.SetTeam: http.HandlerFunc(teamServer.SetTeam),
|
||||
atc.RenameTeam: http.HandlerFunc(teamServer.RenameTeam),
|
||||
atc.DestroyTeam: http.HandlerFunc(teamServer.DestroyTeam),
|
||||
|
|
|
@ -166,6 +166,125 @@ var _ = Describe("Teams API", func() {
|
|||
})
|
||||
})
|
||||
|
||||
Describe("GET /api/v1/teams/:team_name", func() {
|
||||
var response *http.Response
|
||||
var fakeTeam *dbfakes.FakeTeam
|
||||
|
||||
BeforeEach(func() {
|
||||
fakeTeam = new(dbfakes.FakeTeam)
|
||||
fakeTeam.IDReturns(1)
|
||||
fakeTeam.NameReturns("a-team")
|
||||
fakeTeam.AuthReturns(atc.TeamAuth{
|
||||
"owner": map[string][]string{
|
||||
"groups": {}, "users": {"local:username"},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
JustBeforeEach(func() {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/v1/teams/a-team", server.URL), nil)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
response, err = client.Do(req)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Context("when not authenticated and not admin", func() {
|
||||
BeforeEach(func() {
|
||||
fakeaccess.IsAuthorizedReturns(false)
|
||||
fakeaccess.IsAdminReturns(false)
|
||||
})
|
||||
|
||||
It("returns 401", func() {
|
||||
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when not authenticated to specified team, but have admin authority", func() {
|
||||
BeforeEach(func() {
|
||||
dbTeamFactory.FindTeamReturns(fakeTeam, true, nil)
|
||||
fakeaccess.IsAuthenticatedReturns(true)
|
||||
fakeaccess.IsAdminReturns(true)
|
||||
fakeaccess.IsAuthorizedReturns(false)
|
||||
})
|
||||
|
||||
It("returns 200 ok", func() {
|
||||
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
||||
})
|
||||
|
||||
It("returns application/json", func() {
|
||||
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
||||
})
|
||||
|
||||
It("returns a team JSON", func() {
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(body).To(MatchJSON(`
|
||||
{
|
||||
"id": 1,
|
||||
"name": "a-team",
|
||||
"auth": {
|
||||
"owner": {
|
||||
"groups": [],
|
||||
"users": [
|
||||
"local:username"
|
||||
]
|
||||
}
|
||||
}
|
||||
}`))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when authenticated to specified team", func() {
|
||||
BeforeEach(func() {
|
||||
dbTeamFactory.FindTeamReturns(fakeTeam, true, nil)
|
||||
fakeaccess.IsAuthenticatedReturns(true)
|
||||
fakeaccess.IsAdminReturns(false)
|
||||
fakeaccess.IsAuthorizedReturns(true)
|
||||
})
|
||||
|
||||
It("returns 200 ok", func() {
|
||||
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
||||
})
|
||||
|
||||
It("returns application/json", func() {
|
||||
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
||||
})
|
||||
|
||||
It("returns a team JSON", func() {
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(body).To(MatchJSON(`
|
||||
{
|
||||
"id": 1,
|
||||
"name": "a-team",
|
||||
"auth": {
|
||||
"owner": {
|
||||
"groups": [],
|
||||
"users": [
|
||||
"local:username"
|
||||
]
|
||||
}
|
||||
}
|
||||
}`))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when authenticated as another team", func() {
|
||||
BeforeEach(func() {
|
||||
dbTeamFactory.FindTeamReturns(fakeTeam, true, nil)
|
||||
fakeaccess.IsAuthenticatedReturns(true)
|
||||
})
|
||||
|
||||
It("return 401", func() {
|
||||
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
||||
})
|
||||
})
|
||||
})
|
||||
Describe("PUT /api/v1/teams/:team_name", func() {
|
||||
var (
|
||||
response *http.Response
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package teamserver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/concourse/concourse/atc"
|
||||
"github.com/concourse/concourse/atc/api/accessor"
|
||||
"github.com/concourse/concourse/atc/api/present"
|
||||
)
|
||||
|
||||
func (s *Server) GetTeam(w http.ResponseWriter, r *http.Request) {
|
||||
hLog := s.logger.Session("get-team")
|
||||
|
||||
hLog.Debug("getting-team")
|
||||
|
||||
teamName := r.FormValue(":team_name")
|
||||
team, found, err := s.teamFactory.FindTeam(teamName)
|
||||
if err != nil {
|
||||
hLog.Error("failed-to-get-team", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if !found {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
acc := accessor.GetAccessor(r)
|
||||
var presentedTeam atc.Team
|
||||
|
||||
if acc.IsAdmin() || acc.IsAuthorized(team.Name()) {
|
||||
presentedTeam = present.Team(team)
|
||||
} else {
|
||||
hLog.Error("unauthorized", errors.New("not authorized to "+team.Name()))
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(presentedTeam); err != nil {
|
||||
hLog.Error("failed-to-encode-team", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
|
@ -91,6 +91,7 @@ const (
|
|||
ReportWorkerVolumes = "ReportWorkerVolumes"
|
||||
|
||||
ListTeams = "ListTeams"
|
||||
GetTeam = "GetTeam"
|
||||
SetTeam = "SetTeam"
|
||||
RenameTeam = "RenameTeam"
|
||||
DestroyTeam = "DestroyTeam"
|
||||
|
@ -197,6 +198,7 @@ var Routes = rata.Routes([]rata.Route{
|
|||
{Path: "/api/v1/volumes/report", Method: "PUT", Name: ReportWorkerVolumes},
|
||||
|
||||
{Path: "/api/v1/teams", Method: "GET", Name: ListTeams},
|
||||
{Path: "/api/v1/teams/:team_name", Method: "GET", Name: GetTeam},
|
||||
{Path: "/api/v1/teams/:team_name", Method: "PUT", Name: SetTeam},
|
||||
{Path: "/api/v1/teams/:team_name/rename", Method: "PUT", Name: RenameTeam},
|
||||
{Path: "/api/v1/teams/:team_name", Method: "DELETE", Name: DestroyTeam},
|
||||
|
|
|
@ -102,6 +102,7 @@ func (wrappa *APIAuthWrappa) Wrap(handlers rata.Handlers) rata.Handlers {
|
|||
atc.RegisterWorker,
|
||||
atc.HeartbeatWorker,
|
||||
atc.DeleteWorker,
|
||||
atc.GetTeam,
|
||||
atc.SetTeam,
|
||||
atc.ListTeamBuilds,
|
||||
atc.RenameTeam,
|
||||
|
|
|
@ -202,6 +202,7 @@ var _ = Describe("APIAuthWrappa", func() {
|
|||
atc.RegisterWorker: authenticated(inputHandlers[atc.RegisterWorker]),
|
||||
atc.HeartbeatWorker: authenticated(inputHandlers[atc.HeartbeatWorker]),
|
||||
atc.DeleteWorker: authenticated(inputHandlers[atc.DeleteWorker]),
|
||||
atc.GetTeam: authenticated(inputHandlers[atc.GetTeam]),
|
||||
atc.SetTeam: authenticated(inputHandlers[atc.SetTeam]),
|
||||
atc.RenameTeam: authenticated(inputHandlers[atc.RenameTeam]),
|
||||
atc.DestroyTeam: authenticated(inputHandlers[atc.DestroyTeam]),
|
||||
|
|
|
@ -24,6 +24,7 @@ type FlyCommand struct {
|
|||
Userinfo UserinfoCommand `command:"userinfo" description:"User information"`
|
||||
|
||||
Teams TeamsCommand `command:"teams" alias:"t" description:"List the configured teams"`
|
||||
GetTeam GetTeamCommand `command:"get-team" alias:"gt" description:"Show team configuration"`
|
||||
SetTeam SetTeamCommand `command:"set-team" alias:"st" description:"Create or modify a team to have the given credentials"`
|
||||
RenameTeam RenameTeamCommand `command:"rename-team" alias:"rt" description:"Rename a team"`
|
||||
DestroyTeam DestroyTeamCommand `command:"destroy-team" alias:"dt" description:"Destroy a team and delete all of its data"`
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/concourse/concourse/fly/commands/internal/displayhelpers"
|
||||
"github.com/concourse/concourse/fly/rc"
|
||||
"github.com/concourse/concourse/fly/ui"
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type GetTeamCommand struct {
|
||||
Team string `short:"n" long:"team" required:"true" description:"Get configuration of this team"`
|
||||
Json bool `short:"j" long:"json" description:"Print config as json instead of yaml"`
|
||||
}
|
||||
|
||||
func (command *GetTeamCommand) Execute(args []string) error {
|
||||
target, err := rc.LoadTarget(Fly.Target, Fly.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := target.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
team, found, err := target.Team().Team(command.Team)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !found {
|
||||
return errors.New("team not found")
|
||||
}
|
||||
|
||||
if command.Json {
|
||||
if err := displayhelpers.JsonPrint(team); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
headers := ui.TableRow{
|
||||
{Contents: "name/role", Color: color.New(color.Bold)},
|
||||
{Contents: "users", Color: color.New(color.Bold)},
|
||||
{Contents: "groups", Color: color.New(color.Bold)},
|
||||
}
|
||||
table := ui.Table{Headers: headers}
|
||||
for role, auth := range team.Auth {
|
||||
row := ui.TableRow{
|
||||
{Contents: fmt.Sprintf("%s/%s", team.Name, role)},
|
||||
}
|
||||
var usersCell, groupsCell ui.TableCell
|
||||
hasUsers := len(auth["users"]) != 0
|
||||
hasGroups := len(auth["groups"]) != 0
|
||||
|
||||
if !hasUsers && !hasGroups {
|
||||
usersCell.Contents = "all"
|
||||
usersCell.Color = color.New(color.Faint)
|
||||
} else if !hasUsers {
|
||||
usersCell.Contents = "none"
|
||||
usersCell.Color = color.New(color.Faint)
|
||||
} else {
|
||||
usersCell.Contents = strings.Join(auth["users"], ",")
|
||||
}
|
||||
|
||||
if hasGroups {
|
||||
groupsCell.Contents = strings.Join(auth["groups"], ",")
|
||||
} else {
|
||||
groupsCell.Contents = "none"
|
||||
groupsCell.Color = color.New(color.Faint)
|
||||
}
|
||||
|
||||
row = append(row, usersCell)
|
||||
row = append(row, groupsCell)
|
||||
table.Data = append(table.Data, row)
|
||||
}
|
||||
sort.Sort(table.Data)
|
||||
return table.Render(os.Stdout, Fly.PrintTableHeaders)
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package integration_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os/exec"
|
||||
|
||||
"github.com/concourse/concourse/atc"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gbytes"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
"github.com/onsi/gomega/ghttp"
|
||||
"github.com/tedsuo/rata"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var _ = Describe("GetPipeline", func() {
|
||||
var (
|
||||
team atc.Team
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
team = atc.Team{
|
||||
ID: 1,
|
||||
Name: "myTeam",
|
||||
Auth: atc.TeamAuth{
|
||||
"owner": map[string][]string{
|
||||
"groups": {}, "users": {"local:username"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Context("when not specifying a team name", func() {
|
||||
It("fails and says you should give a team name", func() {
|
||||
flyCmd := exec.Command(flyPath, "-t", targetName, "get-team")
|
||||
|
||||
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
<-sess.Exited
|
||||
Expect(sess.ExitCode()).To(Equal(1))
|
||||
|
||||
Expect(sess.Err).To(gbytes.Say("error: the required flag `" + osFlag("n", "team") + "' was not specified"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when specifying a team name", func() {
|
||||
var path string
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
path, err = atc.Routes.CreatePathForRoute(atc.GetTeam, rata.Params{"team_name": "myTeam"})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Context("and team is not found", func() {
|
||||
JustBeforeEach(func() {
|
||||
atcServer.AppendHandlers(
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("GET", path),
|
||||
ghttp.RespondWithJSONEncoded(http.StatusNotFound, ""),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
It("should print team not found error", func() {
|
||||
flyCmd := exec.Command(flyPath, "-t", targetName, "get-team", "-n", "myTeam")
|
||||
|
||||
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
<-sess.Exited
|
||||
Expect(sess.ExitCode()).To(Equal(1))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when atc returns team config", func() {
|
||||
BeforeEach(func() {
|
||||
atcServer.AppendHandlers(
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("GET", path),
|
||||
ghttp.RespondWithJSONEncoded(200, team),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
It("prints the config as yaml to stdout", func() {
|
||||
flyCmd := exec.Command(flyPath, "-t", targetName, "get-team", "myTeam")
|
||||
|
||||
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
<-sess.Exited
|
||||
Expect(sess.ExitCode()).To(Equal(0))
|
||||
|
||||
var printedConfig atc.Team
|
||||
err = yaml.Unmarshal(sess.Out.Contents(), &printedConfig)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(printedConfig).To(Equal(team))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -594,6 +594,21 @@ type FakeTeam struct {
|
|||
result3 bool
|
||||
result4 error
|
||||
}
|
||||
TeamStub func(string) (atc.Team, bool, error)
|
||||
teamMutex sync.RWMutex
|
||||
teamArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
teamReturns struct {
|
||||
result1 atc.Team
|
||||
result2 bool
|
||||
result3 error
|
||||
}
|
||||
teamReturnsOnCall map[int]struct {
|
||||
result1 atc.Team
|
||||
result2 bool
|
||||
result3 error
|
||||
}
|
||||
UnpauseJobStub func(string, string) (bool, error)
|
||||
unpauseJobMutex sync.RWMutex
|
||||
unpauseJobArgsForCall []struct {
|
||||
|
@ -3230,6 +3245,72 @@ func (fake *FakeTeam) ResourceVersionsReturnsOnCall(i int, result1 []atc.Resourc
|
|||
}{result1, result2, result3, result4}
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) Team(arg1 string) (atc.Team, bool, error) {
|
||||
fake.teamMutex.Lock()
|
||||
ret, specificReturn := fake.teamReturnsOnCall[len(fake.teamArgsForCall)]
|
||||
fake.teamArgsForCall = append(fake.teamArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
fake.recordInvocation("Team", []interface{}{arg1})
|
||||
fake.teamMutex.Unlock()
|
||||
if fake.TeamStub != nil {
|
||||
return fake.TeamStub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2, ret.result3
|
||||
}
|
||||
fakeReturns := fake.teamReturns
|
||||
return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) TeamCallCount() int {
|
||||
fake.teamMutex.RLock()
|
||||
defer fake.teamMutex.RUnlock()
|
||||
return len(fake.teamArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) TeamCalls(stub func(string) (atc.Team, bool, error)) {
|
||||
fake.teamMutex.Lock()
|
||||
defer fake.teamMutex.Unlock()
|
||||
fake.TeamStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) TeamArgsForCall(i int) string {
|
||||
fake.teamMutex.RLock()
|
||||
defer fake.teamMutex.RUnlock()
|
||||
argsForCall := fake.teamArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) TeamReturns(result1 atc.Team, result2 bool, result3 error) {
|
||||
fake.teamMutex.Lock()
|
||||
defer fake.teamMutex.Unlock()
|
||||
fake.TeamStub = nil
|
||||
fake.teamReturns = struct {
|
||||
result1 atc.Team
|
||||
result2 bool
|
||||
result3 error
|
||||
}{result1, result2, result3}
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) TeamReturnsOnCall(i int, result1 atc.Team, result2 bool, result3 error) {
|
||||
fake.teamMutex.Lock()
|
||||
defer fake.teamMutex.Unlock()
|
||||
fake.TeamStub = nil
|
||||
if fake.teamReturnsOnCall == nil {
|
||||
fake.teamReturnsOnCall = make(map[int]struct {
|
||||
result1 atc.Team
|
||||
result2 bool
|
||||
result3 error
|
||||
})
|
||||
}
|
||||
fake.teamReturnsOnCall[i] = struct {
|
||||
result1 atc.Team
|
||||
result2 bool
|
||||
result3 error
|
||||
}{result1, result2, result3}
|
||||
}
|
||||
|
||||
func (fake *FakeTeam) UnpauseJob(arg1 string, arg2 string) (bool, error) {
|
||||
fake.unpauseJobMutex.Lock()
|
||||
ret, specificReturn := fake.unpauseJobReturnsOnCall[len(fake.unpauseJobArgsForCall)]
|
||||
|
@ -3506,6 +3587,8 @@ func (fake *FakeTeam) Invocations() map[string][][]interface{} {
|
|||
defer fake.resourceMutex.RUnlock()
|
||||
fake.resourceVersionsMutex.RLock()
|
||||
defer fake.resourceVersionsMutex.RUnlock()
|
||||
fake.teamMutex.RLock()
|
||||
defer fake.teamMutex.RUnlock()
|
||||
fake.unpauseJobMutex.RLock()
|
||||
defer fake.unpauseJobMutex.RUnlock()
|
||||
fake.unpausePipelineMutex.RLock()
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
type Team interface {
|
||||
Name() string
|
||||
|
||||
Team(teamName string) (atc.Team, bool, error)
|
||||
CreateOrUpdate(team atc.Team) (atc.Team, bool, bool, error)
|
||||
RenameTeam(teamName, name string) (bool, error)
|
||||
DestroyTeam(teamName string) error
|
||||
|
|
|
@ -14,6 +14,27 @@ import (
|
|||
|
||||
var ErrDestroyRefused = errors.New("not-permitted-to-destroy-as-requested")
|
||||
|
||||
// Team get team with the name given as argument.
|
||||
func (team *team) Team(teamName string) (atc.Team, bool, error) {
|
||||
var t atc.Team
|
||||
params := rata.Params{"team_name": teamName}
|
||||
err := team.connection.Send(internal.Request{
|
||||
RequestName: atc.GetTeam,
|
||||
Params: params,
|
||||
}, &internal.Response{
|
||||
Result: &t,
|
||||
})
|
||||
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
return t, true, nil
|
||||
case internal.ResourceNotFoundError:
|
||||
return atc.Team{}, false, nil
|
||||
default:
|
||||
return atc.Team{}, false, err
|
||||
}
|
||||
}
|
||||
|
||||
// CreateOrUpdate creates or updates team teamName with the settings provided in passedTeam.
|
||||
// passedTeam should reflect the desired state of team's configuration.
|
||||
func (team *team) CreateOrUpdate(passedTeam atc.Team) (atc.Team, bool, bool, error) {
|
||||
|
|
|
@ -12,6 +12,75 @@ import (
|
|||
)
|
||||
|
||||
var _ = Describe("ATC Handler Teams", func() {
|
||||
Describe("Team", func() {
|
||||
var expectedTeam atc.Team
|
||||
teamName := "myTeam"
|
||||
expectedURL := "/api/v1/teams/myTeam"
|
||||
|
||||
BeforeEach(func() {
|
||||
expectedTeam = atc.Team{
|
||||
ID: 1,
|
||||
Name: "myTeam",
|
||||
Auth: atc.TeamAuth{
|
||||
"owner": map[string][]string{
|
||||
"groups": {}, "users": {"local:username"},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
Context("when the team is found", func() {
|
||||
BeforeEach(func() {
|
||||
atcServer.AppendHandlers(
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("GET", expectedURL),
|
||||
ghttp.RespondWithJSONEncoded(http.StatusOK, expectedTeam),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
It("returns the requested team", func() {
|
||||
team, found, err := team.Team(teamName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(found).To(BeTrue())
|
||||
Expect(team).To(Equal(expectedTeam))
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the team is not found", func() {
|
||||
BeforeEach(func() {
|
||||
atcServer.AppendHandlers(
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("GET", expectedURL),
|
||||
ghttp.RespondWith(http.StatusNotFound, ""),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
It("returns false", func() {
|
||||
_, found, err := team.Team(teamName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(found).To(BeFalse())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when not belonging to the team", func() {
|
||||
BeforeEach(func() {
|
||||
atcServer.AppendHandlers(
|
||||
ghttp.CombineHandlers(
|
||||
ghttp.VerifyRequest("GET", expectedURL),
|
||||
ghttp.RespondWith(http.StatusUnauthorized, ""),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
It("returns false and error", func() {
|
||||
_, found, err := team.Team(teamName)
|
||||
Expect(found).To(BeFalse())
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
Describe("CreateOrUpdate", func() {
|
||||
var expectedURL = "/api/v1/teams/team venture"
|
||||
var expectedTeam, desiredTeam atc.Team
|
||||
|
|
Loading…
Reference in New Issue